# 附录 A：Transducing（下）

### 组合柯里化

```var x = curriedMapReducer( strUppercase );
var y = curriedFilterReducer( isLongEnough );
var z = curriedFilterReducer( isShortEnough );```

```var upperReducer = x( listCombination );
var longEnoughReducer = y( listCombination );
var shortEnoughReducer = z( listCombination );```

```function reducer(list,val) {
if (isLongEnough( val )) return z( list, val );
return list;
}```

```var shortEnoughReducer = z( listCombination );
var longAndShortEnoughReducer = y( shortEnoughReducer );```

```// shortEnoughReducer, from z(..):
function reducer(list,val) {
if (isShortEnough( val )) return listCombination( list, val );
return list;
}

// longAndShortEnoughReducer, from y(..):
function reducer(list,val) {
if (isLongEnough( val )) return shortEnoughReducer( list, val );
return list;
}```

```longAndShortEnoughReducer( [], "nope" );
// []

longAndShortEnoughReducer( [], "hello" );
// ["hello"]

longAndShortEnoughReducer( [], "hello world" );
// []```

`longAndShortEnoughReducer(..)` 会过滤出不够长且不够短的值，它在同一步骤中执行这两个过滤。这是一个组合 reducer！

```var longAndShortEnoughReducer = y( z( listCombination) );
var upperLongAndShortEnoughReducer = x( longAndShortEnoughReducer );```

```// upperLongAndShortEnoughReducer:
function reducer(list,val) {
return longAndShortEnoughReducer( list, strUppercase( val ) );
}```

```upperLongAndShortEnoughReducer( [], "nope" );
// []

upperLongAndShortEnoughReducer( [], "hello" );
// ["HELLO"]

upperLongAndShortEnoughReducer( [], "hello world" );
// []```

```var x = curriedMapReducer( strUppercase );
var y = curriedFilterReducer( isLongEnough );
var z = curriedFilterReducer( isShortEnough );

var upperLongAndShortEnoughReducer = x( y( z( listCombination ) ) );

words.reduce( upperLongAndShortEnoughReducer, [] );
// ["WRITTEN","SOMETHING"]```

`x(y(z( .. )))` 是一个组合。我们可以直接跳过中间的 `x` / `y` / `z` 变量名，直接这么表示该组合：

```var composition = compose(
curriedMapReducer( strUppercase ),
curriedFilterReducer( isLongEnough ),
curriedFilterReducer( isShortEnough )
);

var upperLongAndShortEnoughReducer = composition( listCombination );

words.reduce( upperLongAndShortEnoughReducer, [] );
// ["WRITTEN","SOMETHING"]```

1. `listCombination(..)` 作为组合函数传入，构造 `isShortEnough(..)` 过滤器的 reducer。
2. 然后，所得到的 reducer 函数作为组合函数传入，继续构造 `isShortEnough(..)` 过滤器的 reducer。
3. 最后，所得到的 reducer 函数作为组合函数传入，构造 `strUppercase(..)` 映射的 reducer。

// TODO：检查 transducer 是产生 reducer 还是它本身就是 reducer

```var transducer = compose(
curriedMapReducer( strUppercase ),
curriedFilterReducer( isLongEnough ),
curriedFilterReducer( isShortEnough )
);

words
.reduce( transducer( listCombination ), [] );
// ["WRITTEN","SOMETHING"]```

#### 列表组合：纯与不纯

```function listCombination(list,val) {
return list.concat( [val] );
}```

```function listCombination(list,val) {
list.push( val );
return list;
}```

`listCombination(..)` 不是我们完全有交互的函数。我们不直接在程序中的任何地方使用它，而只是在 transducing 的过程中使用它。

`listCombination(..)` 更多的是转换的内部实现细节。实际上，它通常由 transducing 库提供！而不是你的程序中进行交互的顶层方法。

### 可选的组合

```words
.reduce( transducer( listCombination ), [] )
.reduce( strConcat, "" );
// 写点什么```

```function strConcat(str1,str2) { return str1 + str2; }

function listCombination(list,val) { list.push( val ); return list; }```

```words.reduce( transducer( strConcat ), "" );
// 写点什么```

Boom！ 这就是 transducing。

## 最后

```var transduceMap = curry( function mapReducer(mapperFn,combinationFn){
return function reducer(list,v){
return combinationFn( list, mapperFn( v ) );
};
} );

var transduceFilter = curry( function filterReducer(predicateFn,combinationFn){
return function reducer(list,v){
if (predicateFn( v )) return combinationFn( list, v );
return list;
};
} );```

