Clojure:缩减器的精确定义

时间:2016-03-11 21:34:13

标签: clojure reducers

Clojure website定义 reducer ,如下所示:

  

reducer是一个可简化的集合(一个知道如何减少自身的集合)与一个简化函数的组合("配方"在还原过程中需要做什么)。

以下是reducer功能的实施(来自Rich' blog post on the topic

(defn reducer
   ([coll xf]
    (reify
     clojure.core.protocols/CollReduce
     (coll-reduce [_ f1 init]
       (clojure.core.protocols/coll-reduce coll (xf f1) init)))))

似乎更准确地说减速器是可简化集合和减少函数变换器(后来称为transducer)的组合,而不是减少功能

减速机不知道"有关减少功能的任何内容,由reduce提供。它所知道的只是一个"配方"用于减少某些功能并修改(转换)它。

我的理解是否正确定义" reducer"?或者是否有一些关于"可还原收集的减少功能"定义

2 个答案:

答案 0 :(得分:0)

文档中的语言混淆了减速器和传感器。换能器可以被认为只是减速器的优化实现,其目标是减少对象分配(和后续GC)。此优化不会更改减速器的概念模型。

因此,坚持使用普通的reduce,其目标是简单地提供一种方法来累积序列的结果。最简单的例子是总计一个序列:

(ns clj.core
  (:require [clojure.string :as str] )
  (:use tupelo.core)) ; it->

(def values (range 6))
(spyx values)

(def total (reduce + 0 values))
(spyx total)

;=> values => (0 1 2 3 4 5)
;=> total => 15

然而,“减少功能”可以做任何事情。它也可以返回序列,而不仅仅是标量值:

(def duplicate (reduce (fn [cum-result new-val]         ; accumulating function
                        (conj cum-result new-val))
                      []                                ; initial value
                      values))                          ; sequence to process
(spyx duplicate)
;=> duplicate => [0 1 2 3 4 5]

这是一个更复杂的缩减函数,它计算输入序列的积分:

(def integral (reduce (fn [cum-state new-val]             ; accumulating function
                        (let [integ-val (+ (:running-total cum-state)  new-val) ]
                          { :integ-vals     (conj (:integ-vals cum-state) integ-val)
                            :running-total  integ-val} ))
                      {:integ-vals [] :running-total 0}   ; initial value
                      values))                            ; sequence to process
(spyx integral)
;=> integral => {:integ-vals [0 1 3 6 10 15], :running-total 15}

所以这与map相比有很大的不同。我们将map称为:

(def y (map f x))

其中xy是序列,结果类似于

y(0) = f( x(0) )   ; math notation used here
y(1) = f( x(1) )
y(2) = f( x(2) )
...

因此每个y(i)仅依赖 函数f和x(i)。相反,我们将reduce定义为:

(def y(reduce f init x))

其中xy是序列,init是标量(如0[])。结果看起来像

y(0) = f( init, x(0) )   ; math notation used here
y(1) = f( y(0), x(1) )
y(2) = f( y(1), x(2) )
...

因此减少功能 f 2值的函数:累积结果和新的x值。

答案 1 :(得分:0)

当您从博客中查看reducer函数的来源时:

(defn reducer
  ([coll xf]
   (reify
    clojure.core.protocols/CollReduce
    (coll-reduce [_ f1 init]
      (clojure.core.protocols/coll-reduce coll (xf f1) init)))))

你可以看到reducer要求集合自行减少(通过调用coll上的coll-reduce)并提供一个通过调用reduce函数变换器((xf f1))生成的reduce函数。 / p>

所以我会说这句话:

  

减速器是可减少集合减少函数变换器(后来称为传感器)的组合,而不是减少函数。

更准确,因为你需要开始的是可简化的集合还原函数转换器。减少函数只是调用reduce函数变换器的结果。