`
wqy159
  • 浏览: 56671 次
  • 性别: Icon_minigender_2
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

functional.js 介绍及源码分析

阅读更多

网站:JavaEye 作者:Lich_Ray 发表时间: 2007-07-26 22:17 此文章来自于 http://www.iteye.com
声明:本文系JavaEye网站原创文章,未经JavaEye网站或者作者本人书面许可,任何其他网站严禁擅自发表本文,否则必将追究法律责任!
原文链接: http://www.iteye.com/topic/105854

引用
本文对刚刚在网络上现身的 JavaScript 函数式编程库 functional.js 进行详尽的解读(地址已更正,感谢 hax)。

functional.js 是模仿 Haskell 语言标准库 Prelude 制作的函数式编程库,主要实现了:

  • 扩展的克里化函数

  • 运算符函数化

  • 紧缩的匿名函数语法

  • 无须指定参数的匿名函数语法

  • 函数向导语法

  • 基本的通用列表操作

  • 部分扩展基于对象化


其中,扩展语法由字符串表示。未能实现的特性有:

  • 尾递归优化

  • 模式匹配(包括参数匹配、列表匹配、情况分析)

  • 惰性运算(包括无穷列表)

  • 列表领悟

  • 扩展绑定、同时绑定

  • 其它列表操作(以及对于列表操作的基于对象化)


下面我们一边分析源代码,一边讲解库的用法。

一、库安装和概览
functional.js 库的所有用户级操作分为3个部分:


  1. 全局操作,绑定在全局对象
  2. Functional 上,主要是高阶函数操作和列表操作,所谓库安装即把这些内容可选的、安全地复制到全局环境
  3. 函数扩展,实现特殊高阶函数特性的工具(特供内部)

  4. 语法扩展,绑定在
  5. String.prototype 上,负责将字符串表示的 lambda 语法翻译为相应的高阶函数(特供内部)

下面是安装函数 Functional.install 的源代码(中文注释为笔者所加,下同):
代码

一般只要执行 Functional.install() 一句即可。

二、高阶函数操作
1. Functional.compose ([Function]) // 匿名的参数类型指的是 arguments 的类型,下同
  接受一列参数个数被认为相等的(允许 Currying 算子)函数为参数,返回一个函数,它接受一定的参数,能够对它们累积倒序 apply 那列函数。
  示例:compose('1+', '2*')(2) => 5
  
2. Functional.sequence ([Function])
  累积 apply 的顺序为参数顺序,为 compose 的反序。
  示例:sequence('1+', '2*')(2) => 6

以上两个操作亦可见于 Function.prototype,用法:'1+'.lambda().sequence('2*')(2) ==> 6

3. Function.prototype.flip ()
  返回一个函数,是原函数对象 this 参数接受顺序颠倒后的版本,不应属于函数扩展类。
  示例:flip('a/b')(1, 2) => 2
  
4. Function.prototype.saturate ([]) {
  返回一个函数,是原函数对象 this 忽略自己接受的参数,仅接受指定参数的版本。
  形式:f.saturate(args...)(args2...) == f(args...)
  
5. Function.prototype.aritize (n::Number) // 有名的参数类型由 :: 指定,下同
  返回一个函数,是原函数对象 this 忽略自己接受的参数列表中下标为 n 的参数的版本。
  
6. Function.S (f, g::Function)
  以单个大写字母命名的是函数的原子操作,应被收入 Functional 对象,这个很奇怪。
  形式:S(f, g)(args...) == f(g(args...), args...)
  
三、通用列表操作
1. 绑定在 Functional 对象上的部分完全照抄 Haskell Prelude 以及 Clean 的命名,它们是:


  1. map(f,
  2. [x1, x2...]) = [f(x, 0), f(x2, 1), ...]
  3. foldl,
  4. reduce(f, init, [x0, x1, x2]) == f(f(f(init, x0), x1), x2)
  5. filer,
  6. select('%2', [1,2,3,4]) -> [1, 3]
  7. foldr(f,
  8. init, [x0, x1, x2]) == fn(x0, f(x1, f(x2, init)))
  9. some(f,
  10. [x1, x2, x3, ...]) == f(x1) || f(x2) || f(x3)...
  11. every(f,
  12. [x1, x2, x3, ...]) == f(x1) && f(x2) && f(x3)...

以上操作的介绍网上到处都是,不再赘述;但有一点不同,即它们除了接受正常参数之外,还在最后接受一个可选参数 object::Object,它被用于指定操作执行的对象/环境。
另外,这些操作全部基于命令式风格实现,对于没有尾递归优化的 JavaScript 来说,效率有保障。

四、群体谓词操作
1. Functional.and ([Function])
  接受一列函数为参数,返回一个函数,它接受一个参数,对该参数 apply 那列函数,如结果全为 true,返回 true;否则返回 false。
  形式:and(f1, f2...)(args...) == f1(args...) && f2(args...)...
  示例:and('>1', '>2')(2) => false
  
2. Functional.or ([Function])
  接受一列函数为参数,返回一个函数,它接受一个参数,对该参数 apply 那列函数,如结果全为 false,返回 false;否则返回 true。
  形式:or(f1, f2...)(args...) == f1(args...) || f2(args...)...
  示例:or('>1', '>2')(2) => true
  
3. Functional.not = function(fn::Function)
  返回一个函数,是参数返回的布尔值的函数(谓词,下同) fn 取否的版本。
  形式:f.not()(args...) == !f(args...)
  
4. Functional.equal ([Function])
  接受一列函数为参数,返回一个函数,它接受一个参数,对该参数 apply 那列函数,如结果全部 == ,返回 true;否则返回 false。
  形式:equal(f1, f2...)(args...) == f1(args...) == f2(args...)...
  示例:equal()() => true // 特殊情况

五、函数扩展
  这一章仅仅是介绍内部实现。
1. Function.prototype.bind (object::Object,[])
  返回一个函数,作为 this 函数对象的副本,使其将在 object 环境下执行,并额外携带参数。
  形式:f.bind(obj, args...)(args2...) == f.apply(obj, [args..., args2...])
  
2. Function.prototype.curry ([])
这是实现克里化特性的关键函数,思想来自网络

代码

  返回那个传说中的可在参数不足时分步调用的函数——Currying 算子。
  形式:f.curry(args1...)(args2...) == f(args1..., args2...)

其它的 curry 类函数有:


  • rcurry,对从右边开始缺少参数的函数作克里化

  • ncurry,不接受全部参数就不
  • apply 参数的版本
  • rncurry,前者的反序版本

  • uncurry,作者一再强调,这不是
  • curry 的反转版本。它会拆分出第一个已得参数,形式为:f.uncurry(a, b...) == f(a)(b...)

3. Function.prototype.partial ([])
  在此函数定义之前,有定义 _ = Function._ = {} 。结合它们可以允许你像在 Haskell 中那样在参数列表中用 _ 忽略参数。但现在空谈是没用的,要结合第七章的语法扩展。
  
4. Function.prototype.guard (guard:>Function, otherwise)
  类似的,是一个允许在函数定义中使用向导功能的工具,尚缺少语法扩展支持。
  形式:f.guard(g, h)(args...) == f(args...), when g(args...) is true
    f.guard(g ,h)(args...) == h(args...), when g(args...) is false

六、工具函数
1. Functional.invoke (methodName::String, [])
  示例:invoke('toString')(123) => "123"
  
2. Functional.pluck (name::String)
  示例:pluck('length')("abc") => 3
  
3. Functional.until (pred:>Function, fn:>Function) // 用 :> 表示将参数强制转换类型

代码

  类似 Haskell 的 until,是一种函数式的循环,用命令式风格实现。
  
4. Functional.zip ([])
  特别注意,此 zip 并非 Haskell 中的 zip,它接受可变参数列表而不是列表的列表。
  形式:zip(a, b...) == [[a0, b0], [a1, b1], ...]

以上的章节中绑定在 Functional 上函数都可作为 Function 的对象方法直接使用,我们看这一行:

代码

前文对它们作出了定义,这里忽略。用法:name(arg, args...) == arg.name(args...)。

七、语法扩展
1. String.prototype.lambda ()
  把字符串表示的字符串翻译为函数扩展可接受的函数,进一步转为 JavaScript 函数。

代码

八、过滤器生成器
  仅供特别好学的同志们参考。
1. Function.prototype.prefilterObject (filter::Function)
  形式:fn.prefilterObject(filter).apply(object, args...) == fn.apply(filter(object), args...)
  
2. Function.prototype.prefilterAt (index::Number, filter::Function)
  形式:fn.prefilterAt(i, filter)(a1, a2, ..., a_{n}) == fn(a1, a2, ..., filter(a_{i}), ..., a_{n})
  
3. Function.prototype.prefilterSlice (filter::Function, start, end::Number)
  形式:fn.prefilterSlice(i0, i1, filter)(a1, a2, ..., a_{n}) == fn(a1, a2, ..., filter(args_{i0}, ..., args_{i1}), ..., a_{n})

九、其它用户级函数
1. Functional.id = Functional.I = function(x) {return x};

2. Functional.constfn = Functional.K = function(x) {return function() {return x}};

3. .toFunction ()
  在 String.prototype,Function.prototype,Function(需要参数 fn::Function) 上都有绑定,把对象转换为一个合适的 Functional 函数。但你不需要把代码写这样,map('*2'.toFunction(),alist),因为全局用户级函数都会对应为函数的参数自动执行 toFunction(),只要 map('*2',alist) 就行了。另外,String.prototype 上还有 JavaScript-Like 的 call、apply 方法。

十、结语
  functional.js 很强,很有用,很牛X;但同时也很年轻(7.20 发布),很多可以实现的功能还不完善,不说列表领悟什么的吧,至少应该把 Haskell Prelude 库在通用列表操作方面的函数的移植工作完成。我们期待 Oliver Steele 的表现。




《 functional.js 介绍及源码分析 》 的评论也很精彩,欢迎您也添加评论。查看详细 >>

推荐相关文章:
  javascript中的FP
   Programming in Emacs Lisp笔记(十八) 终结




JavaEye推荐
上海乐福狗信息技术有限公司:诚聘技术经理和开发工程师
免费下载IBM社区版软件--它基于开放的标准,支持广泛的开发类型,让您的开发高效自主!
京沪穗蓉四地免费注册,SOA技术高手汇聚交锋.
上海:优秀公司德比:高薪诚聘 资深Java工程师
广州:优易公司:诚聘Java工程师,开发经理
上海:尤恩斯国际集团:诚聘开发工程师
北京:优秀公司NHNChina招聘:WEB开发,系统管理,JAVA开发, DBA


分享到:
评论

相关推荐

    undersercore源码分析

    在Underscore的源码分析过程中,可以学习到如何编写简洁、高效的代码,同时深化对JavaScript基础知识的理解。此外,尽管Lodash在性能和功能上都超越了Underscore,但Underscore源码的短小精悍更适合JavaScript开发者...

    baconjsFRPfunctionalreactiveprogrammingJS编程库

    **标题解析:** "baconjsFRPfunctionalreactiveprogrammingJS编程库" 指的是 Bacon.js,一个基于 Functional Reactive Programming(函数响应式编程,简称FRP)的JavaScript编程库。 **描述详解:** "bacon.js - ...

    react-weather-app-源码.rar

    React天气应用源码分析 React天气应用是一款基于React.js开发的Web应用程序,它允许用户查看当前及未来的天气信息。在这款应用中,React作为一个强大的JavaScript库,被用来构建用户界面,提供高效、可复用的组件。...

    基于ssm+mysql羽毛球馆管理系统源码数据库论文.doc

    后台功能主要包括用户管理(注册、登录、权限控制)、场地资源管理(发布、预订、状态更新)、预约处理(确认、取消、超时处理)和数据分析(使用统计、优化策略)。通过合理的业务逻辑设计和数据库操作,实现系统...

    java8的源码

    Java 8增加了对类型注解的支持,可以在类型声明(如类、接口、方法和字段)上使用注解,这对于编译时检查和静态分析工具有很大帮助。 以上就是Java 8源码中包含的一些关键特性。通过深入学习和理解这些特性,...

    Functional-UI5-示例:这是我的Functional-UI5存储库的补充

    Functional-UI5 示例是基于JavaScript开发的一个项目,它主要用于展示如何在SAP UI5框架下构建功能丰富的...同时,通过对源码的分析和调试,可以提升开发者解决实际问题的能力,为未来开发更复杂的应用打下坚实基础。

    基于springboot+Web的校园爱心捐赠互助管理系统源码数据库论文.docx

    end platform through the springboot framework structure and Java programming language, realizes the presentation and feedback of data information through the web server, and the main functional ...

    不是严肃的JavaScript全栈

    这将是一个很好的学习素材,因为通过阅读和分析源码,我们可以深入理解各种技术的实际应用和最佳实践。 【标签】中的关键词提供了更多具体的技术方向: 1. **React**:这是一个流行的JavaScript库,用于构建用户...

    jdk-8u162-windows-x64.rar

    JDK 8增加了类型注解,允许在类型声明(包括类、接口、方法和变量)上使用注解,增强了静态分析和编译时检查的能力。 **8. Parallel GC优化** 在JDK 8中,垃圾收集器进行了优化,特别是Parallel GC(并行垃圾回收)...

    FMI_论坛

    4. **Node.js和服务器端处理**:使用Node.js可以处理后台任务,如模型预处理、仿真计算和结果分析。 5. **前端框架**:如React或Vue.js,可以用于构建用户友好的交互界面,展示模型参数,启动和控制仿真。 6. **...

    java8-src-sample

    这些特性使得 Java 8 成为一个里程碑式的更新,不仅提高了开发效率,也使 Java 适应了更广泛的应用场景,如云计算、大数据分析等。通过深入研究 "java8-src-sample" 中的源码示例,开发者可以更好地理解和应用这些...

    purescript-pop:使用PureScript事件和行为创建的功能性React式编程(FRP)演示

    通常,这样的结构会包括README文件(介绍项目)、源码目录、测试文件、配置文件等。 综合这些信息,我们可以预期这个项目会包含以下知识点: 1. **PureScript基础**: PureScript的语法、类型系统、模块系统和如何...

    一份介绍动态语言和FP的PPT

    而“FP”是“Functional Programming”的缩写,是一种编程范式,它强调将计算视为函数的数学运算,而不是对状态或数据流的改变。FP倾向于避免副作用,推崇纯函数,以及使用高阶函数和不可变数据结构。 在这份名为...

    philip2:Elm到OCaml编译器

    由于其特性,OCaml常用于编译器、操作系统、数据分析和金融软件等领域。 **Elm到OCaml的编译过程** "philip2"编译器的工作原理可能是将Elm源代码转换为中间表示(IR),然后将这个IR翻译成OCaml代码。这个过程中,...

Global site tag (gtag.js) - Google Analytics