JavaScript Programming 原文地址:http://www.pfeiffer-mediation.de/remast/javascript.php 翻译:ShiningRay 函数式JavaScript编程指南 简介 你是否知道JavaScript其实也是一个函数式编程语言呢?本指南将教你如何利用JavaScript的函数式特性。 要求:你应当已经对JavaScript和DOM有了一个基本的了解。 写这篇指南的目的是因为关于JavaScript编程的资料太多了但是极少的资料提到了JavaScript的函数式特性。在本指南中,我只会讲解这些基本知识而不会深入其它的函数式语言或这是Lambda算子。 你可以点击所有的例子然后你所看到的代码就会被执行,这样就可以令指南变得具有交互性。你也可以使用这个沙箱来尝试。 第一课 —— 匿名函数 我们将首先介绍匿名函数。一个匿名函数就是一个没有名字的函数。你可以认为他们是一次性函数。当你只需要用一次某个函数式,他们就特别有用。通过使用匿名函数,没有必要把函数一直放在内存中,所以使用匿名函数更加有效率。 例Example: 下面两个函数处理同样的事情,而average在给z赋值结束之后一直保留——但匿名函数则不会。 function average(x,y) { return (x+y)/2; } var z = average(1,3); alert(z); var z = function(x,y) { return (x+y)/2; } (1,3); alert(z); 这很自然得引出了我们下面的一节课函数作为值。 第二课 – 函数作为值 事实上,我们一般在JavaScript中声明函数的方式可以看作是一个简化了的语法(也就是语法糖,syntactic sugar)。 例:下面两个表达式其实完全一样。所以左边的表达式仅仅是右边的简写。 function average(x,y) { return (x+y)/2; } alert( average(1,3) ); var average = [...]
函数Currying,是我所一直不能确定的英文翻译之一 ,另外还有一个Web的翻译。 函数Currying的意思就是将参数和函数关联起来,变成一个新的函数。比如一个二元参数f a b 当给出f 1的时候,应该返回什么呢?一般的语言中,要么是将b设为一个默认值,要么就是直接出错,而当有了Currying,那么f 1其实返回一个函数g x = f 1 x。 当然这个描述也不够好。 其实其命名是为了纪念一个逻辑学家 Haskell Curry 的――函数式语言Haskell也是为纪念这个人,当然这个东西并不是他第一个发现。 既然作为姓名,数学中可能不会进行翻译,就叫做Curry化,或者柯里化,不知道还有什么更好的翻译方法,能较为直接地体现其真正的含义。
作者: William Taysom 原文地址:http://www.jadetower.org/muses/archives/000307.html 翻译:ShiningRay 我在过去的几周内一直在写JavaScript代码——使用我们的对话框系统来个性化Mozilla。假设你要求:“嘿,电脑,我要教你如何在Amazon.com上找书。首先你象这样进入Amazon,然后在这里输入你要的书的名字。点击“Go”然后……”我的困难在于对Mozilla编码使我的对话框系统可以“看”浏览器中正在进行什么然后自己可以执行这些动作。 由于Mozilla中较高的层次是用JavaScript实现的。所以我一直在废寝忘食研究它(我的Rhino book里面全是我做的书签)我写的越多,我越觉得它像Lisp。 考虑以下代码: semanticAccepter = acceptOnlyIf( acceptNot(emptyTextAccepter), scriptFilter, acceptAny( textAccepter, linkAccepter, formRelatedElementAccepter, linkImageAccepter)); usefulContentOfThePage = new SemTree(semanticAccepter); 这里SemTree是一个对象,它允许你从一个HTML DOM 树中选出某些你感兴趣的节点,去掉那些你不感兴趣的节点。(根本上说,这是一个TreeWalker 类的包装器。)若要建立一个 SemTree ,你要给出一个接受器。一个接受器只是一个判断给定节点是否能被接受的一个函数: function emptyTextAccepter(n) { return (n instanceof Text) && n.data.match(/^\s*$/); } 一旦有了一些基本的接受器和筛选器,很容易就可以定义组合筛选器──一种将筛选器以特殊形式组合起来的函数: function acceptAny() { var disjuncts = arguments; return function(n) { for (var i = 0; [...]
作者: Denys Duchier 翻译: Shining Ray @ Nirvana Studio 写本文旨在回应comp.lang.python新闻组中关于延续的讨论。 对于call/cc(call with current continuation)的情结和关于他的操作解释粗糙的细节内容,至今一直掩盖了延续的简洁和优雅。在本文中,我想用两个方式来纠正这个问题: 首先用一个简单且直观的方式展示延续的概念。 第二通过提供_可运行的_Python代码,来描述如何使用延续而不用call/cc来实现搜索引擎。 我将展示: 一个针对命题公式确定性检查工具。 一个基本的带回溯和裁剪的prolog引擎。 我希望这能帮助那些对于这个论题有些迷惑的人搞清这个问题。我还想指出上面讲到的两个程序是我在今天晚上花了几个小时写的,他们应该可以给你关于下面将要讲述的技术的能力的一些衡量尺度。 1. 简化延续 习惯上一般来说,一个函数返回一个值是这样的: def foo(x): return x+1 这隐含了它的值返回的地方。而延续的想法是通过添加一个延续参数来明确要返回的地方。函数不“返回”值,而是通过把值作为一个参数传递给延续“继续”处理值。在基于延续的程序中,以上函数foo变成了: def foo(x,c): c(x+1) 从这个角度看,函数从不使用返回“return”。取代的是它“继续”。正因为这个原因,延续有时候会被描述为“带参数的goto”。 上面描述的想法是。更精确地说,它是CPS(Continuation Passing Style,延续传送风格)的一个初步代码转换。基本的想法是给每个函数添加一个额外的“延续”参数,并进一步转化函数体以便不用返回他的值,而是把值传送给这个额外的延续参数。 在foo函数的例子中已经大体描述了这个概念。然而,更确切的,要注意CPS转换同时展开了所有的非lambda算子的嵌套表达式(换句话说,就是他显式地连接了所有子表达式的计算)。让我们看一个例子: def baz(x,y): return 2*x+y 在延续传送的观点中,甚至像*和+之类的基本操作符都要带一个额外的延续参数。我们通过以下定义进行模拟:def add(x,y,c): c(x+y) def mul(x,y,c): c(x*y) 现在,CPS可以把上面的baz函数转换成: def baz(x,y,c): mul(2,x,lambda v,y=y,c=c: add(v,y,c)) 换句话说,2*x的计算现在使用了一个延续来接收结果v并使用它来计算 v+y并最终把这个结果传给总的延续c。 当在这个上下文中理解了call/cc之后,它就不再神秘了。它只是一个特殊的手段,能让我们的双手去接触那个不可见的由CPS引入的额外的延续参数,并让我们像程序中其他函数值那样使用它。思考call/cc(f),其中f需要接受当前延续作为参数。其实说到底,call/cc(f)可以通过CPS转换成call_cc(f,c),而c就是CPS所引进的延续参数同时call_cc可以按照以下方式定义: [...]