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

不过要小心处理宏——它们很有趣,但也容易被滥用。;)

感谢提供的例子!
我猜这可能通过宏(甚至想到了 `defns` 命名)来完成,但我还没有触摸这个方面。

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

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

...