【问题标题】:Why is Clojure's complement function defined as a multi-arity function?为什么 Clojure 的补码函数定义为多元函数?
【发布时间】:2021-10-15 08:31:04
【问题描述】:

这里是 Clojure 的 complement 函数的实现:

(defn complement
  "Takes a fn f and returns a fn that takes the same arguments as f,
  has the same effects, if any, and returns the opposite truth value."
  {:added "1.0"
   :static true}
  [f]
  (fn
    ([] (not (f)))
    ([x] (not (f x)))
    ([x y] (not (f x y)))
    ([x y & zs] (not (apply f x y zs)))))

为什么将其定义为多元函数?在我看来,以下实现将达到相同的结果:

(defn alternative-complement [f]
  (fn [& args] (not (apply f args))))

出于什么原因,Clojure 的 complement 将无参数、单个参数和两个参数视为“特殊情况”?

【问题讨论】:

  • 也许是因为编译器更容易优化 0、1 和 2 参数的具体情况?从而避免使用序列的运行时开销。
  • 正是出于这个原因。在clojure.core 中还有许多其他此类方法的示例。
  • 添加了here,这是可以预料的,这是一种优化。
  • 我确定这个问题之前已经在这里问过,但我找不到。 stackoverflow.com/questions/10769005/… 已关闭。

标签: clojure


【解决方案1】:

在后台,当您使用 Java 的可变参数功能时,编译器 creates an array 用于参数。有一个 performance penalty 与此数组创建相关联。

为了消除这种性能损失,我们为最常用的情况添加了特定的参数,并针对这些情况进行了优化。如果可以通过某种方式确定complement 在大多数情况下用于接受零、一个或两个参数的函数,那么认为值得为零、一个和两个参数函数添加特定的参数。支持带有两个以上参数的函数,但可能会导致轻微的性能损失。

Java 自己的核心库利用方法重载来消除可变参数对性能的影响。请参阅 Java 11 的 List,其中包含静态 of 方法的十二个重载,最大允许 ten elements

static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {
    return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5,
                                                         e6, e7, e8, e9, e10);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-13
    • 2017-07-07
    • 1970-01-01
    • 1970-01-01
    • 2020-03-28
    • 2014-04-11
    相关资源
    最近更新 更多