什么是lisp/scheme中的符号?

dot*_*00b 38 lisp scheme racket

为了全能的爱,我还没有理解符号的目的'iamasymbol.我理解数字,布尔值,字符串...变量.但是符号对于我的小思维思维来说太过分了.我究竟用它做什么用的?它们应该如何在程序中使用?我对这个概念的把握只是失败了.

Lui*_*las 31

符号是一个具有简单字符串表示的对象(默认情况下)保证被实现 ; 即,任何两个写入相同的符号都是内存的相同对象(引用相等).

为什么Lisps有符号?好吧,它主要是Lisps将自己的语法作为语言的数据类型嵌入的事实.编译器和解释器使用符号来表示程序中的标识符; 因为Lisp允许您将程序的语法表示为数据,所以它提供符号,因为它们是表示的一部分.

除此之外它们有什么用处?嗯,有几件事:

  • Lisp通常用于实现嵌入式域特定语言.许多用于此的技术来自编译器世界,因此符号在这里是一个有用的工具.
  • Common Lisp中的宏通常涉及比这个答案提供的更详细的符号处理.(尽管特别是,为宏扩展生成唯一标识符需要能够生成一个保证永远不会与任何其他符号相等的符号.)
  • 固定枚举类型更好地实现为符号而不是字符串,因为符号可以通过引用相等来比较.
  • 您可以构建许多数据结构,从而可以通过使用符号和引用相等来获得性能优势.

  • 最好的答案. (2认同)
  • 那 `(eq (make-symbol "test") (make-symbol "test"))` 怎么样?我认为您关于保证符号被保留的声明仅适用于这些符号被“读取”的情况。不过,关于编译器的真正有趣的一点是;我从来没有这样想过:-) (2认同)

Rya*_*per 27

在Scheme和Racket中,符号就像一个不可变的字符串,碰巧被中断,因此可以与符号进行比较eq?(快速,基本上是指针比较).符号和字符串是单独的数据类型.

符号的一个用途是轻量级枚举.例如,有人可能会说,一个方向是'north,'south,'east,或'west.你当然可以使用字符串来达到同样的目的,但效率会稍差.使用数字是个坏主意; 以尽可能明显和透明的方式表示信息.

再举一个例子,SXML是使用列表,符号和字符串表示XML.特别是,字符串表示字符数据,符号表示元素名称.因此,XML <em>hello world</em>将由值表示,该值(list 'em "hello world")可以更紧凑地编写'(em "hello world").

符号的另一个用途是作为键.例如,您可以将方法表实现为将符号映射到实现函数的字典.要调用方法,请查找与方法名称对应的符号.Lisp/Scheme/Racket使得这非常简单,因为语言已经在标识符(语言的语法的一部分)和符号(语言中的值)之间具有内置的对应关系.这种对应使得支持变得容易,实现了用户定义的语言语法扩展.例如,可以使用"方法名称"(由类系统定义的语法概念)与符号之间的隐式对应关系,将类系统实现为宏库:

(send obj meth arg1 arg2)
=>
(apply (lookup-method obj 'meth) obj (list arg1 arg2))
Run Code Online (Sandbox Code Playgroud)

(在其他Lisps中,我所说的大部分都是真实的,但还有其他一些事情需要了解,比如包和函数与可变插槽,IIRC.)

  • 如果你来自 C 或 C#(只是从你的用户名猜测,.NET noob):当你在这些语言中使用 `enum` 时使用符号(并且枚举不是特定数字的标签)。`enum {北,南,东,西}`可以是`'north``'south``'east``'west`。您不需要像在 C 中使用 `enum` 那样“声明”那些。继续使用它们。然而,符号不能做`enum { north = 123 }`。为此,您需要更像 C `#define`: `(define north 123)`。 (3认同)

Ser*_*iuc 8

摘自Harold Abelson 和 Gerald Jay Sussman 1996 年对计算机程序第二版结构和解释

为了操作符号,我们的语言中需要一个新元素:引用数据对象的能力。假设我们要构造列表 (ab)。我们不能用 (list ab) 来完成这个,因为这个表达式构造了一个 a 和 b 值的列表,而不是符号本身。这个问题在自然语言的上下文中是众所周知的,其中单词和句子可以被视为语义实体或字符串(句法实体)。自然语言中的常见做法是使用引号来表示一个词或一个句子要按字面意思视为一串字符。例如,“John”的第一个字母显然是“J”。如果我们告诉某人“大声说出你的名字”,我们希望听到那个人的名字。然而,如果我们告诉某人“大声说出‘你的名字’,”我们期待听到“你的名字”这个词。请注意,我们被迫嵌套引号来描述其他人可能会说的话。 我们可以遵循相同的做法来识别将被视为数据对象而不是要评估的表达式的列表和符号。 但是,我们的引用格式与自然语言的格式不同,我们只在要引用的对象的开头放置一个引号(传统上,单引号符号 ')。我们可以在 Scheme 语法中避免这种情况,因为我们依靠空格和括号来分隔对象。因此,单引号字符的含义是引用下一个对象。现在我们可以区分符号和它们的值:

(define a 1)

(define b 2)

(list a b)
(1 2)

(list ’a ’b)
(a b)

(list ’a b)
(a 2)
Run Code Online (Sandbox Code Playgroud)

包含符号的列表看起来就像我们语言的表达式:

(* (+ 23 45) (+ x 9)) 
(define (fact n) (if (= n 1) 1 (* n (fact (- n 1)))))
Run Code Online (Sandbox Code Playgroud)

示例:符号微分


Laz*_*key 7

lisp中的符号是人类可读的标识符.他们都是单身人士.因此,如果您在代码中的某处声明'foo然后再次使用'foo,它将指向内存中的相同位置.

样本使用:不同的符号可以代表棋盘上的不同部分.


Tom*_*Tom 5

符号只是值的特殊名称.值可以是任何值,但该符号用于每次引用相同的值,并且此类事物用于快速比较.正如你所说,你是在思考,他们就像C中的数字常量,这就是它们通常被实现的方式(内部存储的数字).

  • 特别地,通过使用(eq?sym1 sym2),可以在恒定时间内检查两个符号的相等性.符号不是"Scheme"或"Lisp"概念:它们是通用的.想想术语"符号表".(http://en.wikipedia.org/wiki/Symbol_table)像Scheme或Racket这样的语言中的符号只是暴露了这个值的概念,就像一个字符串,但有这个额外的属性快速平等检查. (2认同)