【问题标题】:Generating a symbol from a string and applying it as a function从字符串生成符号并将其作为函数应用
【发布时间】:2023-03-10 22:49:02
【问题描述】:

我只是在学习clojure,而且我正在碰壁。

我正在尝试将算术表达式读取为中缀字符串并在 Clojure 中对其进行处理。

例如"1 + 2" -> (+ 1 2)

我读入了“+”,然后把它变成了这样的符号:

(def plus (symbol "clojure.core" "+"))

这似乎工作正常,但是当我调用它时,我没有得到我所期望的:

user=> plus
+

user=> (plus 1 1)
1
user=> (plus 1 2)
2
user=> (plus 1 2 3)
ArityException Wrong number of args (3) passed to: Symbol  clojure.lang.AFn.throwArity (AFn.java:437)

我在这里错过了什么?

【问题讨论】:

  • @yonki 原因是“+”是原始表达式中的字符串
  • 这只是一个更好地学习语言的练习。重点不是把东西加在一起,重点是探索 clojure 中符号和函数是如何相互作用的。
  • 抱歉删除评论,希望做出更有意义的回答。
  • Clojure first and rest 的可能重复项

标签: clojure


【解决方案1】:

默认情况下,符号具有附加到它们的功能。默认情况下附加到它们的功能是在地图中查找此键。这就是为什么您的 plus 行为异常的原因。它正在尝试在地图中查找元素。

(plus 1 1) 这实际上是在地图 1 中查找符号 + 向上,如果未找到,则返回默认值 1。

(plus 1 2) 与上述相同,但默认值为 2。

clojure docs for symbols

【讨论】:

  • 那么第一个参数中的(假设的)映射是否在寻找符号 plus 的定义?
  • @Will 它只是一张普通的旧地图,例如('+ {'+ 3}) -> 3.
  • @Will:是的。更具体地说,它正在寻找映射到键 plus 的值。更具体地说,它不是地图本身,而是 Symbol 类的调用方法。
  • @Will 它正在查找符号 +。 (def plus '+) (plus {'+ 4 'plus 5}) 将返回 4 而不是 5。
【解决方案2】:

您编写这样的代码的原因是什么?如果你想拥有名为plus 的函数,它将是+ 的同义词,只需写(def plus +)

Clojure + 是正常功能。您可以像(+ 1 2 3 4 5) 一样使用它。没有理由把它变成象征。

Clojure 根本没有运算符。只有函数和宏。

不过,如果你坚持使用symbol,你需要像这样评估它

(def plus (eval (symbol "clojure.core/+"))).

查看(symbol "clojure.core/+")+ 本身的类。

(class (symbol "clojure.core/+")) ;;clojure.lang.Symbol

(class +) ;;clojure.core$_PLUS_

符号本身不能作为“在此符号下”的函数调用。如果您想“将符号转换为可调用函数”,则必须对其进行评估。

【讨论】:

  • 如果我输入 (eval (plus 1 1)) 它会运行,但我会得到与以前相同的行为。
  • 然后试试((eval plus) 1 2 3 4)。您的代码工作方式为:获取 (plus 1 1) 返回的内容并对其进行评估。我的工作方式为:eval plus 并为以下参数调用它。
  • 符号实现 AFn 并且因此是可调用的。或输入(eval `(~plus 1 1 1))
  • 啊哈!所以我在 SYMBOL 上调用 eval,它告诉 clojure 进行查找并找到底层的 clojure.core/+,然后我可以使用它来处理参数。好的,明白了。
  • @Will ns-resolve 只是一个较低级别的函数,专门用于查找由符号映射的 var。 eval 会这样做,还有很多其他的东西,比如调用函数。
猜你喜欢
  • 1970-01-01
  • 2018-03-14
  • 1970-01-01
  • 2011-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-20
  • 1970-01-01
相关资源
最近更新 更多