代码之家  ›  专栏  ›  技术社区  ›  Laurence Gonsalves

为什么Clojure除了“符号”之外还有“关键字”?

  •  122
  • Laurence Gonsalves  · 技术社区  · 15 年前

    我从一开始就对其他Lisp(特别是方案)有了初步的了解。最近我一直在读 Clojure . 我看到它有“符号”和“关键字”。我熟悉的符号,但不熟悉关键字。

    其他Lisp有关键字吗?关键字与符号有什么不同,除了有不同的符号(例如:冒号)?

    5 回复  |  直到 7 年前
        1
  •  128
  •   Community Navdeep Singh    7 年前

    这里是 Clojure documentation 关键字和符号。

    关键字是对自身进行计算的符号标识符。他们提供非常快速的平等测试…

    符号是通常用来指代其他事物的标识符。它们可以在程序形式中用于引用函数参数、let绑定、类名和全局变量…

    关键字通常用作轻量级的“常量字符串”,例如哈希图的键或多方法的调度值。符号通常用于命名变量和函数,除了在宏等中,直接将它们作为对象进行操作是不常见的。但是没有什么能阻止你在任何地方使用一个符号,你使用一个关键词(如果你不介意一直引用它们的话)。

    最简单的方法就是阅读 Keyword.java Symbol.java 在clojure来源。有一些明显的实现差异。例如,Clojure中的符号可以有元数据,关键字不能。

    除了单冒号语法之外,还可以使用双冒号来生成限定命名空间的关键字。

    user> :foo
    :foo
    user> ::foo
    :user/foo
    

    普通的Lisp有关键字,Ruby和其他语言也有。当然,它们在这些语言中略有不同。常见的lisp关键字和clojure关键字之间的一些区别:

    1. Clojure中的关键字不是符号。

      user> (symbol? :foo)  
      false
      
    2. 关键字不属于任何命名空间,除非您明确限定它们:

      user> (namespace :foo)
      nil
      user> (namespace ::foo)
      "user"
      

    (谢谢) Rainer Joswig 给我一些要看的东西。)

        2
  •  29
  •   Rainer Joswig Michael Fox    15 年前

    普通LISP 有关键字符号。

    关键字也是符号。

    (symbolp ':foo) -> T
    

    什么使关键字特别:

    • :foo由公共lisp阅读器解析为符号关键字::foo
    • 关键字自我评估::foo->:foo
    • 关键字符号的主包是关键字包:关键字:foo->:foo
    • 关键字从package关键字导出
    • 关键字是常量,不允许分配其他值

    否则关键词就是普通符号。所以关键字可以命名函数或具有属性列表。

    记住:在常见的Lisp中,符号属于一个包。这可以写为:

    • foo,当符号在当前包中可访问时
    • foo:bar,当符号foo从包栏导出时
    • foo::bar,当符号foo在包栏中时

    对于表示:foo的关键字符号,关键字:foo和关键字::foo都是相同的符号。因此,通常不使用后两个符号。

    所以:foo只是被解析为package关键字,假设在符号名称之前没有给出包名称,默认情况下意味着关键字package。

        3
  •  5
  •   Greg Hewgill    15 年前

    关键字是对自身进行评估的符号,因此您不必记住引用它们。

        4
  •  4
  •   Ivan Pierre    9 年前

    对于关键字,当关键字为 首先建造。当将关键字作为哈希键查找时,只需 返回预先计算的哈希值。对于字符串和符号,哈希是 每次查找时重新计算。

    为什么相同的命名关键字总是相同的,它们包含自己的哈希值。 由于地图和集合中的搜索是由散列键组成的,因此在进行大量搜索时(而不是搜索本身),这有助于提高搜索效率。

        5
  •  3
  •   Carl Smotricz    12 年前

    :许多集合还专门处理关键字,允许使用一些真正方便的语法。

    (:user-id (get-users-map))
    

    是一样的

    ((get-users-map) :user-id)
    

    这让事情变得更加灵活