2024 Clojure 状态调查! 中分享您的想法。

欢迎!请查看 关于 页面,了解更多关于这个网站如何运作的信息。

+1 投票
Clojure

所以在使用多参函数时我遇到了一些错误。例如

(defn foo
  ([]
   (foo "blah"))
  ([bar]
   (println bar)))

然后我想再做一个版本

(defn foo2
  ([]
   (foo "blah"))
  ([bar]
   (println (str "your foo is " bar)))

现在在 foo2 中我忘记了调用 foo(而不是将它改为 foo2)。如果像调用 (recur ...) 递归一样调用 (self ...),不会更容易吗?或者这样的东西存在而我从来没有注意到过?

PS
这是一个在尔鲁的第一次帖子,我很高兴地学习 Clojure :)

2 答案

+2 投票

被选中
 
最佳答案

正如 Alex 指出的,self 并不存在,但既然 Clojure 是一个 Lisp,你可以很容易地添加这种支持。我不建议你这样做,但这很有趣。

我们将需要符号宏,这些宏的工作方式类似于宏,但它们是符号(在这种情况下,我们将使用来自 org.clojure/clojure.tools.macro 库的 symbol-macrolet)。

试试这个!

从命令行

clj -Sdeps '{:deps {org.clojure/tools.macro {:mvn/version "0.1.2"}}}'

一旦你有一个 repl,我们将导入 tools.macro 库

(require '[clojure.tools.macro :refer [symbol-macrolet]])

然后,我们将定义一个新的宏,defns,这将允许你使用 self 来引用函数名

(defmacro defns
 [name & args]
 `(symbol-macrolet [~'self ~name]
    (defn ~name
      ~@args)))

用法

使用 defns 定义一个函数

(defns foo
 ([] (self 2))
 ([n] (* 2 n)))

测试一下

user=> (foo)
4
user=> (foo 5)
10

尽管宏很有趣,也很容易滥用,所以要小心使用宏;)

by
感谢提供的示例!
我猜这可能可以通过宏来完成(甚至想到了 `defns` 命名方式 :)),但我还没有涉及这个方面。

我的当前解决方案是在顶部使用一次 `(let [self function-name] …body…)`,以避免编写长长的函数名:)
+1 投票
by

欢迎!不,那不存在,你需要在那里调用 foo2。

...