请在2024 年 Clojure 状态调查!分享您的想法。

欢迎!请参阅关于页面以获取更多关于此如何工作的信息。

0
;;gets a list like (1 + (1 + 2))
;;returns (+ 1 (+ 1 2))
(defmacro infix [expression]
  (letfn [(helper [expression]
               (cond (not (list? expression)) expression
                     (= (count expression) 0) '()
                     (= (count expression) 1)  (recur (first expression))
                     (not (function? (first expression))) (let [a (first expression)
                                                                op (second expression)
                                                                b (nth expression 2)]
                                                                  (recur (cons (list op a b)
                                                                               (drop 3 expression))))
                    :else expression))]
  (helper expression)))

(macroexpand '(infix (1 + 1 * 2 * 4))) ;; => ((+ 1 1) * 2 * 4)
(macroexpand '(infix (((1))))) ;; => 1

(not (function? ....)中,第 n 个递归似乎不起作用。代码哪里出错了?

1 答案

+3

被选中
 
最佳答案

我认为这里可能有几个与谓词相关的问题。对于第一个条件,我认为您可能需要使用比list?(仅用于列表集合)更广泛的东西,而是可能使用包含seqs(如sequential?)的东西。我不确定function?是什么,但在您的情况下,这将是符号,因此symbol?应该有效。我怀疑这可能是您当前的问题,因为那是您看不到的分支。您可能想在cond中添加一个:else分支来告诉您它不匹配。

by
编辑 by
谢谢。函数 sequential? 解决了这个问题,但为什么普通的列表检查没有呢?
在调试后我发现表达式 (list? '((+ 1 1) * 2 * 4)) 以某种方式返回了 false。
by
`list?` 的文档说明:如果 x 实现 IPersistentList 则返回 true

你确定确切的表达式返回了 false,还是你在展示一个示例?`list?` 的结果取决于该形式的构建方式。例如

(list? (cons '(+ 1 1) '(* 2 * 4))) => false
(list? (list '(+ 1 1) * 2 * 4)) => true

第一个原因是因为 `cons` 返回的类型是 `clojure.lang.Cons` 类型。
by
你说对了,谢谢!我忘记 Clojure 没有 cons 单元了。
...