首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Clojure的核心函数参数位置似乎相当混乱。背后的逻辑是什么?

Clojure的核心函数参数位置似乎相当混乱。背后的逻辑是什么?
EN

Stack Overflow用户
提问于 2020-03-27 20:21:53
回答 3查看 135关注 0票数 1

对于我来说,作为一个新的Clojurian,一些核心功能在讨论论点的顺序/位置时似乎有点违背直觉和困惑,下面是一个例子:

代码语言:javascript
复制
> (nthrest (range 10) 5) 
=> (5 6 7 8 9)

> (take-last 5 (range 10)) 
=> (5 6 7 8 9)

也许它背后有一些我还没有看到的规则/逻辑?

我不相信Clojure核心团队做出了这么多出色的技术决定,并且忘记了函数命名/参数排序的一致性。

还是我应该只记得它的原样?

谢谢

略微偏离主题:

rand&rand-intrandom-sample --另一个函数命名似乎不一致的例子,但这是一个很少使用的函数,所以这不是什么大事。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-03-27 20:34:14

对于某些函数(特别是"seq,seq“),对args进行排序,以便可以按以下方式使用partial

代码语言:javascript
复制
(ns tst.demo.core
  (:use tupelo.core tupelo.test))

(dotest
  (let [dozen      (range 12)
        odds-1     (filterv odd? dozen)
        filter-odd (partial filterv odd?)
        odds-2     (filter-odd dozen) ]
    (is= odds-1 odds-2
      [1 3 5 7 9 11])))

对于其他函数,Clojure通常遵循“最大-优先”或“最重要-优先”的顺序(通常这些排序具有相同的结果)。因此,我们看到的例子如下:

代码语言:javascript
复制
(get <map> <key>)
(get <map> <key> <default-val>)

这还表明,根据定义,任何可选值都必须是最后值(以便使用"rest“args)。这在大多数语言(例如Java)中很常见。

说句公道话,我真的不喜欢使用部分函数,因为它们有用户定义的名称(最好是)或者是内联使用(更常见)。请考虑以下代码:

代码语言:javascript
复制
  (let [dozen   (range 12)
        odds    (filterv odd? dozen)

        evens-1 (mapv (partial + 1) odds)
        evens-2 (mapv #(+ 1 %) odds)
        add-1   (fn [arg] (+ 1 arg))
        evens-3 (mapv add-1 odds)]

    (is= evens-1 evens-2 evens-3
      [2 4 6 8 10 12]))

也是

我个人认为真的很烦人,试图像使用evens-1那样使用partial解析代码,特别是对于用户定义的函数,甚至没有+那么简单的标准函数。

partial与2个或更多的args一起使用时,情况尤其如此。

  • 对于1-arg的情况,用于evens-2的函数文字对我来说更容易读懂。
  • 如果有2个或更多的args,创建一个命名函数(如evens-3所示),或者创建一个常规的(defn some-fn ...)全局函数。
票数 0
EN

Stack Overflow用户

发布于 2020-03-27 21:27:04

对于这个问题,Clojure.org有一个常见问题:订单

核心功能中arg顺序的经验法则是什么? 主集合操作数优先。这样,我们就可以编写→及其类似的类,并且它们的位置与它们是否具有可变的参数无关。在面向对象语言和通用Lisp (slot-value, aref, elt)中有这样的传统。 思考序列的一种方法是从左边读取序列,并从右读取序列: <- 1 2 3 4 大多数序列函数消耗并产生序列。因此,一种形象化的方法是把它看作是一条链: map <-过滤器<- 1 2 3 4 考虑许多seq函数的一种方法是,它们以某种方式被参数化了: (地图f) <- (过滤器预d) <- 1 2 3 4 因此,序列函数将它们的源函数和它们之前的任何其他参数放在最后,而部分函数允许像上面那样直接参数化。在函数式语言和Lisps中有这样的传统。 注意,这与最后取主操作数是不一样的。一些序列函数有多个源(级联、交织)。当序列函数是可变的,它通常是在它们的来源。 改编自Rich的评论

票数 7
EN

Stack Overflow用户

发布于 2020-03-27 21:04:42

使用seqs的函数通常使用实际的seq作为最后一个参数。(地图、过滤器、遥控器等)

访问和“更改”单个元素将集合作为第一个元素: conj、assoc、get、update。

这样,您就可以使用具有一致性的集合的(->>)宏,以及一致地创建转换器。

只有很少有人不得不求助于(as->)来改变参数顺序。如果您必须这样做,这可能是一个检查您自己的功能是否遵循该约定的机会。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60893605

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档