- 显式传递identity元素/concat函数 const map = f => id => concat => xs(这样会很啰嗦,而且会泄漏内部API)
- 仅映射实现monoid接口的可迭代对象(这很酷,但会引入新类型?)
- 依赖于ArrayIterator、StringIterator等的原型或构造函数身份。
Array.prototype.values.prototype.isPrototypeOf([].values()); // false
Array.prototype.isPrototypeOf([].values()); // false
我的问题:
ArrayIterator
/StringIterator
/...的原型在哪里?- 是否有更好的方法来解决给定的问题?
编辑:[][Symbol.iterator]()
和("")[Symbol.iterator]()
似乎共享同一个原型:
Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())) ====
Object.getPrototypeOf(Object.getPrototypeOf(("")[Symbol.iterator]()))
似乎无法通过原型进行区分。
编辑:这是我的代码:
const values = o => keys(o).values();
const next = iter => iter.next();
const foldl = f => acc => iter => {
let loop = (acc, {value, done}) => done
? acc
: loop(f(acc) (value), next(iter));
return loop(acc, next(iter));
}
// static `map` version only for `Array`s - not what I desire
const map = f => foldl(acc => x => [...acc, f(x)]) ([]);
console.log( map(x => x + x) ([1,2,3].values()) ); // A
console.log( map(x => x + x) (("abc")[Symbol.iterator]()) ); // B
A
行产生了所需的结果。然而,B
行产生了一个Array
而不是String
,连接只能工作,因为在这方面String
和Number
是巧合等价的。编辑:似乎有些混淆我这样做的原因:我希望使用可迭代/迭代器协议来抽象迭代细节,以便我的fold/unfold和派生map/filter等函数是通用的。问题是,你不能这样做,除非还有一个协议来处理identity/concat。我的小“hack”依赖于原型身份的想法并没有奏效。
@redneb在他的回答中提出了一个好观点,我同意他的观点,即并不是每个可迭代对象都是可映射的。但是,在记住这一点的同时,我仍然认为在JavaScript中以这种方式利用协议是有意义的,直到未来版本可能有适用于此类用法的可映射或集合协议。
Iterable
/ArrayIterator
/StringIterator
接口的起源是什么?它们来自某个标准的 JavaScript 框架吗?还是你自己定义的? - rednebArrayIterator
或StringIterator
原型,但有迭代协议:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Iteration_protocols - micnicmap
函数这样不相关的部分)。而且这个实现并没有自我记录来解释这一点,foldl
函数只会增加额外的复杂性,而不会真正帮助理解它的要点。如果你试图猜测相关迭代器的正确构造函数(而不是[]
),唯一的方法就是将迭代器字符串化...这看起来很脆弱。 - Estus Flask