Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macros 计算Clojure标记文字的参数_Macros_Clojure_Literals - Fatal编程技术网

Macros 计算Clojure标记文字的参数

Macros 计算Clojure标记文字的参数,macros,clojure,literals,Macros,Clojure,Literals,我一直在尝试使用Clojure标记的文本,并注意到读者不像宏那样计算参数。这是有道理的,但这样做的合适解决方案是什么?显式评估 示例:给定此函数 (defn my-data ([[arg]] (prn (symbol? arg)) :ok)) 这个定义data\u readers.clj {myns/my-data my.ns/my-data} 以下行为不同: > (let [x 1] (my.ns/my-data [x])) false :ok 因此,传入的

我一直在尝试使用Clojure标记的文本,并注意到读者不像宏那样计算参数。这是有道理的,但这样做的合适解决方案是什么?显式评估

示例:给定此函数

(defn my-data
  ([[arg]]
     (prn (symbol? arg))
     :ok))
这个定义
data\u readers.clj

{myns/my-data my.ns/my-data}
以下行为不同:

> (let [x 1] (my.ns/my-data [x]))
false
:ok
因此,传入的
x
在传入
my data
之前进行评估。另一方面:

> (let [x 1] #myns/my-data [x])
true
:ok
因此,如果我想在
my data
中使用
x
的值,则
my data
函数需要对其进行处理,即检查
x
是否为符号,如果是,则使用
(eval x)
。那看起来很难看。有更好的方法吗?

总结 在您的示例中,无法获取本地
x
的值,这主要是因为本地值仅在运行时获得赋值,而标记的文本则在读取时处理。(其间还有编译时间;不可能在编译时获取局部值;因此宏也无法获取局部值。)1

更好的方法是在运行时使用常规函数,因为毕竟您希望基于某些参数的运行时值构造一个值。标记的文字实际上是文字,应该这样使用

扩大讨论 为了说明上述问题:

(binding [*data-readers* {'bar (fn [_] (java.util.Date.))}]
  (eval (read-string "(defn foo [] #bar x)")))
foo
将始终返回相同的值,因为读取器只有一次机会返回
#bar x
的值,然后该值被烘焙到
foo
的字节码中

还要注意的是,我们可以存储调用
readstring
返回的数据结构,而不是直接将其传递给
eval
,并在将来的任意时刻编译它;
foo
返回的值将保持不变。很明显,这样一个文字价值不可能依赖于任何当地人的未来价值;事实上,在读卡器的操作过程中,甚至不清楚哪些符号将被命名为局部变量——这是由编译器决定的,在涉及宏的情况下,决定的结果可能不明显

当然,读者可以自由返回一个类似于函数调用、本地名称等的表单,以显示一个示例:

(binding [*data-readers* {'bar (fn [sym] (list sym 1 2 3 4 5))}]
  (eval (read-string "#bar *")))
;= 120
;; substituting + for * in the string yields a value of 15
这里的
#条f
相当于
(f 1 2 3 4 5)
。不用说,这是对符号的滥用,并没有真正做到你所要求的


1值得指出的是,
eval
无法访问局部变量(它总是在全局范围内运行),但局部变量在运行前没有赋值的问题更为根本。

Summary 在您的示例中,无法获取本地
x
的值,这主要是因为本地值仅在运行时获得赋值,而标记的文本则在读取时处理。(其间还有编译时间;不可能在编译时获取局部值;因此宏也无法获取局部值。)1

更好的方法是在运行时使用常规函数,因为毕竟您希望基于某些参数的运行时值构造一个值。标记的文字实际上是文字,应该这样使用

扩大讨论 为了说明上述问题:

(binding [*data-readers* {'bar (fn [_] (java.util.Date.))}]
  (eval (read-string "(defn foo [] #bar x)")))
foo
将始终返回相同的值,因为读取器只有一次机会返回
#bar x
的值,然后该值被烘焙到
foo
的字节码中

还要注意的是,我们可以存储调用
readstring
返回的数据结构,而不是直接将其传递给
eval
,并在将来的任意时刻编译它;
foo
返回的值将保持不变。很明显,这样一个文字价值不可能依赖于任何当地人的未来价值;事实上,在读卡器的操作过程中,甚至不清楚哪些符号将被命名为局部变量——这是由编译器决定的,在涉及宏的情况下,决定的结果可能不明显

当然,读者可以自由返回一个类似于函数调用、本地名称等的表单,以显示一个示例:

(binding [*data-readers* {'bar (fn [sym] (list sym 1 2 3 4 5))}]
  (eval (read-string "#bar *")))
;= 120
;; substituting + for * in the string yields a value of 15
这里的
#条f
相当于
(f 1 2 3 4 5)
。不用说,这是对符号的滥用,并没有真正做到你所要求的


1值得指出的是,
eval
无法访问局部变量(它总是在全局范围内运行),但局部变量在运行前没有赋值的问题更为根本。

Summary 在您的示例中,无法获取本地
x
的值,这主要是因为本地值仅在运行时获得赋值,而标记的文本则在读取时处理。(其间还有编译时间;不可能在编译时获取局部值;因此宏也无法获取局部值。)1

更好的方法是在运行时使用常规函数,因为毕竟您希望基于某些参数的运行时值构造一个值。标记的文字实际上是文字,应该这样使用

扩大讨论 为了说明上述问题:

(binding [*data-readers* {'bar (fn [_] (java.util.Date.))}]
  (eval (read-string "(defn foo [] #bar x)")))
foo
将始终返回相同的值,因为读取器只有一次机会返回
#bar x
的值,然后该值被烘焙到
foo
的字节码中

还要注意的是,我们可以存储调用
readstring
返回的数据结构,而不是直接将其传递给
eval
,并在将来的任意时刻编译它;
foo
返回的值将保持不变。很明显,这样一个文字值不可能依赖于未来