【问题标题】:data types: symbol vs enumerated?数据类型:符号与枚举?
【发布时间】:2014-09-30 00:07:11
【问题描述】:

我想知道symbolenumerated 类型之间有什么区别和关系?

在阅读符号类型的第一个链接时,我产生了我的问题

在最简单的实现中,它们(符号类型)是 本质上命名的整数(例如 C 中的枚举类型)。

我按照第二个链接阅读了枚举类型,但无法弄清楚它们的区别和关系。

例如,它们似乎同时存在于 Common Lisp herehere 中,但我的问题不仅限于 CL,维基百科的两篇文章也不限于此。

谢谢。

【问题讨论】:

    标签: c types enums lisp symbols


    【解决方案1】:

    假设我们有几个文本样式:boldìtalicthinregular。现在我们有了一个绘制一些文本的函数:

    (defun draw-text-string (text style stream)
       ...)
    

    整数枚举

    我们将如何传递样式信息?我们可以将它们编码为数字:

    (defconstant +regular+ 0)
    (defconstant +thin+    1)
    (defconstant +bold+    2)
    (defconstant +italic+  3)
    

    我们可以将它们编码为位:

    (defconstant +regular+ #b0001) ; 1
    (defconstant +thin+    #b0010) ; 2
    (defconstant +bold+    #b0100) ; 4
    (defconstant +italic+  #b1000) ; 8
    

    枚举类型通常将这些映射隐藏在类型声明后面。

    当我们调用绘图函数时,我们以某种方式传递这些数字:

    (draw-text-string "hello" +thin+ *standard-output*)
    

    我们可以这样写:

    (draw-text-string "hello" 1 *standard-output*)
    

    如果我们有位编码,我们也可以传递一个集合:

    (draw-text-string "hello" (logxor +thin+ +italic+) *standard-output*)
    (draw-text-string "hello" 10                       *standard-output*)
    

    优点是编码非常紧凑。如果我们调试程序,在 Lisp 中我们会看到数字。在静态类型语言中,调试器可以访问类型信息并将值显示为名称。

    这种枚举通常不会在 Lisp 中完成 - 仅当需要与外部例程接口时,通常遵循 C 约定。

    枚举值作为符号

    在 Lisp 中,也可以使用符号来实现这一目的。作为单个符号或作为符号列表。这里符号本身就是值,它们不用作变量。

    (draw-text-string "hello" 'thin *standard-output*)
    (draw-text-string "hello" '(thin italic) *standard-output*)
    

    在 Common Lisp 中,我们经常使用自评估关键字符号。这样我们就不需要考虑包(命名空间)了。

    (draw-text-string "hello" :thin *standard-output*)
    (draw-text-string "hello" '(:thin :italic) *standard-output*)
    

    两者的优点是我们传递命名对象(符号),在 Lisp 系统中调试期间更容易理解。缺点是我们现在可以传递符号列表,这比数字或位向量之类的效率略低。

    运行时类型检查通常通过MEMBER 类型完成。

    【讨论】:

      【解决方案2】:

      符号可以用作枚举类型,但符号并不是真正的枚举类型,除非您考虑所有可能符号的集合(并且,假设符号可以无限长,那么有无限数量的可能的符号)是一个枚举。

      符号的优点,以及它与枚举相似的主要方式,是符号是固定的。因此,如果您在一个源文件中写入'foo 并在另一个源文件中写入'foo,它们都会计算为相同的符号(它们将具有相同的对象标识)。这使得它们非常适合用作哈希键、case 表达式等。

      【讨论】:

      • 谢谢,克里斯!我想知道在 C 中,如何定义符号类型的对象?
      • 您基本上必须创建一个实习池(基本上是一个哈希表),用于生成所有符号。您的符号生成函数将获取符号的名称,在实习池中查找它,如果它不存在则添加它,或者返回实习池中的现有实例。在任何一种情况下,因此返回的所有符号都将驻留在实习池中。
      • 一个潜在的麻烦点是大多数 C 程序不使用垃圾收集,因此您的实习生池只会增长,而不会缩小。这对您来说可能有问题,也可能没有问题。
      • 一旦你有一个合适的哈希表实现,实习池真的很容易实现。这是 Guava 的实现(在 Java 中):code.google.com/p/guava-libraries/source/browse/guava/src/com/…
      • (1) 如果我理解正确的话,在哈希表中,一个key是“符号类型的变量”的名称,而key的值是一个符号,是值被变量占用? (2) “符号类型的变量”的名称又是符号吗?
      猜你喜欢
      • 2012-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-02
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多