Clojure中#的含义

时间:2019-03-08 04:27:10

标签: clojure

在Clojure中,您可以使用#

创建匿名函数

例如

#(+ % 1) 

是一个接受参数并将其加1的函数。

但是我们还必须对正则表达式使用# 例如

(clojure.string/split "hi, buddy" #",")

这两个#是否相关?

4 个答案:

答案 0 :(得分:7)

还有集合#{},完全限定的类名构造函数#my.klass_or_type_or_record[:a :b :c],实例#inst "yyyy-mm-ddThh:mm:ss.fff+hh:mm" and some others

在以下情况下它们是相关的:#启动clojure reader可以识别的序列,该序列将每个这样的实例分派给适当的读者。有一个guide对此进行了扩展

我认为存在此约定是为了将不同语法的数量减少到一种,从而简化读者。

答案 1 :(得分:3)

这两种用途没有(直接)关系。

在Clojure中,当您看到#符号时,这是一个很大的线索,表明您正在与 Clojure Reader “说话”,而不是 Clojure编译器。在此处查看阅读器上的完整文档:https://clojure.org/reference/reader

阅读器负责将纯文本从源文件转换为数据结构的集合。例如,比较Clojure和Java,我们有

; Clojure          ; Java
"Hello"      =>    new String( "Hello" )

[ "Goodbye" "cruel" "world!" ]   ; Clojure vector of 3 strings

; Java ArrayList of 3 strings
var msg = new ArrayList<String>();
msg.add( "Goodbye" );
msg.add( "cruel" );
msg.add( "world!" );

类似地,即使在Clojure源代码中(在编译器将其转换为Java字节码之前),Reader也可以识别一些快捷方式,只是为了节省您的键入时间。即使在Clojure编译器启动之前,这些“阅读器宏”也将从您的“简短格式”源代码转换为“标准Clojure”。例如:

@my-atom                       =>   (deref my-atom)    ; not using `#`
#'map                          =>   (var map)
#{ 1 2 3 }                     =>   (hash-set 1 2 3)
#_(launch-missiles 12.3 45.6)  =>   ``                 ; i.e. "nothing"
#(+ 1 %)                       =>   (fn [x] (+ 1 x))

,依此类推。如@deref运算符所示,并非所有阅读器宏都使用#(哈希/磅/八字形)符号。请注意,即使在向量文字的情况下:

[ "Goodbye" "cruel" "world!" ]

阅读器创建的结果就像您键入的内容一样:

(vector "Goodbye" "cruel" "world!" )

答案 2 :(得分:0)

其他Lisps具有适当的可编程读取器,因此可以读取宏。 Clojure实际上没有可编程的读取器-用户无法轻松添加新的读取宏-但是Clojure系统确实在内部使用读取宏。 #读取宏是dispatch宏,#之后的字符是另一个读取宏表的键。

是的,#确实意味着什么;但是它是如此的深刻和怪异,以至于您真的不需要知道这一点。

答案 3 :(得分:-1)

  

这两个#有关系吗?

不,不是。 #文字的使用方式有所不同。您已经提到了其中的一些:这些是匿名函数和正则表达式模式。这是更多情况:

  • 在表达式前加上#_只会从编译器中删除它,因为它从未被写入过。例如:#_(/ 0 0)在阅读器级别将被忽略,因此不会出现任何异常。

  • 标记基元以将其强制为复杂类型,例如#inst "2019-03-09"将产生java.util.Date类的实例。还有#uuid和其他内置标签。您可以注册自己的。

  • 标记普通地图以将其强制为类型地图,例如#project.models/User {:name "John" :age 42}将产生一个声明为(defrecord User ...)的地图。