Clojure 如何遍历列表并生成元素列表
我试图在clojure中转换逻辑函数。我希望用户能够键入Clojure 如何遍历列表并生成元素列表,clojure,Clojure,我试图在clojure中转换逻辑函数。我希望用户能够键入(convert'(和x y z),以生成(nor(或x)(或y)(或z)。因此,我正在创建一个包含第一个元素或的列表,然后尝试创建在执行for循环时创建的其余元素列表。但是for循环只会合并所有列表,并将或保留在列表之外。我还想知道如何跳过t中的第一个元素他列出了列表,但这不是我现在的优先事项。我对clojure有点陌生,不知道如何将所有列表返回到更大的列表中。not和或函数与问题无关 (defn lookup "Look up a
(convert'(和x y z)
,以生成(nor(或x)(或y)(或z)
。因此,我正在创建一个包含第一个元素或的列表,然后尝试创建在执行for
循环时创建的其余元素列表。但是for
循环只会合并所有列表,并将或保留在列表之外。我还想知道如何跳过t中的第一个元素他列出了列表,但这不是我现在的优先事项。我对clojure有点陌生,不知道如何将所有列表返回到更大的列表中。not
和或函数与问题无关
(defn lookup
"Look up a value, i, in map m and returns the result if it exists.
Otherwise returns i."
[i m]
(get m i i))
(defn makelist
[l]
(for[i[l]] (list 'nor i)))
(defn convert
[l]
(let [p1 (first l)]
(cond
(= p1 'not) (map (fn [i] (lookup i '{not nor})) l)
(= p1 'or) (list 'nor (map(fn [i] (lookup i '{or nor})) l))
(= p1 'and) (list 'nor (makelist l))
:else (print "error"))))
我得到的输出是(nor((nor)(x y z)))
。我想要的输出是(nor(nor)和(nor x)(nor y)(nor z)
。我也不想要(nor和)
,但在我想出如何跳过第一个元素之前,我只想把列表分开。我看到两个问题:
makelist
具有(对于[i[l]]…)
,因此它只生成一个项目,其中i
绑定到整个传入列表l
——这里需要的是(对于[i]l]…)
,以便处理l
的每个元素
convert
的子句为和创建一个包含两个元素的列表:nor
和的结果(makelist l)
——这里需要的是(cons'nor(makelist l))
这样您可以得到一个列表,其中或作为第一个元素,然后是调用makelist
结果的所有元素
我没有检查convert
的其他两个部分以查看您是否有类似的错误,但是通过上面的两个更改(convert'(和x y z))
将产生(nor(和)(或x)(或y)(或y)(或z))
我可以看到两个问题:
makelist
具有(对于[i[l]]…)
,因此它只生成一个项目,其中i
绑定到整个传入列表l
——这里需要的是(对于[i]l]…)
,以便处理l
的每个元素
convert
的子句为和创建一个包含两个元素的列表:nor
和的结果(makelist l)
——这里需要的是(cons'nor(makelist l))
这样您可以得到一个列表,其中或作为第一个元素,然后是调用makelist
结果的所有元素
我没有检查convert
的其他两个部分以查看是否存在类似的错误,但是通过上面的两个更改(convert'(和x y z))
将生成(nor(和)(或x)(或y)(或z))
只是为了好玩:我会在心里扩展和概括您的任务,根据一些规则重写数据结构,这样您就可以声明(可能是递归的)重写规则,将任何输入转换为任何所需的输出
让我们从简单的转换函数开始:
(defn convert [rules data]
(if-let [res (some (fn [[condition rewrite]]
(when (condition data) (rewrite data)))
rules)]
res
data))
(def my-rules [[sequential? (fn [data] (map #(convert my-rules %) data))]
[number? inc]
[keyword? (comp clojure.string/upper-case name)]])
#'user/my-rules
user> (convert my-rules [:hello :guys "i am" 30 [:congratulate :me]])
;;=> ("HELLO" "GUYS" "i am" 31 ("CONGRATULATE" "ME"))
它会找到适合您输入的第一条规则(如果有),并应用其转换函数:
(defn convert [rules data]
(if-let [res (some (fn [[condition rewrite]]
(when (condition data) (rewrite data)))
rules)]
res
data))
(def my-rules [[sequential? (fn [data] (map #(convert my-rules %) data))]
[number? inc]
[keyword? (comp clojure.string/upper-case name)]])
#'user/my-rules
user> (convert my-rules [:hello :guys "i am" 30 [:congratulate :me]])
;;=> ("HELLO" "GUYS" "i am" 31 ("CONGRATULATE" "ME"))
使用这种方法,您的规则将如下所示:
(def rules
[[(every-pred coll? (comp #{'not} first)) (fn [data] (map (partial convert [[#{'not} (constantly 'nor)]]) data))]
[(every-pred coll? (comp #{'or} first)) (fn [data] (map (partial convert [[#{'or} (constantly 'nor)]]) data))]
[(every-pred coll? (comp #{'and} first)) (fn [[_ & t]] (cons 'nor (map #(list 'nor %) t)))]])
#'user/rules
user> (convert rules '(and x y z))
;;=> (nor (nor x) (nor y) (nor z))
好的,它可以工作,但是看起来很难看。我们仍然可以省去一些重复,为跳棋和变形金刚介绍一些基本功能:
(defn first-is
"returns a function checking that the input is collection and it's head equals to value"
[value]
(every-pred coll? (comp #{value} first)))
将规则转换为:
(def rules
[[(first-is 'not) (fn [data] (map (partial convert [[#{'not} (constantly 'nor)]]) data))]
[(first-is 'or) (fn [data] (map (partial convert [[#{'or} (constantly 'nor)]]) data))]
[(first-is 'and) (fn [[_ & t]] (cons 'nor (map #(list 'nor %) t)))]])
#'user/rules
user> (convert rules '(and x y z))
;;=> (nor (nor x) (nor y) (nor z))
然后介绍替换重写规则:
(defn replacing
([new] [(constantly true) (constantly new)])
([old new] [#{old} (constantly new)]))
带我们去
(def rules
[[(first-is 'not) (fn [data] (map (partial convert [(replacing 'not 'nor)]) data))]
[(first-is 'or) (fn [data] (map (partial convert [(replacing 'or 'nor)]) data))]
[(first-is 'and) (fn [[_ & t]] (cons 'nor (map #(list 'nor %) t)))]])
现在我们可以看到,对一个函数有一个需求,它转换集合中的每个项。让我们介绍一下:
(defn convert-each [rules]
(fn [data] (map #(convert rules %) data)))
(def rules
[[(first-is 'not) (convert-each [(replacing 'not 'nor)])]
[(first-is 'or) (convert-each [(replacing 'or 'nor)])]
[(first-is 'and) (fn [[_ & t]] (cons 'nor (map #(list 'nor %) t)))]])
user> (convert rules '(or x y z))
;;=> (nor x y z)
user> (convert rules '(and x y z))
;;=> (nor (nor x) (nor y) (nor z))
现在它好多了,但最后一条仍然有点难看。我可以考虑引入一个函数,用单独的规则转换头部和尾部,然后使用转换后的头部和尾部:
(defn convert-cons [head-rules tail-conversion]
(fn [[h & t]] (cons (convert head-rules h) (tail-conversion t))))
(defn transforming [transformer]
[(constantly true) transformer])
(def rules
[[(first-is 'not) (convert-each [(replacing 'not 'nor)])]
[(first-is 'or) (convert-each [(replacing 'or 'nor)])]
[(first-is 'and) (convert-cons [(replacing 'nor)]
(convert-each [(transforming #(list 'nor %))]))]])
user> (convert rules '(and x y z))
;;=> (nor (nor x) (nor y) (nor z))
只是为了好玩:我会在心里扩展和概括您的任务,根据一些规则重写数据结构,这样您就可以声明(可能是递归的)重写规则,将任何输入转换为任何期望的输出
让我们从简单的转换函数开始:
(defn convert [rules data]
(if-let [res (some (fn [[condition rewrite]]
(when (condition data) (rewrite data)))
rules)]
res
data))
(def my-rules [[sequential? (fn [data] (map #(convert my-rules %) data))]
[number? inc]
[keyword? (comp clojure.string/upper-case name)]])
#'user/my-rules
user> (convert my-rules [:hello :guys "i am" 30 [:congratulate :me]])
;;=> ("HELLO" "GUYS" "i am" 31 ("CONGRATULATE" "ME"))
它会找到适合您输入的第一条规则(如果有),并应用其转换函数:
(defn convert [rules data]
(if-let [res (some (fn [[condition rewrite]]
(when (condition data) (rewrite data)))
rules)]
res
data))
(def my-rules [[sequential? (fn [data] (map #(convert my-rules %) data))]
[number? inc]
[keyword? (comp clojure.string/upper-case name)]])
#'user/my-rules
user> (convert my-rules [:hello :guys "i am" 30 [:congratulate :me]])
;;=> ("HELLO" "GUYS" "i am" 31 ("CONGRATULATE" "ME"))
使用这种方法,您的规则将如下所示:
(def rules
[[(every-pred coll? (comp #{'not} first)) (fn [data] (map (partial convert [[#{'not} (constantly 'nor)]]) data))]
[(every-pred coll? (comp #{'or} first)) (fn [data] (map (partial convert [[#{'or} (constantly 'nor)]]) data))]
[(every-pred coll? (comp #{'and} first)) (fn [[_ & t]] (cons 'nor (map #(list 'nor %) t)))]])
#'user/rules
user> (convert rules '(and x y z))
;;=> (nor (nor x) (nor y) (nor z))
好的,它可以工作,但是看起来很难看。我们仍然可以省去一些重复,为跳棋和变形金刚介绍一些基本功能:
(defn first-is
"returns a function checking that the input is collection and it's head equals to value"
[value]
(every-pred coll? (comp #{value} first)))
将规则转换为:
(def rules
[[(first-is 'not) (fn [data] (map (partial convert [[#{'not} (constantly 'nor)]]) data))]
[(first-is 'or) (fn [data] (map (partial convert [[#{'or} (constantly 'nor)]]) data))]
[(first-is 'and) (fn [[_ & t]] (cons 'nor (map #(list 'nor %) t)))]])
#'user/rules
user> (convert rules '(and x y z))
;;=> (nor (nor x) (nor y) (nor z))
然后介绍替换重写规则:
(defn replacing
([new] [(constantly true) (constantly new)])
([old new] [#{old} (constantly new)]))
带我们去
(def rules
[[(first-is 'not) (fn [data] (map (partial convert [(replacing 'not 'nor)]) data))]
[(first-is 'or) (fn [data] (map (partial convert [(replacing 'or 'nor)]) data))]
[(first-is 'and) (fn [[_ & t]] (cons 'nor (map #(list 'nor %) t)))]])
现在我们可以看到,对一个函数有一个需求,它转换集合中的每个项。让我们介绍一下:
(defn convert-each [rules]
(fn [data] (map #(convert rules %) data)))
(def rules
[[(first-is 'not) (convert-each [(replacing 'not 'nor)])]
[(first-is 'or) (convert-each [(replacing 'or 'nor)])]
[(first-is 'and) (fn [[_ & t]] (cons 'nor (map #(list 'nor %) t)))]])
user> (convert rules '(or x y z))
;;=> (nor x y z)
user> (convert rules '(and x y z))
;;=> (nor (nor x) (nor y) (nor z))
现在它好多了,但最后一条仍然有点难看。我可以考虑引入一个函数,用单独的规则转换头部和尾部,然后使用转换后的头部和尾部:
(defn convert-cons [head-rules tail-conversion]
(fn [[h & t]] (cons (convert head-rules h) (tail-conversion t))))
(defn transforming [transformer]
[(constantly true) transformer])
(def rules
[[(first-is 'not) (convert-each [(replacing 'not 'nor)])]
[(first-is 'or) (convert-each [(replacing 'or 'nor)])]
[(first-is 'and) (convert-cons [(replacing 'nor)]
(convert-each [(transforming #(list 'nor %))]))]])
user> (convert rules '(and x y z))
;;=> (nor (nor x) (nor y) (nor z))
你能展示(或解释)吗lookup
?@jas的定义我刚刚在其中添加了它。但是使用lookup的部分效果很好,我只是不知道如何进行添加连接词。我们的教授在课堂上告诉我们如何在使用let时忽略列表元素。使用下划线表示您不关心的元素。let[[ux]l]将x绑定到列表l中的第二个元素,忽略第一个元素。请注意您发布的内容。发布文字作业是一个很好的方法,会让您陷入困境。您的处理方式与我的不同,但看起来这可能有效。您能展示(或解释)吗lookup
?@jas的定义我刚刚在那里添加了它。但是使用lookup的部分很好,我只是不知道如何开始添加连接词。我们的教授在课堂上告诉我们如何忽略