Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure:实现comp功能_Clojure - Fatal编程技术网

Clojure:实现comp功能

Clojure:实现comp功能,clojure,Clojure,4法律规定如下: 编写一个函数,它允许您创建函数组合。参数列表应包含数量可变的函数,并创建一个函数,从右向左应用这些函数 (= [3 2 1] ((__ rest reverse) [1 2 3 4])) (= 5 ((__ (partial + 3) second) [1 2 3 4])) (= true ((__ zero? #(mod % 8) +) 3 5 7 9)) (= "HELLO" ((__ #(.toUpperCase %) #(apply str %) take) 5

4法律规定如下:


编写一个函数,它允许您创建函数组合。参数列表应包含数量可变的函数,并创建一个函数,从右向左应用这些函数

(= [3 2 1] ((__ rest reverse) [1 2 3 4]))

(= 5 ((__ (partial + 3) second) [1 2 3 4]))

(= true ((__ zero? #(mod % 8) +) 3 5 7 9))

(= "HELLO" ((__ #(.toUpperCase %) #(apply str %) take) 5 "hello world"))
这里的
\uuuu
应该由解决方案代替

在此问题中,不应使用函数
comp


我找到的解决方案是:

(fn [& xs]
  (fn [& ys]
    (reduce #(%2 %1)
            (apply (last xs) ys) (rest (reverse xs)))))

它起作用了。但是我真的不明白
reduce
在这里是如何工作的。它如何表示
(应用f_1(应用f_2…(应用f_n-1(应用f_n参数))…)

让我们试着分三个阶段修改该解决方案。每个阶段都停留一段时间,看看您是否得到了它。如果这样做,请停止,以免我更迷惑您

首先,让我们有更多的描述性名称

(defn my-comp [& fns]
  (fn [& args]
    (reduce (fn [result-so-far next-fn] (next-fn result-so-far))
      (apply (last fns) args) (rest (reverse fns)))))
然后考虑一些因素

(defn my-comp [& fns]
  (fn [& args]
    (let [ordered-fns (reverse fns)
          first-result (apply (first ordered-fns) args)
          remaining-fns (rest ordered-fns)]
    (reduce 
      (fn [result-so-far next-fn] (next-fn result-so-far))
      first-result
      remaining-fns))))
接下来将reduce替换为执行相同操作的循环

(defn my-comp [& fns]
  (fn [& args]
    (let [ordered-fns (reverse fns)
          first-result (apply (first ordered-fns) args)]
      (loop [result-so-far first-result, remaining-fns (rest ordered-fns)]
        (if (empty? remaining-fns)
            result-so-far
            (let [next-fn (first remaining-fns)]
              (recur (next-fn result-so-far), (rest remaining-fns))))))))
考虑这个例子:

(def c (comp f1 ... fn-1 fn))

(c p1 p2 ... pm)
调用
c
时:

  • 第一个
    comp
    最右边的参数
    fn
    应用于
    p*
    参数

  • 然后对上一步的结果应用
    fn-1

    (……)

  • 然后将
    f1
    应用于上一步的结果,并返回其结果

您的样品溶液的作用完全相同

  • 首先,最右边的参数
    (最后一个xs)
    应用于
    ys
    参数:

    (apply (last xs) ys)
    
  • 其余参数反向输入
    reduce

    (rest (reverse xs))
    
  • reduce
    获取提供的初始结果和函数列表,并将函数迭代应用于结果:

    (reduce #(%2 %1) ..init.. ..functions..)
    
    • 以下是
      comp
      的一个简单(我认为)定义:

      (defn comp [& fs]
        (reduce (fn [result f]
                  (fn [& args]
                    (result (apply f args))))
                identity
                fs))
      
      嵌套的匿名函数一开始可能会使其难以读取,因此让我们尝试通过将它们拉出并给它们命名来解决这个问题

      (defn chain [f g]
        (fn [& args]
          (f (apply g args))))
      
      此函数
      chain
      comp
      类似,只是它只接受两个参数

      ((chain inc inc) 1)              ;=> 3
      ((chain rest reverse) [1 2 3 4]) ;=> (3 2 1)
      ((chain inc inc inc) 1)          ;=> ArityException
      
      comp
      top
      chain
      的定义非常简单,有助于分离
      reduce
      为展会带来的内容

      (defn comp [& fs]
        (reduce chain identity fs))
      
      它将前两个函数链接在一起,其结果是一个函数,然后将该函数与下一个函数链接,依此类推

      因此,使用上一个示例:

      ((comp #(.toUpperCase %) #(apply str %) take) 5 "hello world") ;=> "HELLO"
      
      仅使用
      chain
      (无
      reduce
      )的等效值为:

      从根本上讲,
      reduce
      是关于迭代的

      它只是捕获了一个序列的迭代模式并积累了一个结果。我认为
      reduce
      有一种神秘感,这实际上会使它比需要的更难理解,但如果你只是分解它,你肯定会得到它(并且可能会惊讶于你发现它有多么有用).

      我的解决方案是:

      (fn [& fs]
        (reduce (fn [f g]
                  #(f (apply g %&))) fs))
      
      让我们尝试一下:

      ((
        (fn [& fs]
          (reduce (fn [f g]
                    #(f (apply g %&))) fs)) 
      
        #(.toUpperCase %) 
        #(apply str %) 
        take) 
      
        5 "hello world"))
      
      fs是一个函数列表:

      #(.toUpperCase %) 
      #(apply str %) 
      take
      
      第一次通过reduce,我们设置了

      f <--- #(.toUpperCase %)
      g <--- #(apply str %)
      
      f <--- uppercase the result of apply str
      g <--- take
      
      f以下是我的解决方案:

      (defn my-comp
        ([] identity)
        ([f] f)
        ([f & r]
         (fn [& args]
           (f (apply (apply my-comp r) args)))))
      

      我更喜欢A.Webb的解决方案,尽管它的行为与
      comp
      不完全一样,因为它在调用时不返回
      标识
      。只需添加一个零算术体就可以解决这个问题。

      我真的很喜欢将comp分解为链并减少-很容易摸索。
      #(f (apply g %&)) <---- uppercase the result of apply str
      
      f <--- uppercase the result of apply str
      g <--- take
      
      #(f (apply g %&)) <---- uppercase composed with apply str composed with take
      
      (defn my-comp
        ([] identity)
        ([f] f)
        ([f & r]
         (fn [& args]
           (f (apply (apply my-comp r) args)))))