<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_Neil Chen's Blog</title><subtitle type="text"/><id>http://feed.cnblogs.com/blog/u/9493/rss</id><updated>2012-05-15T13:34:47Z</updated><author><name>木野狐(Neil Chen)</name><uri>http://www.cnblogs.com/RChen/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RChen/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/9493/rss"/><entry><id>http://www.cnblogs.com/RChen/archive/2012/05/15/2502287.html</id><title type="text">时隔3年，再做双倍超立方数的题目，这次用Lisp</title><summary type="text">09年的时候，有一阵子大家都在做网易的“有道难题”里面的双倍超立方数问题。我当时看到题目后也随手用 Python 做了一下，但当时那个解法是最笨的穷举法，所以除了练习了一次 Python 的基本语法之外，也没有什么特别的收获了。 最近又把 SICP 翻出来看到了流这一部分。在我发自内心的赞叹那些用流描述的数列在形式上是何等优美的同时，我想实际测量一下应用了这么多复杂的流的函数操作之后，程序的执行效率如何。而双倍超立方数正好是一个适合拿来练习的题目。 这次我用的开发环境是 DrRacket. 这个东西的前身其实叫做 DrScheme. 是 scheme 的一种开发环境，在 Windows 上..</summary><published>2012-05-15T13:32:00Z</published><updated>2012-05-15T13:32:00Z</updated><author><name>木野狐(Neil Chen)</name><uri>http://www.cnblogs.com/RChen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RChen/archive/2012/05/15/2502287.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RChen/archive/2012/05/15/2502287.html"/><content type="html">&lt;p&gt;09年的时候，有一阵子大家都在做网易的&amp;#8220;有道难题&amp;#8221;里面的双倍超立方数问题。我当时看到题目后也&lt;a href="http://www.cnblogs.com/RChen/archive/2009/06/04/1496121.html" target="_blank"&gt;随手用 Python 做了一下&lt;/a&gt;，但当时那个解法是最笨的穷举法，所以除了练习了一次 Python 的基本语法之外，也没有什么特别的收获了。&lt;/p&gt;  &lt;p&gt;最近又把 SICP 翻出来看到了流这一部分。在我发自内心的赞叹那些用流描述的数列在形式上是何等优美的同时，我想实际测量一下应用了这么多复杂的流的函数操作之后，程序的执行效率如何。而双倍超立方数正好是一个适合拿来练习的题目。&lt;/p&gt;  &lt;p&gt;这次我用的开发环境是 DrRacket. 这个东西的前身其实叫做 DrScheme. 是 scheme 的一种开发环境，在 Windows 上比较容易安装。而因为 SICP 是用 scheme 语言描述的，所以用这个环境来开发就是理所当然的事了。&lt;/p&gt;  &lt;p&gt;双倍超立方数的表述形式为：&lt;/p&gt;  &lt;p&gt;c = a^3 + b^3&lt;/p&gt;  &lt;p&gt;对给定的c，如果有且只有两组正整数(a, b)使上式成立，那么c就称为双倍超立方数。&lt;/p&gt;  &lt;p&gt;基于对称性，可以设 a &amp;lt;= b.&lt;/p&gt;  &lt;p&gt;下面我们来观察一下从 1^3 + 1^3 开始的两个自然数的立方和组成的数列是怎样的：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/RChen/201205/201205152131304106.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="double_cubic_1" border="0" alt="double_cubic_1" src="http://images.cnblogs.com/cnblogs_com/RChen/201205/201205152131327321.png" width="534" height="472" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;容易观察到，上述图中的 (a, b) 组合是没有重复的。也就是说，这代表了所有 (a, b) 的可能的组合情况。双倍超立方数题目的要求是，比如我们需要求出不超过n（比如100万）的所有双倍超立方数的个数。如果我们能够对上述流中的数字在仅进行一趟从小到大的遍历，在遍历过程中判断出其中哪些立方和出现了2次，则可以有效的减少遍历的次数，得到答案。因此问题的关键转化为如何有效的按立方和从小到大的次序遍历上述矩阵。&lt;/p&gt;  &lt;p&gt;可以看到，矩阵中横向、纵向、以及从左下到右上的每一条对角线方向上的数字的立方和都是单调递增的。但是很难直观的对整个矩阵找到这样一条单调递增的遍历路径。&lt;/p&gt;  &lt;p&gt;进一步观察计算结果，可以发现，沿对角线方向的数字序列，两两数字之间的间隔最小。可以把每一条对角线上的数字序列定义为一个流，然后所有对角线组成的流进行合并（merge）。合并的方式是，依次取每个流的头部元素互相比较大小，按从小到大的次序组合进结果流中。因为按对角线方向元素间隔相对来说最小，在流进行合并的时候，能够连续的从同一个流中获取多个连续的元素，那么在合并时需要不断切换从不同的流中获取下一个元素的情况应该就比较少一些，如果实现得当，代码的局部性 (locality) 也许会比较好，也许合并算法上也可以有进一步优化的可能。（当然这个只是我目前的推断，还没有证实）&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/RChen/201205/201205152131333318.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="double_cubic_2" border="0" alt="double_cubic_2" src="http://images.cnblogs.com/cnblogs_com/RChen/201205/201205152131356642.png" width="416" height="407" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;按照这个思路，整个问题解法的步骤如下：&lt;/p&gt;  &lt;p&gt;1. 得到一个按大小顺序排列的两个数立方和的流（通过多个对角线的数字流 merge 得到）    &lt;br /&gt;在合并的同时，对每个和数出现的次序进行 count. 同时在结果流里面保留每个和出现的次数；     &lt;br /&gt;2. 对步骤1得到的流，进行过滤操作 (stream-filter)，仅保留上述出现次数恰好为 2 的那些结果；     &lt;br /&gt;3. 对步骤2得到的流计算长度 (stream-length），结果就是 &amp;lt;= N 的双倍超立方数的个数。&lt;/p&gt;  &lt;p&gt;测试下来发现，N=100万的时候，执行速度还是非常快的，跟 Python 版解法的速度差不多。可以看到，利用流，以及作用于流的各种函数（filter, map, merge 等等操作）作为一种高级的数据结构抽象，可以从另一个角度理解问题。而因为流是惰性求值的，这个特性也使得运算的时间和空间开销等方面都处于一个可接受的范围。&lt;/p&gt;  &lt;p&gt;下面是我调试通过的代码。其中还有很大的优化空间，比如很简单的就可以对同一个数字反复求立方的操作进行记忆，避免重复运算的时间开销。&lt;/p&gt;  &lt;p&gt;代码的上半部分都是用来操作流的一些通用的帮助函数，有些是 SICP 书里的，另外有几个是我自己写的。双倍超立方数问题的相关实现可以直接看代码的后半部。&lt;/p&gt;  &lt;p&gt;执行这个代码可以正确的打印出100万以下双倍超立方数的数目：43.&lt;/p&gt;  &lt;p&gt;下面代码中关于流的一些辅助函数的解释，可以参考我上一篇随笔：&lt;a href="http://www.cnblogs.com/RChen/archive/2012/05/11/2495281.html" target="_blank"&gt;Racket, SICP stream learning&lt;/a&gt;&lt;/p&gt;  #lang racket&lt;br/&gt;;***********************************************&lt;br/&gt;; 双倍超立方数问题求解。&lt;br/&gt;; &lt;br/&gt;; 木野狐(Neil Chen)@博客园&lt;br/&gt;;&lt;br/&gt;; 开发环境：DrRacket v5.2.1&lt;br/&gt;; 2012-05-15&lt;br/&gt;;***********************************************&lt;br/&gt;&lt;br/&gt;;=========== 准备工作（流操作相关函数）开始 =====&lt;br/&gt;(define (stream-car stream) (car stream))&lt;br/&gt;&lt;br/&gt;(define (stream-cdr stream) (force (cdr stream)))&lt;br/&gt;&lt;br/&gt;(define-syntax cons-stream&lt;br/&gt;  (syntax-rules ()&lt;br/&gt;    [(cons-stream x y) (cons x (delay y))]))&lt;br/&gt;&lt;br/&gt;(define the-empty-stream '())&lt;br/&gt;&lt;br/&gt;(define (stream-null? stream)&lt;br/&gt;  (null? stream))&lt;br/&gt;&lt;br/&gt;(define (stream-filter pred stream)&lt;br/&gt;  (cond ((stream-null? stream) the-empty-stream)&lt;br/&gt;        ((pred (stream-car stream))&lt;br/&gt;         (cons-stream (stream-car stream)&lt;br/&gt;                      (stream-filter pred (stream-cdr stream))))&lt;br/&gt;        (else (stream-filter pred (stream-cdr stream)))))&lt;br/&gt;&lt;br/&gt;(define (stream-ref s n)&lt;br/&gt;  (if (stream-null? s) the-empty-stream&lt;br/&gt;      (if (= n 0)&lt;br/&gt;          (stream-car s)&lt;br/&gt;          (stream-ref (stream-cdr s) (- n 1)))))&lt;br/&gt;&lt;br/&gt;(define (stream-map proc . argstreams)&lt;br/&gt;  (if (stream-null? (car argstreams))&lt;br/&gt;      the-empty-stream&lt;br/&gt;      (cons-stream (apply proc (map stream-car argstreams))&lt;br/&gt;                   (apply stream-map &lt;br/&gt;                          (cons proc (map stream-cdr argstreams))))))&lt;br/&gt;&lt;br/&gt;(define (stream-enumerate-interval low high)&lt;br/&gt;  (if (&amp;gt; low high)&lt;br/&gt;      the-empty-stream&lt;br/&gt;      (cons-stream low&lt;br/&gt;                   (stream-enumerate-interval (+ low 1) high))))&lt;br/&gt;&lt;br/&gt;(define (enumerate-interval low high)&lt;br/&gt;  (if (&amp;gt; low high)&lt;br/&gt;      '()&lt;br/&gt;      (cons low&lt;br/&gt;            (enumerate-interval (+ low 1) high))))&lt;br/&gt;&lt;br/&gt;(define (stream-length stream)&lt;br/&gt;  (define (iter s acc)&lt;br/&gt;    (if (stream-null? s) acc&lt;br/&gt;        (iter (stream-cdr s) (+ 1 acc))))&lt;br/&gt;  (iter stream 0))&lt;br/&gt;;=========== 准备工作（流操作相关函数）结束 ======&lt;br/&gt;&lt;br/&gt;(define (integers-starting-from n)&lt;br/&gt;  (cons-stream n (integers-starting-from (+ n 1))))&lt;br/&gt;&lt;br/&gt;(define integers&lt;br/&gt;  (integers-starting-from 1))&lt;br/&gt;&lt;br/&gt;(define (cube n)&lt;br/&gt;  (* n n n))&lt;br/&gt;&lt;br/&gt;(define cube-numbers&lt;br/&gt;  (stream-map cube integers))&lt;br/&gt;&lt;br/&gt;(define (merge-with-count s1 s2)&lt;br/&gt;  (cond ((stream-null? s1) s2)&lt;br/&gt;        ((stream-null? s2) s1)&lt;br/&gt;        (else&lt;br/&gt;         (let ((s1car (stream-car s1))&lt;br/&gt;               (s2car (stream-car s2)))&lt;br/&gt;           (let ((e1 (if (list? s1car) (car s1car) s1car))&lt;br/&gt;                 (c1 (if (list? s1car) (cadr s1car) 1))&lt;br/&gt;                 (e2 (if (list? s2car) (car s2car) s2car))&lt;br/&gt;                 (c2 (if (list? s2car) (cadr s2car) 1)))                         &lt;br/&gt;             (cond ((&amp;lt; e1 e2) (cons-stream (list e1 c1) &lt;br/&gt;                                           (merge-with-count (stream-cdr s1) s2)))&lt;br/&gt;                   ((&amp;gt; e1 e2) (cons-stream (list e2 c2)&lt;br/&gt;                                           (merge-with-count s1 (stream-cdr s2))))&lt;br/&gt;                   (else (cons-stream (list e1 (+ c1 c2)) (merge-with-count (stream-cdr s1) (stream-cdr s2))))))))))&lt;br/&gt;&lt;br/&gt;(define (stream-merge-with-count . argstreams)&lt;br/&gt;  (if (= 0 (length argstreams))&lt;br/&gt;      the-empty-stream&lt;br/&gt;      (merge-with-count (car argstreams)&lt;br/&gt;                        (apply stream-merge-with-count (cdr argstreams)))))&lt;br/&gt;&lt;br/&gt;; 得到第 n 条对角线上的数字的流&lt;br/&gt;(define (diag n)&lt;br/&gt;  (stream-map (lambda (i)   &lt;br/&gt;                (+ (cube i)&lt;br/&gt;                   (cube n)))&lt;br/&gt;              (stream-enumerate-interval 1 n)))&lt;br/&gt;&lt;br/&gt;(define (new-double-cubic-numbers-below n)&lt;br/&gt;  (let ((max (floor (expt (- n 1) (/ 1 3)))))&lt;br/&gt;    (stream-map car&lt;br/&gt;                (stream-filter &lt;br/&gt;                 (lambda (s)&lt;br/&gt;                   (and (list? s)&lt;br/&gt;                        (= 2 (cadr s))&lt;br/&gt;                        (not (&amp;gt; (car s) n))))&lt;br/&gt;                 (apply stream-merge-with-count &lt;br/&gt;                        (map diag &lt;br/&gt;                             (enumerate-interval 1 max)))))))&lt;br/&gt;&lt;br/&gt;(stream-length (new-double-cubic-numbers-below 1000000))&lt;img src="http://www.cnblogs.com/RChen/aggbug/2502287.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/RChen/archive/2012/05/15/2502287.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/RChen/archive/2012/05/11/2495281.html</id><title type="text">Racket, SICP stream learning</title><summary type="text">在 windows 上重新安装了最新的 Racket 5.2.1. 恍然发现，Common-Lisp 的安装真的比较坑爹啊，Racket 可能才是研究和学习 lisp 比较理想的选择！ 不管是 Windows 还是 Ubuntu，自学习 Lisp 以来，Common Lisp 的各种实现 + 开发环境也安装了很多了，每一个配置起来都比较麻烦，也都有这样那样的问题。而相比而言，安装 Racket...</summary><published>2012-05-10T17:23:00Z</published><updated>2012-05-10T17:23:00Z</updated><author><name>木野狐(Neil Chen)</name><uri>http://www.cnblogs.com/RChen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RChen/archive/2012/05/11/2495281.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RChen/archive/2012/05/11/2495281.html"/><content type="html">&lt;p&gt;在 windows 上重新安装了最新的 Racket 5.2.1.&lt;/p&gt;  &lt;p&gt;恍然发现，Common-Lisp 的安装真的比较坑爹啊，Racket 可能才是研究和学习 lisp 比较理想的选择！&lt;/p&gt;  &lt;p&gt;不管是 Windows 还是 Ubuntu，自学习 Lisp 以来，Common Lisp 的各种实现 + 开发环境也安装了很多了，每一个配置起来都比较麻烦，也都有这样那样的问题。而相比而言，安装 Racket 却超级傻瓜化。&lt;/p&gt;  &lt;p&gt;一番周折后，终于调通了 SICP 220 页开始的对于 stream 的一些示例代码。其中需要注意的是：&lt;/p&gt;  &lt;p&gt;书中提到的 cons-stream 是一个 special form, 但是我一开始写成了简单的 function 如下：&lt;/p&gt;  ; this won't work as a simple function&lt;br/&gt;(define (cons-stream a b)&lt;br/&gt;    (cons a (delay b)))&lt;p&gt;但这个实际是是不 work 的。如果流比较大或者是无限流，几乎一定会导致无限递归、内存溢出。解决的办法参考了 stack overflow 上一个答案，利用 Racket 的 define-syntax 语法定义宏。其实和 Common Lisp 里宏有点接近，只是定义时使用的语法有差异，用到方括号，详见代码。&lt;/p&gt;&lt;p&gt;和 Common Lisp 中列表的 subseq 函数相似，我简单的实现了一个 stream-subseq 函数，用于截取流中某一区间的子序列，配合 display-stream 函数打印会比较方便的了解流中间任意一段的信息，后面的测试输出代码我基本都这么写了。&lt;/p&gt;&lt;p&gt;通过无限流移位后相加、相乘甚至配合其他运算进行任意组合，是流使用起来感觉最妙的地方。代码中包含了 SICP 原书中附带的一个筛法求素数序列的实现。&lt;/p&gt;&lt;p&gt;通过几个例子简单的试验下来发现，的确 stream 的功效是强大的。因为本质上每一步计算都是惰性求值，所以即使是要估算序列中很后面的数值，也不会像列表那样带来很多分配空间的开销。斐波那契数列可以轻而易举的算到很后面。下面是我调试通过的测试代码：&lt;/p&gt;#lang racket&lt;br/&gt;&lt;br/&gt;;(define (delay exp)&lt;br/&gt;;  (lambda () exp))&lt;br/&gt;;  ;(memo-proc (lambda ()&lt;br/&gt;;  ; exp)))&lt;br/&gt;;&lt;br/&gt;;(define (force delayed-object)&lt;br/&gt;;  (delayed-object))&lt;br/&gt;;&lt;br/&gt;;(define (memo-proc proc)&lt;br/&gt;;  (let ((already-run? false) (result false))&lt;br/&gt;;    (lambda ()&lt;br/&gt;;      (if (not already-run?)&lt;br/&gt;;          (begin (set! result (proc))&lt;br/&gt;;                 (set! already-run? true)&lt;br/&gt;;                 result)&lt;br/&gt;;          result))))&lt;br/&gt;&lt;br/&gt;(define (stream-car stream) (car stream))&lt;br/&gt;&lt;br/&gt;(define (stream-cdr stream) (force (cdr stream)))&lt;br/&gt;&lt;br/&gt;; this won't work as a simple function&lt;br/&gt;;(define (cons-stream a b)&lt;br/&gt;;  (cons a (delay b)))&lt;br/&gt;&lt;br/&gt;; This is scheme syntax for macro&lt;br/&gt;; http://stackoverflow.com/questions/5610480/scheme-sicp-r5rs-why-is-delay-not-a-special-form&lt;br/&gt;(define-syntax cons-stream&lt;br/&gt;  (syntax-rules ()&lt;br/&gt;    [(cons-stream x y) (cons x (delay y))]))&lt;br/&gt;&lt;br/&gt;(define the-empty-stream '())&lt;br/&gt;&lt;br/&gt;(define (stream-null? stream)&lt;br/&gt;  (null? stream))&lt;br/&gt;&lt;br/&gt;(define (stream-filter pred stream)&lt;br/&gt;  (cond ((stream-null? stream) the-empty-stream)&lt;br/&gt;        ((pred (stream-car stream))&lt;br/&gt;         (cons-stream (stream-car stream)&lt;br/&gt;                      (stream-filter pred (stream-cdr stream))))&lt;br/&gt;        (else (stream-filter pred (stream-cdr stream)))))&lt;br/&gt;&lt;br/&gt;(define (stream-ref s n)&lt;br/&gt;  (if (stream-null? s) the-empty-stream&lt;br/&gt;      (if (= n 0)&lt;br/&gt;          (stream-car s)&lt;br/&gt;          (stream-ref (stream-cdr s) (- n 1)))))&lt;br/&gt;&lt;br/&gt;(define (stream-map proc . argstreams)&lt;br/&gt;  (if (stream-null? (car argstreams))&lt;br/&gt;      the-empty-stream&lt;br/&gt;      (cons-stream (apply proc (map stream-car argstreams))&lt;br/&gt;                   (apply stream-map &lt;br/&gt;                          (cons proc (map stream-cdr argstreams))))))&lt;br/&gt;&lt;br/&gt;(define (stream-for-each proc s)&lt;br/&gt;  (if (stream-null? s)&lt;br/&gt;      'done&lt;br/&gt;      (begin (proc (stream-car s))&lt;br/&gt;             (stream-for-each proc (stream-cdr s)))))&lt;br/&gt;&lt;br/&gt;; Neil, 2012-05-10&lt;br/&gt;(define (stream-subseq stream a b)&lt;br/&gt;  (cond ((stream-null? stream) the-empty-stream)&lt;br/&gt;        ((= a b) the-empty-stream)&lt;br/&gt;        ((&amp;gt; a b) the-empty-stream)&lt;br/&gt;        (else (cons-stream (stream-ref stream a)&lt;br/&gt;              (stream-subseq stream (+ a 1) b)))))&lt;br/&gt;&lt;br/&gt;(define (display-line x)&lt;br/&gt;  (newline)&lt;br/&gt;  (display x))&lt;br/&gt;&lt;br/&gt;(define (display-stream s)&lt;br/&gt;  (stream-for-each display-line s))&lt;br/&gt;&lt;br/&gt;; examples&lt;br/&gt;;(let ((x (delay (+ 1 2))))&lt;br/&gt;;  (for ([i (in-range 1 10)])&lt;br/&gt;;            (display (force x))))&lt;br/&gt;;&lt;br/&gt;(define (integers-starting-from n)&lt;br/&gt;  (cons-stream n (integers-starting-from (+ n 1))))&lt;br/&gt;&lt;br/&gt;(define integers&lt;br/&gt;  (integers-starting-from 1))&lt;br/&gt;&lt;br/&gt;;(display-line (stream-ref integers 0))&lt;br/&gt;(let ((x (stream-subseq integers 10000 10010)))&lt;br/&gt;  (display-stream x))&lt;br/&gt;&lt;br/&gt;(define odd-numbers &lt;br/&gt;  (stream-filter odd? integers))&lt;br/&gt;&lt;br/&gt;(display-stream (stream-subseq odd-numbers 50 60))&lt;br/&gt;  &lt;br/&gt;;(let ((x (cons-stream 1 (cons-stream 2 '(3)))))&lt;br/&gt;;  (display-stream x))&lt;br/&gt;&lt;br/&gt;(define (stream-add s n)&lt;br/&gt;  (stream-map (lambda (x)&lt;br/&gt;                (+ x n)) s))&lt;br/&gt;&lt;br/&gt;(define (add-streams s1 s2)&lt;br/&gt;  (stream-map + s1 s2))&lt;br/&gt;&lt;br/&gt;(define fib&lt;br/&gt;  (cons-stream 1&lt;br/&gt;               (cons-stream 1&lt;br/&gt;                            (add-streams fib&lt;br/&gt;                                        (stream-cdr fib)))))&lt;br/&gt;&lt;br/&gt;(display-stream (stream-subseq fib 150 160))&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;(define (divisible? x y)&lt;br/&gt;  (= (remainder x y) 0))&lt;br/&gt;&lt;br/&gt;(divisible? 10 2)&lt;br/&gt;&lt;br/&gt;(define (sieve stream)&lt;br/&gt;  (cons-stream&lt;br/&gt;   (stream-car stream)&lt;br/&gt;   (sieve (stream-filter&lt;br/&gt;           (lambda (x)&lt;br/&gt;             (not (divisible? x (stream-car stream))))&lt;br/&gt;           (stream-cdr stream)))))&lt;br/&gt;&lt;br/&gt;(define primes&lt;br/&gt;  (sieve (integers-starting-from 2)))&lt;br/&gt;&lt;br/&gt;(display-stream (stream-subseq primes 1000 1010))&lt;p&gt;接下来打算认真体会一下书中提到的欧拉发明的序列加速器的算法。真的是很厉害的 idea.&lt;/p&gt;&lt;img src="http://www.cnblogs.com/RChen/aggbug/2495281.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/RChen/archive/2012/05/11/2495281.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/RChen/archive/2012/04/28/2475568.html</id><title type="text">Operation is not valid due to the current state of the object</title><summary type="text">在一个 asp.net webform 的程序 postback 时，碰到了这个异常，而且无法调试。Google 了一下，发现原因原来是 asp.net 对一个 form post 的字段数有限制，在打过最新的安全更新后，这个限制的数目是1000个，超过了就会报这个异常。解决的办法是在 web.config 里面加一个设置，增大这个限制值：&lt;appSettings&gt;&lt;addkey="aspnet:MaxHttpCollectionKeys"value="2001"/&gt;&lt;/appSettings&gt;而为什么会有这么多 fi</summary><published>2012-04-28T10:17:00Z</published><updated>2012-04-28T10:17:00Z</updated><author><name>木野狐(Neil Chen)</name><uri>http://www.cnblogs.com/RChen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RChen/archive/2012/04/28/2475568.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RChen/archive/2012/04/28/2475568.html"/><content type="html">&lt;p&gt;在一个 asp.net webform 的程序 postback 时，碰到了这个异常，而且无法调试。&lt;/p&gt;&lt;p&gt;Google 了一下，发现原因原来是 asp.net 对一个 form post 的字段数有限制，在打过最新的安全更新后，这个限制的数目是1000个，超过了就会报这个异常。&lt;/p&gt;&lt;p&gt;解决的办法是在 web.config 里面加一个设置，增大这个限制值：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;span style="color: #0000ff; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000; "&gt;appSettings&lt;/span&gt;&lt;span style="color: #0000ff; "&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;key&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="aspnet:MaxHttpCollectionKeys"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;value&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="2001"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;appSettings&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;而为什么会有这么多 field 被提交呢，我这个页面用了一个 Telerik 的 RadGrid，其中每一行都有一个 checkbox 进行多选提交，但记录数才100多条，远没到1000.&lt;/p&gt;&lt;p&gt;看来原因可能是 telerik Grid 生成的 html 里面，多生成了很多非必要的表单字段，用来维护一些状态信息之类的，导致表单提交的字段数膨胀了几乎10倍。如果改用轻量级的表格自己实现的话，优化的空间还是很大的。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;a href="http://stackoverflow.com/questions/8832470/operation-is-not-valid-due-to-the-current-state-of-the-object-error-during-pos"&gt;http://stackoverflow.com/questions/8832470/operation-is-not-valid-due-to-the-current-state-of-the-object-error-during-pos&lt;/a&gt;&amp;nbsp;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/RChen/aggbug/2475568.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/RChen/archive/2012/04/28/2475568.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/RChen/archive/2012/03/21/2409513.html</id><title type="text">lisp 笔记 - 闭包</title><summary type="text">一般语言由 primitives 组成, lisp 由 meta-primitives 组成。lisp 不定义 primitives. “Any time there is a primitive, there is a barrier, a non-orthogonality, in the design of the system.” let 用来创建 lexical scope. ...</summary><published>2012-03-21T03:25:00Z</published><updated>2012-03-21T03:25:00Z</updated><author><name>木野狐(Neil Chen)</name><uri>http://www.cnblogs.com/RChen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RChen/archive/2012/03/21/2409513.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RChen/archive/2012/03/21/2409513.html"/><content type="html">&lt;p&gt;一般语言由 primitives 组成, lisp 由 meta-primitives 组成。lisp 不定义 primitives. “Any time there is a primitive, there is a barrier, a non-orthogonality, in the design of the system.”&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;let 用来创建 lexical scope.&lt;/p&gt;  &lt;p&gt;lexical scope 的好处是这些绑定在编译后不需要为其实际分配任何内存 slot, 甚至一些显而易见的逻辑会被直接编译优化成简单的常量。&lt;/p&gt;  &lt;p&gt;lisp 中 dynamic scope 通过 defvar 创建，类似于全局变量。dynamic scope 的变量必须在 environment 中开辟实际内存区域（runtime). 因此性能可能稍微不如 lexical scope. dynamic scope 的变量在遇到同名的 lexical scope 变量时可能被 shadow. shadow 的过程实际是在进入 lexical scope 时在 dynamic scope 的那个 environment 中先备份原来的值，然后改写该值，在退出 scope 前再次从备份中恢复原来的值。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;let over lambda 是用来创建闭包的惯用法；&lt;/p&gt;  &lt;p&gt;闭包本质是 state + 1个 function.&lt;/p&gt;  &lt;p&gt;object 是 state + multiple functions.&lt;/p&gt;  &lt;p&gt;在 let over lambda 结构中用 values 返回多个引用了相同 bindings 的 lambdas，可以实现 class 和 object.&lt;/p&gt;  &lt;p&gt;let over lambda over let over lambda 可以实现 class variable (static variable).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;let + lambda 的各种组合用法可以实现大多数语言中的 OO 系统特性。该组合甚至可以实现更独特的一些应用场景。抛开继承，在大多数情况下一个 OO 系统是不必要的。OO 系统是基于 let 和 lambda 的一种特定实现。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/RChen/aggbug/2409513.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/RChen/archive/2012/03/21/2409513.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/RChen/archive/2011/12/31/2308299.html</id><title type="text">Common Lisp 在 Windows 上的开发环境比较</title><summary type="text">经过最近试验用 EMacs 玩 Lisp 后，发现在 Windows 上使用各种坑爹：快捷键不符合 Windows 正常操作习惯（当然也可以用插件模拟，不过麻烦）；点击菜单经常假死；切换 buffer 经常会假死；实在受不鸟了。重新切换回去用之前配置的 Eclipse + CUSP 插件，发现原来是没学会怎样使用——比如不知道怎样仅仅 Eval 一段选中的表达式。现在会了，重新用上了现代 IDE 各种爽。</summary><published>2011-12-30T17:05:00Z</published><updated>2011-12-30T17:05:00Z</updated><author><name>木野狐(Neil Chen)</name><uri>http://www.cnblogs.com/RChen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RChen/archive/2011/12/31/2308299.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RChen/archive/2011/12/31/2308299.html"/><content type="html">&lt;p&gt;经过最近试验用 EMacs 玩 Lisp 后，发现在 Windows 上使用各种坑爹：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;快捷键不符合 Windows 正常操作习惯（当然也可以用插件模拟，不过麻烦）；&lt;/p&gt;&lt;p&gt;点击菜单经常假死；&lt;/p&gt;&lt;p&gt;切换 buffer 经常会假死；&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;实在受不鸟了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;重新切换回去用之前配置的 Eclipse + CUSP 插件，发现原来是没学会怎样使用&amp;#8212;&amp;#8212;比如不知道怎样仅仅 Eval 一段选中的表达式。现在会了，重新用上了现代 IDE 各种爽。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/RChen/aggbug/2308299.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/RChen/archive/2011/12/31/2308299.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/RChen/archive/2011/12/29/2306016.html</id><title type="text">翻译英文技术文章是一件很可耻的事情吗？</title><summary type="text">不知从何时起，在博客园首页上我看到了越来越多的翻译文章，其特点是 —— 仅阅读标题或者 80% 甚至 90% 的正文，你无法判断这是一篇译文。而英文文章原作者的名字都被可耻的藏匿到了翻滚好几屏以后的最底端。作为一个老的博客园用户，我心生疑惑：难道翻译别人的文章是一件很可耻的事情吗？这么见不得人？ 根据我本人的学习成长经验，在翻译原文文章的过程中，当你逐字逐句体会一篇经典时，译者自身也能得到...</summary><published>2011-12-29T05:57:00Z</published><updated>2011-12-29T05:57:00Z</updated><author><name>木野狐(Neil Chen)</name><uri>http://www.cnblogs.com/RChen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RChen/archive/2011/12/29/2306016.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RChen/archive/2011/12/29/2306016.html"/><content type="html">&lt;p&gt;不知从何时起，在博客园首页上我看到了越来越多的翻译文章，其特点是 —— 仅阅读标题或者 80% 甚至 90% 的正文，你无法判断这是一篇译文。而英文文章原作者的名字都被可耻的藏匿到了翻滚好几屏以后的最底端。作为一个老的博客园用户，我心生疑惑：难道翻译别人的文章是一件很可耻的事情吗？这么见不得人？&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;根据我本人的学习成长经验，在翻译原文文章的过程中，当你逐字逐句体会一篇经典时，译者自身也能得到技术上更细致的体会和认识。这就和我们学习编程时，习惯照书敲一遍代码是一个道理。我想这应该也是大部分译者的目的吧？—— 在自己提高的同时，顺带造福别人。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;每个人学习技术都有一个成长阶段的。一般看的原文文章多了之后，渐渐的就只看原文的了，可能逐字逐句来翻译的时间也变少了，通过快速浏览原文就可以对某个技术获得认知。通过翻译文章来提高技术，也渐渐变成了一项奢侈的时间投资。当然，也有人会完全出于公益的目的，翻译很多文章或者书籍来造福初学者或英文不太好的同行。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;不管是哪种目的，出于对原文作者最起码的尊重，我真诚的建议：大家在翻译文章时应该在一开头就写明该文章是译文，原作者是谁，以及原文的链接。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;对翻译技术文章你有什么看法？欢迎讨论。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/RChen/aggbug/2306016.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/RChen/archive/2011/12/29/2306016.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/RChen/archive/2011/12/29/2305517.html</id><title type="text">写了个博客备份的 ruby 程序</title><summary type="text">现在网上账号随时都有被盗的危险，感觉不太放心，于是用 ruby 做了一个备份我在博客园的所有随笔的小程序，总共只用了110行代码，包括长段的注释，还是面向对象，结构良好的。 第一次写正经的 ruby 程序，发现抽象层次高的语言做事情就是省心省力啊，爽。</summary><published>2011-12-28T16:58:00Z</published><updated>2011-12-28T16:58:00Z</updated><author><name>木野狐(Neil Chen)</name><uri>http://www.cnblogs.com/RChen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RChen/archive/2011/12/29/2305517.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RChen/archive/2011/12/29/2305517.html"/><content type="html">&lt;p&gt;现在网上账号随时都有被盗的危险，感觉不太放心，于是用 ruby 做了一个备份我在博客园的所有随笔的小程序，总共只用了110行代码，包括长段的注释，还是面向对象，结构良好的。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;第一次写正经的 ruby 程序，发现抽象层次高的语言做事情就是省心省力啊，爽。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/RChen/aggbug/2305517.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/RChen/archive/2011/12/29/2305517.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/RChen/archive/2011/12/20/2294117.html</id><title type="text">体验 Clozure CL</title><summary type="text">Clozure CL 简称 CCL. 网站在 http://ccl.clozure.com/ 是一个高性能的开源 Common Lisp 实现，其特性包括 native 线程的支持等等。还包括一个 IDE，但好像只是 for Mac 的。windows 上估计跑不起来。不过不要紧，我也可以将它 setup 到 Emacs 中。 CCL 可以通过 svn 直接下载到本机的一个目录。然后打开 .e...</summary><published>2011-12-19T17:43:00Z</published><updated>2011-12-19T17:43:00Z</updated><author><name>木野狐(Neil Chen)</name><uri>http://www.cnblogs.com/RChen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RChen/archive/2011/12/20/2294117.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RChen/archive/2011/12/20/2294117.html"/><content type="html">&lt;p&gt;Clozure CL 简称 CCL. 网站在 &lt;a href="http://ccl.clozure.com/"&gt;http://ccl.clozure.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;是一个高性能的开源 Common Lisp 实现，其特性包括 native 线程的支持等等。还包括一个 IDE，但好像只是 for Mac 的。windows 上估计跑不起来。不过不要紧，我也可以将它 setup 到 Emacs 中。&lt;/p&gt;  &lt;p&gt;CCL 可以通过 svn 直接下载到本机的一个目录。然后打开 .emacs.d\init.el 文件，将原先 clisp 的配置注释掉，加入一行指向 CCL 的 exe 即可：&lt;/p&gt;  ;(setq inferior-lisp-program &amp;quot;clisp&amp;quot;)&lt;br/&gt;(setq inferior-lisp-program &amp;quot;e:/ccl/wx86cl.exe&amp;quot;)&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;接下来我简单的测试对比了一下 clisp 和 CCL 的性能。各进行1千万次简单的加法运算：&lt;/p&gt;&lt;p&gt;clisp:&lt;/p&gt;CL-USER&amp;gt; (time (loop for i from 1 to 10000000 do (+ 100 100)))&lt;br/&gt;Real time: 16.82791 sec.&lt;br/&gt;Run time: 16.8125 sec.&lt;br/&gt;Space: 4580 Bytes&lt;br/&gt;NIL&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;CCL:&lt;/p&gt;CL-USER&amp;gt; (time (loop for i from 1 to 10000000 do (+ 100 100)))&lt;br/&gt;(LOOP FOR I FROM 1 TO 10000000 DO (+ 100 100)) took 78 milliseconds (0.078 seconds) to run &lt;br/&gt;                    with 2 available CPU cores.&lt;br/&gt;During that period, 78 milliseconds (0.078 seconds) were spent in user mode&lt;br/&gt;                    0 milliseconds (0.000 seconds) were spent in system mode&lt;br/&gt; 32 bytes of memory allocated.&lt;br/&gt;NIL&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;天壤之别！CCL 还利用上了我电脑上的双核 CPU. 比较下来 clisp 的性能可以用垃圾来形容。而且，CCL 是支持多线程的，clisp 不支持。&lt;/p&gt;&lt;p&gt;虽然 clisp 性能差，不过，目前来说保留它的理由是可以用来运行 Portable Allegro Serve 的代码。而我粗略的试了一下在 CCL 下跑这个代码会报错。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/RChen/aggbug/2294117.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/RChen/archive/2011/12/20/2294117.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/RChen/archive/2011/12/15/2289330.html</id><title type="text">试用 Portable Allegro Serve</title><summary type="text">安装好 Common Lisp 的开发环境后，想试试看 web 开发。 虽然 Allegro Serve 运行起来更简单，但是要在 Allegro CL 中运行，而后者是个商业软件，暂时我没有购买的打算。退而求其次，只好用 Portable Allegro Serve. 这个开源代码貌似很久没更新了。下载后，运行出了很多小问题。简要记录如下： 用 CLisp 来运行的时候，可能下...</summary><published>2011-12-15T11:34:00Z</published><updated>2011-12-15T11:34:00Z</updated><author><name>木野狐(Neil Chen)</name><uri>http://www.cnblogs.com/RChen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RChen/archive/2011/12/15/2289330.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RChen/archive/2011/12/15/2289330.html"/><content type="html">&lt;p&gt;安装好 &lt;a href="http://www.cnblogs.com/RChen/archive/2011/12/14/2287439.html" target="_blank"&gt;Common Lisp 的开发环境&lt;/a&gt;后，想试试看 web 开发。&lt;/p&gt;  &lt;p&gt;虽然 Allegro Serve 运行起来更简单，但是要在 Allegro CL 中运行，而后者是个商业软件，暂时我没有购买的打算。退而求其次，只好用 Portable Allegro Serve.&lt;/p&gt;  &lt;p&gt;这个开源代码貌似很久没更新了。下载后，运行出了很多小问题。简要记录如下：&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;用 CLisp 来运行的时候，可能下载的 aserve 代码里包含的那些中间文件是由其他 lisp 实现生成的，也可能是 clisp 的早期版本，会报错误提示这些中间文件 out-dated 了。解决的办法很简单，只要将 aserve 代码的子孙目录中所有 .fas 和 .lib 文件全部删掉即可，可以写个简单的脚本来做这个 clean 的工作。删掉后，重新加载时会自动重新生成这些中间文件。这个非常类似于 Python 的 .pyc 文件。&lt;/li&gt;    &lt;li&gt;加载 install.lisp 的时候会报一个函数调用 ipaddr-to-dotted 找不到。这是因为代码里有个地方的调用少写了该函数所在包的前缀。解决办法是，打开 aserve\log.cl, 找到这个函数调用的地方，将函数写法替换为 acl-compat.socket:ipaddr-to-dotted 即可。&lt;/li&gt;    &lt;li&gt;执行 (start :port 8080) 启动服务器的时候，会报错如下：     &lt;br /&gt;&lt;/li&gt;    &lt;p&gt;&lt;font color="#ff0000"&gt;Evaluation aborted on #&amp;lt;SIMPLE-TYPE-ERROR #x1A2AAEF9&amp;gt;.       &lt;br /&gt;Lisp connection closed unexpectedly: connection broken by remote peer        &lt;br /&gt;&lt;/font&gt;      &lt;br /&gt;首先需要通过 Emacs 里打开 *inferior-lisp* buffer，然后重新加载这些代码来测试。得到一个更为详细的错误：&lt;/p&gt;    &lt;p&gt;&lt;font color="#ff0000"&gt;*** - FUNCALL: undefined function ACL-COMPAT.MP:MAKE-PROCESS&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;可以判断是因为 clisp 不支持多线程造成的问题。&lt;/p&gt;    &lt;p&gt;解决办法：启动 aserve 多提供一个参数如下：     &lt;br /&gt;      &lt;br /&gt;(start :port 8080 &lt;strong&gt;:listeners 0&lt;/strong&gt;)&lt;/p&gt; &lt;/ol&gt;&lt;img src="http://www.cnblogs.com/RChen/aggbug/2289330.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/RChen/archive/2011/12/15/2289330.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/RChen/archive/2011/12/14/2287439.html</id><title type="text">Windows XP, Emacs, CLisp, SLIME</title><summary type="text">LispBox 已经不再维护了，很多代码跑不起来，只好手工配置这套工具。 终于搞定了所有的安装配置，好麻烦。其中 clisp 最新的2.49版本配置了总是报错，只好用2.48版。其他都是当前最新的。 Emacs 23.3 CLisp 2.48 SLIME (CVS current snapshot) 安装的步骤如下。 首先下载 clisp 2.48 的 exe 版本，...</summary><published>2011-12-14T05:09:00Z</published><updated>2011-12-14T05:09:00Z</updated><author><name>木野狐(Neil Chen)</name><uri>http://www.cnblogs.com/RChen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RChen/archive/2011/12/14/2287439.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RChen/archive/2011/12/14/2287439.html"/><content type="html">&lt;p&gt;LispBox 已经不再维护了，很多代码跑不起来，只好手工配置这套工具。&lt;/p&gt;  &lt;p&gt;终于搞定了所有的安装配置，好麻烦。其中 clisp 最新的2.49版本配置了总是报错，只好用2.48版。其他都是当前最新的。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Emacs 23.3&lt;/p&gt;  &lt;p&gt;CLisp 2.48&lt;/p&gt;  &lt;p&gt;SLIME (CVS current snapshot)&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;安装的步骤如下。&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;首先下载 clisp 2.48 的 exe 版本，安装到 c:\clisp.&lt;/li&gt;    &lt;li&gt;打开 CLisp，查看当前 HOME 目录的位置。方法是输入 (user-homedir-pathname). 找到后，在其中建立一个空的文本文件命名为 .clisprc.lisp.     &lt;br /&gt;我机器上的目录如下：C:\Documents and Settings\[UserName]\.clisprc.lisp&lt;/li&gt;    &lt;li&gt;安装 Emacs. 直接将下载的 zip 包解压到一个目录就好。我是 c:\emacs.&lt;/li&gt;    &lt;li&gt;下载 SLIME 的 CVS 快照版本，解压到 c:\emacs\slime-2011-12-13&lt;/li&gt;    &lt;li&gt;打开 Emacs，确定当前的 HOME 目录。方法是输入 (insert (getenv “HOME”)) 命令后输入 C-c C-e 来执行，看输出。我机器上得到的结果是：     &lt;br /&gt;C:\Documents and Settings\[UserName]\Application Data&lt;/li&gt;    &lt;li&gt;建立一个文本文件到：     &lt;br /&gt;C:\Documents and Settings\[UserName]\Application Data\.emacs.d\init.el      &lt;br /&gt;输入内容如下并保存：      &lt;br /&gt;&lt;/li&gt;    ;;; Initialize slime.&lt;br/&gt;(setq inferior-lisp-program &amp;quot;clisp&amp;quot;)&lt;br/&gt;(add-to-list 'load-path &amp;quot;c:\\emacs\\slime-2011-12-13\\&amp;quot;)&lt;br/&gt;(require 'slime-autoloads)&lt;br/&gt;(eval-after-load &amp;quot;slime&amp;quot;&lt;br/&gt;  '(progn (slime-setup '(slime-fancy))))&lt;br/&gt;&lt;br/&gt;;;; Automatically use slime mode on .cl and .lisp files.&lt;br/&gt;(add-to-list 'auto-mode-alist '(&amp;quot;\\.cl$&amp;quot; . common-lisp-mode))&lt;br/&gt;(add-to-list 'auto-mode-alist '(&amp;quot;\\.lisp$&amp;quot; . common-lisp-mode))&lt;br/&gt;&lt;br/&gt;;;; Start slime.&lt;br/&gt;(slime)  &lt;li&gt;安装 &lt;a title="Quicklisp" href="http://www.quicklisp.org/"&gt;Quicklisp&lt;/a&gt;. 下载 quicklisp.lisp 后，打开 CLisp 控制台 load 该文件，然后执行之，按提示执行安装命令即可。&lt;/li&gt;  &lt;li&gt;修改配置文件 C:\Documents and Settings\[UserName]\.clisprc.lisp 如下：    &lt;br /&gt;&lt;/li&gt;  ;;; Play nice with shebangs&lt;br/&gt;(set-dispatch-macro-character #\# #\!&lt;br/&gt; (lambda (stream character n)&lt;br/&gt;  (declare (ignore character n))&lt;br/&gt;  (read-line stream nil nil t)&lt;br/&gt;  nil))&lt;br/&gt;&lt;br/&gt;;;; The following lines added by ql:add-to-init-file:&lt;br/&gt;#-quicklisp&lt;br/&gt;(let ((quicklisp-init (merge-pathnames &amp;quot;quicklisp/setup.lisp&amp;quot; (user-homedir-pathname))))&lt;br/&gt;  (when (probe-file quicklisp-init)&lt;br/&gt;    (load quicklisp-init)))  &lt;br /&gt;  &lt;br /&gt;&lt;/ol&gt;&lt;p&gt;安装过程完全参考的这里：&lt;a href="http://yellosoft.us/installing-common-lisp"&gt;http://yellosoft.us/installing-common-lisp&lt;/a&gt;&lt;/p&gt;&lt;p&gt;接下来可以大干一场了。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/RChen/aggbug/2287439.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/RChen/archive/2011/12/14/2287439.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
