免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 5431 | 回复: 29
打印 上一主题 下一主题

flw,不是要比吗? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-01-22 20:18 |只看该作者 |倒序浏览
先给你扫扫盲!对于lisp的知识
Lisp之根源
保罗格雷厄姆


约翰麦卡锡于1960年发表了一篇非凡的论文,他在这篇论文中对编程的贡献有如欧几里德对几何的贡献.1 他向我们展示了,在只给定几个简单的操作符和一个表示函数的记号的基础上, 如何构造出一个完整的编程语言. 麦卡锡称这种语言为Lisp, 意为List Processing, 因为他的主要思想之一是用一种简单的数据结构表(list)来代表代码和数据.

值得注意的是,麦卡锡所作的发现,不仅是计算机史上划时代的大事, 而且是一种在我们这个时代编程越来越趋向的模式.我认为目前为止只有两种真正干净利落, 始终如一的编程模式:C语言模式和Lisp语言模式.此二者就象两座高地, 在它们中间是尤如沼泽的低地.随着计算机变得越来越强大,新开发的语言一直在坚定地趋向于Lisp模式. 二十年来,开发新编程语言的一个流行的秘决是,取C语言的计算模式,逐渐地往上加Lisp模式的特性,例如运行时类型和无用单元收集.

在这篇文章中我尽可能用最简单的术语来解释约翰麦卡锡所做的发现. 关键是我们不仅要学习某个人四十年前得出的有趣理论结果, 而且展示编程语言的发展方向. Lisp的不同寻常之处--也就是它优质的定义--是它能够自己来编写自己. 为了理解约翰麦卡锡所表述的这个特点,我们将追溯他的步伐,并将他的数学标记转换成能够运行的Common Lisp代码.


七个原始操作符
开始我们先定义表达式.表达式或是一个原子(atom),它是一个字母序列(如 foo),或是一个由零个或多个表达式组成的表(list), 表达式之间用空格分开, 放入一对括号中. 以下是一些表达式:


foo
()
(foo)
(foo bar)
(a b (c) d)

最后一个表达式是由四个元素组成的表, 第三个元素本身是由一个元素组成的表.
在算术中表达式 1 + 1 得出值2. 正确的Lisp表达式也有值. 如果表达式e得出值v,我们说e返回v. 下一步我们将定义几种表达式以及它们的返回值.

如果一个表达式是表,我们称第一个元素为操作符,其余的元素为自变量.我们将定义七个原始(从公理的意义上说)操作符: quote,atom,eq,car,cdr,cons,和 cond.


(quote x) 返回x.为了可读性我们把(quote x)简记 为'x.

> (quote a)
a
> 'a
a
> (quote (a b c))
(a b c)


(atom x)返回原子t如果x的值是一个原子或是空表,否则返回(). 在Lisp中我们按惯例用原子t表示真, 而用空表表示假.

