Tcl中匿名函数的实现 (lambda)

@ 2009-07-19 15:05:06
标签:

    # 2008/12/05 01:20 @ Sean Zhang

    参考文章:

    • lambda
    • http://wiki.tcl.tk/3330|Closures
    • [[http://wiki.tcl.tk/15778|Simple Closures and Objects]]
    • [[http://wiki.tcl.tk/20662|A brief introduction to closures and continuations for event-based programming]]

    下面几个词基本上都是说同样的事情。

    • 匿名函数
    • anonymous function
    • lambda

    函数 f(x) = x+1 和 g(x) = x+1 除了名字不一样,本质上没什么不同。因此有些时候可以忽略掉函数名字表示为 (x) = x+1 。

    • [[http://wiki.tcl.tk/519|Lambda in Tcl]]

    所以这从概念上类似于

    proc "" {args} { 
     # body
    }
    
    # 也因此可以看作
    interp alias {} lambda {} proc {}
    
    lambda x {expr {$x+1}}
    

    这样做的问题是只能定义一个lambda,实用价值不是很大。我们需要对不同的匿名函数进行区分。

    实现方法之一 (proc)

       namespace eval lambda {variable unique 0}
       proc lambda {argList body} {
           set name ::lambda::cmd[incr ::lambda::unique]
           proc $name $argList $body
           return $name
       }
    

    这个方法通过定义函数来实现,但无法自动释放函数。

    关于函数的自动释放,[[http://wiki.tcl.tk/997|Local procedures]] 展示了一种思路,但对lambda来说似乎并不是很有用。

    实现方法之二 (apply)

    proc lambda {params body} { list ::apply [list $params $body] }
    
    # 返回值是一个list,而不是一个command。这主要用于 -command option
    #e.g.
    lsort -command [lambda {a b} { ... }] $xs
    

    Currying

    • [[http://wiki.tcl.tk/2882|Custom curry]]

    暂时不知道该怎么称呼,就叫做函数模板吧。

    proc curry {args} {
        set name [info level 0]
        eval [list interp alias {} $name {}] $args
        set name
    } ;# RS
    
    # e.g.
    
    set func [curry puts 2]
    $func
    

    这里的问题仍然是如何方便地释放这些已经定义过的资源

    标签:

      分享到:
      comments powered by Disqus

      31/35ms