【问题标题】:How Clojure uses reducer to implement map?Clojure如何使用reducer实现map?
【发布时间】:2019-09-29 02:34:07
【问题描述】:

我正在阅读七周内的七个并发模型,并且没有关于 Clojure 的先验知识。我很难理解下面的代码,它在集合上实现了 map 函数(可简化)。

我已将我的具体问题放在代码正文中,但我对代码逻辑更感兴趣。我知道 coll-reduce 是为一堆序列对象定义的,但是在这段代码中如何使用它来实现 map 让我很困惑。

感谢任何提示。

;---
; Excerpted from "Seven Concurrency Models in Seven Weeks",
; published by The Pragmatic Bookshelf.
; Copyrights apply to this code. It may not be used to create training material, 
; courses, books, articles, and the like. Contact us if you are in doubt.
; We make no guarantees that this code is fit for any purpose. 
; Visit http://www.pragmaticprogrammer.com/titles/pb7con for more book information.
;---
(ns reducers.core
  (:require [clojure.core.protocols :refer [CollReduce coll-reduce]]
            [clojure.core.reducers :refer [CollFold coll-fold]]))

(defn make-reducer [reducible transformf]
  (reify
    CollReduce
    (coll-reduce [_ f1]
      (coll-reduce reducible (transformf f1) (f1)))   ; what's the meaning of (f1) here?
    (coll-reduce [_ f1 init]
      (coll-reduce reducible (transformf f1) init))))

(defn my-map [mapf reducible]
  (make-reducer reducible
    (fn [reducef]
      (fn [acc v]
        (reducef acc (mapf v))))))

(into [] (my-map (partial * 2) [1 2 3 4]))  ; I don't really understand what's reducef and what's acc here

【问题讨论】:

    标签: clojure


    【解决方案1】:

    首先,map、mapcat、filter等都可以在reduce方面实现。考虑以下向量映射的简单实现(使用更详细的名称以增加清晰度):

    (defn my-map [mapping-function collection]
      (reduce
        (fn [accumulator element]
          (conj accumulator (mapping-function element)))
        []
        collection))
    
    (println (my-map (partial + 2) [1 2 3])) ; prints [3 4 5]
    

    如果您来自花括号,则大致相当于 Javascript 数组

        function myMap(mappingFunction, collection) {
          return collection.reduce(function(acc, element) {
            acc.push(mappingFunction(element));
            return acc;
          }, []);
        }
    

    据我所知,您发布的版本中所有额外措辞的原因是,它在各种集合类型上具有多态性并且运行速度相当快,而我的极小版本仅适用于向量并且速度很慢。至于您对代码的具体问题:

    (coll-reduce reducible (transformf f1) (f1)))   ; what's the meaning of (f1) here?
    

    这里的f1 是一个通用的归约函数。

    这里我不太明白什么是reducef,什么是ac

    想想 map-defined-in-terms-of-reduce 做了什么:

    1. 从集合中取出一个项目
    2. 对其执行功能
    3. 将更改后的值添加到新集合(通常是同一类型)。

    这里,mapf 是我们用来转换集合元素的函数,acc 是累加器:正在构建的新集合,reducef 是负责获取转换输出的归约函数连同积累的新收藏一起加入他们。

    【讨论】:

      猜你喜欢
      • 2014-10-31
      • 2011-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多