> (atom 'a)
t
> (atom '(a b c))
()
> (atom '())
t

既然有了一个自变量需要求值的操作符, 我们可以看一下quote的作用. 通过引用(quote)一个表,我们避免它被求值. 一个未被引用的表作为自变量传给象 atom这样的操作符将被视为代码:


> (atom (atom 'a))
t

反之一个被引用的表仅被视为表, 在此例中就是有两个元素的表:


> (atom '(atom 'a))
()

这与我们在英语中使用引号的方式一致. Cambridge(剑桥)是一个位于麻萨诸塞州有90000人口的城镇. 而``Cambridge''是一个由9个字母组成的单词.

引用看上去可能有点奇怪因为极少有其它语言有类似的概念. 它和Lisp最与众不同的特征紧密联系:代码和数据由相同的数据结构构成, 而我们用quote操作符来区分它们.


(eq x y)返回t如果x和y的值是同一个原子或都是空表, 否则返回().

> (eq 'a 'a)
t
> (eq 'a 'b)
()
> (eq '() '())
t


(car x)期望x的值是一个表并且返回x的第一个元素.

> (car '(a b c))
a


(cdr x)期望x的值是一个表并且返回x的第一个元素之后的所有元素.
> (cdr '(a b c))
(b c)


(cons x y)期望y的值是一个表并且返回一个新表,它的第一个元素是x的值, 后面跟着y的值的各个元素.

> (cons 'a '(b c))
(a b c)
> (cons 'a (cons 'b (cons 'c '())))
(a b c)
> (car (cons 'a '(b c)))
a
> (cdr (cons 'a '(b c)))
(b c)

(cond (...) ...(...)) 的求值规则如下. p表达式依次求值直到有一个返回t. 如果能找到这样的p表达式,相应的e表达式的值作为整个cond表达式的返回值.

> (cond ((eq 'a 'b) 'first)
        ((atom 'a)  'second))
second

当表达式以七个原始操作符中的五个开头时,它的自变量总是要求值的.2 我们称这样 的操作符为函数.


函数的表示
接着我们定义一个记号来描述函数.函数表示为(lambda (...) e),其中 ...是原子(叫做参数),e是表达式. 如果表达式的第一个元素形式如上
((lambda (...) e) ...)

则称为函数调用.它的值计算如下.每一个表达式先求值,然后e再求值.在e的求值过程中,每个出现在e中的的值是相应的在最近一次的函数调用中的值.


> ((lambda (x) (cons x '(b))) 'a)
(a b)
> ((lambda (x y) (cons x (cdr y)))
   'z
   '(a b c))
(z b c)

如果一个表达式的第一个元素f是原子且f不是原始操作符
(f ...)

并且f的值是一个函数(lambda (...)),则以上表达式的值就是

((lambda (...) e) ...)

的值. 换句话说,参数在表达式中不但可以作为自变量也可以作为操作符使用:


> ((lambda (f) (f '(b c)))
   '(lambda (x) (cons 'a x)))
(a b c)

有另外一个函数记号使得函数能提及它本身,这样我们就能方便地定义递归函数.3 记号

(label f (lambda (...) e))

表示一个象(lambda (...) e)那样的函数,加上这样的特性: 任何出现在e中的f将求值为此label表达式, 就好象f是此函数的参数.

假设我们要定义函数(subst x y z), 它取表达式x,原子y和表z做参数,返回一个象z那样的表, 不过z中出现的y(在任何嵌套层次上)被x代替.

> (subst 'm 'b '(a b (a b c) d))
(a m (a m c) d)

我们可以这样表示此函数
(label subst (lambda (x y z)
               (cond ((atom z)
                      (cond ((eq z y) x)
                            ('t z)))
                     ('t (cons (subst x y (car z))
                               (subst x y (cdr z)))))))

我们简记f=(label f (lambda (...) e))为
(defun f (...) e)

于是

(defun subst (x y z)
  (cond ((atom z)
         (cond ((eq z y) x)
               ('t z)))
        ('t (cons (subst x y (car z))
                  (subst x y (cdr z))))))

偶然地我们在这儿看到如何写cond表达式的缺省子句. 第一个元素是't的子句总是会成功的. 于是
(cond (x y) ('t z))

等同于我们在某些语言中写的

if x then y else z


一些函数
既然我们有了表示函数的方法,我们根据七个原始操作符来定义一些新的函数. 为了方便我们引进一些常见模式的简记法. 我们用cxr,其中x是a或d的序列,来简记相应的car和cdr的组合. 比如(cadr e)是(car (cdr e))的简记,它返回e的第二个元素.

> (cadr '((a b) (c d) e))
(c d)
> (caddr '((a b) (c d) e))
e
> (cdar '((a b) (c d) e))
(b)

我们还用(list ...)表示(cons ...(cons '()) ...).
> (cons 'a (cons 'b (cons 'c '())))
(a b c)
> (list 'a 'b 'c)
(a b c)

现在我们定义一些新函数. 我在函数名后面加了点,以区别函数和定义它们的原始函数,也避免与现存的common Lisp的函数冲突.


(null. x)测试它的自变量是否是空表.

(defun null. (x)
  (eq x '()))

> (null. 'a)
()
> (null. '())
t


(and. x y)返回t如果它的两个自变量都是t, 否则返回().

(defun and. (x y)
  (cond (x (cond (y 't) ('t '())))
        ('t '())))

> (and. (atom 'a) (eq 'a 'a))
t
> (and. (atom 'a) (eq 'a 'b))
()


(not. x)返回t如果它的自变量返回(),返回()如果它的自变量返回t.

(defun not. (x)
  (cond (x '())
        ('t 't)))

> (not. (eq 'a 'a))
()
> (not. (eq 'a 'b))
t


(append. x y)取两个表并返回它们的连结.

(defun append. (x y)
   (cond ((null. x) y)
         ('t (cons (car x) (append. (cdr x) y)))))

> (append. '(a b) '(c d))
(a b c d)
> (append. '() '(c d))
(c d)


(pair. x y)取两个相同长度的表,返回一个由双元素表构成的表,双元素表是相应位置的x,y的元素对.

(defun pair. (x y)
  (cond ((and. (null. x) (null. y)) '())
        ((and. (not. (atom x)) (not. (atom y)))
         (cons (list (car x) (car y))
               (pair. (cdr) (cdr y))))))

> (pair. '(x y z) '(a b c))
((x a) (y b) (z c))


(assoc. x y)取原子x和形如pair.函数所返回的表y,返回y中第一个符合如下条件的表的第二个元素:它的第一个元素是x.

(defun assoc. (x y)
  (cond ((eq (caar y) x) (cadar y))
        ('t (assoc. x (cdr y)))))

> (assoc. 'x '((x a) (y b)))
a
> (assoc. 'x '((x new) (x a) (y b)))
new


一个惊喜
因此我们能够定义函数来连接表,替换表达式等等.也许算是一个优美的表示法, 那下一步呢? 现在惊喜来了. 我们可以写一个函数作为我们语言的解释器:此函数取任意Lisp表达式作自变量并返回它的值. 如下所示:

(defun eval. (e a)
  (cond
    ((atom e) (assoc. e a))
    ((atom (car e))
     (cond
       ((eq (car e) 'quote) (cadr e))
       ((eq (car e) 'atom)  (atom   (eval. (cadr e) a)))
       ((eq (car e) 'eq)    (eq     (eval. (cadr e) a)
                                    (eval. (caddr e) a)))
       ((eq (car e) 'car)   (car    (eval. (cadr e) a)))
       ((eq (car e) 'cdr)   (cdr    (eval. (cadr e) a)))
       ((eq (car e) 'cons)  (cons   (eval. (cadr e) a)
                                    (eval. (caddr e) a)))
       ((eq (car e) 'cond)  (evcon. (cdr e) a))
       ('t (eval. (cons (assoc. (car e) a)
                        (cdr e))
                  a))))
    ((eq (caar e) 'label)
     (eval. (cons (caddar e) (cdr e))
            (cons (list (cadar e) (car e)) a)))
    ((eq (caar e) 'lambda)
     (eval. (caddar e)
            (append. (pair. (cadar e) (evlis. (cdr  e) a))
                     a)))))

(defun evcon. (c a)
  (cond ((eval. (caar c) a)
         (eval. (cadar c) a))
        ('t (evcon. (cdr c) a))))

(defun evlis. (m a)
  (cond ((null. m) '())
        ('t (cons (eval.  (car m) a)
                  (evlis. (cdr m) a)))))

eval.的定义比我们以前看到的都要长. 让我们考虑它的每一部分是如何工作的.
eval.有两个自变量: e是要求值的表达式, a是由一些赋给原子的值构成的表,这些值有点象函数调用中的参数. 这个形如pair.的返回值的表叫做环境. 正是为了构造和搜索这种表我们才写了pair.和assoc..

eval.的骨架是一个有四个子句的cond表达式. 如何对表达式求值取决于它的类型. 第一个子句处理原子. 如果e是原子, 我们在环境中寻找它的值:


> (eval. 'x '((x a) (y b)))
a

第二个子句是另一个cond, 它处理形如(a ...)的表达式, 其中a是原子. 这包括所有的原始操作符, 每个对应一条子句.


> (eval. '(eq 'a 'a) '())
t
> (eval. '(cons x '(b c))
         '((x a) (y b)))
(a b c)

这几个子句(除了quote)都调用eval.来寻找自变量的值.
最后两个子句更复杂些. 为了求cond表达式的值我们调用了一个叫 evcon.的辅助函数. 它递归地对cond子句进行求值,寻找第一个元素返回t的子句. 如果找到了这样的子句, 它返回此子句的第二个元素.


> (eval. '(cond ((atom x) 'atom)
                ('t 'list))
         '((x '(a b))))
list

第二个子句的最后部分处理函数调用. 它把原子替换为它的值(应该是lambda 或label表达式)然后对所得结果表达式求值. 于是


(eval. '(f '(b c))
       '((f (lambda (x) (cons 'a x)))))

变为
(eval. '((lambda (x) (cons 'a x)) '(b c))
       '((f (lambda (x) (cons 'a x)))))

它返回(a b c).
eval.的最后cond两个子句处理第一个元素是lambda或label的函数调用.为了对label 表达式求值, 先把函数名和函数本身压入环境, 然后调用eval.对一个内部有 lambda的表达式求值. 即:


(eval. '((label firstatom (lambda (x)
                            (cond ((atom x) x)
                                  ('t (firstatom (car x))))))
         y)
       '((y ((a b) (c d)))))

变为
(eval. '((lambda (x)
           (cond ((atom x) x)
                 ('t (firstatom (car x)))))
         y)
        '((firstatom
           (label firstatom (lambda (x)
                            (cond ((atom x) x)
                                  ('t (firstatom (car x)))))))
          (y ((a b) (c d)))))

最终返回a.
最后,对形如((lambda (...) e) ...)的表达式求值,先调用evlis.来求得自变量(...)对应的值(...),把()...()添加到环境里, 然后对e求值. 于是


(eval. '((lambda (x y) (cons x (cdr y)))
         'a
         '(b c d))
       '())

变为
(eval. '(cons x (cdr y))
       '((x a) (y (b c d))))

最终返回(a c d).

后果
既然理解了eval是如何工作的, 让我们回过头考虑一下这意味着什么. 我们在这儿得到了一个非常优美的计算模型. 仅用quote,atom,eq,car,cdr,cons,和cond, 我们定义了函数eval.,它事实上实现了我们的语言,用它可以定义任何我们想要的额外的函数.

当然早已有了各种计算模型--最著名的是图灵机. 但是图灵机程序难以读懂. 如果你要一种描述算法的语言, 你可能需要更抽象的, 而这就是约翰麦卡锡定义 Lisp的目标之一.

约翰麦卡锡于1960年定义的语言还缺不少东西. 它没有副作用, 没有连续执行 (它得和副作用在一起才有用), 没有实际可用的数,4 没有动态可视域. 但这些限制可以令人惊讶地用极少的额外代码来补救. Steele和Sussman在一篇叫做``解释器的艺术''的著名论文中描述了如何做到这点.5

如果你理解了约翰麦卡锡的eval, 那你就不仅仅是理解了程序语言历史中的一个阶段. 这些思想至今仍是Lisp的语义核心. 所以从某种意义上, 学习约翰麦卡锡的原著向我们展示了Lisp究竟是什么. 与其说Lisp是麦卡锡的设计,不如说是他的发现. 它不是生来就是一门用于人工智能, 快速原型开发或同等层次任务的语言. 它是你试图公理化计算的结果(之一).

随着时间的推移, 中级语言, 即被中间层程序员使用的语言, 正一致地向Lisp靠近. 因此通过理解eval你正在明白将来的主流计算模式会是什么样.


注释
把约翰麦卡锡的记号翻译为代码的过程中我尽可能地少做改动. 我有过让代码更容易阅读的念头, 但是我还是想保持原汁原味.
在约翰麦卡锡的论文中,假用f来表示, 而不是空表. 我用空表表示假以使例子能在Common Lisp中运行. (fixme)

我略过了构造dotted pairs, 因为你不需要它来理解eval. 我也没有提apply, 虽然是apply(它的早期形式, 主要作用是引用自变量), 被约翰麦卡锡在1960年称为普遍函数, eval只是不过是被apply调用的子程序来完成所有的工作.

我定义了list和cxr等作为简记法因为麦卡锡就是这么做的. 实际上 cxr等可以被定义为普通的函数. List也可以这样, 如果我们修改eval, 这很容易做到, 让函数可以接受任意数目的自变量.

麦卡锡的论文中只有五个原始操作符. 他使用了cond和quote,但可能把它们作为他的元语言的一部分. 同样他也没有定义逻辑操作符and和not, 这不是个问题, 因为它们可以被定义成合适的函数.

在eval.的定义中我们调用了其它函数如pair.和assoc.,但任何我们用原始操作符定义的函数调用都可以用eval.来代替. 即

(assoc. (car e) a)

能写成

(eval. '((label assoc.
                (lambda (x y)
                  (cond ((eq (caar y) x) (cadar y))
                        ('t (assoc. x (cdr y))))))
         (car e)
         a)
        (cons (list 'e e) (cons (list 'a a) a)))

麦卡锡的eval有一个错误. 第16行是(相当于)(evlis. (cdr e) a)而不是(cdr e), 这使得自变量在一个有名函数的调用中被求值两次. 这显示当论文发表的时候, eval的这种描述还没有用IBM 704机器语言实现. 它还证明了如果不去运行程序, 要保证不管多短的程序的正确性是多么困难.

我还在麦卡锡的论文中碰到一个问题. 在定义了eval之后, 他继续给出了一些更高级的函数--接受其它函数作为自变量的函数. 他定义了maplist:


(label maplist
       (lambda (x f)
         (cond ((null x) '())
               ('t (cons (f x) (maplist (cdr x) f))))))

然后用它写了一个做微分的简单函数diff. 但是diff传给maplist一个用x做参数的函数, 对它的引用被maplist中的参数x所捕获.6
这是关于动态可视域危险性的雄辩证据, 即使是最早的更高级函数的例子也因为它而出错. 可能麦卡锡在1960年还没有充分意识到动态可视域的含意. 动态可视域令人惊异地在Lisp实现中存在了相当长的时间--直到Sussman和Steele于 1975年开发了Scheme. 词法可视域没使eval的定义复杂多少, 却使编译器更难写了.

评分

参与人数 1可用积分 -5 收起 理由
flw -5 文不对题+发错版面。

查看全部评分

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
2 [报告]
发表于 2007-01-22 20:34 |只看该作者
比什么?比复制粘贴?
你复制过来一大堆 lisp 的文字,
一不注明出处(扣你的分),二和 Perl 版讨论的主题不符(再扣你的分),三你的 subject 是声称要和比试,结果却发了一大堆莫名其妙的东西(再扣你的分),莫非是说我不会复制?再或者你这段文字是用 emacs 打开的网页赋值到 BBS 上的?莫名其妙。

BTW:lisp 固然是好的,不过阁下如此浮躁,那么在 lisp 上的造诣未必有在下深。呵呵。
另外如果你想证明你的 emacs 很牛逼,那么你可以把 C/C++ 版那个 vim 帖子里 106 页回复中提出每个问题都用 emacs 解决一遍——那些我用 vim 都是可以搞定的。

论坛徽章:
0
3 [报告]
发表于 2007-01-22 20:57 |只看该作者
估计傻瓜才会那么做
Emacs的强大,作为Emacs的高手俺只能告诉你一句
linux不过是Emacs的寄主,基本没有什么在linux下Emacs无法做到的
因为你不会欣赏什么是美。

[ 本帖最后由 helbreathszw 于 2007-1-22 21:07 编辑 ]

评分

参与人数 1可用积分 -5 收起 理由
flw -5 文不对题

查看全部评分

论坛徽章:
0
4 [报告]
发表于 2007-01-22 21:01 |只看该作者
送你一篇文章,好好读一下,就知道为什么我看不惯你们的帮助新手的模式了
还有在国内的所谓的perl推广,perl给人的那种美感都被你们破坏殚精
因为你们不是在给他们展示perl,程序的美妙,而是在完成任务一样,
从你给新手的一问一答就明显看出来了。
可悲!
原文: http://www.paulgraham.com/taste.html
中文译者: 戴雨文
<版权信息结束>


--------------------------------------------------------------------------------

"哥白尼对天动说美学上的反对是他拒绝托勒密体系的重要原因..."
- Thomas Kuhn, The Copernican Revolution

"在Kelly Johnson的训练之下,我们狂热地坚信他的主张: 一架看上去很美的飞机飞得也会同样的美."
- Ben Rich, Skunk Works

"美是第一道检验: 世上没有永久的地方容纳丑陋的数学."
- G. H. Hardy, A Mathematician's Apology

我最近与一位在MIT任教的朋友聊天. 他的领域现在很热门,来自即将成为研究生的申请表每年都潮水般地涌向他. "他们中的大多数看上去都很聪明,"他说. "我不能确定的是他们是否有鉴赏力."

鉴赏力. 你现在不常听到这个词了. 不过我们仍然需要其中的概念,不管人们叫它什么. 我朋友的意思是,他希望学生不仅是好的技术人员, 而且会用他们的技术知识设计出美好的事物.

数学家称出色的工作是"美的", 就象不论是过去还是现在,科学家,工程师,音乐家,建筑师,设计师,作家和画家用"美"来形容作品一样. 他们使用同一个形容词,是一种巧合,还是他们所说的有某种含义上的重合? 如果有重合, 我们能否利用一个领域里关于美的发现,去找到另一个领域(的美)?

对于我们设计者来说,这些不仅是理论问题. 如果的确有叫做美的东西,我们必须能够认识它. 我们需要好的鉴赏力来做出好的事物. 与其视美为空洞的抽象物, 我们不如把它看成一个实际的问题: 你如何做出好的物品?

如果你现在提起鉴赏力, 许多人会告诉你"鉴赏力是主观的". 他们实际上是这样感觉的,所以他们这样认为. 当他们喜欢某样东西的时候,也不知道是为什么. 可能是因为它美,也可能是他们的妈妈有同样的东西,或者是在杂志上看到某个电影明星有同样的东西,或者他们知道这东西很昂贵. 他们的思维处于未经权衡的随心所欲的混乱状态.

大多数人从小就被鼓励让这种随心所欲处在未经权衡的状态下. 如果你取笑你的弟弟在图画书上把人的皮肤涂成绿色, 你妈妈可能会说"你喜欢你的方式,他喜欢他的方式"之类的话.

你妈妈这时并不是想教你重要的美学理论,她只不过想让你俩停止斗嘴.

就象成人告诉我们的许多半真半假的事一样, 这件事与他们说的其它的事矛盾. 再三地跟你说了"鉴赏力只不过是个人的喜好"之后, 他们带你去了博物馆, 并告诉你,你得用点心, 因为达芬奇是一个伟大的艺术家.

这时闪过孩子脑海里的是什么? 他会认为"伟大的艺术家"是什么意思呢? 经过多年的"每个人喜欢用他自己的方式做事"的灌输之后,他不太可能直接得出结论:所谓伟大的艺术家,就是他的作品要比别人的好. 在他托勒密式的宇宙观里,更可能的结论是:伟大的艺术家是对你有好处的,就象书上说椰菜对人的身体有好处一样.

说鉴赏力是个人喜好是避免争论的好办法. 问题是,它不是真的. 当你开始设计事物时,你会感觉到这点.

无论人们做什么工作,他们自然地想做得好些. 足球队员想赢得比赛, CEO想增加收入. 在工作中做得更好, 使人感到愉快和骄傲. 不过如果你的工作是设计,而且其中没有美这码事, 那么就没有办法把工作做得更好. 如果鉴赏力仅是个人喜好, 那每个人都是完美的: 你无论喜欢什么都行,不必多说了.

就象任何一项工作, 当你持续地设计物体,你会得到更好的效果. 你的鉴赏力会改变. 而且就象任何在工作中越做越好的人一样,你知道你也在进步. 如果是这样的话,你原来的鉴赏力不仅和现在不同,而且比现在的坏. 让鉴赏力不会有错的公理见鬼去吧.

现在盛行的相对主义可能会妨碍你对鉴赏力的思考,即使你自己的鉴赏力正在发展. 但是如果你面对现实并承认,至少对你而言,存在着好的设计和坏的设计, 然后你可以开始仔细研究好的设计. 你的鉴赏力是如何改变的? 当你犯错误的时候,想想什么使你犯这个错误? 其他人从设计中学到了什么?

你一旦开始思索这些问题, 就会惊讶地发现美的观念在多少不同的领域是相通的. 同样的完美设计的原则一遍又一遍地出现在人们的面前.

好的设计是简单的. 从数学到绘画,你都能听到它. 在数学里它意味着一个较短的证明往往较好. 特别是公理,越少越好. 在程序设计领域,也是同样的道理. 对建筑师和设计者来说,这意味着美应该依赖于一些精心选择的结构性的元素,而不是过多的表面装饰. (装饰本身并不坏,坏在被用来掩饰平淡的实体.) 类似地, 在绘画领域, 经过仔细观察和扎实临摹的静物画往往比一幅浮华但没头脑的画(比如带花边的衣领)更令人感兴趣. 在写作领域,它意味着简洁地说出你想说的.

当你被迫做得简单,说明你正在面对实际的问题. 如果你不能放弃装饰,你就得放弃本质.

好的设计是永恒的. 数学里的每个证明都是永久的,除非它有错误. 那哈代说 "世上没有永久的地方容纳丑陋的数学"是什么意思呢? 他的意思和Kelly Johnson的一样: 丑陋的东西不可能是最好的解决办法. 一定有更好的办法,最终有人会发现它.

以永恒为目标是发现最佳答案的一个方法: 如果你能想象到别人能超过你,你还是自己来吧. 一些最伟大的大师在这方面做得如此之好,几乎没给后来者留下多少空间. 丢勒之后的雕刻师不得不生活在他的阴影下.

奇怪的是, 如果你想做出吸引将来的人类的事物,一种方法是设法吸引过去的人类. 很难猜测将来会怎样, 但我们可以肯定, 将来会象过去一样,不会关心现在的时尚. 因此如果你能做出吸引当代的人和1500年的人的东西,极有可能它会吸引2500年的人类.

好的设计解决正确的问题. 典型的(烹饪用的)炉子有四个出火口,形成一个正方形,各有一个开关控制它们. 你如何安排这些开关? 最简单的答案是把它们排成一行. 但这是答非所问. 开关是给人用的,如果你把它们排成一行,不幸的厨师不得不每次都停下来思考一下哪个开关是控制哪个出火口的. 更好的办法是象出火口那样安排成一个正方形.

许多坏的设计是勤勉的,但是被误导了. 二十世纪中叶有一股使用无衬线(sans-serif)字体的风气. 这些字体的确更接近纯粹的基本的字形. 但这不是你在文本里要解决的问题. 字母能被容易地认出是更重要的事情. 虽然象是维多利亚时代的风格, 但Times Roman的小写字母g很容易与小写字母y区分.

问题可以解决也可以改进. 在软件领域, 一个难以对付的问题通常可以被一个等价的较易解决的问题代替. 物理学因为要解决的问题变为预测可观察事物的行为,而不是把它与经典著作调和起来,而发展得更快了.

好的设计是有启发性的. 简奥斯汀的小说几乎没有描写,不是告诉你每样事物是什么样子的, 她讲故事如此之好以至于你可以自己想象出场景. 类似地, 有启发的画通常比合盘托出的画更有吸引力. 每个看过蒙娜丽莎的人都有他自己的关于她的故事.

此原则在建筑或设计界的体现是,建筑物或物体应该让你自如地使用: 比如说一幢好的建筑物,能充当这样一个背景,让住在此处的人过任何他们想过的生活, 而不是生活起居就象在执行建筑师的程序.

在软件领域,它意味着你应该给用户一些基本的元素,它们可以象拼装玩具一样自由地组合. 在数学里,它意味着一个能成为许多新工作的基础的证明比一个因难但不能引出什么新发现的证明更可取. 在科学领域,一般来说,(被别人)引用的多少是自身价值的粗略指标.

好的设计常常有点滑稽. 这点并不总是正确. 但丢勒(Durer)的雕刻, 沙里宁(Saarinen)的womb char, pantheon, 以及最初的Porsche 911在我看来都有点儿滑稽. 哥德尔的不完全定理就象一个恶作剧.

我想这是因为幽默与力量有关吧. 有幽默感就有力量: 保持幽默感就是对不幸一笑了之, 而失去幽默感就会被它伤害. 因此力量的标志,或至少是特长,是不要把事情看得太严重. 自信会你显得对全过程采取一种轻松的态度. 就象希区柯克(Hitchcock)在他的电影中, 勃鲁盖尔(Brueghel)在他的绘画中,莎士比亚(Shakespeare)在他的戏剧中所表现的一样.

好的设计不必表现得滑稽,但很难想象没有幽默感的东西会是好的设计.

好的设计是困难的. 看一下有过伟大成就的人物,有一点是共同的:他们曾经努力地工作. 如果你不努力,可能你在浪费时间.

困难的问题需要巨大的努力. 困难的数学证明需要天才的解答,而且它往往是令人着迷的. 工程界也是这样.

你爬山的时候会把所有不必要的东西从背包里拿出来. 同样一个要在困难的地点,或只有很小的预算的条件下造房的建筑师,会发现他必须做出优雅的设计. 流行和浮华的东西只能被撇在一边了.

并不是所有的努力都是好的. 苦痛也有优劣之分. 你希望那种飞奔起来的痛,而不是站在钉子上的痛, 困难的问题可能对设计师有好处, 而刁难的顾客和不可靠的原料可没什么好处.

传统上美术领域的最高位置留给了人物画. 传统是有原因的,不是因为人物画在我们头脑里留下印象,而其它画种没有. 我们是如此善于观察人脸,迫使画脸的人不懈努力使我们感到满意. 如果你画树的时候把树枝画偏了五度,没人会发现. 如果你把人眼画偏了五度, 人人都会注意到.

当Bauhaus学派采纳Sullivan的"形式跟随功能"的时候,他们指的是,形式应该跟随功能. 而且如果功能足够困难, 形式也必须跟随,因为没有出错的余地. 野生动物是美丽的,因为它们有艰苦的生活.

好的设计看上去很容易. 就象优秀的运动员,伟大的设计者使人觉得设计很容易. 通常这是一种表象. 经过好几遍的修改, 才会有读起来朗朗上口的文章.

在科技界,一些最伟大的发现看上去是如此简单,你会对自己说,我也想得到. 发现者有资格回答这个问题: 哪你为什么没有(想到)呢?

达芬奇的一些头像画仅寥寥数笔. 你注视着这些画,心里暗想,你所要做的只是把这八九条线画到正确的位置,然后一幅杰作就产生了. 是的, 但你必须把它们画到恰好正确的位置. 一点儿偏差就会让整幅画失败.

线条画要求近乎完美,因此事实上它是最难的视觉媒体. 用数学的术语说,它是封闭的解. 不那么优秀的艺术家用逐渐逼近的方法解决同样的问题. 十岁左右的孩子放弃绘画的一个原因是,他们决心象大人一样画画,而且第一次就尝试画一张人脸. 当头一棒!

在许多领域,容易是和练习联系在一起的. 也许练习训练你用潜意识来完成得用意识来完成的任务. 在一些情况下, 你精确地训练你的身体. 专业钢琴家按键快于大脑传给手的信号. 经过一段时间训练的画家,可以把视觉感知从眼传到手, 尤如条件反射.

当说一个人"进入化境"时, 我认为他们是指脊髓控制了身体,脊髓少些犹豫, 而且解放了意识,让它思考更难的问题.

好的设计使用对称. 我认为对称可能只是取得简单性的途径之一,但它很重要,值得单独提出来. 自然界大量地应用它, 这是一个好迹象.

有两类对称: 重复和递归. 递归是指在亚层次上重复,就象树叶的脉络.

对称在一些领域里不流行了,作为对以前过多使用的反弹. 建筑师在维多利亚时代开始有意识地使用不对称, 到了1920年代,不对称成为现代主义建筑的明确前提. 但即使是这类建筑也只是在中轴线上不对称,还有许多小的地方是对称的.

在写作中各个层次上都有对称,从句子中的词组到小说的结构. 音乐和绘画也是如此. 由相同颗粒组成的马赛克画(和某些塞尚的画)有特别的视觉冲击力. 组合而成的对称产生了一些最难忘的作品: 亚当的诞生和美洲哥特式教堂.

在数学和工程里递归特别有用. 归纳法惊人地简洁. 能够用递归解决的软件问题几乎肯定是最好的解决办法. 埃菲尔铁塔引人注意的部分原因是它是递归的: 一个塔叠着一个塔.

对称,尤其是重复的危险在于,它可能会代替思考.

好的设计模仿自然. 与其说模仿自然有本质上的好处,还不如说大自然已经花了亿万年的时间探索问题的解决方案. 如果你的答案模仿了自然,那是个好迹象.

复制并不是作弊. 没人会否认故事应该象生活. 从生活中找到灵感也是绘画的法宝, 虽然它的任务经常被误解. 目标是不要简单地作个记录, 要点是它给你某些值得玩味的东西: 当你的目光注视着一个物体,你的手会做出更有趣的工作.

效法自然在工程领域也是起作用的. 船很久以来就有脊骨和加强筋,好象动物的胸腔. 在某些情况下我们不得不等待更好的技术出现: 早期的飞机设计者错误地把飞机设计成鸟的样子, 但是他们没有足够轻的材料或动力(莱特兄弟的引擎重152磅,却只有12马力的输出.),也没有精巧的导航系统使得机器象鸟一样飞翔. 不过我预测小型的能象鸟一样飞行的无人驾驶飞机会在五十年内出现.

既然有了强大的计算能力,我们不但可以模仿大自然的结果,也可以模拟大自然的方法. 基因算法能让我们创造出因为太复杂而在通常条件下设计不出的东西.

好的设计是再设计. 第一次就把事情做对的可能性是很小的. 专家料到会扔掉一些初期的作品,他们为计划的改变作了计划.

把作品扔掉需要自信. 你必须这样想,会有更多的成果出现. 举个例子,人们刚开始学画的时候,不情愿重画那些不好的地方. 他们觉得做到这步已经很幸运了,如果重做的话,可能会更糟. 于是他们说服自己这画还没有那么糟, 真的 -- 事实上,也许就该这么画.

(这样说服自己)真是危险; 为了培养一种不满足的精神而犯错会更好. 达芬奇的素描里,经常是五六次尝试才能画出一条线的准确位置. 与众不同的Porsche 911的背后,是笨拙的原型. Wright原先的Guggenheim的设计里, 右半部是个金字塔形的建筑(ziggurat),他把它倒转成现在的模样.

犯错是正常的. 不要把错误视为灾难, 而要把它们弄得容易证实和修复. 达芬奇或多或少发明了素描, 使得画画能够承受更多的负荷和探索. 开发源代码的软件错误少些,因为它承认犯错误的可能性.

如果介质能使改变变得容易, 是有帮助的. 油画颜料在十五世纪取代蛋彩的时候, 画家开始能够处理一些诸如人像画等困难的题材, 因为不象蛋彩,油画颜料可以混合和覆盖.

好的设计可以复制. 对复制的态度通常会走一条弯路. 新手还没有了解就开始模仿; 然后他有意识地试图原创; 最后,他认识到正确比原创更重要.

无知的模仿几乎就是坏设计的秘方. 如果你不知道你的想法从哪里来,你可能在模仿一个模仿者. 拉斐尔风格在十九世纪中期是如此流行,以至于每个学画的人都要模仿他, 甚至是模仿的模仿. 正是这种风气,而不是拉斐尔本人的作品,惹恼了拉斐尔前派艺术家.

有雄心的人不满足于模仿. 鉴赏力成长的第二阶段是有意识地以原创为目标.

我认为最伟大的大师们有一种忘我的精神. 他们一心想得到正确的答案,因此如果正确答案的某些部分已经被人发现了,那么没有理由不用它. 他们有足够的自信从别人那儿汲取养料,而不担心在此过程中失去自己的观念.

好的设计通常是奇特的.一些最杰出的作品有不可思议的品质: 欧拉公式, 勃鲁盖尔(Brueghel)的雪中猎人 ,SR-71, Lisp. 它们不仅是美的, 而且是奇异地美.

我不知道原因. 可能是我自己愚昧无知. 开罐器对狗来说一定也是不可思议的. 如果我足够聪明的话, 会觉得ei*pi = -1 是世界上最自然的事情. 不论如何,此公式肯定是真理.

我在本文里提到的大多数品质是可以培养的, 但我不认为奇异性可以培养. 你能做的最好的事情是有这个苗头的时候,不要去压制它. 爱因斯坦没有试图把相对论弄得奇特. 他试图找出真理, 而这真理显得很奇特.

唯一值得拥有的风格是你不能刻意追求的那种. 对奇异性来说, 尤其是这样. 没有捷径可走. 风格主义派(Mannerists), 浪漫派(Romantics)和两代美国高中生苦苦寻找的西北航路是不存在的. 到达它(奇异性)的唯一办法是经受好的(设计),然后从另一头出来.

好的设计成批出现.十五世纪佛罗伦萨的居民包括:布鲁内勒斯基(Brunelleschi), 吉尔伯提(Ghiberti), 多纳泰罗 (Donatello), 马萨其奥(Masaccio), 菲利波·利比(Filippo Lippi), 弗拉·安吉利科(Fra Angelico), 维洛及欧(Verrocchio), 波提切利(Botticelli), 达芬奇(Leonardo da Vinci), 和米开朗基罗 (Michelangelo). 米兰当时和佛罗伦萨一样大, 你能说出多少米兰艺术家?

十五世纪的佛罗伦萨发生了一些事情,而且它是不可遗传的, 因为现在不发生了. 你必须假定无论达芬奇和米开朗基罗有什么先天的因素,米兰人也应该有. 可以米兰的达芬奇呢?

美国现在的人口大约是十五世纪佛罗伦萨的一千倍. 一千个达芬奇和一千个米开朗基罗生活在我们中间. 如果仅由DNA支配一切, 我们天天会碰到艺术杰作. 我们没有, 原因是你要创造达芬奇, 不仅需要他天生的能力, 还要1450年的佛罗伦萨.

没有什么比一群有才能的人在相关问题上进行探索更强大的了. 比较起来, 基因无足轻重: 具有达芬奇的基因不足以补偿住得离米兰近而离佛罗伦萨远. 现代人迁移得更多了, 但伟大的作品仍然不成比例地来自几个热点地区: 鲍豪斯 (Bauhaus), 曼哈顿计划, 纽约客, 洛克希德的Skunk Works, 施乐的帕洛阿尔托研究中心(Xerox Parc).

在任何时候,只有有限的课题和有限的做出伟大工作的小组. 如果你离这些中心太远, 就几乎不可能有出色的工作. 你可以在某种程度上顺应或反对这种趋势, 但你不能脱离它.(也许你能, 但米兰的达芬奇没有成功.)

好的设计通常是大胆的.历史上的每个时期,人们都会相信一些荒谬的东西, 而且是如此坚定, 你得冒着被排斥甚至暴力的风险说出不同的意见.

如果我们的时代有不同的话,真是太好了. 就我目前的观察,还没有.

这个问题不仅折磨着每个时代,而且某种程度上折磨着每个领域. 许多文艺复兴时期的作品在那个时代长期被认为是可怕的:根据Vasari的说法,Botticelli忏悔并放弃了绘画,Fra Bartolommeo和Lorenzo di Credi actually居然烧掉了部分作品. 爱因斯坦的相对论令许多同时代的物理学家感到不快, 几十年来没有被完全接受, 在法国,直到1950年代.

今天的实验性的错误是明天的理论. 如果你想发现伟大的新事物, 不该对传统智慧和理论不太涉及到的地方视而不见, 而要特别地注意它们.

作为特例,我认为看见丑陋要比想象出美丽容易. 大多数创造出美丽事物的人是通过修改他们觉得丑陋的地方来达到目标的. 伟大的作品往往是这样产生的: 某人看到某物并想, 我可以做得比这好. 乔托(Giotto)看到传统的按公式刻画出来的圣母像让几个世纪的人们感到满意,但他却觉得看上去笨拙和不自然. 哥白尼为一个同时代人普遍接受的理论深深苦恼, 觉得一定有更好的解决办法.

不能忍受丑陋还不够. 在发展出知道哪儿需要修改的嗅觉之前, 你得对该领域非常理解. 你得埋头苦干. 你成为专家之后, 你会听到内心的声音: What a hack! 一定会有更好的办法. 不要忽略这种声音,培养它们. 伟大作品的秘决是: 非常准确的鉴赏力加上能使它满足的能力.

[ 本帖最后由 helbreathszw 于 2007-1-22 21:06 编辑 ]

评分

参与人数 1可用积分 -5 收起 理由
flw -5 恶意灌水

查看全部评分

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
5 [报告]
发表于 2007-01-23 11:51 |只看该作者
helbreathszw  建议你来当perl 版主....看能不能有不同的模式....

论坛徽章:
0
6 [报告]
发表于 2007-01-23 14:55 |只看该作者
原帖由 apile 于 2007-1-23 11:51 发表
helbreathszw  建议你来当perl 版主....看能不能有不同的模式....


赞!

论坛徽章:
0
7 [报告]
发表于 2007-01-23 15:44 |只看该作者
……你们干啥呢?

论坛徽章:
0
8 [报告]
发表于 2007-01-23 21:02 |只看该作者
哦,原来是有人要踢场子
EMAC与VI有什么好比的,特点不同。再说用个工具用得好与不好,值得一比么?
看到用一个手指或两个手的两根手指戳键盘的人,一般我会比较佩服的。

论坛徽章:
0
9 [报告]
发表于 2007-01-24 09:18 |只看该作者
"因为你们不是在给他们展示perl,程序的美妙,而是在完成任务一样,
从你给新手的一问一答就明显看出来了。"

楼主既然看不惯版主们的帮助新手的模式,为何不亲自给新手回答一百个问题,
也好把 perl 程序的美妙之处全部发扬出来?让俺们这些美学盲人开开眼。

顺便提一句,戴雨文的译文不怎么样,错误不止一处。错误就是丑。

原文也一样,象一堆柴火堆在那里。断章取义,不知道在表达什么意思。
如果用美学的观点来看,这种文章就是丑陋的代表。点上火烧了,还能体供点热量。

论坛徽章:
0
10 [报告]
发表于 2007-01-24 10:30 |只看该作者
楼主觉得你的行为是在美化Perl的环境么?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP