(本文为草稿,校对时间待定)
原文链接:https://norvig.com/luv-slides.ps
坏的声明:只是一个虚构的例子
(defun lookup (name)
(declare (type string name))
(if (null name)
nil
(or (gethash name *symbol-table*)
(make-symbol-entry name))))
应该为(declare (type (or string null) name))
在命名中保持一致:
like-this
,而非LikeThis
*special-variable*
+constant+
(或某种惯例)
structure.slot
-p
或?
; !
或 n
; ->
或 -to-
delete-file
integer-length
name-file
和 file-name
&optional
和 &key
;小心使用1或2个&optional
参数key
、test
、end
)明智地选择名字:
crntct
和processcontextdescr
就无法通过这个测试。previous
或final
而不是last
。大多数文本编辑器将第0列中的左圆括号作为顶级表达式的开始。除非你提供反斜杠,否则在第0列的字符串内的左圆括号可能会混淆编辑器:
(defun factorial (n)
"Compute the factorial of an integer.
\(don't worry about non-integer args)."
(if (= n 0) 1
(* n (factorial (- n 1)))))
许多文本编辑器将第0列中的(def
视为定义,但不会将其他列中的(def
视为定义。所以你可能需要这样做:
(progn
(defun foo ...)
(defun bar ...)
)
在多行字符串作为文字常量的情况下,例如:
(defun find-subject-line (message-header-string)
(search "
Subject:" message-header-string))
考虑使用读取时求值和对format
的调用:
(defun find-subject-line (message-header-string)
(search #.(format nil "~%Subject:") message-header-string))
当同一个字符串被多次使用时,考虑使用全局变量或已命名常量:
(defparameter *subject-marker* (format nil "~%Subject:"))
(defun find-subject-line (message-header-string)
(search *subject-marker* message-header-string))
对于较长的格式化字符串,你可以使用
或@
来缩进后续行。下面两种形式做同样的事情:
(format t "~&This is a long string.~@
This is more of that string.")
This is a long string.
This is more of that string.
(format t "~&This is a long string.~
~%This is more of that string.")
This is a long string.
This is more of that string.
后一种语法允许您轻松缩进固定数量:
(format t "~&This is a long string.~
~% This is more of that string, indented by one)
This is a long string.
This is more of that string, indented by one.
避免在字符串中使用#|
和|#
,因为这会在以后尝试去注释掉这样一个字符串时产生混淆。反斜杠再一次起到帮助:
好的:
(defun begin-comment () (write-string "#\|"))
(defun end-comment () (write-string "|\#"))
这意味着您可以稍后注释掉包含这些字符串的部分,而无需编辑字符串本身。
如果您的编辑器提供支持(注释区域和取消注释区域命令),那么最好使用显式的“;;”注释。这样读者就不会对哪些部分被注释掉了感到困惑。
以下情况是“危险信号”。它们通常是问题的症状,尽管从技术上讲,它们中的大多数确实发生在完全合法的情况下。如果你看到这些危险信号之一,你的代码并不一定有问题,但你仍然应该谨慎地进行:
eval
的使用gentemp
的使用 (没有已知的好用途)append
的使用setf
或调用了mentmacroexpand
的宏里缺失&environment
参数。error
类型编写状况处理器(包括对ignore-errors
的使用)。c...r
函数的使用,除了caar
、cad...r
以外。(这里的“…”全是d
)defvar
和defparameter
flet
和labels
#'(lambda ...)
,而不是 ``(lambda …)`#'f
只是(function f)
:test #'equal
对破坏性函数有以下原则:
nconc
的部分结果时),都会使用破坏性更新。坏的:
(defun combine-indep-lambdas (arc-exp)
(apply #'*
(mapcar #'eval-arc-exp (cdr arc-exp))))
apply
超出调用参数限制mapcar
产生垃圾cdr
违反数据抽象好的
:
(reduce #'* (in-arcs arc-exp) :key #'eval-arc-exp)
学会使用累加器:
(defun product (numbers &optional (key #'identity)
(accum 1))
"Like (reduce #'* numbers), but bails out early
when a zero is found."
(if (null numbers)
accum
(let ((term (funcall key (first numbers))))
(if (= term 0)
0
(product (rest numbers) key (* accum term))))))
考虑下:
(collect-fn 'number (constantly 1) #'* numbers)
花时间构建代码以使其能够在多任务处理下正常工作是合理的。
尽管还没有可移植的标准,但许多商业 Lisp 实现都具有此功能。它与现有的语言语义非常吻合。
setq
和属性列表。without-interrupts
、without-aborts
、without-preemption
等工具同步进程考虑真正的并行性,但如果事情突然变得并行化,请不要浪费大量时间来构建程序以使其正常运行。
将串行程序变成并行程序是一项不平凡的改变,它不会偶然发生(例如,由于 Common Lisp 语义的一些一夜之间的变化)。 需要一种全新的语言来支持这一点; 你会有时间做准备。
墨菲定律:“如果事情可能出错,那就一定会出错。”
不要因为你很确定某件事永远不会发生而忽略了对这件事情的检查。即便如此,也不要忽略它们。从系统中得到“这不可能发生”的错误是很常见的,很明显,人们并不总是像他们想象的那样聪明。
“你需要研究别人的作品。他们解决问题的方法以及他们使用的工具会让你以一种全新的方式看待自己的工作。” – Gary Kildall
“我从看别人的节目中学到了很多”-- Jonathan Sachs
“我仍然认为,对编程能力的测试之一就是给程序员30页左右的代码,看他能多快地通读和理解。” – Bill Gates
“准备(成为一名程序员)的最好方法是编写程序,并学习其他人编写的优秀程序。在我的例子中,我去了计算机科学中心的垃圾桶,捞出他们的操作系统清单。”-- Bill Gates
“你必须愿意阅读别人的代码,然后编写自己的代码,然后让其他人审查你的代码。” – Bill Gates
任务:使定义和使用表结构变得容易。
defstruct
一样分离用户代码和实现者代码,同时支持两者。
课程学习:
Lisp允许您轻松地开发原型。
“做好舍弃第一个原型的准备,你往往需要这种舍弃。” – Fred Brooks
“我在做任何事情之前都会考虑很多,一旦我做了一件事,我就不怕把它扔掉。程序员回头看一段代码,就像看一本书中糟糕的章节一样,然后毫不回头地把它删掉,这一点非常重要。” – John Warnock
“不要太早决定;千万不要过早地做决定。保持一个比你认为你需要的更普遍的数量级,因为你最终会长期需要它。让某些东西快速工作,然后能够将其丢弃。” – John Warnock
“所以我倾向于一次写几行然后试一试,让它工作,然后再写几行。我尝试在每次迭代中做最少的工作来进行真正的实质性更改。” – Wayne Ratliff
“1-2-3从一个可工作的程序开始,并在其整个发展过程中一直是一个可工作的程序。” – Jonathan Sachs
学会打字。如果你每分钟打不到60个字,你就在阻碍自己。
此外,当你在一个复杂的项目上努力工作时,练习是很重要的。缺乏体育锻炼使大多数程序员疲惫不堪。它会导致精神敏锐度的丧失。 – John Page
问:怎样才能成为一名优秀的程序员?
“怎样才能擅长任何事情?怎样才能成为一名优秀的作家?优秀的人是两个因素的结合:一种偶然的符合学科需要的心理,加上一种不愚蠢的心理能力。这是一种罕见的组合,但它一点也不神秘。一个好的程序员必须喜欢编程并对它感兴趣,所以他会努力学习更多。一名优秀的程序员还需要审美意识,外加负罪感,以及对何时违反这种审美意识的敏锐意识。负罪感迫使他更加努力地改进节目,使其更符合审美。” – Bob Frankston
介绍Common Lisp:
推荐和必备品:
更进一步:
期刊: