各种语言实现函数累加器函数

这两天都在看《黑客与画家》,作者 Paul Graham 是一个推崇 Lisp 为编程能力最强的语言的支持者。第13章,作者各种强调 Lisp 的强大,最后在该章节末尾给出了一个例子来说明各个编程语言的能力是不一样的,Lisp 是最强大的。

原文引入如下:

为了解释我所说的语言编程能力不一样,请考虑下面的问题。我们需要写一个函数,它能够生成累加器,即这个函数接受参数 n,然后返回另一个函数,后者接受参数 i,然后返回 n 增加了 i 后的值。「这里说的是增加,而不是 n 和 i 的相加(plus)。累加器就是应该完成 n 的累加。」

接下来,作者了给出了各种语言实现上述问题的写法:

Common Lisp:

(defun foo (n)
  (lambda (i) (incf n i)))

Scheme:

(define (foo n)
  lambda (i) (set! n (+ n i) n))

Goo:

(df foo(n) (op incf n _))

Arc:

(def foo (n) [++ n _])

作者把 Scheme, Goo, Arc 这三种语言称作 Lisp 的方言(哈哈哈,大概是想说,这些都是在模仿 Lisp 吧)

Ruby:

def foo (n)
  lambda {|i| n += i} end

Perl:

sub foo {
  my ($n) = @_;
  sub {$n += shift}
}

Smalltalk:

foo: n
  |s|
  s := n.
  ^[:i| s := s+i. ]

Javascript:

function foo(n) {
  return function (i) {
    return n += i; } }

Python:

def foo(n):
    s = [n]
    def bar(i):
        s[0] += i
        return s[0]
    return bar

作者还提到,Python 用户完全可以合理地质疑为什么不能写成下面这样,并且他猜想,Python 有一天会支持这样的写法:

def foo(n):
    return lambda i: return n += i

或者:

def foo(n):
    lambda i: n += i

Python 采用面向对象模拟闭包的实现:

def foo(n):
    class acc:
        def __init__(self, s):
            self.s = s
        def inc(self, i):
            self.s += i
            return self.s
    return acc(n).inc

或者:

class foo:
    def __init__(self, n):
        self.n = n
    def __call__(self, i):
        self.n += i
        return self.n

其他语言根本无法解决这个问题,肯 安得森说,Java 只能写出一个近视的解法:

public interface Inttoint {
  public int call(int i);
}

public static Inttoint foo(final int n) {
  return new Inttoint () {
    int s = n;
    public int call(int i) {
      s = s + i;
      return s;
  }};
}

感觉这个就比较精彩了,我看得懂只有 js、java 和 python,perl 虽然去年看过一本 perl 入门的书,但是现在已经忘干净了。

作者还强调,其他语言无法解决这个问题,这句话并不完全正确。因为所有编程语言都是图灵等价的,意味着可以使用任何一种语言写出任何一个程序。只不过不同语言实现起来难度和复杂度不一样而已。

Lisp 的那种写法,看得我好别扭,还是看 js 最舒服。

1 评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注