jjzjj

javascript - 为什么民间故事和 lambda 如此不同?

coder 2023-07-03 原文

我正在通过阅读 DrBoolean 的 book 来学习 JavaScript FP .
我四处寻找函数式编程库。我找到了 Ramda 和 Folktale。两者都声称是函数式编程库。
但它们是如此不同:

  • Ramda似乎包含处理列表的实用函数:map、reduce、filter 和纯函数:curry、compose。它不包含任何处理 monad、functor 的内容。
  • Folktale但是不包含任何列表或函数的实用程序。它似乎在 javascript 中实现了一些代数结构,如 monad: Maybe, Task...

  • 实际上我发现了更多的库,它们似乎都属于两类。 Underscore 和 lodash 就像 Ramda。梦幻之地,自由幻想就像民间故事。
    这些非常不同的库都可以称为功能库吗?如果是,是什么使每个库都成为功能库?

    最佳答案

    功能特点

    函数式编程或函数库的定义没有明确的界限。 Javascript 内置了函数式语言的一些特性:

  • 一流的高阶函数
  • Lambdas/匿名函数,带闭包

  • 其他一些可以在 Javascript 中小心完成:
  • 不变性
  • 引用透明度

  • 还有一些是 ES6 的一部分,现在部分或完全可用:
  • 紧凑、简洁的功能
  • 通过尾调用优化实现高性能递归

  • 还有很多其他的确实超出了 Javascript 的正常范围:
  • 模式匹配
  • 懒人评价
  • 同质性

  • 然后,一个库可以挑选并选择它试图支持的功能类型,并且仍然可以合理地称为“功能性”。

    梦幻乐园规范

    Fantasy-land是许多标准类型的规范,从数学范畴论和抽象代数移植到函数式编程,类型如 Monoid , Functor , 和 Monad .这些类型相当抽象,并且可能扩展了更熟悉的概念。例如,仿函数是容器,可以是 map用函数遍历,数组的方式可以是map使用 Array.prototype.map 完成.

    民间故事

    Folktale是实现 Fantasy-land 规范各个部分的类型集合和一小部分配套实用程序函数。这些类型类似于 Maybe , Either , Task (非常类似于其他地方称为 Future 的东西,并且是 Promise 的更合法的表亲)和 Validation

    Folktale 可能是 Fantasy-land 规范最著名的实现,并且备受推崇。但是没有明确的或默认的实现; Fantasy-land 只指定抽象类型,当然一个实现必须创建这样的具体类型。 Folktale 声称自己是一个函数式库,这一点很明确:它提供了函数式编程语言中常见的数据类型,这些类型使得以函数式方式编程变得更加容易。

    这个例子,来自 Folktale documentation ( 注意 :不在最新版本的文档中),显示了它的使用方式:
    // We load the library by "require"-ing it
    var Maybe = require('data.maybe')
    
    // Returns Maybe.Just(x) if some `x` passes the predicate test
    // Otherwise returns Maybe.Nothing()
    function find(predicate, xs) {
      return xs.reduce(function(result, x) {
        return result.orElse(function() {
          return predicate(x)?    Maybe.Just(x)
          :      /* otherwise */  Maybe.Nothing()
        })
      }, Maybe.Nothing())
    }
    
    var numbers = [1, 2, 3, 4, 5]
    
    var anyGreaterThan2 = find(function(a) { return a > 2 }, numbers)
    // => Maybe.Just(3)
    
    var anyGreaterThan8 = find(function(a) { return a > 8 }, numbers)
    // => Maybe.Nothing
    

    lambda

    Ramda (免责声明:我是作者之一)是一种非常不同类型的库。它不会为您提供新类型。1 相反,它提供了一些功能,以便更轻松地对现有类型进行操作。它是围绕将较小的函数组合成较大的函数、处理不可变数据、避免副作用的概念而构建的。

    Ramda 尤其适用于列表,但也适用于对象,有时也适用于字符串。它还以与 Folktale 或其他 Fantasy-land 实现互操作的方式委派了许多调用。例如,Ramda 的 map功能,操作与 Array.prototype 上的类似, 所以 R.map(square, [1, 2, 3, 4]); //=> [1, 4, 9, 16] .但是因为Folktale的Maybe实现梦幻之地Functor spec,也指定了map,你也可以使用Ramda的map用它:
    R.map(square, Maybe.Just(5)); //=> Maybe.Just(25);
    R.map(square, Maybe.Nothing); //=> Maybe.Nothing
    

    Ramda 声称自己是一个函数式库,因为它可以轻松组合函数,永远不会改变您的数据,并且只呈现纯函数。 Ramda 的典型用法是通过组合较小的函数来构建更复杂的函数,如 philosphy of Ramda 上的一篇文章所示。
    // :: [Comment] -> [Number]  
    var userRatingForComments = R.pipe(
        R.pluck('username')      // [Comment] -> [String]
        R.map(R.propOf(users)),  // [String] -> [User]
        R.pluck('rating'),       // [User] -> [Number]
    );
    

    其他图书馆

    Actually I found more libraries, they all seem fall into the two categorys. underscore, lodash are very like Ramda. Fantasy-land, pointfree-fantasy are like folktale.



    这并不准确。首先,Fantasy-land 只是一个规范,图书馆可以决定为各种类型实现。 Folktale 是该规范的众多实现之一,可能是最全面的实现,当然也是最成熟的实现之一。 Pointfree-fantasyramda-fantasy是其他的,还有many more .

    Underscorelodash从表面上看,它们与 Ramda 相似,因为它们是抓包式库,提供了大量功能,但与 Folktale 之类的东西相比,内聚性要低得多。甚至特定功能也经常与 Ramda 重叠。但在更深层次上,Ramda 与那些库有着非常不同的关注点。 Ramda 的近亲可能是像 FKit 这样的库。 , Fnuc , 和 Wu.js .

    Bilby属于它自己的一个类别,提供了许多工具,例如 Ramda 提供的工具和一些与 Fantasy-land 一致的类型。 (Bilby 的作者也是 Fantasy-land 的原作者。)

    您的来电

    所有这些库都有权被称为功能性的,尽管它们在功能方法和功能 promise 程度方面差异很大。

    其中一些库实际上可以很好地协同工作。 Ramda 应该可以很好地与 Folktale 或其他 Fantasy-land 实现配合使用。由于它们的关注点几乎没有重叠,因此它们确实不冲突,但 Ramda 所做的足以使互操作相对顺畅。对于您可以选择的其他一些组合,这可能不太正确,但是 ES6 更简单的函数语法也可能会减轻集成的痛苦。

    库的选择,甚至是使用的库风格,将取决于您的项目和您的偏好。有很多不错的选择可供选择,而且数量还在增长,其中许多正在大大改进。现在是在 JS 中进行函数式编程的好时机。

    1嗯,有一个副项目,ramda-fantasy做一些类似于 Folktale 所做的事情,但它不是核心库的一部分。

    关于javascript - 为什么民间故事和 lambda 如此不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33027305/

    有关javascript - 为什么民间故事和 lambda 如此不同?的更多相关文章

    1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

      类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

    2. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

      我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

    3. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

      我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

    4. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

      我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

    5. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

      为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

    6. ruby - ruby 中的 TOPLEVEL_BINDING 是什么? - 2

      它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput

    7. ruby - Infinity 和 NaN 的类型是什么? - 2

      我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串

    8. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

      如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

    9. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

      关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

    10. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

      我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

    随机推荐