【问题标题】:using clojure symbol function to make indirect function call使用clojure符号函数进行间接函数调用
【发布时间】:2011-09-09 06:13:21
【问题描述】:

我期望下面我应该能够通过符号函数间接调用我的函数平方,但它不起作用。我在这里做错了什么:

user=> (defn squared [x] (* x x))
#'user/squared
user=> (squared 2)
4
user=> ((symbol "squared") 2)
nil
user=> ((symbol "user" "squared") 2)
nil
user=> 

【问题讨论】:

  • 除了代码的基本问题(希望我的回答能解决)之外,如果您愿意详细说明,我对您正在解决的问题有点好奇。 .?
  • 它有点像兔子洞,我是一个完全的新手......但基本上我遇到了“无法获取宏的价值”,因为我正在做类似(a :b c & d)其中 a 和 c 都是宏。我希望如果我将其切换为 (a :b :c & d) 然后将 :c 转换为符号它将起作用。我觉得这实际上是完全错误的,但由于我对((symbol "squared") 2) 的小想法没有用,我想我会问它是如何工作的......
  • 如果您在(a :b c & d) 表单中遇到此类错误,则很可能a 会生成一个扩展,其中包括c 在非操作员位置逐字逐句。如果您只想在扩展中包含c 宏的名称(而您传递给a 的实际内容是宏c 的符号名称),那么您只需在扩展中添加一个引号,以便您在适当的位置返回'c 而不是c。如果你真的想调用c宏,你需要确保它最终被插入到a产生的扩展中的操作符位置。
  • 实际上我真正想做的是编写一些宏,它采用(defmacro [x] ...),我知道x 是像(f a b c) 这样的形式,我想将其转换为(fn [n] (f n a b c))。但我不确定这是否可能,或者如果可能的话,我什至不确定如何开始。如果您想尝试一下,我觉得我应该提出一个新问题。
  • (defmacro transform [[f & args]] (fn [n#] (~f n# ~@args))) 应该可以工作。

标签: clojure


【解决方案1】:

符号本身不包含你的函数,它命名的 Var 存在。

这表示“获取由名称为 "squared" 的符号 (symbol) 命名的 Var (resolve) 的内容 (@ = deref) 并将其(作为函数)应用于论据2

(@(resolve (symbol "squared")) 2)

这表示“取由符号等命名的 Var”:

((resolve (symbol "squared")) 2)

两者都可以工作,因为 Vars 在被要求充当函数时,会遵从存储在其中的函数。 (如果在未绑定函数的情况下尝试将 Var 作为函数使用,则会导致错误。)

这表示“取名为 "squared" 的符号并将其作为函数应用到参数 2”——请注意,符号本身用作函数:

((symbol "squared") 2)

现在符号可以用作函数(它们实现了clojure.lang.IFn 接口),但是当它们以这种方式使用时,它们的行为方式是它们在参数中查找自己,即将它们的参数视为映射并执行在里面查找:

('foo {'foo 2})
; is equivalent to
(get {'foo 2} 'foo)

如果传递给符号的参数不是在其中进行查找有意义的参数,则返回 nil

【讨论】:

  • (@(resolve (symbol "squared")) 2) 不起作用.....这是它的输出 - [# 4 4]
  • 它对我有用——我只是将squared 的定义粘贴到REPL 中,然后是(@(resolve (symbol "squared")) 2)(从您的评论中复制)并得到4 作为响应:pastie.org/2508000 可以请仔细检查您使用的 squared 等定义是否相同?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-24
  • 2017-03-12
  • 1970-01-01
相关资源
最近更新 更多