clojure - Clojure如何使用reducer实现map?
问题描述
我正在阅读七周内的七个并发模型,并且没有关于 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
解决方案
首先,map、mapcat、filter等都可以用reduce来实现。考虑以下向量 map 的简单实现(使用更详细的名称以增加清晰度):
(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 和 acc 是什么
想想 map-defined-in-terms-of-reduce 做了什么:
- 从集合中取出一个项目
- 对其执行功能
- 将更改后的值添加到新集合(通常是相同类型)。
这里,mapf
是我们用来转换集合元素的函数,acc
是累加器:正在构建的新集合,reducef
是归约函数,负责将转换的输出与累积的新集合一起并将它们连接起来。
推荐阅读
- php - .httaccess 带重定向
- javascript - 在 sidenav 搜索菜单中的用户搜索期间删除中断链接
- html - 为什么在伪元素之前没有得到 100% 的容器高度?
- python - 这是什么意思“reshape 函数返回其参数修改后的形状,而 ndarray.resize 方法修改数组本身”?
- python - 使用企业搜索 API 的 Twython
- c - 我的自分割检查功能没有按预期工作
- java - Java中的通用VS通配符
- reactjs - 如何为托管在一个 Azure 应用服务中的多个应用程序添加重写规则
- .net - 所有文本的正则表达式公式,包括 HTML 标签内,但不在“a”标签中
- c# - “没有足够的权限访问:GET-members /emailAddress” - C#、RestSharp、Postman、LinkedIn API