Clojure地图。传递函数多个参数

时间:2015-07-31 08:10:52

标签: dictionary collections clojure functional-programming

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

;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正在使用的函数的方法。

5 个答案:

答案 0 :(得分:7)

已经提到的另一个选项是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)

答案 1 :(得分:4)

你几乎做对了。

有几种可能的方法:

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函数。

希望它有所帮助!

答案 2 :(得分:3)

有几种方法可以解决这个问题。一个是通过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 :(得分:3)

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

功能

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

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

但功能

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

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

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

您可以使用plusXmap返回的功能。

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

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

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

如您所见,您无需为封闭命名。

答案 4 :(得分:1)

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

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

当然,相反,“4”会输入您的号码,或者按照上面建议使用(let [x 4] ...)换行。

它可能不是最高效的,但我想。