2

clojure 中在表达式开头使用 # 的构造的名称是什么,中间是 %?例如

#(fn [a b] (% b a))

我已经尝试搜索它的文档,但由于定义它的两个字符都不是字母数字,所以我的搜索并不太成功。

4

4 回答 4

8

它是匿名函数声明的读取器宏。有关阅读器宏的完整列表,请参见http://clojure.org/reader

例如,#(* 5 %)转换为(fn [x] (* 5 x)).

您的示例在阅读阶段转换为(fn [op] (fn [a b] (op a b)))(op是我在那里选择的占位符。)

于 2012-04-07T14:30:55.613 回答
6

它出现在(至少)两个地方:

  1. 其他有用的函数和宏下(但没有提到 %1 %2 等)。

  2. 阅读器(解析程序)中 - # 导致通过表查找发送到阅读器宏(您必须仔细查看,但这确实描述了 %1 等)

在这两种情况下,它都没有有用的名称(实际上,“Dispatch”可能是隐含的名称 - 请参阅第二个链接)。更一般地,“#”被称为octothorp,除其他外(在智利,“gato”(猫)出于某种未知原因)。

(是的, %1 %2 是第一个和第二个参数,等等,而 %& 是“rest” - 你可以只使用 % 作为第一个 - 请参阅第二个链接)。

PS 正如其他人所说,它是函数的简写。所以(fn [a b] (+ a b))相当于#(+ %1 %2)

Clojure> (#(println % % %2) 1 2)
1 1 2
nil
Clojure> (#(apply println %&) 1 2 3)
1 2 3
nil
于 2012-04-07T14:32:28.813 回答
2

#() 构造是匿名函数定义的简写。% 符号用作其参数的简写。

第一个参数的 %。%integer 表示多个参数(即 %1 %2)。%& 用于包装在序列中的其余(未使用的)参数。

=> (#(println % %2 %3 %&) 1 2 3 4 5)
1 2 3 (4 5)

您可以通过对其进行宏扩展来查看它创建的功能

#((\ %1 %2) * %2))
=> (macroexpand-1 '#((\ %1 %2) * %2))
(fn* [p1__744# p2__745#] ((\space p1__744# p2__745#) * p2__745#))

用正常的话来说,以下是相同的:

  #((\ %1 %2) * %2))
  (fn [p1 p2] ((\ p1 p2) * p2))

请注意,您的示例创建了一个匿名函数,其中包含一个新的匿名函数。

于 2012-04-07T14:57:34.257 回答
1

"#" 应该是 lambda 字符,% 表示预期的第一个参数

于 2012-04-07T14:33:58.983 回答