为了账号安全,请及时绑定邮箱和手机立即绑定

我对换能器的理解和 js 代码是否正确

我对换能器的理解和 js 代码是否正确

吃鸡游戏 2021-06-20 17:19:59
我读过的关于换能器的网络文章JS转换器:JavaScript 中的高效数据处理管道 @ Eric Elliott -Medium理解 JavaScript 中的转换器 @ Roman Liutikov-Medium很难理解一半...什么是换能器?更简单的 JavaScript 转换器如何使用转换器提高数据转换效率ClojureRich Hickey-cognitect 推出传感器Transducers-Clojure.org我阅读了大约 2 页的 Clojure 官方教程,并了解了基本语法。我参考了内置函数参考来理解转换器示例代码。我对以上两篇文章的理解大概是75%...我的问题我想知道以下理解/js代码是否正确。请帮帮我。<(_ _)>关于换能器by 的返回值compose()是一个转换器。Transducer 通过transduce()作为参数传递给函数来执行,此外, (2)Transducer 通过将数组直接传递给 来执行transducer()。在(2)的过程中,不产生中间值,并执行如下链接的有效过程。了解 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,4console.log( transduce(transducer, addReducer, arr) ) // 6
查看完整描述

2 回答

?
慕标琳琳

TA贡献1830条经验 获得超9个赞

您的代码与传感器无关。您对filter和 的定义m̀ap表明它使用普通的 JSfilter和map


const map = fn => arr => arr.map (fn),

const filter = fn => arr => arr.filter (fn),


const combo = compose(map(add1), filter(even));

combo(arr); ==> [2, 4]

发生的情况是初始数组被传递给mapwith add1,它将生成数组[2, 3, 4],然后它被传递给filterwitheven并[2, 4]创建一个新数组。


换能器也一样:


const arr = [1, 2, 3];


const add1 = n => n + 1;

const even = n => n% 2 === 0;


const compose = (...fns) => {

  const [firstFunc, ...restFuncs] = fns.reverse();

  return (...args) => restFuncs.reduce((acc, fn) => fn(acc), firstFunc(...args));

};


const mapping = 

  fn => join => (acc, e) => join(acc, fn(e));


const filtering = 

  isIncluded => join => (acc, e) => isIncluded(e) ? join(acc, e) : acc;


const transducer = compose(mapping(add1), filtering(even));

const arrayJoin = (acc, e) => ([...acc, e]);

const result = arr.reduce(transducer(arrayJoin), []);

console.log(result);


所以区别在于,当您将 传递join给换能器时,会发生这种情况:


mapping(add1)(filtering(even)(arrayAdd))

filtering是添加到某些集合的唯一步骤。当mapping调用join是filtering直接调用。这就是为什么签名(acc, e)在工作部分和join功能上是相同的。当代码运行时,添加和过滤同时完成,结果只有一个生成的数组,没有中间值。


查看完整回答
反对 回复 2021-06-24
?
江户川乱折腾

TA贡献1851条经验 获得超5个赞

转换器利用了函数组合从 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 函数中。


我们来看看地图转换器:


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是,这只是一个方便的功能,对理解概念并不重要。

关于换能器,差不多就是这样。


查看完整回答
反对 回复 2021-06-24
  • 2 回答
  • 0 关注
  • 135 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信