Clojure 如何遍历列表并生成元素列表

Clojure 如何遍历列表并生成元素列表,clojure,Clojure,我试图在clojure中转换逻辑函数。我希望用户能够键入(convert'(和x y z),以生成(nor(或x)(或y)(或z)。因此,我正在创建一个包含第一个元素或的列表,然后尝试创建在执行for循环时创建的其余元素列表。但是for循环只会合并所有列表,并将或保留在列表之外。我还想知道如何跳过t中的第一个元素他列出了列表,但这不是我现在的优先事项。我对clojure有点陌生,不知道如何将所有列表返回到更大的列表中。not和或函数与问题无关 (defn lookup "Look up a

我试图在clojure中转换逻辑函数。我希望用户能够键入
(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的部分很好,我只是不知道如何开始添加连接词。我们的教授在课堂上告诉我们如何忽略