Как Clojure использует редуктор для реализации карты? - PullRequest
2 голосов
/ 29 сентября 2019

Я читаю Семь моделей параллелизма за семь недель и не имею предварительных знаний о Clojure.Мне очень трудно понять приведенный ниже код, который реализует функцию отображения над коллекциями (приводимые).

Я поставил свои конкретные вопросы в теле кода, но меня больше интересует логика кода.Я понимаю, что Coll-Reduce определено для нескольких объектов последовательности, но то, как оно используется в этом коде для реализации карты, меня действительно смущает.

Любая подсказка приветствуется.

;---
; 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

1 Ответ

0 голосов
/ 30 сентября 2019

Во-первых, 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 - это общая сокращающая функция.

Я не совсем понимаю, что здесь происходит и что происходит

Подумайте о том, что делает карта, определенная в терминах сокращения:

  1. Возьмите элемент из коллекции
  2. Выполните функцию наit
  3. Добавление измененного значения в новую коллекцию (обычно того же типа).

Здесь mapf - это функция, которую мы используем для преобразования элементов коллекции, acc - это аккумулятор: создание новой коллекции, а reducef - функция сокращения, отвечающая за вывод результатов преобразования вместе с накопленной новой коллекцией и присоединение к ним.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...