Function Clojure如何处理函数定义?

Function Clojure如何处理函数定义?,function,clojure,binding,symbols,lexical-scope,Function,Clojure,Binding,Symbols,Lexical Scope,我在研究Clojure,我读到在Clojure中函数定义只是数据,也就是说参数向量只是一个普通向量。如果是这样的话,为什么我可以这样做 (def add (fn [a b] (+ a b))) 但不是这个 (def vector-of-symbols [a b]) ? 我知道我通常必须避开这样的符号: (def vector-of-symbols [`a `b]) 但是为什么我不在fn/defn中做呢?我假设这是因为fn/defn是宏。我试着检查它们的来源,但到目前为止它们对我来说太先

我在研究Clojure,我读到在Clojure中函数定义只是数据,也就是说参数向量只是一个普通向量。如果是这样的话,为什么我可以这样做

(def add (fn [a b]
  (+ a b)))
但不是这个

(def vector-of-symbols [a b])
?

我知道我通常必须避开这样的符号:

(def vector-of-symbols [`a `b])
但是为什么我不在
fn
/
defn
中做呢?我假设这是因为
fn
/
defn
是宏。我试着检查它们的来源,但到目前为止它们对我来说太先进了。我重新创建
defn
的尝试也失败了,我不知道为什么(我从教程中选取了一个例子):

有人能解释一下,Clojure到底是如何将数据结构,尤其是符号,转换成代码的?关于宏示例,我遗漏了什么

更新显然,宏不起作用,因为我的项目实际上在Clojurescript中(在Clojure中它起作用)。我不认为这有什么关系,但随着我的进步,我发现越来越多的东西在Clojurescript中对我不起作用


更新2这有助于:

函数与Clojure中的其他数据一样是一级公民

要定义向量,请使用
(vector…
或reader has syntaxic sugar
[…]
,对于列表,它是
(list…
)或
(…)
,对于set
(set…
{…}
,引用不将列表作为函数调用进行求值


因此,函数的工厂函数是
fn
(实际上
fn*
,它来自Clojure的Java核心,
fn
是一系列用于管理解构和所有操作的宏)

(fn
args body

是返回函数的函数调用,其中args是参数事件的向量。empty和body是一系列Clojure表达式,将使用绑定到环境的参数进行计算。如果不计算任何值,则返回nil。还有一个语法糖
#(…)
,其中
%x
作为参数x,
%
作为参数1

(fn…
返回一个函数值。所以

(定义我的超级函数(fn[a b c d](println“coucu”)(+a b c d)))

将符号
my super function
返回的匿名函数绑定(fn[a b c d](println“coucou”)(+a b c d))

(定义我的向量[1 2 3])


将符号
my_vector
与学习资源列表的向量
[1 2 3]
绑定:

正如@jas所说,您的defn2宏看起来很好

主要的一点是,宏是一种高级功能,人们几乎从不需要它。宏相当于编译器扩展,这几乎从来都不是问题的最佳解决方案。还要记住,函数可以做一些宏不能做的事情

另一点:
语法quote
(又称backquote)`与单引号非常不同'。在您的示例中,您需要
['a'b]
的单引号。更好的做法是引用整个向量形式
“[ab]

至于你的主要问题,关于如何将源文件文本转换成代码的解释很差。这是一个两步过程。Clojure阅读器使用文本字符串数据(来自文件或文字字符串),并生成列表、向量、字符串、数字和符号等数据结构。Clojure编译器将这些数据结构作为输入,并生成可执行的java字节码

这是令人困惑的,因为在打印时,无法区分向量
[1 2 3]
的文本表示与输入到读取器
[1 2 3]
的文本字符串之间的区别。理想情况下,它应该是彩色编码的或其他的。Java等中不存在这个问题,因为它们没有宏,因此在源代码(文本)和宏使用的数据结构(非文本)之间没有混淆


有关在Clojure中创建宏的更详细答案,请。

您的
defn2
宏对我来说很好。确保在定义它的同一命名空间中调用它,或使用完全限定名。“这是一个两步过程。Clojure阅读器…Clojure编译器…”我是否正确理解:1。读取器只解析符号,但实际上并不从语义上绑定它们;2.
fn
宏最终会根据编译器专门处理的内在特殊函数
fn*
生成定义,编译器在这种情况下使用特殊的符号语义解释?我只是想澄清一下,我试图理解这一点:当我们直接使用fn*时,`(def add4(fn*[f g](+f g)),为什么不使用[f g]和(+f g)在正常函数调用期间的计算?我猜,这回答了我的问题,
fn
是一种特殊形式?
fn*
,它来自Clojure的Java核心”-从您和A.Thompsons的回答中,我了解到编译器以一种特殊的方式处理
fn*
,特别是参数向量?或者它们是在某个地方转义成原始符号的?例如,当我们直接使用
fn*
时,
(def add4(fn*[f g](+f g))
,为什么不
[f g]
(+f g)
像在正常函数调用过程中一样计算?我猜,这回答了我的问题,
fn
是一种特殊形式吗?
(defmacro defn2 [name param & body] 
  `(def ~name (fn ~param ~@body)))

(defn2 add [a b] (+ a b)) ;;I get "Use of undeclared Var app.core/defn2"