Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何映射任意的可重用项?_Javascript_Functional Programming_Ecmascript 6_Iteration_Iterable - Fatal编程技术网

Javascript 如何映射任意的可重用项?

Javascript 如何映射任意的可重用项?,javascript,functional-programming,ecmascript-6,iteration,iterable,Javascript,Functional Programming,Ecmascript 6,Iteration,Iterable,我为Iterables编写了一个reduce函数,现在我想导出一个可以映射到任意Iterables的通用map。但是,我遇到了一个问题:由于Iterables抽象了数据源,map无法确定它的类型(例如Array,String,map等)。我需要这个类型来调用相应的identity元素/concat函数。我想到了三个解决方案: 显式地传递identity元素/concat函数const map=f=>id=>concat=>xs(这很冗长,但会泄漏内部API) 只有mapIterables实现了m

我为
Iterable
s编写了一个
reduce
函数,现在我想导出一个可以映射到任意
Iterable
s的通用
map
。但是,我遇到了一个问题:由于
Iterable
s抽象了数据源,
map
无法确定它的类型(例如
Array
String
map
等)。我需要这个类型来调用相应的identity元素/concat函数。我想到了三个解决方案:

  • 显式地传递identity元素/concat函数
    const map=f=>id=>concat=>xs
    (这很冗长,但会泄漏内部API)
  • 只有map
    Iterable
    s实现了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();
    常数foldl=f=>acc=>iter=>{
    让循环=(acc,{value,done})=>done
    ?acc
    :循环(f(acc)(值),下一个(iter));
    返回回路(acc,next(iter));
    }
    //静态'map'版本仅适用于'Array',不是我想要的
    常量映射=f=>foldl(acc=>x=>[…acc,f(x)])([]);
    console.log(map(x=>x+x)([1,2,3].values());//A.
    log(map(x=>x+x)(“abc”)[Symbol.iterator]());//B
    我以前没有使用过,但在我看来,它本质上是一个接口,用于让您使用
    for
    循环迭代容器对象。问题是,您试图将该接口用于它不是为之设计的东西。为此,您需要一个单独的接口。可以想象,一个对象可能是“可映射的”,但不是“可映射的”。例如,假设在一个应用程序中,我们使用二叉树,并通过遍历它们(比如按BFS顺序)来为它们实现iterable接口,因为该顺序对于这个特定的应用程序是有意义的。对于这个特殊的iterable,通用映射是如何工作的?它需要返回一个“相同形状”的树,但是这个特殊的可移植实现没有提供足够的信息来重建树


    因此,解决这个问题的方法是定义一个新的接口(称之为
    Mappable
    ,,或任何您喜欢的接口),但它必须是一个独特的接口。然后,您可以为有意义的类型(如数组)实现该接口。

    您可以比较对象字符串,尽管这不是傻瓜式的,因为在某些环境中存在已知的错误,并且在ES6中,用户可以修改这些字符串

    console.log(Object.prototype.toString.call(“[Symbol.iterator]());
    
    log(Object.prototype.toString.call([[Symbol.iterator]())对于任意iterable,没有干净的方法可以做到这一点。可以为其创建地图并参考它

    const iteratorProtoMap = [String, Array, Map, Set]
    .map(ctor => [
      Object.getPrototypeOf((new ctor)[Symbol.iterator]()),
      ctor]
    )
    .reduce((map, entry) => map.set(...entry), new Map);
    
    function getCtorFromIterator(iterator) {
      return iteratorProtoMap.get(Object.getPrototypeOf(iterator));
    }
    
    通过定制iterables的可能性,还可以添加用于添加它们的API

    为了提供用于连接/构造所需iterable的公共模式,可以为映射而不是构造函数提供回调

    显式地传递identity元素/concat函数
    constmap=f=>id=>concat=>xs

    是的,如果
    xs
    参数没有公开构造新值的功能,那么这几乎总是必需的。在Scala中,每个集合类型都为此提供了一个特性,不幸的是,ECMAScript标准中没有与此匹配的内容

    仅映射实现monoid接口的Iterables

    好吧,是的,那可能是一种方法。您甚至不需要引入“新类型”,这方面的标准已经存在。然而,缺点是

    • 大多数内置类型(
      String
      Map
      Set
      )不实现monoid接口,尽管它们是可移植的
    • 不是所有的“可映射”都是幺半群
    另一方面,并非所有的可映射性都是可映射的。试图在任意可重用项上编写
    映射
    ,而不返回到
    数组
    结果注定要失败

    因此,只需寻找
    Functor
    可遍历的接口,并在存在的地方使用它们。它们可能在内部构建在迭代器上,但这与您无关。您可能想做的唯一一件事是为创建此类基于迭代器的映射方法提供一个通用帮助器,以便您可以使用它装饰
    Map
    String
    。该助手还可以将生成器对象作为参数

    依赖于ArrayIterator、StringIterator等的原型或构造函数标识

    这是行不通的,例如,类型化数组使用与普通数组相同的迭代器。由于迭代器没有访问迭代对象的方法,因此无法区分它们。但无论如何,您确实不应该这样做,只要处理迭代器本身,您最多应该映射到另一个迭代器,而不是映射到创建迭代器的iterable类型

    ArrayIterator/StringIterator/的原型在哪里


    它们没有全局变量,但是您可以在创建实例后使用
    Object.getPrototypeOf
    访问它们。

    我知道这个问题已经发布了很多次了