gpt4 book ai didi

clojure - 为什么许多 Clo​​jure 函数是可变参数的?

转载 作者:行者123 更新时间:2023-12-04 00:48:08 25 4
gpt4 key购买 nike

这是我在 Clojure 中不断遇到的一个问题:

user=> (max [3 4 5 6 7])
[3 4 5 6 7] ; expected '7'

有些功能不符合我的预期!
这是使用 apply 的一种解决方案:
user=> (apply max [3 4 5 6 7])
7

其他示例是 concat , 和 min .
作为 Clojure 新手,我的问题是为什么这些函数是可变参数的?我希望他们对序列进行操作。正在使用 apply获得我想要的最佳/惯用方法?

注:我并不是想说拥有可变参数函数不好,或者有更好的方法。我只想知道是否遵循了规则或约定,或者我应该知道这种方法是否有特定的优势。

编辑:我认为最初的问题不清楚。这就是我的意思:

在我使用过的其他编程语言中,有 monoid - 类似操作,例如添加数字、查找更大的元素、连接列表。

这些操作通常有两个用例:

1) 组合两个元素,使用一个接受两个参数的函数
2) 使用接受元素列表(或序列)的函数组合 0 到 n 个元素

可以从第一种情况的函数构建第二种情况的函数(通常使用 reduce )。

然而,Clojure 添加了第三个用例:

3) 使用可变参数函数组合 0 到 n 个元素

那么问题来了,为什么 Clojure 会添加这第三种情况呢?
保罗的回答表明:
  • 这允许更灵活的代码
  • 历史力量在起作用
  • 最佳答案

    1) 方便。 具有数学函数,例如 +当您只是尝试进行一些计算时,将所有内容按顺序包装起来会很烦人。

    2) 效率。 用集合/序列包装所有东西也会效率低下,首先需要创建序列,然后需要在运行时解包,而不是在编译时查找正确的 Java 函数。

    3) 期望。 这就是这些函数在其他 Lisps 中的工作方式,类似地,在其他函数式语言中使用稍微不同的语法,因此人们对 Clojure 的期望是合理的。我想说的是其他函数式语言中的惯用方式来应用诸如 + 之类的函数。序列将使用 reducefoldl/foldr ,所以这也符合Clojure的处理方式。

    4) 灵活性。 事实上,这些函数可以与高阶函数一起使用,例如 map如果它们是可变参数,则使它们更方便使用。假设您有三个向量,并且您想对同一位置的元素应用一个函数。如果您的函数是可变参数,那么您可以只使用具有多个集合的 map (然后 map 也必须是可变参数 ;) ):

    (map + [1 2 3 4] [2 3 4 5] [3 4 5 6])
    ; [6 9 12 15]

    如果所有这些函数都只接受集合,这比你所拥有的要方便得多。

    惯用语: (在 kotarak 的精彩评论后编辑)

    如果您应该使用 reduce,这取决于功能或 apply .

    对于数学函数( +,-,*,/,etc.) 在 Java 世界中接受 2 个参数 reduce 更有意义,因为它可以直接使用 2 个参数的 Java 版本。使用 apply 他们有点做一个隐式 reduce (该函数添加两个参数,然后与结果、下一个参数和其余部分一起递归。这几乎就是 reduce 所做的。)

    对于 str使用 apply可能更有效率。当 str使用多个参数调用它创建一个 StringBuilder,将所有参数添加到它,然后创建一个字符串。使用 reduce StringBuilder 将创建 n-1 次并且每次只添加一个字符串。这就像在 Shlemiel the painter 中一样笑话,导致 O(n^2) 复杂度。

    到目前为止的结论:使用 apply使用数学函数不会造成太大伤害,但使用 reducestr可能很贵。

    关于clojure - 为什么许多 Clo​​jure 函数是可变参数的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7823516/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com