【问题标题】:Clojure map. Pass function multiple parametersClojure 地图。传递函数多个参数
【发布时间】:2015-07-31 08:10:52
【问题描述】:

我正在寻找一种如何以更自定义的方式使用地图功能的方法。如果我想要实现的功能有不同的功能,请告诉我。

;lets say i have addOneToEach function working as bellow

(defn plusOne[singleInt]
   (+ 1 singleInt))

(defn addOneToEach[intCollection] ;[1 2 3 4]
   (map plusOne intCollection))   ;=>(2 3 4 5)

;But in a case I would want to customly define how much to add 

(defn plusX[singleInt x]
   (+ x singleInt))

(defn addXToEach[intCollection x] ;[1 2 3 4]
   ;how do I use plusX here inside map function?
   (map (plusX  ?x?) intCollection))   ;=>((+ 1 x) (+ 2 x) (+ 3 x) (+ 4 x))

我不是在寻找一个将 x 添加到集合中的每个函数的函数,而是一种将额外参数传递给 map 正在使用的函数的方法。

【问题讨论】:

    标签: dictionary collections clojure functional-programming


    【解决方案1】:

    已经提到的另一个选项是partial(请注意,在示例中,参数的顺序无关紧要,因为您只是添加它们,但是从左到右部分绑定它们,所以要小心):

    user=> (doc partial)
    -------------------------
    clojure.core/partial
    ([f] [f arg1] [f arg1 arg2] [f arg1 arg2 arg3] [f arg1 arg2 arg3 & more])
      Takes a function f and fewer than the normal arguments to f, and
      returns a fn that takes a variable number of additional args. When
      called, the returned function calls f with args + additional args.
    nil
    user=> (defn plus-x [x i] (+ x i))
    #'user/plus-x
    user=> (map (partial plus-x 5) [1 2 3])
    (6 7 8)
    

    【讨论】:

      【解决方案2】:

      有几种方法可以解决这个问题。一种是通过letfn 使用显式本地函数:

      (defn add-x-to-each [ints x]
       (letfn [(plus-x [i]
                 (+ i x))]
         (map plus-x ints)))
      

      对于这一小段代码,这可能是多余的,您可以通过匿名函数简单地简化它:

      (defn add-x-to-each [ints x]
        (map #(+ % x) ints))
      

      这两种解决方案基本上都应用了closure 的使用,这是一个需要了解的重要概念:它归结为动态定义一个函数,该函数在定义函数时引用环境中的一个变量。这里我们将plus-x(或匿名)函数的创建推迟到x 被绑定,所以plus-x 可以引用传入add-x-to-each 的任何值。

      【讨论】:

        【解决方案3】:

        你几乎猜对了。

        有几种可能的方法:

        1.

        (defn addXToEach[intCollection x]
           (map #(plusX % x) intCollection))
        

        #(%)(fn [x] (x)) 的含义相同(注意x 正在此处进行评估)。

        2.

        (defn addXToEach[intCollection x]
           (map (fn [item] (plusX item x)) intCollection))
        

        3.

        (defn addXToEach[intCollection x]
           (map #(+ % x) intCollection))
        

        然后您不必定义您的plusX 函数。

        希望对你有帮助!

        【讨论】:

        • 我很高兴它有帮助! :)
        【解决方案4】:

        您正在将map 应用于one 集合,因此map 应用的函数必须采用one 参数。问题是,这个函数是如何组成的?

        功能

        (defn plusOne [singleInt]
           (+ 1 singleInt))
        

        ... 有效。它也被称为inc

        但功能

        (defn plusX [singleInt x]
           (+ x singleInt))
        

        ... 不起作用,因为它需要两个参数。给定一个数字x,您想返回一个将 x 添加到其参数的 函数

        (defn plusX [x]
           (fn [singleInt] (+ x singleInt))
        

        您可以在map 中使用plusX 返回的函数。

        当你编写这样一个函数时,你可以使用额外的参数。这种由包含捕获数据的表达式组成的函数称为闭包

        例如,(plusX 3) 是一个将3 添加到其参数的函数。

        (map (plusX 3) stuff)
        ;(4 5 6 7)
        

        如您所见,您无需命名您的闭包。

        【讨论】:

          【解决方案5】:

          特别是对于+,以下内容也可以使用:

          (map + (repeat 4) [3 4 9 0 2 8 1]) ;=> (7 8 13 4 6 12 5)
          

          当然,代替“4”输入您的号码,或者按照上面的建议用(let [x 4] ...) 包装。

          我猜它可能不是性能最好的。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-06-08
            • 2016-04-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-10-25
            相关资源
            最近更新 更多