【问题标题】:Partial in Clojure takes more than one functionClojure 中的 Partial 需要多个函数
【发布时间】:2016-02-21 04:19:38
【问题描述】:

我试图真正理解 Clojure 中的部分内容。 partial 接受一个函数 f 并且比 f 的正常参数少,并返回一个 fn,它接受可变数量的附加参数。调用时,返回的函数使用 args + 附加 args 调用 f。这是部分的工作示例,对我来说似乎没有意义((partial map *) [1 2 3] [4 5 6] [7 8 9])map* 是函数;因此partial 采用了多个函数并使定义无效。任何人都可以帮助我更好地理解?

【问题讨论】:

  • map 是一个以函数为第一个参数的函数
  • Ada,为了放大noisesmiths 的评论和Chris Murphy 的回答,关键是在Clojure 中,函数就像数字、字符串、向量等一样。所以@987654326 描述中的“参数” @ 可以引用作为函数的参数。

标签: clojure


【解决方案1】:

函数作为参数并没有错。在您的情况下,map * 已创建,以后可以使用:

(def will-map-multiply (partial map *))

与任何偏函数一样,它的其余参数可以稍后提供:

(will-map-multiply [1 2 3] [4 5 6] [7 8 9]) ;=> (28 80 162)

那是“偏袒”其中一个论点。可能是两个:

(def will-map-multiply-again (partial map * [1 2 3]))
(will-map-multiply-again [4 5 6] [7 8 9]) ;=> (28 80 162)

当使用partial 时,第一个参数必须是函数,其他参数可以是任何参数 - 没有理由它们不能也是函数。

您的示例有点复杂,因为相乘 需要两个或更多参数,因此map 需要两个或更多序列。

【讨论】:

  • * not 是否需要两个或多个参数。可以使用任何(当然是非负整数)数量的参数调用它。
  • (*) 返回0
  • @noisesmith 不,(*) 返回 1。
  • 有趣 - 调用一个幺半群(带数字)的运算符返回标识元素,1 表示 *,0 表示 +。试试(/)
  • @ChrisMurphy -/ 没有标识值。它们不像+*;它们基本上只是捷径,不具有交换性或关联性。
【解决方案2】:

你想多了。 partial 的第一个参数必须是一个函数。下一个参数必须是您刚刚命名为第一个参数的函数的任何有效参数 - 包括其他函数,如果您的第一个参数是高阶函数,如 mapreduce 或许多其他函数。

(partial map *)

第一个参数是一个函数,map。下一个参数是map 的有效参数。由于map 需要一个函数作为它的第一个参数,所以这个partial 表达式需要一个函数作为它的第二个参数。

就这么简单。您可以首先将* 视为map 的参数,然后再将其视为partial 的参数。

【讨论】:

    【解决方案3】:

    函数是 Clojure 中的一等值。这意味着,您可以传递它们,例如整数、映射或字符串。

    所以,(partial map *) 没有什么奇怪的,其中函数 * 只是 map 的第一个参数。在您的情况下,partial 构造一个函数,然后将其他集合传递给map。让我们看看:

    (partial map *)
    
    ;; becomes
    
    (fn [coll1 coll2 coll3] ;; other arities ommited
      (map * coll1 coll2 coll3))
    
    ;; let’s call this fn with your collections
    
    ((fn [coll1 coll2 coll3]
     (map * coll1 coll2 coll3)) [1 2 3] [4 5 6] [7 8 9])
    
    ;; becomes
    
    (map * coll1 coll2 coll3)
    

    再次强调,函数在 Clojure 和许多其他函数式语言中是一流的。

    希望这会有所帮助!

    【讨论】:

      【解决方案4】:

      (partial map *) 看起来很奇怪,但是当人们意识到 map 将 function 作为其第一个参数时,它就变得更加清晰了。 * 只是一个函数,它接受可变数量的参数并将它们相乘。所以, (map * [1 2 3] [4 5 6] [7 8 9])* 应用于三个三元组数字并产生[28 80 162]。这一切都与局部无关。混淆源于这样一个事实,即在 clojure 中,函数通常作为 参数 传递给其他函数(实际上这在所有现代语言中变得很普遍,甚至是 JavaScript!)。

      所以,(partial map *) 的确切含义是:采用带有预选第一个参数 (*) 的 map 并创建一个使用其参数作为向量来执行映射的新函数。

      【讨论】:

      • 谢谢大家的提问!他们是很好的解释!我同意我想多了。使用 clojure 语法是如此简洁明了,但一开始并没有跳出来。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      相关资源
      最近更新 更多