【问题标题】:Cannot pass list as argument to function无法将列表作为参数传递给函数
【发布时间】:2018-09-30 17:52:46
【问题描述】:

我有一个替换函数,它将接受诸如(or false x y) 之类的表达式和诸如'{x false, y true} 之类的绑定映射,并将返回带有适当替换的列表。结果在l 中并显示出来。我如何将l 传递给另一个函数以进行其他处理?我要传递给的函数的定义如下所示:

(defn f [expression]
    )

我尝试在调用f 时将l 作为参数传递,但出现以下错误:

IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Symbol  clojure.lang.RT.seqFrom (RT.java:550)

这是我的替代函数:

    (defn deep-substitute [m l]
  (map (fn [i]
         (if (seq? i)
           (deep-substitute m i)
           (m i i)))
       l
       (f 'l)))

我的新函数在使用未评估列表调用它时完全按照我期望的方式工作,但当我将它传递给未评估列表时则不然。

【问题讨论】:

  • 您可能想澄清“未评估列表,但当我将其传递给未评估列表时”的含义。我认为其中之一应该说“已评估”。此外,如果您想处理未评估的代码,您将需要使用宏,或显式引用代码以便将其视为列表。
  • 那你为什么同时传递map l(f 'l),但是只有映射函数有i 参数?
  • FWIW 你也可以使用(clojure.walk/postwalk-replace '{x false y true} '(or false x y)) 来做到这一点。
  • 你怎么称呼它? (deep-substitute '{x false, y true} '(or false x y)) ?

标签: list clojure arguments


【解决方案1】:

deep-substitute 的工作是填写模板表格并返回。如果您尝试让deep-substitute 也负责执行下一步的转换,问题就会变得更加困难。也许让它返回值,然后在返回后将该值传递给另一个转换函数。

这是一个带注释的工作示例:

user>  (defn deep-substitute [m l]      
         (map (fn [i]          
                (if (seq? i)             ;; if this is a sequence, 
                  (deep-substitute m i)  ;; finish the sequence and include the result here
                  (get m i i)))          ;; otherwise get the new value from the map, if found
              l))                        ;; if it's not found, us the value unchanged.
#'user/deep-substitute

然后在您的示例上进行测试:

user> (deep-substitute '{x false, y true} '(or false x y))
(or false false true)

还有一个更嵌套的例子:

user> (deep-substitute '{x false, y true} '(or false (and x (or y x)) y))
(or false (and false (or true false)) true)

一个常见的下一步是将其包装在一个宏中,以便它可以在评估表单之前修改表单,然后评估新创建的表单以找出它变成什么值:

user> (defmacro dsub [m l]
        (deep-substitute m l))
#'user/dsub

测试一下

user> (dsub {x false, y true} (or false (and x (or y x)) y))
true

user> (dsub {x false, y true} (or false  x))
false

或通过嵌套将结果形式(未计算)传递给另一个函数:

user> (defn f [expression]
        (reverse expression))
#'user/f

user> (f (deep-substitute '{x false, y true} '(or false (and x (or y x)) y)))
(true (and false (or true false)) false or)

一种常见的模式是使用线程宏->->>等将结果从一个变换传递到另一个变换,直到通过组合许多简单的操作得到最终结果:

user> (->> '(or false (and x (or y x)) y)
           (deep-substitute '{x false, y true})
           f
           (deep-substitute '{false, 41 true 42}))
(42 (and 41 (or 42 41)) 41 or)

【讨论】:

    【解决方案2】:

    首先尝试使用传递列表的基本方法作为函数的参数。你可以参考下面的例子

    (defn passlist [a]
      (println a))
    (passlist '(1 2 3))
    

    输出将:

    #'user/passlist
    (1 2 3) 
    

    【讨论】:

    • @Carcigenicate 是的,但是如果代码构建在这样一个基本结构中,那么 jt 可能会起作用。