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。

...