```var transducer = compose(
transduceMap( strUppercase ),
transduceFilter( isLongEnough ),
transduceFilter( isShortEnough )
);```

`transducer(..)` 仍然需要一个组合函数（如 `listCombination(..)``strConcat(..)`）来产生一个传递给 `reduce(..)` （连同初始值）的 transduce-reducer 函数。

```function transduce(transducer,combinationFn,initialValue,list) {
var reducer = transducer( combinationFn );
return list.reduce( reducer, initialValue );
}```

```var transducer = compose(
transduceMap( strUppercase ),
transduceFilter( isLongEnough ),
transduceFilter( isShortEnough )
);

transduce( transducer, listCombination, [], words );
// ["WRITTEN","SOMETHING"]

transduce( transducer, strConcat, "", words );
// 写点什么```

### Transducers.js

```var transformer = transducers.comp(
transducers.map( strUppercase ),
transducers.filter( isLongEnough ),
transducers.filter( isShortEnough )
);

transducers.transduce( transformer, listCombination, [], words );
// ["WRITTEN","SOMETHING"]

transducers.transduce( transformer, strConcat, "", words );
// WRITTENSOMETHING```

`transducers.map(..)``transducers.filter(..)` 是特殊的辅助函数，可以将常规的断言函数或映射函数转换成适用于产生特殊变换对象的函数（里面包含了 reducer 函数）；这个库使用这些变换对象进行转换。此转换对象抽象的额外功能超出了我们将要探索的内容，请参阅该库的文档以获取更多信息。

```words.reduce(
transducers.toFn( transformer, strConcat ),
""
);
// WRITTENSOMETHING```

`into(..)` 是另一个提供的辅助函数，它根据指定的空/初始值的类型自动选择默认的组合函数：

```transducers.into( [], transformer, words );
// ["WRITTEN","SOMETHING"]

transducers.into( "", transformer, words );
// WRITTENSOMETHING```

## 总结

Transduce 就是通过减少来转换。更具体点，transduer 是可组合的 reducer。

transducing 主要提高性能，如果在延迟序列（异步 observables）中使用，则这一点尤为明显。

0 条评论

• ### 翻译连载 |《你不知道的JS》姊妹篇 |《JavaScript 轻量级函数式编程》- 第 2 章：函数基础

原文地址：Functional-Light-JS 原文作者：Kyle Simpson－《You-Dont-Know-JS》作者 第 2 章：函数基础 函数式编程...

• ### 翻译连载 |《你不知道的JS》姊妹篇 |《JavaScript 轻量级函数式编程》- 第 3 章：管理函数的输入

原文地址：Functional-Light-JS 原文作者：Kyle Simpson－《You-Dont-Know-JS》作者 第 3 章：管理函数的输入（In...

• ### 翻译 | Thingking in Redux（如果你只了解MVC）

作者：珂珂（沪江前端开发工程师） 本文原创，转载请注明作者及出处。 原文地址：https://hackernoon.com/thinking-in-red...

• ### 巧妙算法背后的直觉：浅谈贝叶斯优化之美

假设有一个函数F(x)，已知计算成本很高，且解析式和导数未知。问：如何找到全局最小值？

• ### JS函数

形式参数 : 在函数声明时, 设置的参数。作用：占位置 ，只能在函数内部使用. 实际参数 : 在函数调用时,传入的参数。 作用 : 函数调用时,会把实参的值赋...

• ### 关于逻辑回归，面试官们都怎么问

「面试官们都怎么问」系列文章主旨是尽可能完整全面地整理ML/DL/NLP相关知识点，不管是刚入门的新手、准备面试的同学或是温故知新的前辈，我们希望都能通过这一系...

看看错误提示：这是个编程链接错误,意思是说在你的程序里引用了某个函数, 但是链接器找不到该定义.

• ### 《Linux命令行与shell脚本编程大全》第十七章 创建函数

可以将shell脚本代码放进函数中封装起来，这样就能在脚本中的任何地方多次使用它了。 17.1 基本的脚本函数 函数：是一个脚本代码块，可以为其命名并在代码中任...

• ### 内置函数 -- filter 和 map

参考地址:http://www.cnblogs.com/sesshoumaru/p/6000788.html

• ### 【R语言经典实例8】如何定义一个R函数。

使用关键字function，并在其后跟随函数参数列表和函数主体。其基本形式如下： function(param1, ...., paramN) expr