论坛首页 综合技术论坛

(鳞爪琐思)为什么fp不需要yield?

浏览 8508 次
该帖已经被评为精华帖
作者 正文
   发表时间:2005-05-30  
FP
ruby的yield如此漂亮,以至于任何一个命令式语言如果不支持yield就是一个遗憾。

它让iterator的实现者用最直观简单的internal iterator的方式书写,而同时仍然允许iterator的使用者用external iterator的方式去用它。



然而,函数式语言对此却不感冒。是函数式语言抱残守缺吗?
其实。函数式语言拥有比yield更一般更强大的continuation机制。

让我们再回忆一下internal iterator的几点缺陷:
1。回调的定义语法繁琐。(java恶心的anonymous class语法)
2。无法在循环中间return, break。


对1,大多函数式语言都支持lamda语法,比anonymous class简单多了,比如:

foreach arr \i-> print i

这句等价于:
for(i:arr);{System.out.println(i);;}


\i ->print i
代表一个匿名函数,它对任何参数都直接打印。
等同于ruby的block语法:
|i|{print i}


而且,很多函数式语言还支持currying。这样,我可以直接写:
foreach arr print



对2,continuation提供了立即跳出循环的方法。
callcc \exit->body

在body中,任何地方如果调用了exit,程序流程都会立即跳出body,回到callcc这个地方来。





比如,对下面的循环:
boolean find(arr, k, max, def);{
  foreach(i:arr);{
    if(i<0); return false;
    else if(i==k); return true;
    else if(i>max); break;
  }
  return def;
}


我们有两个跳出点:
return 跳出find函数;break跳出foreach循环。

对等的用fp的continuation,代码可以写成这样:

find(arr, k, max, def); =
callcc \return ->
  callcc \loopreturn ->
    let
    break = loopreturn false;
    continue = true;
    foreach arr \i->
      if i<0 then return false
      else if i==k then return true
      else if i>max then break
      else continue;
    in return def

我们只要在可能跳出的程序点加上一句
callcc \label->
后面的代码就可以通过调用label函数来跳到这点。

如此,利用callcc函数+internal iterator,我们就可以轻松达到yield要达到的目的,自然也就没有必要单独引入一个yield关键字和一套额外的语义了。

你可能会说:这不就是goto嘛!
其实,上面演示的,是只向循环外跳转的continuation,也是最简单的一类continuation。(jaskell就只支持这种continuation)。
这种continuation还是更象break和return。

当然,一些语言的continuation确实可以做很多非常复杂难解变态的事情(比如scheme),此时,滥用continuation只怕真的不会比滥用goto好多少。

不过,无可否认, 这种continuation的强大程度也是goto望尘莫及的。
   发表时间:2006-09-25  
为什么只有 Ruby?

http://www.nirvanastudio.org/java/why-java-and-almost-every-other-programming-language-sucks.html
0 请登录后投票
   发表时间:2006-09-26  
然。
JavaScript就可以写出这类强大的效果……有兴趣者请参阅Selenium-Core,HtmlTestRunner类。
0 请登录后投票
   发表时间:2006-09-26  
JS 可以实现callcc ? cool.

我下载了selenium core, 但是没有找到 HtmlTestRunner这个类。文件名是什么?
好吧,广告的目的达到了,现在可以告诉咱了吧?

找到了,是selenium-testrunner.js这个文件。
里面倒是有很多事件机制的代码。文件太长了,没看到contiunaiton的部分。
和Timer相关?一步一步驱动?

Rhino Javascript (Java server side JS)支持contiunation。著名的cocoon就是用的这个。

browser JS continuation 也找到几个。

http://chumsley.org/jwacs/

The function_continuation statement
The new function_continuation statement takes no arguments and returns the return continuation for the current function. For example, in the following code:

  function sleep(msec)
  {
    var k = function_continuation;
    setTimeout(function() { resume k; }, msec);
    suspend;
  }

http://neilmix.com/narrativejs/doc/index.html

0 请登录后投票
   发表时间:2006-09-26  
也说不上callcc,只不过是JavaScript不能阻塞调用,要用timer来模拟,我们把它重构成比较漂亮的、一堆lambda传来传去的样子了。
0 请登录后投票
   发表时间:2006-09-27  
有人用JS实现了符合R5RS标准的Scheme,call/cc不在话下吧

http://www.bluishcoder.co.nz/jsscheme/

buaawhl 写道
JS 可以实现callcc ? cool.

我下载了selenium core, 但是没有找到 HtmlTestRunner这个类。文件名是什么?
好吧,广告的目的达到了,现在可以告诉咱了吧?

找到了,是selenium-testrunner.js这个文件。
里面倒是有很多事件机制的代码。文件太长了,没看到contiunaiton的部分。
和Timer相关?一步一步驱动?

Rhino Javascript (Java server side JS)支持contiunation。著名的cocoon就是用的这个。

browser JS continuation 也找到几个。

http://chumsley.org/jwacs/

The function_continuation statement
The new function_continuation statement takes no arguments and returns the return continuation for the current function. For example, in the following code:

  function sleep(msec)
  {
    var k = function_continuation;
    setTimeout(function() { resume k; }, msec);
    suspend;
  }

http://neilmix.com/narrativejs/doc/index.html

0 请登录后投票
   发表时间:2006-09-27  
ShiningRay 写道

有人用JS实现了符合R5RS标准的Scheme,call/cc不在话下吧
http://www.bluishcoder.co.nz/jsscheme/


First-class continuations with even dynamic-wind

这个很牛啊。说明是GPL的,但是找不到source。
有一个download link,是混淆过的JQuery.js。
0 请登录后投票
   发表时间:2006-09-27  
call/cc实际上是个lambda,只要支持lambda的语言都能搞call/cc
0 请登录后投票
   发表时间:2006-09-29  
buaawhl 写道
ShiningRay 写道

有人用JS实现了符合R5RS标准的Scheme,call/cc不在话下吧
http://www.bluishcoder.co.nz/jsscheme/


First-class continuations with even dynamic-wind

这个很牛啊。说明是GPL的,但是找不到source。
有一个download link,是混淆过的JQuery.js。


evidently you haven't read every line on that page.

note the last line:

Original
    Original by Alex Yakovlev from http://alex.ability.ru/scheme.html.


it's implemented in 2000+ lines of js.
0 请登录后投票
   发表时间:2006-09-29  

right.

http://www.bluishcoder.co.nz/jsscheme/
http://alex.ability.ru/scheme.html

这两个link, view source,就可以看到了。thanks.

theCallCC =
TopEnv['call-with-current-continuation'] = function(list,state) {
  state.ready = false;
  return callF( list.car, new Pair( state.cc.clone(), theNil ), state );
}
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics