Clojure 如何制作';()是零吗?
如何使clojure将Clojure 如何制作';()是零吗?,clojure,Clojure,如何使clojure将'()计数为nil 例如: 如何制作这样的东西 (if '() :true :false) ;to be :false ;Or easier (my-fun/macro/namespace/... (if '() :true :false)) :false 而不仅仅是如果。在各个方面 (= nil '()) or (my-something (= nil '())) true 并且每个代码都要(“()零)保存 我在想某种有规律的表达。它将查看代码并将'
'()
计数为nil
例如:
如何制作这样的东西
(if '() :true :false)
;to be
:false
;Or easier
(my-fun/macro/namespace/... (if '() :true :false))
:false
而不仅仅是如果。在各个方面
(= nil '()) or (my-something (= nil '()))
true
并且每个代码都要(“()零)保存
我在想某种有规律的表达。它将查看代码并将'()
替换为nil
,但是有一些东西像(rest'(1))
和许多其他东西是'()
,我不知道如何处理它
我听说宏允许你建立自己的语言。我想换个clojure试试。所以这更多的是关于“clojure如何工作以及如何改变它?”而不是“我真的需要它来完成我的工作。”
谢谢你的帮助。'()
和nil
不是一回事-你为什么想要它呢
不过,您可能需要的是seq
函数,如果给定一个空集合,该函数将返回nil:
(seq [1 2 3])
=> (1 2 3)
(seq [])
=> nil
(seq '())
=> nil
因此,seq
经常被用来测试“空虚”,成语如下:
(if (seq coll)
(do-something-with coll)
(get-empty-result))
空的呢?
?这是最有表现力的
(if (empty? '())
:true
:false)
您说您想使用宏更改Clojure。目前,据我所知,这不是“常规”宏系统所能做到的(术语修复了吗?)。我认为你真正需要的是一个阅读器宏。我在网上看到的东西(例如)似乎表明Clojure 1.4中存在类似于reader宏的东西——但我对此并不熟悉,因为我真的喜欢使用它作为我的IDE,而它目前没有使用Clojure 1.4。也许其他人对这种“可扩展阅读器”的魔力有更好的了解 无论如何,我真的不喜欢这样改变语言,我认为有一个潜在的非常好的选择:即Clojure函数 此函数接受任何集合并按原样返回该集合,如果该集合为空,则返回
nil
。这意味着无论您希望()
返回nil
,都应该将其包装为而不是空的。这个答案与上面mikera的答案非常相似,只是您不必将集合转换为序列(这可能很好)
在“手写”收藏的情况下,使用seq
和not empty
都是非常愚蠢的。毕竟,如果你是手写的(或者更确切地说,是手动输入),那么你就可以确定它是否是空的。当您有一个返回集合的表达式或符号,并且您不知道返回的集合是否为空时,这一点非常有用
例如:
=> (if-let [c (not-empty (take (rand-int 5) [:a :b :c :d]))]
(println c)
(println "Twas empty"))
;//80% of the time, this will print some non-empty sub-list of [:a :b :c :d]
;//The other 20% of the time, this will return...
Twas empty
=> nil
可以重写宏和函数。例如:
(defn classic-lisp [arg]
(if (seq? arg) (seq arg) arg))
(defn = [& args]
(apply clojure.core/= (map classic-lisp args)))
(defmacro when [cond & args]
`(when (classic-lisp ~cond) ~@args))
不幸的是,您不能重写if,因为它是一种特殊形式,而不是宏。您必须用另一个宏包装代码
让我们将if*宏设置为具有常见lisp行为的if:
(defmacro if* [cond & args]
`(if (classic-lisp ~cond) ~@args)
这样,我们可以用if*s替换所有ifs:
(use 'clojure.walk)
(defn replace-ifs [code]
(postwalk-replace '{if if*} (macroexpand-all code)))
(defmacro clojure-the-old-way [& body]
`(do ~@(map replace-ifs body)))
现在:
您应该能够加载文件并替换其中的ifs:
(defn read-clj-file [filename]
;; loads list of clojure expressions from file *filename*
(read-string (str "(" (slurp filename) ")")))
(defn load-clj-file-the-old-way [filename]
(doseq [line (replace-ifs (read-clj-file filename))] (eval line))
请注意,我没有测试加载文件的代码,它可能与leiningen或名称空间不兼容。我相信它应该与overriden=though一起工作。使用类似于Lisp的通用表示法,方便访问java库。一、 可能是,贴错了例子。我还想(+1(如果(=nil’())12))成为2。(seq(+1(if(=nil’())12))没有帮助。我认为Clojure方法更适合用于Java库(通常返回nil/null表示“未找到结果”)。我认为你最好还是接受Clojure的方法。”()在Clojure或Java中没有任何特殊意义。在可能在CL中使用“()”的情况下使用nil/null。我想让这个问题保持简单。但也许这是个错误。我相信编写简短的(common lisp-解释器…)将很容易,它允许在Clojure上运行common lisp或混合代码。这只是其中的一小部分。我理解你的答案,我对此表示感谢。但在另一方面,它就像:a:“我怎么能做某事?”b:“你不想那样做。”我很抱歉,但这并不能让我满意。(我真的很感谢您的努力。)@mikera您应该使用if let
获取seq
的返回值。一个选项是降级到足够旧的Clojure版本。空序列过去是nil,但现在改变了:我认为读卡器宏不适合这个任务。与其他lisp方言相比,在clojure中,它们非常有限。
=> (clojure-the-old-way (if '() :true :false) )
:false
(defn read-clj-file [filename]
;; loads list of clojure expressions from file *filename*
(read-string (str "(" (slurp filename) ")")))
(defn load-clj-file-the-old-way [filename]
(doseq [line (replace-ifs (read-clj-file filename))] (eval line))