我已阅读有关换能器的网络文章

s

  • 换能器:JavaScript中的高效数据处理管道@ Eric Elliott -Medium
  • 了解JavaScript中的换能器@ Roman Liutikov-Medium

  • 从一半很难理解...
  • 什么是换能器?
  • JavaScript的简单转换器
  • 如何使用换能器
  • 来提高数据转换的效率

    Clojure
  • Rich Hickey-cognitect
  • 即将推出
  • Transducers-Clojure.org

  • 我阅读了大约2页的Clojure官方教程,并了解了基本语法。我引用了内置函数引用以了解传感器示例代码。

    我对以上两篇文章的理解可能是75%...

    我的问题

    我想知道以下理解/ js代码是否正确。请帮助我。

    关于换能器
  • compose()返回的值是一个转换器。
  • Transducer通过将传递给transduce()函数作为参数来执行,此外,(2)Transducer通过将数组直接传递给transducer()来执行。
  • 在(2)的过程中,不会生成中间值,并且将执行如下所示的高效过程。
  • Understanding Transducers in JavaScript @ Roman Liutikov -Medium

  • 我的代码

    "use strict";
    
    const map = fn => arr => arr.map(fn),
    filter = fn => arr => arr.filter(fn),
    addReducer = arr => arr.reduce((acc, num) => acc + num, 0),
    add1 = n => n + 1,
    even = n => n % 2 === 0,
    
    compose = (...fns) => initVal => fns.reduce((acc, fn) => fn(acc), initVal),
    transduce = (xform, reducer, arr ) => reducer( xform(arr) );
    
    
    
    const arr = [1,2,3],
    transducer = compose(  /* called transducer or xform */
       map( add1 ), // 2,3,4
       filter( even ), // 2,4
    );
    
    console.log( transducer(arr) ) // 2,4
    console.log( transduce(transducer, addReducer, arr) ) // 6
    

    最佳答案

    换能器利用了这样的事实,即函数组成从arity中抽象出来,即可以返回一个函数而不是“正常值”:

    const comp = f => g => x => f(g(x));
    
    const add = x => y => x + y;
    
    const sqr = x => x * x;
    
    const add9 = comp(add) (sqr) (3); // returns a lambda
    
    console.log(
      add9(6)); // 15


    现在换能器本身很无聊:
    reduce => acc => x => /* body is specific to the transducer at hand */
    

    它只是一个期望使用reducer的闭包(即结合了两个参数的二进制函数),然后可以直接将其馈送到您喜欢的reduce函数中。

    让我们看一下 map 转换器:
    const mapper = f => (reduce => acc => x =>
      reduce(acc) (f(x)));
    

    多余的括号仅说明了传感器的闭合情况。在这种情况下,它将关闭我们的转换函数f。接下来,我们将应用它:

    // map transducer
    
    const mapper = f => reduce => acc => x =>
      reduce(acc) (f(x));
    
    // my favorite fold (reducing function)
    
    const arrFold = alg => zero => xs => {
      let acc = zero;
    
      for (let i = 0; i < xs.length; i++)
        acc = alg(acc) (xs[i], i);
    
      return acc;
    };
    
    // reducer
    
    const add = x => y => x + y;
    
    // transformer
    
    const sqr = x => x * x;
    
    // MAIN
    
    const main = arrFold(mapper(sqr) (add)) (0);
    
    console.log(
      main([1,2,3])); // 14


    好吧,不是那么令人印象深刻吧?传感器的有功功率是由其与功能组成的组合得出的:

    // map transducer
    
    const mapper = f => reduce => acc => x =>
      reduce(acc) (f(x));
    
    // filter transducer
    
    const filterer = p => reduce => acc => x =>
      p(x) ? reduce(acc) (x) : acc;
    
    // my favorite fold (reducing function)
    
    const arrFold = alg => zero => xs => {
      let acc = zero;
    
      for (let i = 0; i < xs.length; i++)
        acc = alg(acc) (xs[i], i);
    
      return acc;
    };
    
    // helpers
    
    const add = x => y => x + y; // reducer
    const sqr = x => x * x; // transformer
    const isOdd = x => (x & 1) === 1; // predicate
    const comp = f => g => x => f(g(x));
    
    // MAIN
    
    const main = arrFold(comp(filterer(isOdd)) (mapper(sqr)) (add)) (0);
    
    console.log(
      main([1,2,3])); // 10


    尽管我们涉及两个换能器,但仅通过Array进行一次遍历。此属性称为循环融合。由于换能器组成返回了另一个功能,因此评估顺序相反,即从左到右,而功能组成通常从右到左。

    可重用性是另一个优势。您只需要定义一次传感器,就可以一次全部使用所有可折叠数据类型。

    还值得注意的是,transduce只是一个便捷函数,对于理解该概念并不重要。

    关于换能器,这差不多可以说了。

    09-18 07:53