﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-庄周梦蝶-随笔分类-计算机科学与基础</title><link>http://www.blogjava.net/killme2008/category/22252.html</link><description>生活、程序、未来</description><language>zh-cn</language><lastBuildDate>Mon, 26 Mar 2012 02:06:44 GMT</lastBuildDate><pubDate>Mon, 26 Mar 2012 02:06:44 GMT</pubDate><ttl>60</ttl><item><title>演示TCP慢启动和滑动窗口机制的动画</title><link>http://www.blogjava.net/killme2008/archive/2011/11/16/363913.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Tue, 15 Nov 2011 23:34:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2011/11/16/363913.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/363913.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2011/11/16/363913.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/363913.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/363913.html</trackback:ping><description><![CDATA[今天看到的一个演示TCP慢启动和滑动窗口机制的动画，很形象<br />
<a href="http://www.osischool.com" target="_blank">osischool.com</a><br />
<embed type="application/x-shockwave-flash" width="620" height="400" src="http://www.blogjava.net/Files/killme2008/tcp_slow_start.zip"></embed><img src ="http://www.blogjava.net/killme2008/aggbug/363913.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2011-11-16 07:34 <a href="http://www.blogjava.net/killme2008/archive/2011/11/16/363913.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>高性能EL——Fel探秘，兼谈EL</title><link>http://www.blogjava.net/killme2008/archive/2011/09/17/358863.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sat, 17 Sep 2011 04:52:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2011/09/17/358863.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/358863.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2011/09/17/358863.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/358863.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/358863.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; Fel是最近javaeye比较火的关键词，这是由网友<a href="http://lotusyu.iteye.com/">lotusyu</a>开发的一个高性能的EL，从作者给出的数据来看，性能非常优异，跟前段时间温少开源的<a href="http://www.iteye.com/topic/993292">Simple EL</a>有的一拼。首先要说，这是个好现象，国内的开源项目越来越多，可以看出开发者的水平是越来越高了，比如我最近还看到有人开源的类似kestel的轻量级MQ&#8212;&#8212;<a href="http://code.google.com/p/fqueue/">fqueue</a>也非常不错，有兴趣可以看下我的分析《<a href="../archive/2011/09/16/358827.html">fqueue初步分析</a>》。<br />
<br />


<p>&nbsp;&nbsp;&nbsp; 进入正文，本文是尝试分析下Fel的实现原理，以及优缺点和<a href="http://code.google.com/p/aviator/">aviator</a>&#8212;&#8212;我自己开源的EL之间的简单比较。</p>


<p>&nbsp; &nbsp; Fel的实现原理跟Simple 
EL是类似，都是使用template生成中间代码&#8212;&#8212;也就是普通的java代码，然后利用javac编译成class，最后运行，当然，这个过程都是动
态的。JDK6已经引入了编译API，在此之前的版本可以调用sun的类来编译，因为javac其实就是用java实现的。回到Fel里
面，FelCompiler15就是用 <em><strong>com.sun.tools.javac.Main</strong></em>来编译，而FelCompiler16用标准的<a href="http://download.oracle.com/javase/6/docs/api/javax/tools/JavaCompiler.html">javax.tools.JavaCompiler</a>来编译的。</p>


<p> &nbsp; &nbsp; 文法和语法解释这块是使用antlr这个parse generator生成的，这块不多说，有兴趣可以看下antlr，整体一个运行的过程是这样：</p>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;expression&nbsp;string&nbsp;</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">&nbsp;antlr&nbsp;</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">&nbsp;AST&nbsp;</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">&nbsp;comiple&nbsp;</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">&nbsp;java&nbsp;source&nbsp;template&nbsp;</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">&nbsp;java&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">&nbsp;Expression&nbsp; <br />
</span></div>

<p>&nbsp;&nbsp;&nbsp; 这个思路我在实现<a href="http://code.google.com/p/aviator/">aviator</a>之前就想过，但是后来考虑到API需要用的sun独有的类，而且要求classpath必须有tools.jar这个依赖包，就放弃了这个思路，还是采用ASM生成字节码的方式。题外，velocity的优化可以采用这个思路，我们有这么一个项目是这么做的，也准备开源了。</p>

<p>&nbsp;</p>

<p>&nbsp;&nbsp;&nbsp; 看看Fel生成的中间代码，例如a+b这样的一个简单的表达式，假设我一开始不知道a和b的类型，编译是这样：</p>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;FelEngine&nbsp;fel&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;FelEngineImpl();&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;Expression&nbsp;exp&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000;">&nbsp; </span><span style="color: #000000; ">fel.compile(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">a+b</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">);&nbsp; <br /></span></div>
<p> </p>

<p>&nbsp;&nbsp;&nbsp; 我稍微改了下FEL的源码，让它打印中间生成的java代码，a+b生成的中间结果为：</p>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">package</span><span style="color: #000000; ">&nbsp;com.greenpineyu.fel.compile;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;com.greenpineyu.fel.common.NumberUtil;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;com.greenpineyu.fel.Expression;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;com.greenpineyu.fel.context.FelContext;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;org.apache.commons.lang.ObjectUtils;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;org.apache.commons.lang.StringUtils;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Fel_0&nbsp;&nbsp;</span><span style="color: #0000FF; ">implements</span><span style="color: #000000; ">&nbsp;Expression{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;Object&nbsp;eval(FelContext&nbsp;context)&nbsp;{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java.lang.Object&nbsp;var_1&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(java.lang.Object)context.get(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">b</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">b&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java.lang.Object&nbsp;var_0&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(java.lang.Object)context.get(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">a</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">a&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;(ObjectUtils.toString(var_0))</span><span style="color: #000000; ">+</span><span style="color: #000000; ">(ObjectUtils.toString(var_1));&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp; <br />
</span></div>

<p>&nbsp;&nbsp;&nbsp;&nbsp; 可见，FEL对表达式解析和解释后，利用template生成这么一个普通的java类，而a和b都从context中获取并转化为<strong>Object</strong>类型，这里没有做任何判断就直接认为a和b是要做字符串相加，然后拼接字符串并返回。</p>

<p>&nbsp;</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp; 问题出来了，因为没有在编译的时候传入context（我们这里是null），FEL会将a和b的类型默认都为java.lang.Object，a+b解释为字符串拼接。但是运行的时候，我完全可以传入a和b都为数字，那么结果就非常诡异了：</p>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FelEngine&nbsp;fel&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;FelEngineImpl();&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;Expression&nbsp;exp&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;fel.compile(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">a+b</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;Map</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">String,&nbsp;Object</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;env</span><span style="color: #000000; ">=</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;HashMap</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">String,&nbsp;Object</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">();&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;env.put(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">a</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;env.put(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">b</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">3.14</span><span style="color: #000000; ">);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(exp.eval(</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;MapContext(env)));&nbsp; <br />
</span></div>

<p>输出：</p>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">13.14</span><span style="color: #000000; ">&nbsp; <br />
</span></div>


<p>&nbsp;&nbsp;&nbsp; 1+3.14的结果，作为字符串拼接就是13.14，而不是我们想要的4.14。如果将表达式换成a*b，就完全运行不了</p>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;com.greenpineyu.fel.exception.CompileException:&nbsp;</span><span style="color: #0000FF; ">package</span><span style="color: #000000; ">&nbsp;com.greenpineyu.fel.compile;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;com.greenpineyu.fel.common.NumberUtil;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;com.greenpineyu.fel.Expression;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;com.greenpineyu.fel.context.FelContext;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;org.apache.commons.lang.ObjectUtils;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;org.apache.commons.lang.StringUtils;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Fel_0&nbsp;&nbsp;</span><span style="color: #0000FF; ">implements</span><span style="color: #000000; ">&nbsp;Expression{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;Object&nbsp;eval(FelContext&nbsp;context)&nbsp;{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java.lang.Object&nbsp;var_1&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(java.lang.Object)context.get(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">b</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">b&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java.lang.Object&nbsp;var_0&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(java.lang.Object)context.get(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">a</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">a&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;(var_0)</span><span style="color: #000000; ">*</span><span style="color: #000000; ">(var_1);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;[Fel_0.java:</span><span style="color: #000000; ">14</span><span style="color: #000000; ">:&nbsp;运算符&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;不能应用于&nbsp;java.lang.Object,java.lang.Object]&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;com.greenpineyu.fel.compile.FelCompiler16.compileToClass(FelCompiler16.java:</span><span style="color: #000000; ">113</span><span style="color: #000000; ">)&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;com.greenpineyu.fel.compile.FelCompiler16.compile(FelCompiler16.java:</span><span style="color: #000000; ">87</span><span style="color: #000000; ">)&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;com.greenpineyu.fel.compile.CompileService.compile(CompileService.java:</span><span style="color: #000000; ">66</span><span style="color: #000000; ">)&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;com.greenpineyu.fel.FelEngineImpl.compile(FelEngineImpl.java:</span><span style="color: #000000; ">62</span><span style="color: #000000; ">)&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;TEst.main(TEst.java:</span><span style="color: #000000; ">14</span><span style="color: #000000; ">)&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;Exception&nbsp;in&nbsp;thread&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">main</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;java.lang.NullPointerException&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;TEst.main(TEst.java:</span><span style="color: #000000; ">18</span><span style="color: #000000; ">)&nbsp; <br />
</span></div>
<p>&nbsp;</p>

<p>&nbsp;&nbsp;&nbsp; 这个问题对于Simple EL同样存在，如果没有在编译的时候能确定变量类型，这无法生成正确的中间代码，导致运行时出错，并且有可能造成非常诡异的bug。</p>

<p>&nbsp;</p>

<p>&nbsp;&nbsp;&nbsp; 这个问题的本质是<strong>因为Fel和Simple EL没有自己的类型系统，他们都是直接使用java的类型的系统，并且必须在编译的时候确定变量类型，才能生成高效和正确的代码，我们可以将它们称为&#8220;强类型的EL&#8220;。</strong></p>

<p>&nbsp;</p>


<p>&nbsp;&nbsp;&nbsp; 现在让我们在编译的时候给a和b加上类型，看看生成的中间代码：</p>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;FelEngine&nbsp;fel&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;FelEngineImpl();&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;fel.getContext().set(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">a</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;fel.getContext().set(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">b</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">3.14</span><span style="color: #000000; ">);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;Expression&nbsp;exp&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;fel.compile(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">a+b</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;Map</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">String,&nbsp;Object</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;env&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;HashMap</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">String,&nbsp;Object</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">();&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;env.put(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">a</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;env.put(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">b</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">3.14</span><span style="color: #000000; ">);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(exp.eval(</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;MapContext(env)));&nbsp; <br />
</span></div>
<p>&nbsp;&nbsp;&nbsp; 查看中间代码：</p>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">package</span><span style="color: #000000; ">&nbsp;com.greenpineyu.fel.compile;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;com.greenpineyu.fel.common.NumberUtil;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;com.greenpineyu.fel.Expression;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;com.greenpineyu.fel.context.FelContext;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;org.apache.commons.lang.ObjectUtils;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;org.apache.commons.lang.StringUtils;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Fel_0&nbsp;&nbsp;</span><span style="color: #0000FF; ">implements</span><span style="color: #000000; ">&nbsp;Expression{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;Object&nbsp;eval(FelContext&nbsp;context)&nbsp;{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">&nbsp;var_1&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;((java.lang.Number)context.get(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">b</span><span style="color: #000000; ">"</span><span style="color: #000000; ">)).doubleValue();&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">b&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">&nbsp;var_0&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;((java.lang.Number)context.get(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">a</span><span style="color: #000000; ">"</span><span style="color: #000000; ">)).doubleValue();&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">a&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;(var_0)</span><span style="color: #000000; ">+</span><span style="color: #000000; ">(var_1);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp; <br />
</span></div>

<p>可以看到这次将a和b都强制转为double类型了，做数值相加，结果也正确了：</p>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">4.140000000000001</span><span style="color: #000000; ">&nbsp; <br />
</span></div>
<p> </p>

<p>&nbsp;&nbsp;&nbsp; Simple EL我没看过代码，这里猜测它的实现也应该是类似的，也应该有同样的问题。</p>


<p>&nbsp;&nbsp;&nbsp; 相比来说，<a href="http://code.google.com/p/aviator/">aviator</a>这是<strong>一个弱类型的EL</strong>，<strong>在编译的时候不对变量类型做任何假设，而是在运行时做类型判断和自动转化</strong>。过去提过，我给aviator的定位是一个介于EL和script之间的东西，<strong>它有自己的类型系统</strong>。
例如，3这个数字，在java里可能是long,int,short,byte，而aviator统一为AviatorLong这个类型。为了在这两个类
型之间做适配，就需要做很多的判断和box,unbox操作。这些判断和转化都是运行时进行的，因此aviator没有办法做到Fel这样的高效，但是已
经做到至少跟groovy这样的弱类型脚本语言一个级别，也超过了JXEL这样的纯解释EL，具体可以看这个<a href="http://code.google.com/p/aviator/wiki/Performance">性能测试</a>。</p>

<p>&nbsp;</p>

<p>&nbsp;&nbsp; 强类型还是弱类型，这是一个选择问题，如果你能在运行前就确定变量的类型，那么使用Fel应该可以达到或者接近于原生java执行的效率，但是失去了灵活性；如果你无法确定变量类型，则只能采用弱类型的EL。</p>

<p>&nbsp;</p>

<p>&nbsp;&nbsp; 
EL涌现的越来越多，这个现象有点类似消息中间件领域，越来越多面向特定领域的轻量级MQ的出现，而不是原来那种大而笨重的通用MQ大行其道，一方面是互
联网应用的发展，需求不是通用系统能够满足的，另一方面我认为也是开发者素质的提高，大家都能造适合自己的轮子。从EL这方面来说，我也认为会有越来越多
特定于领域的，优点和缺点一样鲜明的EL出现，它们包含设计者自己的目标和口味，选择很多，就看取舍。</p><img src ="http://www.blogjava.net/killme2008/aggbug/358863.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2011-09-17 12:52 <a href="http://www.blogjava.net/killme2008/archive/2011/09/17/358863.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Scheme interpreter in clojure</title><link>http://www.blogjava.net/killme2008/archive/2011/01/24/343423.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 24 Jan 2011 02:42:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2011/01/24/343423.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/343423.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2011/01/24/343423.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/343423.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/343423.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 昨天晚上用clojure搞了个scheme解释器，基本上是sicp里的解释器的clojure翻译版本，可能唯一值的一提的是对transient集合的使用，实现副作用的set!。总共代码包含注释才366行，支持的feature包括<br />
<br />
<table class="wiki-content-table" border="2" bordercolor="" cellpadding="" cellspacing="">
    <tbody>
        <tr>
            <th>Feature</th>
            <th>Supported</th>
            <th>Comment</th>
        </tr>
        <tr>
            <td>define</td>
            <td>yes</td>
            <td><br />
            </td>
        </tr>
        <tr>
            <td>lambda</td>
            <td>yes</td>
            <td><br />
            </td>
        </tr>
        <tr>
            <td>variable lookup</td>
            <td>yes</td>
            <td><br />
            </td>
        </tr>
        <tr>
            <td>primitive procedure evaluation</td>
            <td>yes</td>
            <td><br />
            </td>
        </tr>
        <tr>
            <td>compound procedure evaluation</td>
            <td>yes</td>
            <td>no tail recursion yet</td>
        </tr>
        <tr>
            <td>if</td>
            <td>yes</td>
            <td><br />
            </td>
        </tr>
        <tr>
            <td>cond</td>
            <td>yes</td>
            <td><br />
            </td>
        </tr>
        <tr>
            <td>let</td>
            <td>yes<br />
            </td>
            <td><br />
            </td>
        </tr>
        <tr>
            <td>let*</td>
            <td>yes<br />
            </td>
            <td>no named let* yet<br />
            </td>
        </tr>
        <tr>
            <td>letrec</td>
            <td>no</td>
            <td><br />
            </td>
        </tr>
        <tr>
            <td>begin</td>
            <td>yes<br />
            </td>
            <td><br />
            </td>
        </tr>
        <tr>
            <td>set!</td>
            <td>yes<br />
            </td>
            <td><br />
            </td>
        </tr>
        <tr>
            <td>quote</td>
            <td>yes</td>
            <td><br />
            </td>
        </tr>
        <tr>
            <td>quasiquote</td>
            <td>no</td>
            <td><br />
            </td>
        </tr>
        <tr>
            <td>unquote</td>
            <td>no</td>
            <td><br />
            </td>
        </tr>
        <tr>
            <td>delay</td>
            <td>no</td>
            <td><br />
            </td>
        </tr>
        <tr>
            <td>define-syntax</td>
            <td>no</td>
            <td><br />
            </td>
        </tr>
    </tbody>
</table>
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 支持的primitive procedure包括常见的四则运算、car/cdr、list以及display、newline等。代码放在了github上：<a href="https://github.com/killme2008/cscheme">https://github.com/killme2008/cscheme</a>,有兴趣的可以玩玩吧。<br /><img src ="http://www.blogjava.net/killme2008/aggbug/343423.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2011-01-24 10:42 <a href="http://www.blogjava.net/killme2008/archive/2011/01/24/343423.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一道面试题注记</title><link>http://www.blogjava.net/killme2008/archive/2010/10/28/336357.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 28 Oct 2010 02:53:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2010/10/28/336357.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/336357.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2010/10/28/336357.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/336357.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/336357.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; javaeye的一个帖子介绍一道<a href="http://www.javaeye.com/topic/795101">面试题</a>，取数组的最大元素和前n个大元素，取最大元素很简单，遍历即可。取前N大元素，可以利用排序，最简单的实现：<br />
<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;findTopNValues(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;anyOldOrderValues,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;n)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Arrays.sort(anyOldOrderValues);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;result&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[n];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.arraycopy(anyOldOrderValues,&nbsp;anyOldOrderValues.length&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;n,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result,&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">,&nbsp;n);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;result;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span></div>
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; Arrays.sort(int[])使用的是快排，平均的时间复杂度是O( n lg(n))，在一般情况下已经足够好。那么有没有平均情况下O(n)复杂度的算法？这个还是有的，这道题目其实是选择算法的变形，选择一个数组中的第n大元素，可以采用类似快排的方式划分数组，然后只要在一个子段做递归查找就可以，平均状况下可以做到O(n)的时间复杂度，对于这道题来说稍微变形下算法即可解决：<span style="color: #000000;"><br />
<br />
</span>
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;求数组的前n个元素<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;anyOldOrderValues<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;n<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@return</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;findTopNValues(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;anyOldOrderValues,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;n)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;result&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[n];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;findTopNValues(anyOldOrderValues,&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">,&nbsp;anyOldOrderValues.length&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">,&nbsp;n,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n,&nbsp;result);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;result;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;findTopNValues(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;a,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;p,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;r,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;n,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;result)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;全部取到，直接返回</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(i&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;只剩一个元素，拷贝到目标数组</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(p&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;r)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.arraycopy(a,&nbsp;p,&nbsp;result,&nbsp;n&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;i,&nbsp;i);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;len&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;r&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;p&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(i&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;len&nbsp;</span><span style="color: #000000;">||</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;IllegalArgumentException();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;if&nbsp;(len&nbsp;&lt;&nbsp;7)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Arrays.sort(a,&nbsp;p,&nbsp;r+1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;System.arraycopy(a,&nbsp;r&nbsp;-&nbsp;i+1&nbsp;,&nbsp;result,&nbsp;n&nbsp;-&nbsp;i,&nbsp;i);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;return;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;划分</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;q&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;medPartition(a,&nbsp;p,&nbsp;r);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;计算右子段长度</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;k&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;r&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;q&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;右子段长度恰好等于i</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(i&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;k)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;拷贝右子段到结果数组，返回</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.arraycopy(a,&nbsp;q,&nbsp;result,&nbsp;n&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;i,&nbsp;i);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(k&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;i)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;右子段比i长，递归到右子段求前i个元素</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;findTopNValues(a,&nbsp;q&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">,&nbsp;r,&nbsp;i,&nbsp;n,&nbsp;result);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;右子段比i短，拷贝右子段到结果数组，递归左子段求前i-k个元素</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.arraycopy(a,&nbsp;q,&nbsp;result,&nbsp;n&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;i,&nbsp;k);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;findTopNValues(a,&nbsp;p,&nbsp;q&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">,&nbsp;i&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;k,&nbsp;n,&nbsp;result);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;medPartition(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;x[],&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;p,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;r)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;len&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;r&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;p&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;m&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;p&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;(len&nbsp;</span><span style="color: #000000;">&gt;&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(len&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">7</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;l&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;p;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;n&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;r;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(len&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">40</span><span style="color: #000000;">)&nbsp;{&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Big&nbsp;arrays,&nbsp;pseudomedian&nbsp;of&nbsp;9</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;s&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;len&nbsp;</span><span style="color: #000000;">/</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">8</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;med3(x,&nbsp;l,&nbsp;l&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;s,&nbsp;l&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;s);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;med3(x,&nbsp;m&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;s,&nbsp;m,&nbsp;m&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;s);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;med3(x,&nbsp;n&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;s,&nbsp;n&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;s,&nbsp;n);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;med3(x,&nbsp;l,&nbsp;m,&nbsp;n);&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Mid-size,&nbsp;med&nbsp;of&nbsp;3</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(m&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;r)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;temp&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;x[m];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x[m]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;x[r];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x[r]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;partition(x,&nbsp;p,&nbsp;r);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;med3(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;x[],&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;a,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;b,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;c)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;x[a]&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;x[b]&nbsp;</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;(x[b]&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;x[c]&nbsp;</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;b&nbsp;:&nbsp;x[a]&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;x[c]&nbsp;</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;c&nbsp;:&nbsp;a)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;x[b]&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;x[c]&nbsp;</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;b&nbsp;:&nbsp;x[a]&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;x[c]&nbsp;</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;c&nbsp;:&nbsp;a;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;swap(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;a,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;j)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;temp&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;a[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a[i]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;a[j];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a[j]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;partition(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;a[],&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;p,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;r)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;x&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;a[r];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;m&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;p&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;j&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;r;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">true</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j</span><span style="color: #000000;">--</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(j</span><span style="color: #000000;">&gt;=</span><span style="color: #000000;">p</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">a[j]&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;x);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(a[m]&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;x);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(j&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;m)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">break</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;swap(a,&nbsp;m,&nbsp;j);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;swap(a,&nbsp;r,&nbsp;j&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;j&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span></div>
&nbsp;选择算法还有最坏情况下O(n)复杂度的实现，有兴趣可以读算法导论和<a href="http://en.wikipedia.org/wiki/Selection_algorithm">维基百科</a>。题外，我测试了下这两个实现，在我的机器上大概有2倍多的差距，还是很明显。<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/336357.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2010-10-28 10:53 <a href="http://www.blogjava.net/killme2008/archive/2010/10/28/336357.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Actor、Coroutine和Continuation的概念澄清</title><link>http://www.blogjava.net/killme2008/archive/2010/03/23/316273.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Tue, 23 Mar 2010 03:49:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2010/03/23/316273.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/316273.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2010/03/23/316273.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/316273.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/316273.html</trackback:ping><description><![CDATA[<br />    Actor、<a href="http://en.wikipedia.org/wiki/Coroutine">Coroutine</a>和<a href="http://en.wikipedia.org/wiki/Continuation">Continuation</a>这三个概念由于并发的受关注而被经常提到，这里主要想谈下这三者的区别和联系，以便更好的区分问题领域和讨论。首先，Actor和Coroutine在我看来是两种并发模型，仅针对于并发这个领域，而Continuation则是程序设计领域的一个概念，相比于Actor和Coroutine是一个更基础的概念。<br /><br />    那么，什么是Continuation？这个要从表达式的求值说起。一个表达式的求值可以分为两个阶段：“<b>What to evaluate?</b>”和“<b>What to do with the value</b>”，“What to do with the value”就是计算的Continuation。以下面这段代码为例：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> x</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">3</span><span style="color: rgb(0, 0, 0);"> then<br />   </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> x</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br />   </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> x<br />end</span></div><br />    考察其中的表达式x&lt;3，这个表达式就是“what to evaluate?”，代表你将计算的东西，然后根据x&lt;3的结果决定是执行x+1还是直接返回x，这个根据x&lt;3的值来决定下一步的过程就是这个表达式的Continuation，也就是"what to do with the value"。怎么得到某个表达式的Continuation呢？在支持Continuation的语言里提供了call-with-current-continuation的函数，通常简称为call/cc，使用这个函数你就可以在任何代码中得到Continuation。进一步，continuation有什么作用呢？它可以做的事情不少，如nonlocal exits、回溯、多任务的实现等等。例如在scheme中没有break语句，就可以用call/cc实现一些此类高级的控制结构：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">(call</span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);">cc (</span><span style="color: rgb(0, 0, 255);">lambda</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">break</span><span style="color: rgb(0, 0, 0);">)<br />        (</span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">each (</span><span style="color: rgb(0, 0, 255);">lambda</span><span style="color: rgb(0, 0, 0);"> (x) (</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);"> x 0) (</span><span style="color: rgb(0, 0, 255);">break</span><span style="color: rgb(0, 0, 0);"> x)))<br />                </span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(128, 0, 0);">(99 88 -77 66 55))</span><span style="color: rgb(128, 0, 0);"><br /></span><span style="color: rgb(0, 0, 0);">        </span><span style="color: rgb(0, 128, 0);">#</span><span style="color: rgb(0, 128, 0);">t))</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"><br /></span></div><br />    上面这段代码查找列表(99 88 -77 66 55)中的负数，当查找到的时候马上从迭代中退出并返回该值，其中的break就是一个continuation。刚才还提到continuation可以实现回溯，那么就可以实现一个穷举的机器出来用来搜索解空间，也就是类似Prolog中的回溯机制，在SICP这本书里就介绍了如何用call/cc实现一个简单的逻辑语言系统。更著名的就是神奇的amb操作符，有兴趣可以看看<a href="/killme2008/archive/2008/11/15/240672.html">这里</a>。<br />     <br />     接下来我们来看看如何continuation实现多任务，在Continuation的<a href="http://en.wikipedia.org/wiki/Continuation">维基百科</a>里给了一段代码来展示如何用scheme来实现coroutine，我稍微修改了下并添加了注释:<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">;;continuation栈，保存了等待执行的continuation<br />(define call/cc call-with-current-continuation)<br />(define *queue* '())<br /><br />(define (empty-queue?)<br />        (null? *queue*))<br /><br />(define (enqueue x)<br />        (set! *queue* (append *queue* (list x))))<br /><br />(define (dequeue)<br />        (let ((x (car *queue*)))<br />              (set! *queue* (cdr *queue*))<br />         x))<br />;;启动协程<br />(define (resume proc)<br />       (call/cc<br />         (lambda (k)<br />           ;;保存当前continuation，执行proc<br />           (enqueue k)<br />           (proc))))<br />;;让出执行权<br />(define (yield)<br />     (call/cc<br />      (lambda (k)<br />         ;;保存当前continuation，弹出上一次执行的cont并执行<br />        (enqueue k)<br />        ((dequeue)))))<br />;;停止当前协程或者当没有一个协程时停止整个程序,最简单的调度程序<br />(define (thread-exit)<br />     (if (empty-queue?)<br />         (exit)<br />         ((dequeue))))<br /></span></div>（注：scheme以分号开头作为注释）<br /><br />     这其实就是一个coroutine的简单实现，context的保存、任务的调度、resume/yield原语……样样俱全。使用起来类似这样，下面这段程序轮流打印字符串：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">(define (display-str str)<br />        (lambda()<br />         (let loop()<br />              (display str)<br />              (newline)<br />              (yield)<br />              (loop))))<br /><br />;;;创建两个协程并启动调度器<br />(resume (display-str "This is AAA"))<br />(resume (display-str "Hello from BBB"))<br />(thread-exit)<br /></span></div><br />     任务非常简单，打印下传入的字符串并换行，然后让出执行权给另一个任务执行，因此输出：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">This is AAA<br />Hello from BBB<br />This is AAA<br />Hello from BBB<br />This is AAA<br />Hello from BBB<br />This is AAA<br />Hello from BBB<br />……</span></div><br />    谈了这么多continuation的应用，事实上我想说明的是continuation可以用来实现协程，Ruby 1.9中call/cc和Fiber的实现（在cont.c)大体是一样的同样说明了这一点。<br /><br />     接下来我们讨论下Actor和Coroutine的关系，上面提到Actor是一种并发模型，我更愿意称之为一种编程风格，Actor跟message passing、Duck Typing是一脉相承的。Actor风格是可以这么描述：将物理世界抽象成一个一个的Actor，Actor之间通过发送消息相互通信，Actor不关心消息是否能被接收或者能否投递到，它只是简单地投递消息给其他actor，然后等待应答。Actor相比于Coroutine是一种更高层次的抽象，它提供的receive和pattern match的原语更接近于现实世界，而使用coroutine编程你还需要手工介入任务调度，这在Actor中是由一个调度器负责的。<br /><br />    同样，Actor可以用coroutine实现，例如Ruby有个<a href="http://revactor.org/">revactor</a>项目，就是利用1.9引入的Fiber实现actor风格的编程，它的实现非常简单，有兴趣地可以看看，其实跟continuation实现coroutine类似。但是Actor并不是一定要用coroutine才能实现，Actor是一种编程风格，你在Java、C#、C++中同样可以模拟这样的方式去做并发编程，.net社区的老赵<a href="http://www.cnblogs.com/JeffreyZhao/archive/2009/05/11/a-simple-actor-model-implementation.html">实现过一个简单的Actor</a>，<a href="http://www.scala-lang.org/">Scala</a>的Actor实现是基于外部库，利用scala强大的元编程能力使得库的使用像内置于语言。<br /><br />    总结下我想表达的：Continuation是程序设计领域的基础概念，它可以用于实现coroutine式的多任务，Actor是一种比之coroutine更为抽象的编程风格，Actor可以基于Coroutine实现但并非必须，Actor和Coroutine都是现在比较受关注的并发模型。<br /><br /><br /><br /><img src ="http://www.blogjava.net/killme2008/aggbug/316273.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2010-03-23 11:49 <a href="http://www.blogjava.net/killme2008/archive/2010/03/23/316273.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《Unix编程艺术》重读笔记(三)</title><link>http://www.blogjava.net/killme2008/archive/2010/02/22/313571.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sun, 21 Feb 2010 16:46:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2010/02/22/313571.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/313571.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2010/02/22/313571.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/313571.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/313571.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 题外：从老家从早到晚总算折腾回了杭州，进站太早，火车晚点，提包带断，什么倒霉事也遇上了，先发个已经整理好的部分，后续仍待整理。<br />
<br />
<meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8" />
<title></title>
<meta name="GENERATOR" content="OpenOffice.org 3.1  (Linux)" />
<style type="text/css">
<!-- @page { margin: 2cm }
P { margin-bottom: 0.21cm }
H1 { margin-bottom: 0.21cm }
H1.western { font-family: "DejaVu Sans", sans-serif; font-size: 16pt }
H1.cjk { font-family: "DejaVu Sans"; font-size: 16pt }
H1.ctl { font-family: "DejaVu Sans"; font-size: 16pt }
-->
</style>
<h1 class="cjk">多道程序设计：分离进程为独立的功能</h1>
<p>无论在协作进程还是在同一进程的协作子过程层面上，<font face="AR PL UMing CN, serif">Unix</font>设计风格都运用&#8220;<strong>做单件事并做好的方法</strong>&#8220;，强调用定义良好的进程间通信或共享文件来连通小型进程，提倡将程序<strong>分解</strong>为更简单的子进程，并专注考虑这些子进程间的接口，这至少需要通过以下三种方法来实现：</p>
<p><font face="AR PL UMing CN, serif">1</font>、<strong>降低</strong>进程生成的<strong>开销</strong><font face="AR PL UMing CN, serif">(</font>思考下<font face="AR PL UMing CN, serif"><a title="" href="http://www.erlang.org" >Erlang</a></font>的<font face="AR PL UMing CN, serif">process)</font></p>
<p><font face="AR PL UMing CN, serif">2</font>、提供方法（<font face="AR PL UMing CN, serif">shellout</font>、<font face="AR PL UMing CN, serif">IO</font>重定向、管道、消息传递和<font face="AR PL UMing CN, serif">socket</font>）简化<strong>进程间通信</strong></p>
<p><font face="AR PL UMing CN, serif">3</font>、提倡使用能由管道和<font face="AR PL UMing CN, serif">socket</font>传递的简单、透明的<strong>文本数据格式</strong></p>
<p><font face="AR PL UMing CN, serif">Unix IPC</font>方法的分类：</p>
<p><font face="AR PL UMing CN, serif">1</font>、将任务转给专门程序，如<font face="AR PL UMing CN, serif">system(3)</font>，<font face="AR PL UMing CN, serif">popen</font>调用等，称为<strong><font face="AR PL UMing CN, serif">shellout</font></strong></p>
<p><font face="AR PL UMing CN, serif">2</font>、<strong><font face="AR PL UMing CN, serif">Pipe</font></strong>、<strong>重定向和过滤器</strong>，如<font face="AR PL UMing CN, serif">bc</font>和<font face="AR PL UMing CN, serif">dc</font></p>
<p><font face="AR PL UMing CN, serif">3</font>、<strong>包装器</strong>，隐藏<font face="AR PL UMing CN, serif">shell</font>管线的复杂细节。</p>
<p><font face="AR PL UMing CN, serif">4</font>、<strong>安全包装器和<font face="AR PL UMing CN, serif">Bernstein</font>链</strong></p>
<p><font face="AR PL UMing CN, serif">5</font>、<strong>主</strong><font face="AR PL UMing CN, serif">/</font><strong>从</strong>进程</p>
<p><font face="AR PL UMing CN, serif">6</font>、<strong>对等</strong>进程间通信：</p>
<p><font face="AR PL UMing CN, serif">(1)</font>临时文件</p>
<p><font face="AR PL UMing CN, serif">(2)</font>信号</p>
<p><font face="AR PL UMing CN, serif">(3)</font>系统守护程序和常规信号</p>
<p><font face="AR PL UMing CN, serif">(4)socket</font></p>
<p><font face="AR PL UMing CN, serif">(5)</font>共享内存，<font face="AR PL UMing CN, serif">mmap</font></p>
<p><strong>远程过程调用</strong><font face="AR PL UMing CN, serif">(RPC)</font>的缺憾：</p>
<p><font face="AR PL UMing CN, serif">1</font>、<font face="AR PL UMing CN, serif">RPC</font>接口很难做到<strong>可显</strong>，如果不编写和被监控程序同样复杂的专用工具，也难以监控程序的行为。<font face="AR PL UMing CN, serif">RPC</font>接口和库一样具有版本不兼容的问题，由于是分布式的，因此更难被追查。</p>
<p><font face="AR PL UMing CN, serif">2</font>、类型标记越丰富的接口往往越复杂，因而越脆弱。随着时间的推移，由于在接口之间传递的类型总量逐渐变大，单个类型越来越复杂，这些接口往往产生<strong>类型本体蠕变</strong>问题。这是因为接口比字符串更容易失配；如果两端程序的本体不能正确匹配，要让它们通信肯定很难，纠错更是难上加难。</p>
<p><font face="AR PL UMing CN, serif">3</font>、支持<font face="AR PL UMing CN, serif">RPC</font>的常见理由是它比文本流方法允许&#8220;更丰富&#8221;的接口，但是接口的功能之一就是充当阻隔点，防止模块的实现细节彼此泄漏，因此，支持<font face="AR PL UMing CN, serif">RPC</font>的主要理由同时恰恰证明了<strong><font face="AR PL UMing CN, serif">RPC</font>增加而不是降低了程序的全局复杂度</strong>。</p>
<p><font face="AR PL UMing CN, serif">Unix</font>传统强烈赞成透明、可显的接口，这是<font face="AR PL UMing CN, serif">unix</font>文化不断坚持<strong>文本协议<font face="AR PL UMing CN, serif">IPC</font></strong>的动力。</p>
<p><font face="AR PL UMing CN, serif">ESR</font>在这里还谈到<font face="AR PL UMing CN, serif">XML-RPC</font>和<font face="AR PL UMing CN, serif">SOAP</font>等协议，认为是<font face="AR PL UMing CN, serif">RPC</font>和<font face="AR PL UMing CN, serif">unix</font>对文本流支持的一种融合，遗憾的是<font face="AR PL UMing CN, serif">SOAP</font>本身也成为一种重量级、不那么透明的协议了，尽管它也是文本协议。</p>
<p>线程是<strong>有害</strong>的：</p>
<p>线程是那些进程生成<strong>昂贵、<font face="AR PL UMing CN, serif">IPC</font>功能薄弱</strong>的操作系统所特有的概念。</p>
<p>尽管线程通常具有独立的局部变量栈，它们却<strong>共享</strong>同一个<strong>全局内存</strong>，在这个共享地址空间管理<strong>竞争</strong>和<strong>临界区</strong>的任务相当困难，而且成为增加整体复杂度和滋生<font face="AR PL UMing CN, serif">bug</font>的温床。除了普通的竞争问题之外，还产生了一类新问题：<strong>时序依赖</strong>。</p>
<p>当工具的作用不是控制而是增加复杂度的时候，最好<strong>扔掉从零开始。</strong></p>
<h1 class="cjk">微型语言：寻找歌唱的乐符</h1>
<p>（注，这里谈的微型语言，就是现在比较热门的词汇<font face="AR PL UMing CN, serif">DSL</font>）</p>
<p>对软件错误模式进行的大量研究得出的一个最一致的结论是，<strong>程序员每百行程序出错率和所使用的编程语言在很大程度上是无关的</strong>。更高级的语言可以用<strong>更少</strong>的行数完成<strong>更多的任务，</strong>也意味着<strong>更少的</strong><font face="AR PL UMing CN, serif">bug</font>。</p>
<p>防御设计不良微型语言的唯一方法是知道如何设计一个好的微型语言。</p>
<p>语言分类法：</p>
<p><img alt="" src="http://www.blogjava.net/images/blogjava_net/killme2008/taxonomy.png" height="240" width="742" /><br />
</p>
<p>对微型语言的功能测试：<strong>不读手册可以编写吗</strong>？</p>
<p><strong>现代微型语言，要么就完全通用而不紧凑，要么就非常不通用而紧凑；不通用也不紧凑的语言则完全没有竞争力。</strong></p>
<p>一些引申想法：我认为这个评判标准也可以用在任何编程语言上，以此来判断一些语言，<font face="AR PL UMing CN, serif">C</font>语言既通用又紧凑，<font face="AR PL UMing CN, serif">Java</font>是通用而不紧凑，<font face="AR PL UMing CN, serif"><a title="" href="http://www.ruby-lang.org" >ruby</a></font>、<font face="AR PL UMing CN, serif">Python</font>之类的脚本语言也是如此，正则表达式（如果也算语言的话）是不通用而紧凑，<font face="AR PL UMing CN, serif"><a title="" href="http://www.erlang.org" >Erlang</a></font>也是通用而紧凑，<font face="AR PL UMing CN, serif">awk</font>却是既不通用也不紧凑，XSLT也可以归入不通用不紧凑的行列；Javascript是个另类，按理说它也是不通用不紧凑，说它不通用是因为它的主要应用范围还是局限在web开发的UI上，实际上Javascript也是门通用语言,但是很少会有人会用javascript去写批处理脚本,Javascript显然是不紧凑的，太多的边边角角甚至奇奇怪怪的东西需要你去注意，然而就是这样一门不通用不紧凑的语言现在却非常有前途，只能说时势所然。</p>
<p>设计微型语言：</p>
<p><font face="AR PL UMing CN, serif">1</font>、选择<strong>正确的复杂度</strong>，要的是数据文件格式，还是微型语言？</p>
<p><font face="AR PL UMing CN, serif">2</font>、<strong>扩展</strong>和<strong>嵌入</strong>语言</p>
<p><font face="AR PL UMing CN, serif">3</font>、编写<strong>自定义语法</strong>，<font face="AR PL UMing CN, serif">yacc</font>和<font face="AR PL UMing CN, serif">lex</font></p>
<p><font face="AR PL UMing CN, serif">4</font>、<strong>慎用宏</strong>，宏的主要问题是滥用带来的奇怪、不透明的代码，以及对错误诊断的扰乱。</p>
<p><font face="AR PL UMing CN, serif">5</font>、<strong>语言</strong>还是<strong>应用协议</strong>。</p>
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/313571.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2010-02-22 00:46 <a href="http://www.blogjava.net/killme2008/archive/2010/02/22/313571.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《Unix编程艺术》重读笔记(二)</title><link>http://www.blogjava.net/killme2008/archive/2010/02/19/313419.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 19 Feb 2010 11:25:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2010/02/19/313419.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/313419.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2010/02/19/313419.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/313419.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/313419.html</trackback:ping><description><![CDATA[<meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8" />
<title></title>
<meta name="GENERATOR" content="OpenOffice.org 3.1  (Linux)" />
<style type="text/css">
<!-- @page { margin: 2cm }
P { margin-bottom: 0.21cm }
H1 { margin-bottom: 0.21cm }
H1.western { font-family: "DejaVu Sans", sans-serif; font-size: 16pt }
H1.cjk { font-family: "DejaVu Sans"; font-size: 16pt }
H1.ctl { font-family: "DejaVu Sans"; font-size: 16pt }
-->
</style>
<h1 class="cjk">模块性：保持清晰，保持简洁</h1>
<p style="margin-bottom: 0cm;">软件设计有两种方式：一种是设计得极为<strong>简洁</strong>，<strong>没有看得到的缺陷</strong>；另一种是设计得极为<strong>复杂</strong>，<strong>有缺陷也看不出来</strong>。第一种方式的难度要大得多。</p>
<p style="margin-bottom: 0cm;">模块化代码的首要特质就是<strong>封装</strong>，<font face="AR PL UMing CN, serif">API</font>在模块间扮演双重角色，实现层面作为模块之间的<strong>滞塞点</strong>，<strong>阻止</strong>各自的内部细节被相邻模块知晓；在设计层面，正是<font face="AR PL UMing CN, serif">API</font>真正<strong>定义</strong>了整个体系。</p>
<p style="margin-bottom: 0cm;">养成在编码前为<font face="AR PL UMing CN, serif">API</font>编写一段非<strong>正式书面描述</strong>的习惯，是一个非常好的方法。</p>
<p style="margin-bottom: 0cm;">模块的最佳大小，逻<strong>辑行<font face="AR PL UMing CN, serif">200-400</font>行，物理行在<font face="AR PL UMing CN, serif">400-800</font>之间</strong>。</p>
<p style="margin-bottom: 0cm;">紧凑性就是一个设计能否<strong>装入人脑</strong>中的特性。测试软件紧凑性的一个简单方法是：一个<strong>有经验</strong>的用户通常需要<strong>用户手册</strong>吗？如果不需要，那么这个设计是紧凑的。</p>
<p style="margin-bottom: 0cm;">理解紧凑性可以从它的&#8220;反面&#8221;来理解，紧凑性不等于&#8220;<strong>薄弱</strong>&#8221;，如果一个设计构建在易于理解且<strong>利于组合</strong>的抽象概念上，则
这个系统能在具有非常强大、灵活的功能的同时保持紧凑。紧凑也不等同于&#8220;<strong>容易学习</strong>&#8221;：对于某些紧凑
设计而言，在掌握其精妙的内在基础概念模型之前，要理解这个设计相当困难；但一旦理解了这个概念模型，整个视角就会改变，紧凑的奥妙也就十分简单了。紧凑也不意味着&#8220;<strong>小巧</strong>&#8221;。即使一个设计良好的系统，对有经验的用户来说没什么特异之处、&#8220;<strong>一眼</strong>&#8221;就能看懂，但仍然可能包含很多部分。</p>
<p style="margin-bottom: 0cm;">评测一个<font face="AR PL UMing CN, serif">API</font>紧凑性的经验法则是：<font face="AR PL UMing CN, serif">API</font>的<strong>入口点</strong>通常在<strong><font face="AR PL UMing CN, serif">7</font>个</strong>左右，或者按《代码大全<font face="AR PL UMing CN, serif">2</font>》的说法，<font face="AR PL UMing CN, serif">7+2</font>和<font face="AR PL UMing CN, serif">7-2</font>的范围内。</p>
<p style="margin-bottom: 0cm;">重构技术中的很多坏味道，特别是重复代码，是违反正交性的明显例子，&#8220;<strong>重构的原则性目标就是提高正交性</strong>&#8221;。</p>
<p style="margin-bottom: 0cm;"><strong><font face="AR PL UMing CN, serif">DRY</font></strong>原则，或者称为<strong><font face="AR PL UMing CN, serif">SPOT</font></strong>原则（<font face="AR PL UMing CN, serif">single
point of
truth)——</font>真理的单点性。重复的不仅仅是代码，还包括数据结构，数据结构模型应该最小化，提倡寻找一种数据结构，使得模型中的状态跟真实世界系统的状态能够<strong>一一对应</strong>。</p>
<p style="margin-bottom: 0cm;">要提高设计的紧凑性，有一个精妙但强大的方法，就是围绕&#8220;解决一个<strong>定义明确的问题</strong>&#8221;的强核心算法组织设计，避免臆断和捏造，将任务的核心形式化，建立明确的模型。</p>
<p style="margin-bottom: 0cm;"><br />
</p>
<h1 class="cjk">文本化：好协议产生好实践</h1>
<p>文本流是非常有用的通用格式，无需专门工具就可以很容易地读写和编辑文本流，这些格式是<strong>透明</strong>的。如果担心性能问题，就在<strong>协议层面之上或之下</strong>压缩文本协议流，最终产生的设计会比二进制协议更干净，性能<strong>可能</strong>更好。使用二进制协议的唯一正当理由是：如果要处理<strong>大批量的</strong>数据，因而确实关注能否在介质上获得最大位<strong>密度</strong>，或者是非常关心将数据转化为芯片核心结构所必须的时间或指令<strong>开销</strong>。</p>
<p>数据文件元格式：</p>
<p><strong><font face="AR PL UMing CN, serif">1</font>、<font face="AR PL UMing CN, serif">DSV</font>风格</strong>，<font face="AR PL UMing CN, serif">DElimiter-Seperated
Values</font></p>
<p>使用分隔符来分隔值，例如<font face="AR PL UMing CN, serif">/etc/passwd</font></p>
<p>适合场景：数据为列表，名称（首个字段）为关键字，而且记录通常很短（小于<font face="AR PL UMing CN, serif">80</font>个字符）</p>
<p><strong><font face="AR PL UMing CN, serif">2</font>、<font face="AR PL UMing CN, serif">RFC
822</font>格式</strong></p>
<p>互联网电子邮件信息采用的文本格式，使用属性名<font face="AR PL UMing CN, serif">+</font>冒号<font face="AR PL UMing CN, serif">+</font>值的形式，记录属性每行存放一个，如<font face="AR PL UMing CN, serif">HTTP
1.1</font>协议。</p>
<p>适合场景：任何带属性的或者与电子邮件类似的信息，非常适合具有不同字段集合而字段中数据层次又扁平的记录。</p>
<p><strong><font face="AR PL UMing CN, serif">3</font>、<font face="AR PL UMing CN, serif">Cookie-jar</font>格式</strong>。简单使用跟随<font face="AR PL UMing CN, serif">%%</font>的新行符（或者有时只有一个<font face="AR PL UMing CN, serif">%)</font>作为记录分隔符，很适用于记录<strong>非结构化文本</strong>的情况。</p>
<p>适合场景：词以上结构没有自然顺序，而且结构不易区别的文本段，或适用于搜索关键字而不是文本上下文的文本段。</p>
<p> <strong><font face="AR PL UMing CN, serif">4</font>、<font face="AR PL UMing CN, serif">Record-jar</font>格式</strong>，<font face="AR PL UMing CN, serif">cookie-jar</font>和<font face="AR PL UMing CN, serif">RFC-822</font>的结合，形如</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">name:dennis<br />
age:</span><span style="color: #000000;">21</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">%%</span><span style="color: #000000;"><br />
name:catty<br />
age:</span><span style="color: #000000;">22</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">%%</span><span style="color: #000000;"><br />
name:green<br />
age:</span><span style="color: #000000;">10</span></div>
<p>这样的格式。</p>
<p>适合场景：那些类似<font face="AR PL UMing CN, serif">DSV</font>文件，但又有<strong>可变字段数据</strong>而且可能伴随<strong>无结构文本</strong>的字段属性关系集合。</p>
<p><strong><font face="AR PL UMing CN, serif">5</font>、<font face="AR PL UMing CN, serif">XML</font>格式</strong>，适合复杂<strong>递归和嵌套</strong>数据结构的格式，并且经常可以在无需知道数据语义的情况下仅通过语法检查就能发现形式不良损坏或错误生成的数据。缺点在于无法跟传统<font face="AR PL UMing CN, serif">unix</font>工具协作。</p>
<p><strong><font face="AR PL UMing CN, serif">6</font>、<font face="AR PL UMing CN, serif">Windows
INI</font>格式</strong>，形如</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">[DEFAULT]<br />
account</span><span style="color: #000000;">=</span><span style="color: #000000;">esr<br />
<br />
[python]<br />
directory</span><span style="color: #000000;">=/</span><span style="color: #000000;">home</span><span style="color: #000000;">/</span><span style="color: #000000;">ers</span><span style="color: #000000;">/</span><span style="color: #000000;">cvs</span><span style="color: #000000;">/</span><span style="color: #000000;">python<br />
developer</span><span style="color: #000000;">=</span><span style="color: #000000;">1</span><span style="color: #000000;"><br />
<br />
[sng]<br />
directory</span><span style="color: #000000;">=/</span><span style="color: #000000;">home</span><span style="color: #000000;">/</span><span style="color: #000000;">esr</span><span style="color: #000000;">/</span><span style="color: #000000;">WWW</span><span style="color: #000000;">/</span><span style="color: #000000;">sng<br />
numeric_id</span><span style="color: #000000;">=</span><span style="color: #000000;">1001</span><span style="color: #000000;"><br />
developer</span><span style="color: #000000;">=</span><span style="color: #000000;">1</span><span style="color: #000000;"><br />
<br />
[fetchmail]<br />
numeric_id</span><span style="color: #000000;">=</span><span style="color: #000000;">4928492</span></div>
<p>这样的格式</p>
<p>适合场景：数据围绕指定的记录或部分能够自然分成&#8220;名称<font face="AR PL UMing CN, serif">-</font>属性对&#8221;两层组织结构。</p>
<p><font face="AR PL UMing CN, serif">Unix</font>文本文件格式的约定：</p>
<p><font face="AR PL UMing CN, serif">1</font>、如果可能，以新行符结束的每<strong>一行只存一个记录</strong><font face="AR PL UMing CN, serif"><br />
</font></p>
<p><font face="AR PL UMing CN, serif">2</font>、如果可能，每行不超过<strong><font face="AR PL UMing CN, serif">80</font>个</strong>字符</p>
<p><font face="AR PL UMing CN, serif">3</font>、使用&#8221;<strong>＃</strong>&#8220;引入<strong>注释</strong></p>
<p><font face="AR PL UMing CN, serif">4</font>、支持<strong>反斜杠</strong>约定</p>
<p><font face="AR PL UMing CN, serif">5</font>、在每行一条记录的格式中，使用<strong>冒号或连续的空白</strong>作为字段分隔符。</p>
<p><font face="AR PL UMing CN, serif">6</font>、不要过分区分<strong><font face="AR PL UMing CN, serif">tab</font>和<font face="AR PL UMing CN, serif">whitespace</font></strong></p>
<p><font face="AR PL UMing CN, serif">7</font>、优先使用<strong>十六进制</strong>而不是八进制。</p>
<p><font face="AR PL UMing CN, serif">8</font>、对于复杂的记录，使用&#8220;节（<font face="AR PL UMing CN, serif">stanza)&#8221;</font>格式，要么让记录格式和<font face="AR PL UMing CN, serif">RFC
822</font>电子邮件头类似，用冒号终止的字段名关键字作为引导字段。</p>
<p><font face="AR PL UMing CN, serif">9</font>、在节格式中，支持连续行，多个逻辑行折叠成一个物理行</p>
<p><font face="AR PL UMing CN, serif">10</font>、要么包含一个<strong>版本号</strong>，要么将格式设计成相互独立的的<strong>自描述</strong>字节块。</p>
<p><font face="AR PL UMing CN, serif">11</font>、注意浮点数<strong>取整。</strong></p>
<p><font face="AR PL UMing CN, serif">12</font>、<strong>不要</strong>仅对文件的一部分进行压缩或者二进制编码。</p>
<p>应用协议元格式</p>
<p><font face="AR PL UMing CN, serif">1</font>、经典的互联网应用元协议
<font face="AR PL UMing CN, serif">RFC
3117</font>《论应用协议的设计》，如<font face="AR PL UMing CN, serif">SMTP</font>、<font face="AR PL UMing CN, serif">POP3</font>、<font face="AR PL UMing CN, serif">IMAP</font>等协议</p>
<p><font face="AR PL UMing CN, serif">2</font>、作为通用应用协议的<font face="AR PL UMing CN, serif">HTTP</font>，在<font face="AR PL UMing CN, serif">HTTP</font>上构建专用协议，如互联网打印协议<font face="AR PL UMing CN, serif">(IPP</font>）</p>
<p><font face="AR PL UMing CN, serif">3</font>、<font face="AR PL UMing CN, serif">BEEP</font>：块可扩展交换协议，既支持<font face="AR PL UMing CN, serif">C/S</font>模式，又支持<font face="AR PL UMing CN, serif">P2P</font>模式</p>
<p><font face="AR PL UMing CN, serif">4</font>、<font face="AR PL UMing CN, serif">XMP-RPC</font>、<font face="AR PL UMing CN, serif">SOAP</font>和<font face="AR PL UMing CN, serif">Jabber</font>，基于<font face="AR PL UMing CN, serif">XML</font>的协议。</p>
<h1 class="cjk"><br />
</h1>
<h1 class="cjk">透明性：来点光</h1>
<p>美在计算科学中的地位，要比在其他任何技术中的地位都重要，因为<strong>软件是太复杂</strong>了。美是<strong>抵御复杂的终极武器</strong>。</p>
<p>如果没有阴暗的角落和隐藏的深度，软件系统就是透明的。透明性是一种<strong>被动</strong>品质。如果实际上能预测到程序行为的全部或大部分情况，并能建立简单的心理模型，这个程序就是透明的，因为可以<strong>看透</strong>机器究竟在干什么。</p>
<p>如果软件系统所包含的功能是为了帮助人们对软件建立正确的&#8220;<strong>做什么、怎样做</strong>&#8221;的心理模型而设计，这个软件系统就是<strong>可显</strong>的。
</p>
<p>不要让<strong>调试工具</strong>仅仅成为一种事后追加或者用过就束之高阁的东西。它们是通往代码的<strong>窗口</strong>：不要只在墙上凿出粗糙的洞，要修整这些洞并装上窗。如果打算让代码一直可被维护，就始终必须让光照进去。例如<font face="AR PL UMing CN, serif">fetchmail</font>的<font face="AR PL UMing CN, serif">-v</font>选项将处理<font face="AR PL UMing CN, serif">SMTP</font>、<font face="AR PL UMing CN, serif">POP</font>的处理过程打印到标准输出，使得<font face="AR PL UMing CN, serif">fetchmail</font>行为具有可显性。</p>
<p>在&#8220;这<strong>个设计能行吗？</strong>&#8221;之后要提出的头几个问题就是&#8220;<strong>别人能读懂这个设计吗<font face="AR PL UMing CN, serif">?</font>这个设计优雅吗？</strong>&#8221;我们希望，此时大家已经很清楚，这些问题不是废话，<strong>优雅不是一种奢侈</strong>。在人类对软件的反映中，这些品质对于减少软件<font face="AR PL UMing CN, serif">bug</font>和提高软件长期维护性是最基本的。</p>
<p>要追求代码的透明性，最有效的方法是很简单，就是<strong>不要</strong>在具体操作的代码上叠放太多的抽象层。</p>
<p><font face="AR PL UMing CN, serif">OO</font>语言使得抽象变得容易——也许是<strong>太容易</strong>了。<font face="AR PL UMing CN, serif">OO</font>语言鼓励&#8220;具<strong>有厚重的胶合和复杂层次</strong>&#8221;的体系。当问题领域真的很复杂，确实需要大量抽象时，这可能是好事，但如果<font face="AR PL UMing CN, serif">coder</font>到头来用复杂的办法做简单的事情——仅仅是为他们能够这样做，结果便适得其反。</p>
<p>所有的<font face="AR PL UMing CN, serif">OO</font>语言都显示出某种使程序员陷入<strong>过度分层陷阱</strong>的倾向。对象框架和对象浏览器并不能代替良好的设计和文档，但却常常被混为一谈。过多的层次破坏了透明性：我们很难看清这些层次，无法在头脑中<strong>理清</strong>代码到底是<strong>怎样运行</strong>的。简洁、清晰和透明原则通通被破坏了，结果代码中充满了晦涩的<font face="AR PL UMing CN, serif">bug</font>，始终存在维护问题。</p>
<p>胶合层中的&#8220;智能数据&#8221;却经常不代表任何程序处理的自然实体——仅仅只是<strong>胶合物</strong>而已（典型现象就是<strong>抽象类和混入<font face="AR PL UMing CN, serif">(mixin)</font>类</strong>的不断扩散）</p>
<p><font face="AR PL UMing CN, serif">OO</font>抽象的另一个副作用就是程序往往<strong>丧失了优化</strong>的机会。</p>
<p><font face="AR PL UMing CN, serif">OO</font>在其取得成功的领域（<font face="AR PL UMing CN, serif">GUI</font>、仿真和图形）之所以能成功，主要原因之一可能是因为在这些领域里很难弄错类型的本体问题。例如，在<font face="AR PL UMing CN, serif">GUI</font>和图形系统中，类和可操作的可见对象之间有相<strong>当自然的映射关系</strong>。</p>
<p><font face="AR PL UMing CN, serif">Unix</font>风格程序设计所面临的主要挑战就是如何将分离法的优点（将问题从原始的场景中简化、归纳）同代码和设计的薄胶合、浅平透层次结构的优点相组合。</p>
<p>太多的<font face="AR PL UMing CN, serif">OO</font>设计就像是意大利空心粉一样，把&#8220;<strong><font face="AR PL UMing CN, serif">is-a&#8221;</font></strong>和<strong>&#8220;</strong><font face="AR PL UMing CN, serif"><strong>have
a</strong>&#8221;</font>的关系弄得一团糟，或者以厚胶合层为特征，在这个胶合层中，许多对象的存在似乎只不过是为了在陡峭的抽象金字塔上<strong>占个位置</strong>罢了。这些设计都不透明，它们晦涩难懂并且难以调试。</p>
<p><strong>为透明性和可显性而编码：</strong></p>
<p><font face="AR PL UMing CN, serif">1</font>、程序调用层次中（不考虑递归）最大的静态<strong>深度</strong>是多少？如果大于<strong>四</strong>，就要当心。</p>
<p><font face="AR PL UMing CN, serif">2</font>、代码是否具有强大、明显的<strong>不变性质</strong>（约束）？不变性质帮助人们推演代码和发现有问题的情况。</p>
<p><font face="AR PL UMing CN, serif">3</font>、每个<font face="AR PL UMing CN, serif">API</font>中各个函数调用是否<strong>正交</strong>？或者是否存在太多的<font face="AR PL UMing CN, serif">magic
flags</font>或者模式位？</p>
<p><font face="AR PL UMing CN, serif">4</font>、是否存在一些顺手可用的<strong>关键数据结构或全局唯一的记录器</strong>，捕获系统的高层次状态？这个状态是否容易被形象化和检验，还是分布在数目众多的各个全局变量或对象中而难以找到？</p>
<p><font face="AR PL UMing CN, serif">5</font>、程序的数据结构或分类和它们所代表的外部实体之间，是否存在清晰的<strong>一对一映射。</strong></p>
<p><font face="AR PL UMing CN, serif">6</font>、是否容易找到给定函数的代码部分？不仅单个函数、模块，还有整个代码，需要花多少精力才能<strong>读懂</strong>？</p>
<p><font face="AR PL UMing CN, serif">7</font>、代码增加了特殊情况还是避免了<strong>特殊情况</strong>？每一个特殊情况可能对任何其他特殊情况产生影响：所有隐含的冲突都是<font face="AR PL UMing CN, serif">bug</font>滋生的温床。然而更重要的是，特殊情况使得代码更难理解。</p>
<p><font face="AR PL UMing CN, serif">8</font>、代码中有多少个<font face="AR PL UMing CN, serif"><strong>magic
number</strong>?</font>通过审查是否很容易查出代码中的限制（比如关键缓冲区的大小）？</p>
<p><strong>隐藏细节</strong>和<strong>无法访问细节</strong>有着重要区别。不要<strong>过度保护</strong>。</p>
<p>无论何时碰到涉及编辑某类复杂二进制对象的设计问题时，<font face="AR PL UMing CN, serif">unix</font>传统都提倡首先考虑，是否能够编写一个能够在可编辑的文本格式和二进制格式之间来回进行<strong>无损转换</strong>的工具？这类工具可称为<strong>文本化器</strong><font face="AR PL UMing CN, serif">(textualizer).</font></p>
<p><strong>宁愿抛弃、重建代码也不愿修补那些蹩脚的代码。</strong></p>
<p>&#8220;代码是<strong>活代码、睡代码</strong>还是<strong>死代码</strong>？&#8221;活代码周围存在一个非常活跃的开发社团。睡代码之所以&#8220;睡着&#8221;，经常是因为对作者而言，维护代码的<strong>痛苦</strong>超过了代码本身的效用。死代码则是睡得太久，重新实现一段等价代码<strong>更容易</strong>。</p><img src ="http://www.blogjava.net/killme2008/aggbug/313419.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2010-02-19 19:25 <a href="http://www.blogjava.net/killme2008/archive/2010/02/19/313419.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《Unix编程艺术》重读笔记(一)</title><link>http://www.blogjava.net/killme2008/archive/2010/02/18/313402.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 18 Feb 2010 11:23:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2010/02/18/313402.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/313402.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2010/02/18/313402.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/313402.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/313402.html</trackback:ping><description><![CDATA[<meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8" />
<title></title>
<meta name="GENERATOR" content="OpenOffice.org 3.1  (Linux)" />

<!-- @page { margin: 2cm }
P { margin-bottom: 0.21cm }
-->

<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">&nbsp;&nbsp; Unix</font>哲学是自下而上，而不是自上而下的，注重实效，立足于丰富的经验，你不会在正规方法学和标准中找到它。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">&nbsp;&nbsp; Unix</font>管道的发明人<font face="AR PL UMing CN, serif">Doug
McIlroy</font>曾经说过：</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">1</font>、让每个程序就<strong>做好一件事</strong>，如果有新任务就重新开始，不要往新程序中加入功能而搞的复杂。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">2</font>、假定每个程序的输出都会成为另一个程序的输入，哪怕那个程序是未知的。输出中<strong>不要</strong>有无关的<strong>信息干扰</strong>，避免使用严格的分栏格式和二进制格式输入。不要坚持使用交互式输入。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">3</font>、尽可能早将设计和编译的软件投入试用，哪怕是操作系统也不例外，理想情况下应该是几星期内，对抽劣的代码别犹豫，<strong>扔掉重写</strong>。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">4</font>、优先使用<strong>工具</strong>，而非拙劣的帮助来减轻编程任务的负担，工欲善其事，必先利其器。</p>
<p style="margin-bottom: 0cm;"><br />
</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">Rob
Pike</font>在《<font face="AR PL UMing CN, serif">Notes on C
programming</font>》中提到：</p>
<p style="margin-bottom: 0cm;">原则<font face="AR PL UMing CN, serif">1</font>：你无法断行程序会在什么地方耗费运行时间。瓶颈经常出现在想不到的地方，所以别急于胡乱找个地方改代码，除非你已经证实那儿就是<strong>瓶颈</strong>所在。</p>
<p style="margin-bottom: 0cm;">原则<font face="AR PL UMing CN, serif">2</font>：估量。在你没对代码进行估量，特别是没找到最耗时的那部分之前，别去优化速度。</p>
<p style="margin-bottom: 0cm;">原则<font face="AR PL UMing CN, serif">3</font>：花哨的算法，在<font face="AR PL UMing CN, serif">n</font>很小的适合通常很慢，而<font face="AR PL UMing CN, serif">n</font>通常很小。花哨算法的常数复杂度很大，<strong>除非你确定<font face="AR PL UMing CN, serif">n</font>一直很大<font face="AR PL UMing CN, serif">,</font>否则不要用花哨算法</strong>（即使<font face="AR PL UMing CN, serif">n</font>很大，也要优先考虑原则<font face="AR PL UMing CN, serif">2</font>）。</p>
<p style="margin-bottom: 0cm;">原则<font face="AR PL UMing CN, serif">4</font>：花哨的算法比简单的算法更容易出<font face="AR PL UMing CN, serif">bug
,</font>更难实现。尽量使用简单的算法配合简单的数据结构。</p>
<p style="margin-bottom: 0cm;">原则<font face="AR PL UMing CN, serif">5</font>：<strong>数据压倒一切</strong>。如果已经选择了正确的数据结构并且把一切组织得井井有条，正确的算法也就<strong>不言自明</strong>，编程的核心是数据结构，而不是算法。</p>
<p style="margin-bottom: 0cm;">原则<font face="AR PL UMing CN, serif">6</font>：没有原则<font face="AR PL UMing CN, serif">6.</font></p>
<p style="margin-bottom: 0cm;"><br />
</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">Ken
Thompson</font>对原则<font face="AR PL UMing CN, serif">4</font>做了强调：</p>
<p style="margin-bottom: 0cm;"><strong>拿不准就穷举。</strong></p>
<p style="margin-bottom: 0cm;"><br />
</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">Unix</font>哲学的<font face="AR PL UMing CN, serif">17</font>条原则：</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">1</font>、模块原则：简洁的接口拼合简单的部件。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">2</font>、清晰原则：清晰胜于机巧。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">3</font>、组合原则：设计时考虑拼接组合。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">4</font>、分离原则：策略同机制分离，接口同引擎分离。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">5</font>、简洁原则：设计要简洁，复杂度能低则低。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">6</font>、吝啬原则：除非却无他法，不要编写庞大的程序。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">7</font>、透明性原则：设计要可见，以便审查和调试。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">8</font>、健壮原则：健壮源于透明与简洁。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">9</font>、表示原则：把知识叠入数据，以求逻辑质朴而健壮。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">10</font>、通俗原则：接口设计避免标新立异。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">11</font>、缄默原则：如果一个程序没什么好说的，就沉默。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">12</font>、补救原则：出现异常时，马上退出，并给出足够错误信息。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">13</font>、经济原则：宁花机器一分，不花程序员一秒。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">14</font>、生成原则：避免手工<font face="AR PL UMing CN, serif">hack</font>，尽量编写程序去生成程序。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">15</font>、优化原则：雕琢前先要有原型，跑之前先学会走。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">16</font>、多样原则：绝不相信所谓&#8220;不二法门&#8221;的断言。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">17</font>、扩展原则：设计着眼未来，未来总是比预想来得快。</p>
<br />
<p style="margin-bottom: 0cm;"><strong><font face="AR PL UMing CN, serif">Unix</font>哲学之一言以蔽之：<font face="AR PL UMing CN, serif">KISS</font></strong></p>
<p style="margin-bottom: 0cm;"><strong><font face="AR PL UMing CN, serif">Keep
it simple,stupid!</font></strong></p>
<p style="margin-bottom: 0cm;">应用<font face="AR PL UMing CN, serif">unix</font>哲学：</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">1</font>、只要可行，一切都应该做成与来源和目标无关的<strong>过滤器</strong>。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">2</font>、数据流应尽可能的<strong>文本化</strong>（这样可以用标准工具来查看和过滤）。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">3</font>、数据库部署和应用协议应尽可能<strong>文本化</strong>（让人阅读和编辑）。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">4</font>、复杂的前端（用户界面）和后端应该<strong>泾渭分明</strong>。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">5</font>、如果可能，用<font face="AR PL UMing CN, serif">c</font>编写前，先用解释性语言<strong>搭建原型</strong>。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">6</font>、当且仅当只用一门编程语言会提高程序复杂度时，混用语言编程才比单一语言编程来得好。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">7</font>、<strong>宽收严发</strong>（对接收的东西要包容，对输出的东西要严格）</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">8</font>、过滤时，不需要丢弃的消息绝不丢。</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">9</font>、<strong>小就是美</strong>。在确保完成任务的基础上，程序功能尽可能的少。</p>
<p style="margin-bottom: 0cm;"><br />
</p>
<p style="margin-bottom: 0cm;">最后强调的是态度：</p>
<p style="margin-bottom: 0cm;">要良好地运用<font face="AR PL UMing CN, serif">unix</font>哲学，你就应该不断地<strong>追求卓越</strong>，你必须相信，程序设计是一门<strong>技艺</strong>，值得你付出所有的<strong>智慧、创造力和激情</strong>。否则，你的视线就不会超越那些简单、老套的设计和实现；你就会在应该思考的时候急急忙忙跑去编程。你就会在该无情删繁就简的时候反而把问题复杂化&#8212;&#8212;然后你还会反过来奇怪你的代码怎么会那么臃肿，那么难以调试。</p>
<p style="margin-bottom: 0cm;">要良好地运用<font face="AR PL UMing CN, serif">unix</font>哲学，你应该<strong>珍惜你的时间</strong>绝不浪费。一旦某人已经解决了某个问题，就直接拿来利用，不要让<strong>骄傲或偏见</strong>拽住你又去重做一遍。永远不要蛮干；要多用巧劲，省下力气在需要的时候用，好钢用到刀刃上。善用工具，尽可能将一切<strong>自动化</strong>。</p>
<p style="margin-bottom: 0cm;">软件设计和实现是一门充满快乐的<strong>艺术</strong>，一种高水平的<strong>游戏</strong>。如果这种态度对你来说听起来有些荒谬，或者令你隐约感到有些困窘，那么请停下来，想一想，问问自己是不是已经<strong>把什么给遗忘了</strong>。如果只是为了赚钱或者打发时间，你为什么要搞软件设计，而不是别的什么呢？你肯定曾经也认为软件设计值得你付出激情&#8230;&#8230;</p>
<p style="margin-bottom: 0cm;">要良好地运用<font face="AR PL UMing CN, serif">unix</font>哲学，你需要具备（或者找回）这种态度。<strong>你需要用心。你需要去游戏。你需要乐于探索。</strong><font face="AR PL UMing CN, serif">	</font></p>
<p style="margin-bottom: 0cm;"><br />
</p>
<p style="margin-bottom: 0cm;">操作系统的风格元素：</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">1</font>、什么是操作系统的统一性理念</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">2</font>、多任务能力</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">3</font>、协作进程（<font face="AR PL UMing CN, serif">IPC</font>）</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">4</font>、内部边界</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">5</font>、文件属性和记录结构</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">6</font>、二进制文件格式</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">7</font>、首选用户界面风格</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">8</font>、目标受众</p>
<p style="margin-bottom: 0cm;"><font face="AR PL UMing CN, serif">9</font>、开发的门坎</p><img src ="http://www.blogjava.net/killme2008/aggbug/313402.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2010-02-18 19:23 <a href="http://www.blogjava.net/killme2008/archive/2010/02/18/313402.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>不是抽象的漏洞，而是本质复杂性</title><link>http://www.blogjava.net/killme2008/archive/2010/01/10/308942.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sun, 10 Jan 2010 12:25:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2010/01/10/308942.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/308942.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2010/01/10/308942.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/308942.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/308942.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 《Joel on software》谈到所谓抽象漏洞，简单来说就是抽象能解决90%的一般情况，而其他10%的情况你仍然需要跟抽象层面下的细节打交道，也就是抽象本身只能减少你的工作时间，而无法减少你的学习时间。道理简单，举几个例子。<br />
&nbsp;&nbsp;&nbsp; 以SQL语言为例，SQL是所谓说明性的语言，你所写的语句只是一条what，而how是如何做的无需关心，但是真的无需关心吗？事实上是不行，低效的SQL语句对数据库的性能损害非常大，作为程序员你需要知道SQL这个抽象层次下的部分内容，知道数据库是怎么执行这些语句，知道如何去避免一些最差实践。再比如分布式调用希望做到能跟本地调用一样的透明，但实际上还是不行的，网络的不确定性让RPC调用根本无法做到的类似本地调用那样的透明性。隐藏在RPC这个抽象层次下的网络通信细节，你不能不去care。抽象能帮你解决大多数情况，提高你的工作效率，但是剩下的一公里问题，仍然需要你花费更多时间和精力去了解并解决。这事实上也是一个优秀程序员跟普通程序的差别之一，学习了java编程，知道了collection集合框架，不代表你无需再去学习数据结构和算法。<br />
&nbsp;&nbsp;&nbsp; Joel将这个现象称为漏洞抽象。事实上，我并不认为这是抽象本身的漏洞，这反而是软件的本质复杂性在作怪，抽象只能去化简偶然复杂性，例如函数、类、模块化等手段去组织代码，而本质的复杂性是无法避免的。举个不是那么恰当的例子，例如我们有这么个方法，传进一个参数list，我们要遍历list做一些事情，（我知道用迭代器才是正途，先允许我犯这么个错误），你可能这么写：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;doSomething(List</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">String</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;list){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i</span><span style="color: #000000;">=</span><span style="color: #000000;">0</span><span style="color: #000000;">;i</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">list.size();i</span><span style="color: #000000;">++</span><span style="color: #000000;">){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;str</span><span style="color: #000000;">=</span><span style="color: #000000;">list.get(i);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">do&nbsp;something</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<br />
&nbsp;&nbsp; 这样的代码我估计在1.5有for语句增强之前不少人都写过，这样的代码有什么问题呢？考虑下list是ArrayList和LinkedList这两种情况，List是链表的抽象，但是链表的实现形式却是可以用数组或者引用链接，链表的实现形式不同，List.get(index)这个方法的效率会很成问题。我们都知道ArrayList适宜于随机访问，而LinkedList方便插入添加移除，在这个doSomething方法中，显然随机访问的诉求大于添加移除。在通常情况下，这样写都不会成为问题，但是如果这个doSomething方法被经常调用，并且list是一个LinkedList的情况下，这个方法就很可能成为性能瓶颈。我们寄希望于List这个接口可以让我们无需关心list的具体实现，然而现实是你仍然需要知道各种实现的区别和原理，这就是所谓漏洞抽象。这并非抽象的无力，你肯定不会反对&#8220;针对接口编程&#8221;这条原则，而是抽象本身解决不了本质复杂性，这里的本质复杂性就是链表的实现方法，随机访问与添加移除的平衡问题。在我们无法找到更好的链表实现方法来平衡随机访问与添加移除之前，这个本质复杂性就不是抽象能够解决的。<br />
&nbsp;&nbsp;&nbsp; 同样的现象出现在String、StringBuffer、StringBuilder的使用上，字符串的实现方法你仍然需要知道，这是绕不过去的本质复杂性。这里谈到的本质复杂性根本上也是现实世界的本质复杂性的反映，扯远些就更虚了。就现实的工作情况来看，不知道其他人有没有这样的经验，就是在自以为解决某个难题的时候，最后却发现难题以另一个面目出现，问题本身没有得到解决，只是以更好的方式被掩盖了。<br />
&nbsp;&nbsp; 无论是过程式、OO、函数式编程，解决的问题都是为了更好的抽象，抽象是个好东西，但是抽象无法解决那些本质性的问题，因此《人月神话》断言没有银弹，我们仍然需要跟狼人作战。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/308942.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2010-01-10 20:25 <a href="http://www.blogjava.net/killme2008/archive/2010/01/10/308942.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>逻辑学应该从小学教起</title><link>http://www.blogjava.net/killme2008/archive/2009/12/12/305726.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sat, 12 Dec 2009 08:35:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2009/12/12/305726.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/305726.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2009/12/12/305726.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/305726.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/305726.html</trackback:ping><description><![CDATA[&nbsp;&nbsp; &nbsp;最近读数理逻辑方面的资料，感慨自己没有早点接触逻辑学，如果在小学初中阶段就能有逻辑学的系统训练，我想我对数学的理解会完全不一样，对定理证明的思路也将大大开拓。中学时代对数学充满热情，基本上老师讲的都满足不了我，我的学习远远在课堂前面，初中的时候我已经接触了微积分、概率论、立体几何之类，教材是从我舅舅用过的教材垃圾堆里淘出来的，那时候我外婆准备卖了那堆书，就叫我去看看有没有想要的，印象中从那里掏出了不少好东西，武侠小说、马克思恩格斯全集、毛选、数学语文教材之流，在老家那个阅读资料极度缺少的地方，这些书成了我整个初中的精神食粮。上了高中后，家也搬到县城，离书城近了，并且学校有图书馆，更是如鱼得水。扯的太远，回到题目，以数学定理的证明为例，我们熟知的直接证明、反证法、数学归纳法、间接证明、存在性证明、唯一性证明其实背后都有牢固的逻辑定律在支撑，直接证明其实就是蕴含 p-&gt; q，而反证法的原理是<span style="font-family: sans-serif; font-size: 15px; line-height: 22px; ">&#172;&#172;p&nbsp;&#8596; p，间接证明则是原命题与逆否命题等价 p-&gt; q&nbsp;&#8596;&nbsp;&#172;q -&gt;&nbsp;&#172;p等等。如果在教授数学的同时，教授给学生背后的逻辑原理，那么将极大地开阔学生的视野并且让数学证明变的有趣。数理逻辑不仅仅对数学学习有益，对软件开发同样有帮助，例如以谓词和量词来精确地描述和分析系统规格，推理逻辑的使用也能启发你的设计思路，帮你找到一个复杂的设计的等价物。此外，你能更快地比别人做出某些逻辑难题，这也挺有趣。</span><img src ="http://www.blogjava.net/killme2008/aggbug/305726.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2009-12-12 16:35 <a href="http://www.blogjava.net/killme2008/archive/2009/12/12/305726.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>amb解决排列组合问题</title><link>http://www.blogjava.net/killme2008/archive/2009/10/19/298820.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 19 Oct 2009 03:37:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2009/10/19/298820.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/298820.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2009/10/19/298820.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/298820.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/298820.html</trackback:ping><description><![CDATA[&nbsp; 看到这么一个题目：<br />
&nbsp;&nbsp;&nbsp; {3,2,2,6,7,8}排序输出,7不在第二位,68不在一起。<br />
&nbsp; <br />
&nbsp; 这样的题目似乎避免不了遍历，关键还在于过滤条件的安排，怎么让过滤的范围尽量地小。通常的做法是循环遍历，对于类似Prolog这样的语言来说，由于内置了推理引擎，可以简单地描述问题，让引擎来帮你做递归遍历，解决这类问题是非常简单的。Prolog好久没写，以Ruby的amb操作符为例来解决这道题目：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008000;">#</span><span style="color: #008000;">结果为hash，去重</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">$hash</span><span style="color: #000000;">=</span><span style="color: #000000;">{}<br />
amb</span><span style="color: #000000;">=</span><span style="color: #000000;">Amb.new<br />
array</span><span style="color: #000000;">=</span><span style="color: #000000;">[</span><span style="color: #000000;">3</span><span style="color: #000000;">,</span><span style="color: #000000;">2</span><span style="color: #000000;">,</span><span style="color: #000000;">2</span><span style="color: #000000;">,</span><span style="color: #000000;">6</span><span style="color: #000000;">,</span><span style="color: #000000;">7</span><span style="color: #000000;">,</span><span style="color: #000000;">8</span><span style="color: #000000;">]<br />
</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;array<br />
&nbsp;alias&nbsp;remove&nbsp;delete<br />
&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;delete(</span><span style="color: #000000;">*</span><span style="color: #000000;">nums)<br />
&nbsp;&nbsp;&nbsp;result</span><span style="color: #000000;">=</span><span style="color: #000000;">dup<br />
&nbsp;&nbsp;&nbsp;nums.each&nbsp;do&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">n</span><span style="color: #000000;">|</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;result.delete_at(result.index(n))&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;result.index(n)<br />
&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;result<br />
&nbsp;end<br />
end<br />
</span><span style="color: #008000;">#</span><span style="color: #008000;">从集合选元素</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">one</span><span style="color: #000000;">=</span><span style="color: #000000;">amb.choose(</span><span style="color: #000000;">*</span><span style="color: #000000;">array)<br />
two</span><span style="color: #000000;">=</span><span style="color: #000000;">amb.choose(</span><span style="color: #000000;">*</span><span style="color: #000000;">(array.delete(one)))<br />
three</span><span style="color: #000000;">=</span><span style="color: #000000;">amb.choose(</span><span style="color: #000000;">*</span><span style="color: #000000;">(array.delete(one,two)))<br />
four</span><span style="color: #000000;">=</span><span style="color: #000000;">amb.choose(</span><span style="color: #000000;">*</span><span style="color: #000000;">(array.delete(one,two,three)))<br />
five</span><span style="color: #000000;">=</span><span style="color: #000000;">amb.choose(</span><span style="color: #000000;">*</span><span style="color: #000000;">(array.delete(one,two,three,four)))<br />
six</span><span style="color: #000000;">=</span><span style="color: #000000;">amb.choose(</span><span style="color: #000000;">*</span><span style="color: #000000;">(array.delete(one,two,three,four,five)))<br />
<br />
</span><span style="color: #008000;">#</span><span style="color: #008000;">条件1：第二个位置不能是7</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">amb.require(two</span><span style="color: #000000;">!=</span><span style="color: #000000;">7</span><span style="color: #000000;">)<br />
</span><span style="color: #008000;">#</span><span style="color: #008000;">条件2：6跟8不能一起出现</span><span style="color: #008000;"><br />
</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;six_eight_not_join(a,b)<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">#{a}#{b}</span><span style="color: #800000;">"</span><span style="color: #000000;">!=</span><span style="color: #800000;">"</span><span style="color: #800000;">68</span><span style="color: #800000;">"</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #800000;">"</span><span style="color: #800000;">#{a}#{b}</span><span style="color: #800000;">"</span><span style="color: #000000;">!=</span><span style="color: #800000;">"</span><span style="color: #800000;">86</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
end<br />
amb.require(six_eight_not_join(one,two))<br />
amb.require(six_eight_not_join(two,three))<br />
amb.require(six_eight_not_join(three,four))<br />
amb.require(six_eight_not_join(four,five))<br />
amb.require(six_eight_not_join(five,six))<br />
<br />
</span><span style="color: #008000;">#</span><span style="color: #008000;">条件3：不重复,利用全局hash判断</span><span style="color: #008000;"><br />
</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;distinct?(one,two,three,four,five,six)<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;$hash[</span><span style="color: #800000;">"</span><span style="color: #800000;">#{one},#{two},#{three},#{four},#{five},#{six}</span><span style="color: #800000;">"</span><span style="color: #000000;">].nil?<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$hash[</span><span style="color: #800000;">"</span><span style="color: #800000;">#{one},#{two},#{three},#{four},#{five},#{six}</span><span style="color: #800000;">"</span><span style="color: #000000;">]</span><span style="color: #000000;">=</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">记录</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;true<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;false<br />
&nbsp;&nbsp;end<br />
end<br />
amb.require(distinct?(one,two,three,four,five,six))<br />
puts&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">#{one},#{two},#{three},#{four},#{five},#{six}</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
amb.failure</span></div>
<br />
<br />
&nbsp;&nbsp; 三个条件的满足通过amb.require来设置，这里安排的只是一种顺序，可以根据实际测试结果来安排这些条件的顺序以最大程度地提高效率。代码注释很清楚了，我就不多嘴了。Ruby amb的实现可以看<a href="http://www.blogjava.net/killme2008/archive/2008/11/15/240672.html">这里</a>。什么是amb可以看<a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.55.8479">这个</a>。<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/298820.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2009-10-19 11:37 <a href="http://www.blogjava.net/killme2008/archive/2009/10/19/298820.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>os的进程调度（读书笔记）</title><link>http://www.blogjava.net/killme2008/archive/2009/06/28/284459.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sun, 28 Jun 2009 05:28:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2009/06/28/284459.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/284459.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2009/06/28/284459.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/284459.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/284459.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 在多进程、多线程并发的环境里，从概念上看，有多个进程或者多个线程在同时执行，具体到单个CPU级别，实际上任何时刻只能有一个进程或者线程处于执行状态；因此OS需要决定哪个进程执行，哪些进程等待，也就是进程的调度。<br />
一、调度的目标<br />
1、首先要区分程序使用CPU的三种模式：IO密集型、计算密集型和平衡型。对于IO密集型程序来说，响应时间非常重要；对于CPU密集型来说，CPU的周转时间就比较重要；对于平衡型程序来说，响应和周转之间的平衡是最重要的。<br />
2、CPU的调度就是要达到极小化平均响应时间、极大化系统吞吐率、保持系统各个功能部件均处于繁忙状态和提供某种公平的机制。<br />
3、对于实时系统来说，调度的目标就是要达到截止时间前完成所应该完成的任务和提供性能的可预测性。<br />
<br />
二、调度算法<br />
<br />
1、FCFS（First come first serve)，或者称为FIFO算法，先来先处理。这个算法的优点是简单，实现容易，并且似乎公平；缺点在于短的任务有可能变的非常慢，因为其前面的任务占用很长时间，造成了平均响应时间非常慢。<br />
<br />
2、时间片轮询算法，这是对FIFO算法的改进，目的是改善短程序（运行时间短）的响应时间，其方法就是周期性地进行进程切换。这个算法的关键点在于时间片的选择，时间片过大，那么轮转就越接近FIFO，如果太小，进程切换的开销大于执行程序的开销，从而降低了系统效率。因此选择合适的时间片就非常重要。选择时间片的两个需要考虑的因素：一次进程切换所使用的系统消耗以及我们能接受的整个系统消耗、系统运行的进程数。<br />
&nbsp;&nbsp;&nbsp; 时间片轮询看上起非常公平，并且响应时间非常好，然而时间片轮转并不能保证系统的响应时间总是比FIFO短，这很大程度上取决于时间片大小的选择，以及这个大小与进程运行时间的相互关系。<br />
<br />
3、STCF算法（Short time to complete first)，顾名思义就是短任务优先算法。这种算法的核心就是所有的程序都有一个优先级，短任务的优先级比长任务的高，而OS总是安排优先级高的进程运行。<br />
&nbsp;&nbsp;&nbsp; STCF又分为两类：非抢占式和抢占式。非抢占式STCF就是让已经在CPU上运行的程序执行到结束或者阻塞，然后在所有的就绪进程中选择执行时间最短的来执行；而抢占式STCF就不是这样，在每进来一个新的进程时，就对所有进程（包括正在CPU上执行的进程）进行检查，谁的执行时间短，就运行谁。<br />
<br />
&nbsp;&nbsp;&nbsp; STCF总是能提供最优的响应时间，然而它也有缺点，第一可能造成长任务的程序无法得到CPU时间而饥饿，因为OS总是优先执行短任务；其次，关键问题在于我们怎么知道程序的运行时间，怎么预测某个进程需要的执行时间？通常有两个办法：使用启发式方法估算（例如根据程序大小估算），或者将程序执行一遍后记录其所用的CPU时间，在以后的执行过程中就可以根据这个测量数据来进行STCF调度。<br />
<br />
4、优先级调度，STCF遇到的问题是长任务的程序可能饥饿，那么优先级调度算法可以通过给长任务的进程更高的优先级来解决这个问题；优先级调度遇到的问题可能是短任务的进程饥饿，这个可以通过动态调整优先级来解决。实际上动态调整优先级（称为权值）+时间片轮询的策略正是linux的进程调度策略之一的 SCHED_OTHER分时调度策略,它的调度过程如下：<br />
<br />
（1）创建任务指定采用分时调度策略，并指定优先级nice值(-20~19)。<br />
<br />
（2）将根据每个任务的nice值确定在cpu上的执行时间(counter)。<br />
<br />
（3）如果没有等待资源，则将该任务加入到就绪队列中。<br />
<br />
（4）调度程序遍历就绪队列中的任务，通过对每个任务动态优先级的计算(counter+20-nice)结果，选择计算结果最大的一个去运行，当这个时间片用完后(counter减至0)或者主动放弃cpu时，该任务将被放在就绪队列末尾(时间片用完)或等待队列(因等待资源而放弃cpu)中。<br />
<br />
（5）此时调度程序重复上面计算过程，转到第4步。<br />
<br />
（6）当调度程序发现所有就绪任务计算所得的权值都为不大于0时，重复第2步。<br />
<br />
linux还有两个实时进程的调度策略：FIFO和RR,实时进程会立即抢占非实时进程。<br />
<br />
5、显然，没有什么调度算法是毫无缺点的，因此现代OS通常都会采用混合调度算法。例如将不同的进程分为几个大类，每个大类有不同的优先级，不同大类的进程的调度取决于大类的优先级，同一个大类的进程采用时间片轮询来保证公平性。<br />
<br />
6、其他调度算法，保证调度算法保证每个进程享用的CPU时间完全一样；彩票调度算法是一种概率调度算法，通过给进程&#8220;发彩票&#8221;的多少，来赋予不同进程不同的调用时间，彩票调度算法的优点是非常灵活，如果你给短任务发更多&#8220;彩票&#8221;，那么就类似STCF调度，如果给每个进程一样多的&#8220;彩票&#8221;，那么就类似保证调度；用户公平调度算法，是按照每个用户，而不是按照每个进程来进行公平分配CPU时间，这是为了防止贪婪用户启用了过多进程导致系统效率降低甚至停顿。<br />
<br />
7、实时系统的调度算法，实时系统需要考虑每个具体任务的响应时间必须符合要求，在截止时间前完成。<br />
（1）EDF调度算法，就是最早截止任务优先（Earliest deadline first)算法，也就是让最早截止的任务先做。当新的任务过来时，如果它的截止时间更靠前，那么就让新任务抢占正在执行的任务。EDF算法其实是贪心算法的一种体现。如果一组任务可以被调度（也就是所有任务的截止时间在理论上都可以得到满足），那么EDF可以满足。如果一批任务不能全部满足（全部在各自的截止时间前完成），那EDF满足的任务数最多，这就是它最优的体现。EDF其实就是抢占式的STCF，只不过将程序的执行时间换成了截止时间。EDF的缺点在于需要对每个任务的截止时间做计算并动态调整优先级，并且抢占任务也需要消耗系统资源。因此它的实际效果比理论效果差一点。<br />
<br />
（2）RMS调度算法，EDF是动态调度算法，而RMS（rate monotonic scheduling)算法是一种静态最优算法；该算法在进行调度前先计算出所有任务的优先级，然后按照计算出来的优先级进行调度，任务执行中间既不接收新任务，也不进行优先级调整或者CPU抢占。因此它的优点是系统消耗小，缺点就是不灵活了。对于RMS算法，关键点在于判断一个任务组是否能被调度，这里有一个定律，如果一个系统的所有任务的CPU利用率都低于ln2，那么这些任务的截止时间均可以得到满足，ln2约等于0.693147，也就是此时系统还剩下有30%的CPU时间。这个证明是Liu和Kayland在1973年给出的。<br />
<br />
三、优先级反转<br />
1、什么是优先级反转？<br />
&nbsp;&nbsp;&nbsp; 优先级反转是指一个低优先级的任务持有一个被高优先级任务所需要的共享资源。高优先任务由于因资源缺乏而处于受阻状态，一直等到低优先级任务释放资源为止。而低优先级获得的CPU时间少，如果此时有优先级处于两者之间的任务，并且不需要那个共享资源，则该中优先级的任务反而超过这两个任务而获得CPU时间。如果高优先级等待资源时不是阻塞等待，而是忙循环，则可能永远无法获得资源，因为此时低优先级进程无法与高优先级进程争夺CPU时间，从而无法执行，进而无法释放资源，造成的后果就是高优先级任务无法获得资源而继续推进。<br />
<br />
2、解决方案：<br />
（1）设置优先级上限，给临界区一个高优先级，进入临界区的进程都将获得这个高优先级，如果其他试图进入临界区的进程的优先级都低于这个高优先级，那么优先级反转就不会发生。<br />
<br />
（2）优先级继承，当一个高优先级进程等待一个低优先级进程持有的资源时，低优先级进程将暂时获得高优先级进程的优先级别，在释放共享资源后，低优先级进程回到原来的优先级别。嵌入式系统VxWorks就是采用这种策略。<br />
&nbsp;&nbsp;&nbsp; 这里还有一个八卦，1997年的美国的火星探测器（使用的就是vxworks)就遇到一个优先级反转问题引起的故障。简单说下，火星探测器有一个信息总线，有一个高优先级的总线任务负责总线数据的存取，访问总线都需要通过一个互斥锁（共享资源出现了）；还有一个低优先级的，运行不是很频繁的气象搜集任务，它需要对总线写数据，也就同样需要访问互斥锁；最后还有一个中优先级的通信任务，它的运行时间比较长。平常这个系统运行毫无问题，但是有一天，在气象任务获得互斥锁往总线写数据的时候，一个中断发生导致通信任务被调度就绪，通信任务抢占了低优先级的气象任务，而无巧不成书的是，此时高优先级的总线任务正在等待气象任务写完数据归还互斥锁，但是由于通信任务抢占了CPU并且运行时间比较长，导致气象任务得不到CPU时间也无法释放互斥锁，本来是高优先级的总线任务也无法执行，总线任务无法及时执行的后果被探路者认为是一个严重错误，最后就是整个系统被重启。Vxworks允许优先级继承，然而遗憾的工程师们将这个选项关闭了。<br />
<br />
（3）第三种方法就是使用中断禁止，通过禁止中断来保护临界区，采用此种策略的系统只有两种优先级：可抢占优先级和中断禁止优先级。前者为一般进程运行时的优先级，后者为运行于临界区的优先级。火星探路者正是由于在临界区中运行的气象任务被中断发生的通信任务所抢占才导致故障，如果有临界区的禁止中断保护，此一问题也不会发生。<br />
&nbsp; <br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/284459.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2009-06-28 13:28 <a href="http://www.blogjava.net/killme2008/archive/2009/06/28/284459.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sicp 5.1节习题尝试解答</title><link>http://www.blogjava.net/killme2008/archive/2009/06/11/281357.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 10 Jun 2009 16:47:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2009/06/11/281357.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/281357.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2009/06/11/281357.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/281357.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/281357.html</trackback:ping><description><![CDATA[<br />
<strong>5.1</strong> 图就不画在机器上了，麻烦<br />
<br />
<strong>5.2</strong> 用寄存器语言描述5.1题中的阶乘机器，加上了读取和打印,这里的解答全部在实际的寄存机器中验证过，但是仍然按照该节的表示法表示。<br />
<br />
<div style="border-left-color: #cccccc; padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; background-color: #eeeeee; font-size: 13px; width: 98%; "><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(controller<br />
&nbsp; fac</span><span style="color: #000000;">-</span><span style="color: #000000;">loop<br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;n&nbsp;(op&nbsp;read))<br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;product&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;counter&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">))<br />
&nbsp; iter</span><span style="color: #000000;">-</span><span style="color: #000000;">loop<br />
&nbsp;&nbsp;&nbsp;(test&nbsp;(op&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">)&nbsp;(reg&nbsp;counter)&nbsp;(reg&nbsp;n))<br />
&nbsp;&nbsp;&nbsp;(branch&nbsp;(label&nbsp;iter</span><span style="color: #000000;">-</span><span style="color: #000000;">done))<br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;product&nbsp;(op&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">)&nbsp;(reg&nbsp;product)&nbsp;(reg&nbsp;counter))<br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;counter&nbsp;(op&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">)&nbsp;(reg&nbsp;counter)&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">goto</span><span style="color: #000000;">&nbsp;(label&nbsp;iter</span><span style="color: #000000;">-</span><span style="color: #000000;">loop))<br />
&nbsp; iter</span><span style="color: #000000;">-</span><span style="color: #000000;">done<br />
&nbsp;&nbsp;&nbsp;(perform&nbsp;(op&nbsp;print)&nbsp;(reg&nbsp;product))<br />
&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">goto</span><span style="color: #000000;">&nbsp;(label&nbsp;fac</span><span style="color: #000000;">-</span><span style="color: #000000;">loop)))</span></div>
&nbsp;<br />
<strong>5.3</strong> 牛顿法求平方根，将这个过程转化为寄存器语言，第一个版本，假设good-enough?和improve都是基本过程，<br />
<div style="border-left-color: #cccccc; padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; background-color: #eeeeee; font-size: 13px; width: 98%; "><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">;version1<br />
(controller<br />
&nbsp;&nbsp;&nbsp;sqrt</span><span style="color: #000000;">-</span><span style="color: #000000;">loop<br />
&nbsp;&nbsp;&nbsp;&nbsp;(test&nbsp;(op&nbsp;good</span><span style="color: #000000;">-</span><span style="color: #000000;">enough</span><span style="color: #000000;">?</span><span style="color: #000000;">)&nbsp;(reg&nbsp;guess))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(branch&nbsp;(label&nbsp;sqrt</span><span style="color: #000000;">-</span><span style="color: #000000;">done))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(assign&nbsp;guess&nbsp;(op&nbsp;improve)&nbsp;(reg&nbsp;guess))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">goto</span><span style="color: #000000;">&nbsp;(label&nbsp;good</span><span style="color: #000000;">-</span><span style="color: #000000;">enough))<br />
&nbsp;&nbsp;&nbsp;sqrt</span><span style="color: #000000;">-</span><span style="color: #000000;">done)</span></div>
<br />
&nbsp; 第二个版本，展开good-enough?过程，<br />
<div style="border-left-color: #cccccc; padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; background-color: #eeeeee; font-size: 13px; width: 98%; "><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">;version2<br />
(controller<br />
&nbsp;&nbsp;&nbsp;good</span><span style="color: #000000;">-</span><span style="color: #000000;">enough<br />
&nbsp;&nbsp;&nbsp;&nbsp;(assign&nbsp;t&nbsp;(op&nbsp;square)&nbsp;(reg&nbsp;guess))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(assign&nbsp;t&nbsp;(op&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">)&nbsp;(reg&nbsp;t)&nbsp;(reg&nbsp;x))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(assign&nbsp;t&nbsp;(op&nbsp;abs)&nbsp;(reg&nbsp;t))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(test&nbsp;(op&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">)&nbsp;(reg&nbsp;t)&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0.001</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(branch&nbsp;(label&nbsp;sqrt</span><span style="color: #000000;">-</span><span style="color: #000000;">done))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(assign&nbsp;guess&nbsp;(op&nbsp;improve)&nbsp;(reg&nbsp;guess))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">goto</span><span style="color: #000000;">&nbsp;(label&nbsp;good</span><span style="color: #000000;">-</span><span style="color: #000000;">enough))<br />
&nbsp;&nbsp;&nbsp;sqrt</span><span style="color: #000000;">-</span><span style="color: #000000;">done)</span></div>
&nbsp; 最后，展开improve过程，<br />
<div style="border-left-color: #cccccc; padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; background-color: #eeeeee; font-size: 13px; width: 98%; "><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">;version3<br />
(controller<br />
&nbsp; sqrt-init<br />
&nbsp;&nbsp; (assign guess (const 1.0))<br />
&nbsp;&nbsp; (assign x (op read))<br />
&nbsp; good</span><span style="color: #000000;">-</span><span style="color: #000000;">enough<br />
&nbsp;&nbsp;&nbsp;&nbsp;;good</span><span style="color: #000000;">-</span><span style="color: #000000;">enough<br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;t&nbsp;(op&nbsp;square)&nbsp;(reg&nbsp;guess))<br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;t&nbsp;(op&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">)&nbsp;(reg&nbsp;t)&nbsp;(reg&nbsp;x))<br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;t&nbsp;(op&nbsp;abs)&nbsp;(reg&nbsp;t))<br />
&nbsp;&nbsp;&nbsp;(test&nbsp;(op&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">)&nbsp;(reg&nbsp;t)&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0.001</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;(branch&nbsp;(label&nbsp;sqrt</span><span style="color: #000000;">-</span><span style="color: #000000;">done))<br />
&nbsp;&nbsp;&nbsp;&nbsp;;improve<br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;t&nbsp;(op&nbsp;</span><span style="color: #000000;">/</span><span style="color: #000000;">)&nbsp;(reg&nbsp;x)&nbsp;(reg&nbsp;guess))<br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;t&nbsp;(op&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">)&nbsp;(reg&nbsp;guess)&nbsp;(reg&nbsp;t))<br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;guess&nbsp;(op&nbsp;</span><span style="color: #000000;">/</span><span style="color: #000000;">)&nbsp;(reg&nbsp;t)&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2.0</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">goto</span><span style="color: #000000;">&nbsp;(label&nbsp;good</span><span style="color: #000000;">-</span><span style="color: #000000;">enough))<br />
&nbsp; sqrt</span><span style="color: #000000;">-</span><span style="color: #000000;">done)</span></div>
&nbsp;&nbsp; 在start之后，从寄存器guess中得到最后结果。<br />
<br />
<strong>5.4</strong> <br />
a)第一个是一个指数计算过程，用到了递归，因此需要引入continue寄存器来保存和恢复堆栈，实现与阶乘相似，如下<br />
<br />
<div style="border-left-color: #cccccc; padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; background-color: #eeeeee; font-size: 13px; width: 98%; "><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(controller</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;(assign&nbsp;</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">&nbsp;(label&nbsp;expt</span><span style="color: #000000;">-</span><span style="color: #000000;">done))<br />
&nbsp;&nbsp;&nbsp;&nbsp;expt</span><span style="color: #000000;">-</span><span style="color: #000000;">loop<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(test&nbsp;(op&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">)&nbsp;(reg&nbsp;n)&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(branch&nbsp;(label&nbsp;expt</span><span style="color: #000000;">-</span><span style="color: #000000;">base</span><span style="color: #000000;">-</span><span style="color: #0000ff;">case</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;;保存continue<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(save&nbsp;</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(assign&nbsp;n&nbsp;(op&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">)&nbsp;(reg&nbsp;n)&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(assign&nbsp;</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">&nbsp;(label&nbsp;after</span><span style="color: #000000;">-</span><span style="color: #000000;">expt))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">goto</span><span style="color: #000000;">&nbsp;(label&nbsp;expt</span><span style="color: #000000;">-</span><span style="color: #000000;">loop))<br />
&nbsp;&nbsp;&nbsp;&nbsp;after</span><span style="color: #000000;">-</span><span style="color: #000000;">expt<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;;恢复continue<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(restore&nbsp;</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(assign&nbsp;val&nbsp;(op&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">)&nbsp;(reg&nbsp;b)&nbsp;(reg&nbsp;val))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">goto</span><span style="color: #000000;">&nbsp;(reg&nbsp;</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;expt</span><span style="color: #000000;">-</span><span style="color: #000000;">base</span><span style="color: #000000;">-</span><span style="color: #0000ff;">case</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(assign&nbsp;val&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">goto</span><span style="color: #000000;">&nbsp;(reg&nbsp;</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;expt</span><span style="color: #000000;">-</span><span style="color: #000000;">done<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(perform&nbsp;(op&nbsp;display)&nbsp;(reg&nbsp;val)))</span></div>
<br />
b) 迭代型的递归计算过程，尾递归调用，因此不需要continue寄存器来保存和恢复堆栈，这道习题就是希望能分辨非尾递归和尾递归带来的寄存机器语言的区别<br />
<div style="border-left-color: #cccccc; padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; background-color: #eeeeee; font-size: 13px; width: 98%; "><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(controller<br />
&nbsp;&nbsp;&nbsp;&nbsp;(assign&nbsp;product&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(assign&nbsp;n&nbsp;(op&nbsp;read))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(assign&nbsp;b&nbsp;(op&nbsp;read))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(assign&nbsp;counter&nbsp;(reg&nbsp;n))<br />
&nbsp;&nbsp;&nbsp;expt</span><span style="color: #000000;">-</span><span style="color: #000000;">iter</span><span style="color: #000000;">-</span><span style="color: #000000;">loop<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(test&nbsp;(op&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">)&nbsp;(reg&nbsp;counter)&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(branch&nbsp;(label&nbsp;expt</span><span style="color: #000000;">-</span><span style="color: #000000;">done))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(assign&nbsp;counter&nbsp;(op&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">)&nbsp;(reg&nbsp;counter)&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(assign&nbsp;product&nbsp;(op&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">)&nbsp;(reg&nbsp;b)&nbsp;(reg&nbsp;product))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">goto</span><span style="color: #000000;">&nbsp;(label&nbsp;expt</span><span style="color: #000000;">-</span><span style="color: #000000;">iter</span><span style="color: #000000;">-</span><span style="color: #000000;">loop))<br />
&nbsp;&nbsp;&nbsp;expt</span><span style="color: #000000;">-</span><span style="color: #000000;">done<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(perform&nbsp;(op&nbsp;display)&nbsp;(reg&nbsp;product)))</span></div>
<br />
<strong>5.5</strong>&nbsp; 手工模拟就算了，5.2节就可以机器模拟了<br />
<br />
<strong>5.6</strong> 是有一个多余的save和一个多余的restore操作，请看注释：<br />
<div style="border-left-color: #cccccc; padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; background-color: #eeeeee; font-size: 13px; width: 98%; "><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(<br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">&nbsp;(label&nbsp;fib</span><span style="color: #000000;">-</span><span style="color: #000000;">done))<br />
&nbsp;&nbsp;fib</span><span style="color: #000000;">-</span><span style="color: #000000;">loop<br />
&nbsp;&nbsp;&nbsp;(test&nbsp;(op&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">)&nbsp;(reg&nbsp;n)&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;(branch&nbsp;(label&nbsp;immediate</span><span style="color: #000000;">-</span><span style="color: #000000;">answer))<br />
&nbsp;&nbsp;&nbsp;;;compute&nbsp;fib(n</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;(save&nbsp;</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">&nbsp;(label&nbsp;after</span><span style="color: #000000;">-</span><span style="color: #000000;">fib</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;(save&nbsp;n)<br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;n&nbsp;(op&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">)&nbsp;(reg&nbsp;n)&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">goto</span><span style="color: #000000;">&nbsp;(label&nbsp;fib</span><span style="color: #000000;">-</span><span style="color: #000000;">loop))<br />
&nbsp;&nbsp;after</span><span style="color: #000000;">-</span><span style="color: #000000;">fib</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;<br />
&nbsp;&nbsp;&nbsp;;;compute&nbsp;fib(n</span><span style="color: #000000;">-</span><span style="color: #000000;">2</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;(restore&nbsp;n)<br />
&nbsp;&nbsp;&nbsp;;这里多余，(restore&nbsp;</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;n&nbsp;(op&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">)&nbsp;(reg&nbsp;n)&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;;这里多余，(save&nbsp;</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">&nbsp;(label&nbsp;after</span><span style="color: #000000;">-</span><span style="color: #000000;">fib</span><span style="color: #000000;">-</span><span style="color: #000000;">2</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;(save&nbsp;val)&nbsp;;;save&nbsp;fib(n</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">goto</span><span style="color: #000000;">&nbsp;(label&nbsp;fib</span><span style="color: #000000;">-</span><span style="color: #000000;">loop))<br />
&nbsp;&nbsp;after</span><span style="color: #000000;">-</span><span style="color: #000000;">fib</span><span style="color: #000000;">-</span><span style="color: #000000;">2</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;n&nbsp;(reg&nbsp;val))<br />
&nbsp;&nbsp;&nbsp;(restore&nbsp;val)<br />
&nbsp;&nbsp;&nbsp;(restore&nbsp;</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;val&nbsp;(op&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">)&nbsp;(reg&nbsp;val)&nbsp;(reg&nbsp;n))<br />
&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">goto</span><span style="color: #000000;">&nbsp;(reg&nbsp;</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">))<br />
&nbsp;immediate</span><span style="color: #000000;">-</span><span style="color: #000000;">answer<br />
&nbsp;&nbsp;&nbsp;(assign&nbsp;val&nbsp;(reg&nbsp;n))<br />
&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">goto</span><span style="color: #000000;">&nbsp;(reg&nbsp;</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;fib</span><span style="color: #000000;">-</span><span style="color: #000000;">done)</span></div>
<br />
<br />
<br />
&nbsp;&nbsp; <br />
<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/281357.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2009-06-11 00:47 <a href="http://www.blogjava.net/killme2008/archive/2009/06/11/281357.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于网络的错误假设</title><link>http://www.blogjava.net/killme2008/archive/2009/05/02/268602.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sat, 02 May 2009 05:02:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2009/05/02/268602.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/268602.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2009/05/02/268602.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/268602.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/268602.html</trackback:ping><description><![CDATA[每个第一次构建分布式系统的人都可能会做出8个错误的对网络的假设：<br />
<table class="zeroBorder">
    <tbody>
        <tr>
            <td align="right" valign="top">1. </td>
            <td valign="top">The network is reliable</td>
        </tr>
        <tr>
            <td align="right" valign="top">2. </td>
            <td valign="top">Latency is zero </td>
        </tr>
        <tr>
            <td align="right" valign="top">3. </td>
            <td valign="top">Bandwidth is infinite </td>
        </tr>
        <tr>
            <td align="right" valign="top">4. </td>
            <td valign="top">The network is secure </td>
        </tr>
        <tr>
            <td align="right" valign="top">5. </td>
            <td valign="top">Topology doesn't change </td>
        </tr>
        <tr>
            <td align="right" valign="top">6. </td>
            <td valign="top">There is one administrator </td>
        </tr>
        <tr>
            <td align="right" valign="top">7. </td>
            <td valign="top">Transport cost is zero </td>
        </tr>
        <tr>
            <td align="right" valign="top">8. </td>
            <td valign="top">The network is homogeneous</td>
        </tr>
    </tbody>
</table>
<br />
翻译过来就是：<br />
1、网络是稳定可靠的<br />
2、没有延迟<br />
3、带宽无限<br />
4、网络是安全的<br />
5、网络拓扑不会改变<br />
6、只有一个管理员<br />
7、传输成本为0<br />
8、网络是均匀的，现实是各种网络环境都有。<br />
<br />
更多错误假设：<br />
1、网络IO跟磁盘IO一样<br />
&nbsp;&nbsp;&nbsp; 网络IO比之磁盘IO更不可预测、不可靠和不可控，网络IO包括了软硬件两方面的限制。<br />
2、你与对端能够同步<br />
&nbsp; 你无法假设对端是否关闭、接收到数据，这些通常需要你在应用协议里同步。<br />
3、所有的错误都可以被检测到。<br />
&nbsp;&nbsp;&nbsp; 很多错误例如对端关闭引起的读阻塞都需要应用层来处理。<br />
<br />
4、资源无限可用。<br />
5、应用可以无限等待一个远程服务<br />
&nbsp;&nbsp;&nbsp; 任何大规模的应用都需要慎重设计超时、过期策略<br />
<br />
6、远程服务总能响应及时。<br />
7、只有单点失败<br />
8、只有一个资源分配器<br />
9、只有一个时间，也就是全局时间的问题。<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/268602.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2009-05-02 13:02 <a href="http://www.blogjava.net/killme2008/archive/2009/05/02/268602.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>scheme中文编程</title><link>http://www.blogjava.net/killme2008/archive/2009/03/20/261142.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 20 Mar 2009 15:27:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2009/03/20/261142.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/261142.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2009/03/20/261142.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/261142.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/261142.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;&nbsp; 受javaeye上的《Ruby中文编程》启发，帖子中有人提到如果if这样的关键字都可以定义成中文，那就是真正的中文编程。那时我就想到，这个其实要在scheme中实现是多么简单，将sicp书中的解释器稍微修改下就可以了，只要修改解析的部分即可。解释器的完整代码放后面，我们先看看有趣的例子：Code highlighting produced by A...&nbsp;&nbsp;<a href='http://www.blogjava.net/killme2008/archive/2009/03/20/261142.html'>阅读全文</a><img src ="http://www.blogjava.net/killme2008/aggbug/261142.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2009-03-20 23:27 <a href="http://www.blogjava.net/killme2008/archive/2009/03/20/261142.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sicp 4.4.1小节习题</title><link>http://www.blogjava.net/killme2008/archive/2008/11/22/241931.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sat, 22 Nov 2008 05:27:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/11/22/241931.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/241931.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/11/22/241931.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/241931.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/241931.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;&nbsp; 本节开始进入第4章最后一部分——逻辑程序设计。scheme将实现一种查询语言，非常类似prolog。由于解释器的实现在后面，还未读到，前面的习题我都将用prolog做测试，当然也给出scheme版本的解答，待以后测试。&nbsp;&nbsp;&nbsp; 首先给出依照书中所述写出的prolog事实库：Code highlighting prod...&nbsp;&nbsp;<a href='http://www.blogjava.net/killme2008/archive/2008/11/22/241931.html'>阅读全文</a><img src ="http://www.blogjava.net/killme2008/aggbug/241931.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-11-22 13:27 <a href="http://www.blogjava.net/killme2008/archive/2008/11/22/241931.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sicp 4.3.3小节习题</title><link>http://www.blogjava.net/killme2008/archive/2008/11/21/241804.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 21 Nov 2008 02:26:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/11/21/241804.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/241804.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/11/21/241804.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/241804.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/241804.html</trackback:ping><description><![CDATA[<br />
&nbsp;&nbsp;&nbsp; 本节实现了amb求值器，题目都是扩展这个求值器，引入一些特殊的过程。我的尝试解答从4.51开始<br />
习题4.51，要求实现permanent-set!，这个过程的副作用在遇到失败时不撤销，实现如下：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">;扩充analyze&nbsp;<br />
((permanent</span><span style="color: #000000;">-</span><span style="color: #000000;">assignment?&nbsp;exp)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(analyze</span><span style="color: #000000;">-</span><span style="color: #000000;">permanent</span><span style="color: #000000;">-</span><span style="color: #000000;">assignment&nbsp;exp))<br />
<br />
;实现<br />
<br />
(define&nbsp;(permanent</span><span style="color: #000000;">-</span><span style="color: #000000;">assignment?&nbsp;exp)<br />
&nbsp;&nbsp;(tagged</span><span style="color: #000000;">-</span><span style="color: #000000;">list?&nbsp;exp&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">permanent-set!))</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">(define&nbsp;(analyze</span><span style="color: #000000;">-</span><span style="color: #000000;">permanent</span><span style="color: #000000;">-</span><span style="color: #000000;">assignment&nbsp;exp)<br />
&nbsp;&nbsp;&nbsp;(let&nbsp;((var&nbsp;(assignment</span><span style="color: #000000;">-</span><span style="color: #000000;">variable&nbsp;exp))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(vproc&nbsp;(analyze&nbsp;(assignment</span><span style="color: #000000;">-</span><span style="color: #000000;">value&nbsp;exp))))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">(env&nbsp;succeed&nbsp;fail)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(vproc&nbsp;env<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">(val&nbsp;fail2)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set</span><span style="color: #000000;">-</span><span style="color: #000000;">variable</span><span style="color: #000000;">-</span><span style="color: #000000;">value!&nbsp;var&nbsp;val&nbsp;env)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(succeed&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">ok&nbsp;fail2))</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fail))))</span></div>
<br />
习题4.52，实现if-fail的特殊形式，在第一个表达式如果求值成功，就返回该表达式的值，否则返回第二个表达式的值，实现如下：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">;扩充analyze<br />
&nbsp;((</span><span style="color: #0000ff;">if</span><span style="color: #000000;">-</span><span style="color: #000000;">fail?&nbsp;exp)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(analyze</span><span style="color: #000000;">-</span><span style="color: #0000ff;">if</span><span style="color: #000000;">-</span><span style="color: #000000;">fail&nbsp;exp))<br />
;实现<br />
(define&nbsp;(</span><span style="color: #0000ff;">if</span><span style="color: #000000;">-</span><span style="color: #000000;">fail?&nbsp;exp)<br />
&nbsp;&nbsp;(tagged</span><span style="color: #000000;">-</span><span style="color: #000000;">list?&nbsp;exp&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">if-fail))</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">(define&nbsp;(analyze</span><span style="color: #000000;">-</span><span style="color: #0000ff;">if</span><span style="color: #000000;">-</span><span style="color: #000000;">fail&nbsp;exp)<br />
&nbsp;&nbsp;&nbsp;(let&nbsp;((pproc&nbsp;(analyze&nbsp;(</span><span style="color: #0000ff;">if</span><span style="color: #000000;">-</span><span style="color: #000000;">predicate&nbsp;exp)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(cproc&nbsp;(analyze&nbsp;(</span><span style="color: #0000ff;">if</span><span style="color: #000000;">-</span><span style="color: #000000;">consequent&nbsp;exp))))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">(env&nbsp;succeed&nbsp;fail)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(pproc&nbsp;env&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">(pred</span><span style="color: #000000;">-</span><span style="color: #000000;">value&nbsp;fail2)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(succeed&nbsp;pred</span><span style="color: #000000;">-</span><span style="color: #000000;">value&nbsp;fail2))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">()&nbsp;(cproc&nbsp;env&nbsp;succeed&nbsp;fail))))))</span></div>
pproc如果执行成功，就返回结果pred-value，否则就执行fail过程<span style="color: #000000;">(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">()&nbsp;(cproc&nbsp;env&nbsp;succeed&nbsp;fail))</span>，测试略。<br />
<br />
习题4.53，根据题意可知这个过程返回结果应该是(prime-sum-pair '(1 3 5 8) '(20 35 110))的所有结果，执行也是如此：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">;;;&nbsp;AMB</span><span style="color: #000000;">-</span><span style="color: #000000;">Eval&nbsp;value:<br />
((</span><span style="color: #000000;">8</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">35</span><span style="color: #000000;">)&nbsp;(</span><span style="color: #000000;">3</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">110</span><span style="color: #000000;">)&nbsp;(</span><span style="color: #000000;">3</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">20</span><span style="color: #000000;">))</span></div>
<br />
习题4.54，将require实现为特殊形式：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">;扩充analyze<br />
((require?&nbsp;exp)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(analyze</span><span style="color: #000000;">-</span><span style="color: #000000;">require&nbsp;exp))<br />
<br />
;实现<br />
(define&nbsp;(require?&nbsp;exp)<br />
&nbsp;&nbsp;(tagged</span><span style="color: #000000;">-</span><span style="color: #000000;">list?&nbsp;exp&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">require))</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">(define&nbsp;(require</span><span style="color: #000000;">-</span><span style="color: #000000;">predicate&nbsp;exp)<br />
&nbsp;&nbsp;(cadr&nbsp;exp))<br />
(define&nbsp;(analyze</span><span style="color: #000000;">-</span><span style="color: #000000;">require&nbsp;exp)<br />
&nbsp;&nbsp;(let&nbsp;((pproc&nbsp;(analyze&nbsp;(require</span><span style="color: #000000;">-</span><span style="color: #000000;">predicate&nbsp;exp))))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;(env&nbsp;succeed&nbsp;fail)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(pproc&nbsp;env&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">(pred</span><span style="color: #000000;">-</span><span style="color: #000000;">value&nbsp;fail2)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">not</span><span style="color: #000000;">&nbsp;pred</span><span style="color: #000000;">-</span><span style="color: #000000;">value)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fail2)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(succeed&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">ok&nbsp;fail2)))</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fail))))</span></div>
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/241804.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-11-21 10:26 <a href="http://www.blogjava.net/killme2008/archive/2008/11/21/241804.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Ruby amb解决说谎者谜题</title><link>http://www.blogjava.net/killme2008/archive/2008/11/15/240672.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sat, 15 Nov 2008 10:50:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/11/15/240672.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/240672.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/11/15/240672.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/240672.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/240672.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 说谎者谜题是sicp4.3.2小节的一道题目，题目本身不难：<br />
五个女生参加一个考试，她们的家长对考试结果过分关注。为此她们约定，在给家里写信谈到考试的时候，每个姑娘都要写一句真话和一句假话。下面是从她们的信里摘抄出来的句子：<br />
Betty : kitty考第二，我只考了第三<br />
Ethel : 你们应该很高兴听到我考了第一，joan第二<br />
joan :&nbsp;&nbsp; 我考第三，可怜的Ethel垫底<br />
kitty:&nbsp; 我第二，marry只考了第四<br />
marry: 我是第四，Betty的成绩最高。<br />
这五个姑娘的实际排名是什么？<br />
<br />
&nbsp;&nbsp;&nbsp; Ruby本来就有call/cc，因此也可以实现amb操作符，网上已经有一个实现了：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Amb<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;ExhaustedError&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;RuntimeError;&nbsp;end<br />
&nbsp;&nbsp;def&nbsp;initialize<br />
&nbsp;&nbsp;&nbsp;&nbsp;@fail&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;proc&nbsp;{&nbsp;fail&nbsp;ExhaustedError,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">amb&nbsp;tree&nbsp;exhausted</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;}<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;def&nbsp;choose(</span><span style="color: #000000;">*</span><span style="color: #000000;">choices)<br />
&nbsp;&nbsp;&nbsp;&nbsp;prev_fail&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;@fail<br />
&nbsp;&nbsp;&nbsp;&nbsp;callcc&nbsp;{&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">sk</span><span style="color: #000000;">|</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;choices.each&nbsp;{&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">choice</span><span style="color: #000000;">|</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;callcc&nbsp;{&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">fk</span><span style="color: #000000;">|</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@fail&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;proc&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@fail&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;prev_fail<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fk.call(:fail)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;choice.respond_to</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;:call<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sk.call(choice.call)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sk.call(choice)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@fail.call<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;def&nbsp;failure<br />
&nbsp;&nbsp;&nbsp;&nbsp;choose<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;def&nbsp;</span><span style="color: #0000ff;">assert</span><span style="color: #000000;">(cond)<br />
&nbsp;&nbsp;&nbsp;&nbsp;failure&nbsp;unless&nbsp;cond<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;alias&nbsp;:require&nbsp;:</span><span style="color: #0000ff;">assert</span><span style="color: #000000;"><br />
end<br />
</span></div>
<br />
&nbsp;&nbsp;&nbsp; 这一段代码与scheme宏实现amb是完全相同的：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;amb</span><span style="color: #000000;">-</span><span style="color: #000000;">fail&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">*)</span><span style="color: #800000;"><br />
</span><span style="color: #000000;"><br />
(define&nbsp;initialize</span><span style="color: #000000;">-</span><span style="color: #000000;">amb</span><span style="color: #000000;">-</span><span style="color: #000000;">fail<br />
&nbsp;&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;()<br />
&nbsp;&nbsp;&nbsp;&nbsp;(set!&nbsp;amb</span><span style="color: #000000;">-</span><span style="color: #000000;">fail<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(error&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">amb&nbsp;tree&nbsp;exhausted</span><span style="color: #800000;">"</span><span style="color: #000000;">)))))<br />
<br />
(initialize</span><span style="color: #000000;">-</span><span style="color: #000000;">amb</span><span style="color: #000000;">-</span><span style="color: #000000;">fail)<br />
(define&nbsp;call</span><span style="color: #000000;">/</span><span style="color: #000000;">cc&nbsp;call</span><span style="color: #000000;">-</span><span style="color: #000000;">with</span><span style="color: #000000;">-</span><span style="color: #000000;">current</span><span style="color: #000000;">-</span><span style="color: #000000;">continuation)<br />
(define</span><span style="color: #000000;">-</span><span style="color: #000000;">syntax&nbsp;amb<br />
&nbsp;&nbsp;(syntax</span><span style="color: #000000;">-</span><span style="color: #000000;">rules&nbsp;()<br />
&nbsp;&nbsp;&nbsp;&nbsp;((amb&nbsp;alt&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((prev</span><span style="color: #000000;">-</span><span style="color: #000000;">amb</span><span style="color: #000000;">-</span><span style="color: #000000;">fail&nbsp;amb</span><span style="color: #000000;">-</span><span style="color: #000000;">fail))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(call</span><span style="color: #000000;">/</span><span style="color: #000000;">cc<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;(sk)<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(call</span><span style="color: #000000;">/</span><span style="color: #000000;">cc<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;(fk)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set!&nbsp;amb</span><span style="color: #000000;">-</span><span style="color: #000000;">fail<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set!&nbsp;amb</span><span style="color: #000000;">-</span><span style="color: #000000;">fail&nbsp;prev</span><span style="color: #000000;">-</span><span style="color: #000000;">amb</span><span style="color: #000000;">-</span><span style="color: #000000;">fail)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fk&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">fail)))</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(sk&nbsp;alt)))&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" /><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(prev</span><span style="color: #000000;">-</span><span style="color: #000000;">amb</span><span style="color: #000000;">-</span><span style="color: #000000;">fail)))))))</span></div>
&nbsp;&nbsp;&nbsp; 回到谜题，从题意可知每个姑娘的两句话的异或结果为true，并且姑娘的排名肯定不会相同，因此定义两个辅助过程：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">require&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">amb</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;distinct?(items)<br />
&nbsp;&nbsp;items.uniq</span><span style="color: #000000;">==</span><span style="color: #000000;">items<br />
end<br />
</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;xor(exp1,exp2)<br />
&nbsp;(exp1&nbsp;</span><span style="color: #0000ff;">or</span><span style="color: #000000;">&nbsp;exp2)&nbsp;</span><span style="color: #0000ff;">and</span><span style="color: #000000;">&nbsp;!(exp1&nbsp;</span><span style="color: #0000ff;">and</span><span style="color: #000000;">&nbsp;exp2)<br />
end</span></div>
&nbsp;&nbsp;&nbsp; 剩下的完全就是将题目翻译成代码即可了，没有多少可以解释的东西：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">amb</span><span style="color: #000000;">=</span><span style="color: #000000;">Amb.new<br />
betty</span><span style="color: #000000;">=</span><span style="color: #000000;">amb.choose(</span><span style="color: #000000;">*</span><span style="color: #000000;">[</span><span style="color: #000000;">1</span><span style="color: #000000;">,</span><span style="color: #000000;">2</span><span style="color: #000000;">,</span><span style="color: #000000;">3</span><span style="color: #000000;">,</span><span style="color: #000000;">4</span><span style="color: #000000;">,</span><span style="color: #000000;">5</span><span style="color: #000000;">])<br />
ethel</span><span style="color: #000000;">=</span><span style="color: #000000;">amb.choose(</span><span style="color: #000000;">*</span><span style="color: #000000;">[</span><span style="color: #000000;">1</span><span style="color: #000000;">,</span><span style="color: #000000;">2</span><span style="color: #000000;">,</span><span style="color: #000000;">3</span><span style="color: #000000;">,</span><span style="color: #000000;">4</span><span style="color: #000000;">,</span><span style="color: #000000;">5</span><span style="color: #000000;">])<br />
joan</span><span style="color: #000000;">=</span><span style="color: #000000;">amb.choose(</span><span style="color: #000000;">*</span><span style="color: #000000;">[</span><span style="color: #000000;">1</span><span style="color: #000000;">,</span><span style="color: #000000;">2</span><span style="color: #000000;">,</span><span style="color: #000000;">3</span><span style="color: #000000;">,</span><span style="color: #000000;">4</span><span style="color: #000000;">,</span><span style="color: #000000;">5</span><span style="color: #000000;">])<br />
kitty</span><span style="color: #000000;">=</span><span style="color: #000000;">amb.choose(</span><span style="color: #000000;">*</span><span style="color: #000000;">[</span><span style="color: #000000;">1</span><span style="color: #000000;">,</span><span style="color: #000000;">2</span><span style="color: #000000;">,</span><span style="color: #000000;">3</span><span style="color: #000000;">,</span><span style="color: #000000;">4</span><span style="color: #000000;">,</span><span style="color: #000000;">5</span><span style="color: #000000;">])<br />
marry</span><span style="color: #000000;">=</span><span style="color: #000000;">amb.choose(</span><span style="color: #000000;">*</span><span style="color: #000000;">[</span><span style="color: #000000;">1</span><span style="color: #000000;">,</span><span style="color: #000000;">2</span><span style="color: #000000;">,</span><span style="color: #000000;">3</span><span style="color: #000000;">,</span><span style="color: #000000;">4</span><span style="color: #000000;">,</span><span style="color: #000000;">5</span><span style="color: #000000;">])<br />
<br />
amb.require(xor(kitty</span><span style="color: #000000;">==</span><span style="color: #000000;">2</span><span style="color: #000000;">,betty</span><span style="color: #000000;">==</span><span style="color: #000000;">3</span><span style="color: #000000;">))<br />
amb.require(xor(ethel</span><span style="color: #000000;">==</span><span style="color: #000000;">1</span><span style="color: #000000;">,joan</span><span style="color: #000000;">==</span><span style="color: #000000;">2</span><span style="color: #000000;">))<br />
amb.require(xor(joan</span><span style="color: #000000;">==</span><span style="color: #000000;">3</span><span style="color: #000000;">,ethel</span><span style="color: #000000;">==</span><span style="color: #000000;">5</span><span style="color: #000000;">))<br />
amb.require(xor(kitty</span><span style="color: #000000;">==</span><span style="color: #000000;">2</span><span style="color: #000000;">,marry</span><span style="color: #000000;">==</span><span style="color: #000000;">4</span><span style="color: #000000;">))<br />
amb.require(xor(marry</span><span style="color: #000000;">==</span><span style="color: #000000;">4</span><span style="color: #000000;">,betty</span><span style="color: #000000;">==</span><span style="color: #000000;">1</span><span style="color: #000000;">))<br />
amb.require(distinct?([betty,ethel,joan,kitty,marry]))<br />
puts&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">betty:#{betty}&nbsp;ethel:#{ethel}&nbsp;joan:#{joan}&nbsp;kitty:#{kitty}&nbsp;marry:#{marry}</span><span style="color: #800000;">"</span></div>
<br />
&nbsp;&nbsp;&nbsp; 答案就是：<br />
&nbsp;&nbsp;&nbsp; <strong>betty:3 ethel:5 joan:2 kitty:1 marry:4&nbsp;</strong>&nbsp; <br />
<br />
&nbsp;&nbsp;&nbsp; 最后给出一个Prolog的解答：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">notmember(A,[]).<br />
notmember(A,[B</span><span style="color: #000000;">|</span><span style="color: #000000;">L]):</span><span style="color: #000000;">-</span><span style="color: #000000;"><br />
&nbsp;&nbsp;A\</span><span style="color: #000000;">==</span><span style="color: #000000;">B,<br />
&nbsp;&nbsp;notmember(A,L).<br />
distinct([A,B,C,D,E]):</span><span style="color: #000000;">-</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;notmember(A,[B,C,D,E]),<br />
&nbsp;&nbsp;&nbsp;notmember(B,[A,C,D,E]),<br />
&nbsp;&nbsp;&nbsp;notmember(C,[A,B,D,E]),<br />
&nbsp;&nbsp;&nbsp;notmember(D,[A,B,C,E]),<br />
&nbsp;&nbsp;&nbsp;notmember(E,[A,B,C,D]).<br />
xor(Exp1,Exp2):</span><span style="color: #000000;">-</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;(Exp1;Exp2),\</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;(Exp1,Exp2).<br />
solve(Betty,Ethel,Joan,Kitty,Marry):</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;X</span><span style="color: #000000;">=</span><span style="color: #000000;">[</span><span style="color: #000000;">1</span><span style="color: #000000;">,</span><span style="color: #000000;">2</span><span style="color: #000000;">,</span><span style="color: #000000;">3</span><span style="color: #000000;">,</span><span style="color: #000000;">4</span><span style="color: #000000;">,</span><span style="color: #000000;">5</span><span style="color: #000000;">],<br />
&nbsp;&nbsp;&nbsp;member(Betty,X),<br />
&nbsp;&nbsp;&nbsp;member(Ethel,X),<br />
&nbsp;&nbsp;&nbsp;member(Joan,X),<br />
&nbsp;&nbsp;&nbsp;member(Kitty,X),<br />
&nbsp;&nbsp;&nbsp;member(Marry,X),<br />
&nbsp;&nbsp;&nbsp;distinct([Betty,Ethel,Joan,Kitty,Marry]),<br />
&nbsp;&nbsp;&nbsp;xor(Kitty</span><span style="color: #000000;">=</span><span style="color: #000000;">:</span><span style="color: #000000;">=</span><span style="color: #000000;">2</span><span style="color: #000000;">,Betty</span><span style="color: #000000;">=</span><span style="color: #000000;">:</span><span style="color: #000000;">=</span><span style="color: #000000;">3</span><span style="color: #000000;">),<br />
&nbsp;&nbsp;&nbsp;xor(Ethel</span><span style="color: #000000;">=</span><span style="color: #000000;">:</span><span style="color: #000000;">=</span><span style="color: #000000;">1</span><span style="color: #000000;">,Joan</span><span style="color: #000000;">=</span><span style="color: #000000;">:</span><span style="color: #000000;">=</span><span style="color: #000000;">2</span><span style="color: #000000;">),<br />
&nbsp;&nbsp;&nbsp;xor(Joan</span><span style="color: #000000;">=</span><span style="color: #000000;">:</span><span style="color: #000000;">=</span><span style="color: #000000;">3</span><span style="color: #000000;">,Ethel</span><span style="color: #000000;">=</span><span style="color: #000000;">:</span><span style="color: #000000;">=</span><span style="color: #000000;">5</span><span style="color: #000000;">),<br />
&nbsp;&nbsp;&nbsp;xor(Kitty</span><span style="color: #000000;">=</span><span style="color: #000000;">:</span><span style="color: #000000;">=</span><span style="color: #000000;">2</span><span style="color: #000000;">,Marry</span><span style="color: #000000;">=</span><span style="color: #000000;">:</span><span style="color: #000000;">=</span><span style="color: #000000;">4</span><span style="color: #000000;">),<br />
&nbsp;&nbsp;&nbsp;xor(Marry</span><span style="color: #000000;">=</span><span style="color: #000000;">:</span><span style="color: #000000;">=</span><span style="color: #000000;">4</span><span style="color: #000000;">,Betty</span><span style="color: #000000;">=</span><span style="color: #000000;">:</span><span style="color: #000000;">=</span><span style="color: #000000;">1</span><span style="color: #000000;">).</span></div>
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/240672.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-11-15 18:50 <a href="http://www.blogjava.net/killme2008/archive/2008/11/15/240672.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sicp 4.3.2部分习题</title><link>http://www.blogjava.net/killme2008/archive/2008/11/15/239073.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 14 Nov 2008 16:02:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/11/15/239073.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/239073.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/11/15/239073.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/239073.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/239073.html</trackback:ping><description><![CDATA[<br />
<strong>4.38</strong>，谜题就有翻译错误，问题更是错的离谱。原题是这样的：<br />
Baker, Cooper, Fletcher, Miller, and Smith live on different floors of an apartment house<br />
that contains only five floors. Baker does not live on the top floor. Cooper does not live on<br />
the bottom floor. Fletcher does not live on either the top or the bottom floor. Miller lives on<br />
a higher floor than does Cooper. Smith does not live on a floor adjacent to Fletcher's.<br />
Fletcher does not live on a floor adjacent to Cooper's. Where does everyone live?<br />
<br />
其中说Miller住的比Cooper高，却翻译成了Miller住的比Cooper高一层，如果按照这个翻译来谜题是没有答案的。<br />
回到4.38，题目是这样的：<br />
Modify the multiple-dwelling procedure to omit the requirement that Smith and Fletcher do<br />
not live on adjacent floors. How many solutions are there to this modified puzzle?<br />
<br />
翻译却成了增加Smith和Fletcher不住在相邻层这个条件，谜题本来就是如此，何来的增加？错将omit翻译成了&#8220;增加&#8221;。<br />
这道题很简单咯，将<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(require&nbsp;(not&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(abs&nbsp;(</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;smith&nbsp;fletcher))&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)))</span></div>
注释掉即可，答案增加到5个：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;(multiple</span><span style="color: #000000;">-</span><span style="color: #000000;">dwelling)<br />
<strong>((baker&nbsp;</strong></span><strong><span style="color: #000000;">1</span><span style="color: #000000;">)&nbsp;(cooper&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">)&nbsp;(fletcher&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">)&nbsp;(miller&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">)&nbsp;(smith&nbsp;</span><span style="color: #000000;">5</span></strong><span style="color: #000000;"><strong>))</strong><br />
</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;(amb)<br />
<strong>((baker&nbsp;</strong></span><strong><span style="color: #000000;">1</span><span style="color: #000000;">)&nbsp;(cooper&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">)&nbsp;(fletcher&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">)&nbsp;(miller&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">)&nbsp;(smith&nbsp;</span><span style="color: #000000;">3</span></strong><span style="color: #000000;"><strong>))</strong><br />
</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;&nbsp;(amb)<br />
<strong>((baker&nbsp;</strong></span><strong><span style="color: #000000;">1</span><span style="color: #000000;">)&nbsp;(cooper&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">)&nbsp;(fletcher&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">)&nbsp;(miller&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">)&nbsp;(smith&nbsp;</span><span style="color: #000000;">3</span></strong><span style="color: #000000;"><strong>))</strong><br />
</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;&nbsp;(amb)<br />
<strong>((baker&nbsp;</strong></span><strong><span style="color: #000000;">3</span><span style="color: #000000;">)&nbsp;(cooper&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">)&nbsp;(fletcher&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">)&nbsp;(miller&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">)&nbsp;(smith&nbsp;</span><span style="color: #000000;">1</span></strong><span style="color: #000000;"><strong>))</strong><br />
</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;&nbsp;(amb)<br />
<strong>((baker&nbsp;</strong></span><strong><span style="color: #000000;">3</span><span style="color: #000000;">)&nbsp;(cooper&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">)&nbsp;(fletcher&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">)&nbsp;(miller&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">)&nbsp;(smith&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">))</span></strong></div>
<br />
<strong>4.39</strong>，约束条件的顺序肯定是有影响的，能缩小搜索范围的强约束条件排在前面，弱约束条件排在后面，可以减少整体的判断次数。在DrScheme中，可以启用profile来分析顺序带来的影响，打开language-&gt;R5RS-&gt;Show Details，选择Debugging and Profiling 即可。运行scheme程序，然后在View-&gt;Show Profile中查看具体分析结果,在该视图中将详细列出各个函数调用的时间和次数。<br />
在没有调整顺序前：<br />
Msec&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Calls&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Function<br />
40&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; multiple-dwelling<br />
0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1716&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; require<br />
4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2524&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; distinct?<br />
<br />
说明multiple-dwelling调用了一次，花费了40毫秒，而require和distinct?函数分别被调用了1716次和2524次。<br />
然后我将<br />
(require<br />
&nbsp;&nbsp;&nbsp;&nbsp; (distinct? (list baker cooper fletcher miller smith)))<br />
<br />
这个我认为弱约束条件放到了最后，测试的结果并不让人满意：<br />
Msec&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Calls&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Function<br />
44 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; multiple-dwelling<br />
4 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6035 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; require<br />
0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 129 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; distinct?<br />
<br />
并没有大的提高，甚至反而所下降。猜测问题在于我使用的amb实现是call/cc、宏实现的，待俺完成amb求值器再测试一下。<br />
<br />
<strong>4.40</strong>，题目都提示咯，嵌套let语句,我的解答：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(multiple</span><span style="color: #000000;">-</span><span style="color: #000000;">dwelling2)<br />
&nbsp;&nbsp;(let&nbsp;((baker&nbsp;&nbsp;&nbsp;(amb&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(not&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;baker&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((cooper&nbsp;&nbsp;(amb&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(not&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;cooper&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((fletcher&nbsp;(amb&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(not&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;fletcher&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">)))&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(not&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;fletcher&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(not&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(abs&nbsp;(</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;fletcher&nbsp;cooper))&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((miller&nbsp;(amb&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;miller&nbsp;cooper))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((smith&nbsp;&nbsp;&nbsp;(amb&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(not&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(abs&nbsp;(</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;smith&nbsp;fletcher))&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(distinct</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;(list&nbsp;baker&nbsp;cooper&nbsp;fletcher&nbsp;miller&nbsp;smith)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list&nbsp;(list&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">baker&nbsp;baker)</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">cooper&nbsp;cooper)</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">fletcher&nbsp;fletcher)</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">miller&nbsp;miller)</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">smith&nbsp;smith))))))))</span></div>
<br />
profile一下，<span style="color: #000000;">multiple</span><span style="color: #000000;">-</span><span style="color: #000000;">dwelling2的调用</span>时间缩小到8毫秒，require和distinct?的调用次数分别降低到了404和129次。<br />
<br />
<br />
<strong>4.42</strong>，说谎者谜题，<br />
五个女生参加一个考试，她们的家长对考试结果过分关注。为此她们约定，在给家里写信谈到考试的时候，每个姑娘都要写一句真话和一句假话。下面是从她们的信里摘抄出来的句子：<br />
Betty : kitty考第二，我只考了第三<br />
Ethel : 你们应该很高兴听到我考了第一，joan第二<br />
joan :&nbsp;&nbsp; 我考第三，可怜的Ethel垫底<br />
kitty:&nbsp; 我第二，marry只考了第四<br />
marry: 我是第四，Betty的成绩最高。<br />
这五个姑娘的实际排名是什么？<br />
<br />
将题目翻译成代码就OK了，说明性编程真是舒坦：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(liars</span><span style="color: #000000;">-</span><span style="color: #000000;">puzzle)<br />
&nbsp;&nbsp;(let&nbsp;((betty&nbsp;(amb&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ethel&nbsp;(amb&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(joan&nbsp;(amb&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(kitty&nbsp;(amb&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(marry&nbsp;(amb&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(require<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(distinct</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;(list&nbsp;betty&nbsp;ethel&nbsp;joan&nbsp;kitty&nbsp;marry)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(or&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;kitty&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">)&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;betty&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(not&nbsp;(and&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;kitty&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">)&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;betty&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">))))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(or&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ethel&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;joan&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(not&nbsp;(and&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ethel&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;joan&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">))))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(or&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;joan&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">)&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ethel&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(not&nbsp;(and&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;joan&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">)&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ethel&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">))))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(or&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;kitty&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">)&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;marry&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(not&nbsp;(and&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;kitty&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">)&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;marry&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">))))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(or&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;marry&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">)&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;betty&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(not&nbsp;(and&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;marry&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">)&nbsp;(</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;betty&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">))))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(list&nbsp;(list&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">betty&nbsp;betty)</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">ethel&nbsp;ethel)</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">joan&nbsp;joan)</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">kitty&nbsp;kitty)</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">marry&nbsp;marry))))</span></div>
<br />
答案是：<br />
((betty 3) (ethel 5) (joan 2) (kitty 1) (marry 4))<br />
<br />
4.43.也很有趣的题目，游艇迷题，<br />
&nbsp;&nbsp; Mary Ann Moore的父亲有一条游艇，他的四个朋友Colonel Dowing、Mr.Hall、Sir Barnacle Hood和Dr.Parker也各有一条。这五个人都有一个女儿，每个人都用另一个人的女儿的名字来为自己的游艇命名。Sir Barnacle的游艇叫Gabrielle，Mr.Moore拥有Lorna，Mr.Hall的游艇叫Rosalind，Melissa属于Colonel Downing（取自Sir Barnacle的女儿的名字），Garielle的父亲的游艇取的是Dr.Parker的女儿的名字。请问，谁是Lorna的父亲。<br />
<br />
先说下结果，Lorna的父亲是Downing。<br />
具体解答如下,先定义辅助过程：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(father&nbsp;yacht&nbsp;daughter)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(cons&nbsp;yacht&nbsp;daughter))<br />
(define&nbsp;(yacht&nbsp;father)<br />
&nbsp;&nbsp;(car&nbsp;father))<br />
(define&nbsp;(daughter&nbsp;father)<br />
&nbsp;&nbsp;(cdr&nbsp;father))</span></div>
<br />
然后翻译题目为代码即可，暂不考虑效率问题：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(yacht</span><span style="color: #000000;">-</span><span style="color: #000000;">puzzle)<br />
&nbsp;&nbsp;(let&nbsp;((moore&nbsp;(father&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">lorna&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">mary))&nbsp;&nbsp;;;Mr.Moore<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(downing&nbsp;(father&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">melissa&nbsp;(amb&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">mary&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">melissa&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">gabrielle&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">rosalind&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">lorna))))&nbsp;&nbsp;;;Colonel&nbsp;Downing<br />
&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(not&nbsp;(equal</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;(yacht&nbsp;downing)&nbsp;(daughter&nbsp;downing))))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((hall&nbsp;(father&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">rosalind&nbsp;(amb&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">mary&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">melissa&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">gabrielle&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">rosalind&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">lorna))))&nbsp;&nbsp;;;Mr.Hall<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(not&nbsp;(equal</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;(yacht&nbsp;hall)&nbsp;(daughter&nbsp;hall))))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((barnacle&nbsp;(father&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">gabrielle&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">melissa))&nbsp;&nbsp;&nbsp;;;Sir&nbsp;Barnacle&nbsp;Hood<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(parker&nbsp;(father&nbsp;(amb&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">mary&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">melissa&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">gabrielle&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">rosalind&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">lorna)&nbsp;(amb&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">mary&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">melissa&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">gabrielle&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">rosalind&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">lorna))))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;;Dr.Parker<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(not&nbsp;(equal</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;(yacht&nbsp;parker)&nbsp;(daughter&nbsp;parker))))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((gabrielle</span><span style="color: #000000;">-</span><span style="color: #000000;">father&nbsp;(amb&nbsp;moore&nbsp;downing&nbsp;hall&nbsp;barnacle&nbsp;parker)))&nbsp;;;Garielle</span><span style="color: #000000;">'</span><span style="color: #000000;">s&nbsp;Father</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(equal</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;(daughter&nbsp;gabrielle</span><span style="color: #000000;">-</span><span style="color: #000000;">father)&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">gabrielle))&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(equal</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;(yacht&nbsp;gabrielle</span><span style="color: #000000;">-</span><span style="color: #000000;">father)&nbsp;(daughter&nbsp;parker)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(distinct</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;(map&nbsp;daughter&nbsp;(list&nbsp;moore&nbsp;downing&nbsp;hall&nbsp;barnacle&nbsp;parker))))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(require&nbsp;(distinct</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;(map&nbsp;yacht&nbsp;(list&nbsp;moore&nbsp;downing&nbsp;hall&nbsp;barnacle&nbsp;parker))))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">moore&nbsp;(yacht&nbsp;moore)&nbsp;(daughter&nbsp;moore))</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">downing&nbsp;(yacht&nbsp;downing)&nbsp;(daughter&nbsp;downing))</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">hall&nbsp;(yacht&nbsp;hall)&nbsp;(daughter&nbsp;hall))</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">barnacle&nbsp;(yacht&nbsp;barnacle)&nbsp;(daughter&nbsp;barnacle))</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">parker&nbsp;(yacht&nbsp;parker)&nbsp;(daughter&nbsp;parker))))))))</span></div>
<br />
运行(yacht-puzzle)的结果为：<br />
((moore lorna mary) (downing melissa lorna) (hall rosalind gabrielle) (barnacle gabrielle melissa) (parker mary rosalind))<br />
<br />
三元组：父亲名、游艇名、女儿名，因此lorna的父亲是Downing。Garielle的父亲是Mr.Hall，Mr.Hall的游艇名叫做Rosalind，正是Dr.Parker的女儿名字。<br />
<br />
延伸题目，如果没有Mary Ann姓Moore这个条件，答案将有三个，分别是：<br />
((moore lorna mary) (downing melissa lorna) (hall rosalind gabrielle) (barnacle gabrielle melissa) (parker mary rosalind))<br />
((moore lorna gabrielle) (downing melissa rosalind) (hall rosalind mary) (barnacle gabrielle melissa) (parker mary lorna))<br />
((moore lorna lorna) (downing melissa mary) (hall rosalind gabrielle) (barnacle gabrielle melissa) (parker mary rosalind))<br />
<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/239073.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-11-15 00:02 <a href="http://www.blogjava.net/killme2008/archive/2008/11/15/239073.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sicp 4.3.1小节两题</title><link>http://www.blogjava.net/killme2008/archive/2008/11/04/238455.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 03 Nov 2008 17:20:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/11/04/238455.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/238455.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/11/04/238455.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/238455.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/238455.html</trackback:ping><description><![CDATA[本节开始介绍神奇的amb函数，为引入逻辑程序设计做铺垫。关于amb，有清华王垠的一个文档：<br />
http://cs2.swfc.edu.cn/~wanghuan/wangyin1/amb/amb.html<br />
<br />
4.35，与an-element-of类似：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(an</span><span style="color: #000000;">-</span><span style="color: #000000;">integer</span><span style="color: #000000;">-</span><span style="color: #000000;">between&nbsp;low&nbsp;high)<br />
&nbsp;&nbsp;(require&nbsp;(not&nbsp;(</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;low&nbsp;high)))<br />
&nbsp;&nbsp;(amb&nbsp;low&nbsp;(an</span><span style="color: #000000;">-</span><span style="color: #000000;">integer</span><span style="color: #000000;">-</span><span style="color: #000000;">between&nbsp;(</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;low&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)&nbsp;high)))</span></div>
<br />
4.36,与练习3.69相关，貌似我没解过这道题，略过。<br />
<br />
4.37,两点大大缩小了搜索范围：<br />
1）通过限制i^2+j^2&lt;= high^2，平方和大于上限平方的全部过滤掉<br />
2）k的判断不再通过amb取值，而是求平方和的平方根是否为整数来判断，进一步缩小了搜索范围<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/238455.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-11-04 01:20 <a href="http://www.blogjava.net/killme2008/archive/2008/11/04/238455.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sicp 4.2.2小节部分习题</title><link>http://www.blogjava.net/killme2008/archive/2008/11/02/238138.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sat, 01 Nov 2008 17:18:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/11/02/238138.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/238138.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/11/02/238138.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/238138.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/238138.html</trackback:ping><description><![CDATA[<br />
4.27，<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">;;;&nbsp;L</span><span style="color: #000000;">-</span><span style="color: #000000;">Eval&nbsp;input:<br />
(define&nbsp;count&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br />
<br />
;;;&nbsp;L</span><span style="color: #000000;">-</span><span style="color: #000000;">Eval&nbsp;value:<br />
ok<br />
<br />
;;;&nbsp;L</span><span style="color: #000000;">-</span><span style="color: #000000;">Eval&nbsp;input:<br />
(define&nbsp;(id&nbsp;x)<br />
&nbsp;&nbsp;(set</span><span style="color: #000000;">!</span><span style="color: #000000;">&nbsp;count&nbsp;(</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;count))<br />
&nbsp;&nbsp;x)<br />
<br />
;;;&nbsp;L</span><span style="color: #000000;">-</span><span style="color: #000000;">Eval&nbsp;value:<br />
ok<br />
<br />
;;;&nbsp;L</span><span style="color: #000000;">-</span><span style="color: #000000;">Eval&nbsp;input:<br />
(define&nbsp;w&nbsp;(id&nbsp;(id&nbsp;</span><span style="color: #000000;">10</span><span style="color: #000000;">)))<br />
<br />
;;;&nbsp;L</span><span style="color: #000000;">-</span><span style="color: #000000;">Eval&nbsp;value:<br />
ok<br />
<br />
;;;&nbsp;L</span><span style="color: #000000;">-</span><span style="color: #000000;">Eval&nbsp;input:<br />
count<br />
<br />
;;;&nbsp;L</span><span style="color: #000000;">-</span><span style="color: #000000;">Eval&nbsp;value:<br />
</span><span style="color: #000000;">1</span><span style="color: #000000;"><br />
<br />
;;;&nbsp;L</span><span style="color: #000000;">-</span><span style="color: #000000;">Eval&nbsp;input:<br />
w<br />
<br />
;;;&nbsp;L</span><span style="color: #000000;">-</span><span style="color: #000000;">Eval&nbsp;value:<br />
</span><span style="color: #000000;">10</span><span style="color: #000000;"><br />
<br />
;;;&nbsp;L</span><span style="color: #000000;">-</span><span style="color: #000000;">Eval&nbsp;input:<br />
count<br />
<br />
;;;&nbsp;L</span><span style="color: #000000;">-</span><span style="color: #000000;">Eval&nbsp;value:<br />
</span><span style="color: #000000;">2</span><span style="color: #000000;"><br />
</span></div>
<br />
至于原因，w在没有强迫求值前，仅仅执行了一步(id 10)，因此此时count为1，当要求打印w的时候force执行了第二步(id 10)，因此count增加为2。<br />
<br />
4.28，当参数也是函数的时候，例如：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;square&nbsp;(lambda(x)&nbsp;(</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;x&nbsp;x)))<br />
(define&nbsp;(test&nbsp;proc&nbsp;a)<br />
&nbsp;&nbsp;(proc&nbsp;a))<br />
(test&nbsp;square&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">)</span></div>
<br />
如果对operator不采用actual-value，那么square将延时求值，在执行(proc a)时无法辨认eval的过程类型。<br />
<br />
4.29，俺第一个想到的就是树形递归的斐波那契数列：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(fib&nbsp;n)<br />
&nbsp;&nbsp;(cond&nbsp;((</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">&nbsp;n)&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;n)&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;(fib&nbsp;(</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;n&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">))&nbsp;(fib&nbsp;(</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;n&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">))))))</span></div>
不带记忆功能和带记忆功能的force-it之间的性能差距非常明显。<br />
<br />
第二问，有趣的地方在于square过程，注意到(define (square x) (* x x))，x在body出现了两次，那么如果是使用不带记忆功能的force-it， x将被求值两次，如果x本身带有副作用（例如例子里面的id过程），那么显然副作用也将被调用两次，因此答案不言自明。带记忆功能的force-it版本中，count将仍然是1，而在不带记忆功能的版本中count将增长到2。<br />
<br />
4.30，第一问，我也谈不出所以然为什么ben的说法是正确的，关注下第二问的两个过程在不同eval-sequence下的表现，(p1 1)的结果没有改变都是(1 2)，而(p2 1)在原始版本的eval-sequence中结果是1，而在Cy修改后的版本中(对中间步骤采用actual-value)结果是(1 2)，也就是说在原始版本中的(set! x (cons x '(2)))的副作用根本没有实现，而在修改后的版本中实现了。俺觉的这个问题很迷惑，惰性求值与side effect相互作用很奇特，不过我更偏向原始版本，因为我觉的这样的实现更容易看清代码的意图，也就是说在透明性上更好，例如我分析p2过程就可以认为直接返回参数x；而实现副作用很容易让人掉入陷阱，并且很可能引进难以查找的bug。<br />
<br />
<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/238138.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-11-02 01:18 <a href="http://www.blogjava.net/killme2008/archive/2008/11/02/238138.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sicp 4.2.1两题</title><link>http://www.blogjava.net/killme2008/archive/2008/10/31/237917.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 31 Oct 2008 15:12:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/10/31/237917.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/237917.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/10/31/237917.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/237917.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/237917.html</trackback:ping><description><![CDATA[<br />
4.25，如果在scheme解释器的应用序求值下,unless定义为一个过程，那么<br />
(* (factorial (- n 1))<br />
将无穷递归下去。如果在正则序时，由于延时求值，仅当需要计算时才求值此表达式，不会造成无穷递归，在1的时候正常结束递归。<br />
<br />
4.26，在上一节求值器的基础上定义unless的语法形式还是很简单的，<br />
首先在analyze过程添加分析unless:<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&nbsp;((unless</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;exp)&nbsp;(analyze&nbsp;(unless</span><span style="color: #000000;">-&gt;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;exp)))</span></div>
<br />
然后定义unless?和unless-&gt;if<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(unless</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;exp)<br />
&nbsp;&nbsp;(tagged</span><span style="color: #000000;">-</span><span style="color: #000000;">list</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;exp&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">unless))</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">(define&nbsp;(unless</span><span style="color: #000000;">-&gt;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;exp)<br />
&nbsp;&nbsp;(make</span><span style="color: #000000;">-</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(cadr&nbsp;exp)&nbsp;(cadddr&nbsp;exp)&nbsp;(caddr&nbsp;exp)))</span></div>
<br />
最后一问，构造一个unless与高阶函数联合使用的场景，在此场景下，unless不能定义成特殊形式，仅在定义成过程的情况下有效，我想像不出此场景。<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/237917.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-10-31 23:12 <a href="http://www.blogjava.net/killme2008/archive/2008/10/31/237917.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>漂亮的代码</title><link>http://www.blogjava.net/killme2008/archive/2008/10/09/233468.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 09 Oct 2008 15:58:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/10/09/233468.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/233468.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/10/09/233468.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/233468.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/233468.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; Ruby的创造者为《代码之美》撰写的文章标题是《代码如散文》。程序和散文有一些共性，首先是两者都必须有清晰的意图，散文内容是什么，想表达什么，程序的功能是什么，能做什么；其次两者在意图的表达上（功能的实现上）都依赖于写作的具体风格，编程的隐喻之一就是写作。你想表达的思想是好的，但是如果表达得难以理解，那么要把这个思想传播给读者将非常困难。代码被读和修改的次数是相当多的，因此一个很重要的观点就是你写的代码是给人读的，你需要考虑可读性的问题，归结于写出漂亮的代码。<br />
&nbsp;&nbsp; 判断代码是否漂亮似乎没有什么国家标准，更没有国家免检。代码是写给人读的，从这个角度上看，如果一段代码能让人很容易地读懂，让人感觉心情愉快，修改起来也不费什么力气，这似乎就是漂亮的代码咯。那么显然，漂亮的代码的真正含义是<strong>帮助程序员感到快乐和提高生产率</strong>。有了这个指导性的方向，你可以从这么几个方面去努力写出漂亮的代码：简洁性、保守性、简单性、灵活性和平衡。<br />
&nbsp;&nbsp; 简洁性，文中以Ruby和Java版本的Hello World入手比较，在Ruby和其他动态语言中，你所做的就是你想表达的：打印Hello World<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">print</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">Hello&nbsp;World\n</span><span style="color: #800000;">"</span></div>
换成java，哦，你先要定义一个类，这个类有个入口main方法，在main方法中调用System.out对象的println方法打印：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Sample{<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;main(String&nbsp;[]args){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">Hello&nbsp;World</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
我记的我初学java的时候就特别不理解为什么要定义一个类，为什么方法要static、args，而我仅仅想要的只是打印一个字符串，可语言硬塞给了我太多的概念：类、方法、入口、参数。这些额外的东西牵扯了太多的注意力，而往往却忘记了初衷是什么。因此在《unix编程艺术》一书中对OO的一个评价是：鼓励具有厚重的胶合和复杂层次的体系，大大降低了代码的简洁性和透明性，你无法一眼看出代码是想做什么的。OO的抽象能力很强大，因此在很多场景下是这种抽象能力的滥用，实现最简单的功能也是一定要有类，有类才有对象，有对象才有光：）而往往这些对象却非问题领域中的自然实体，而是某种胶合物，为了抽象而抽象。<br />
&nbsp;&nbsp; 简洁同样意味着消除冗余。代码的重复是万恶之源，拷贝黏贴是滋生bug的温床，在重构概念如此深入人心的今天，这一点毋庸置疑。因此，谨记请DRY原则。语言级别的冗余可能是需要的，例如Ruby允许方法调用省略括号：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">task&nbsp;:name</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">:test<br />
task({:name</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">:test})<br />
<br />
</span></div>
这两行代码想表达的意思一样，显然第一种方式更简洁，这种语言级别的冗余显然是有利于程序员的，尽管将实现的难度推给了语言的设计和实现者。<br />
&nbsp;&nbsp; 漂亮代码另一个有争议的方面就是它的熟悉性，人们对于新东西的接受程度远没有想象中的高，大家都喜欢自己熟悉的东西而非全新的思考方式（嗯，极客例外）。这其实是Ruby一直鼓吹的最小惊奇原则的另一种表达。Ruby看来就是这么个保守的语言，他有很强大的OO能力，但是没有全然照搬smalltalk，他有FP的能力但是却没有让你惊掉下巴，他仍然遵循着古老的顺序、循环、选择的程序结构。<br />
&nbsp;&nbsp; 简单性强调是减轻程序员的工作负担，语言和类库API的优化应当有利于使用者，将困难留给实现者。前面提到的语言的冗余性就是一例。程序的复杂性来源有这么几个：商业上基于推销热点而非实际需求考虑出发带来的&#8220;特性清单&#8221;、业务领域本身的复杂度、程序员的自傲心理，最根本在于软件的开发的复杂性。如果能将复杂的功能，用人人理解的简单代码表达出来，当然漂亮！<br />
&nbsp;&nbsp; 简单并不意味着简陋，保守也不意味着死板。灵活性同样是代码漂亮与否的判断标准，是否隔离了变化点，是否拥有一定的扩展能力，是否无需借助工具的增强而实现某些巧妙的调用。同样以Ruby为例，open class和元编程给了内置你在语言级别的&#8220;工具&#8221;，你无需借助antlr、cglib等等类库去做一些看似复杂的东西。你将感受到编程的快乐，而非为了工具而去做一些违背本意的事情。灵活性可能是把双刃剑，过分的强调灵活性、可扩展性也可能带来复杂的代码，注意你的&#8220;炫耀&#8221;心理。<br />
&nbsp;&nbsp; 最后要强调的是平衡，在这些因素之间做出平衡，我觉的吧，没有更多实践的经验想平衡这些因素是相当困难的，如果了解了平衡的艺术，也许算是透出那么点&#8220;编程的艺术&#8221;的味道。Matz一直强调的一点是编程的乐趣，如果没有乐趣，我想我不会干这行，如果没有乐趣，我想我的工作效率将极度低下，从你认为是枯燥的工作中找乐子，存了这么个心理，你总能找出很多可以做的有趣事情，问题在于，你肯不肯做？<br />
<br />
ps.加张图片，俺的blog国家免检<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/killme2008/p147756914.jpg" width="200" height="201" /><br />
&nbsp;&nbsp; <br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/233468.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-10-09 23:58 <a href="http://www.blogjava.net/killme2008/archive/2008/10/09/233468.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>远程调用的语义</title><link>http://www.blogjava.net/killme2008/archive/2008/08/19/223133.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Tue, 19 Aug 2008 15:47:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/08/19/223133.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/223133.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/08/19/223133.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/223133.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/223133.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 远程调用由于涉及到服务器和客户端等多个节点以及需要通过网络通讯等，会引入更多的故障可能。本地调用的语义都是<strong>恰好一次</strong>，不会多也不会少。而远程调用的语义就比较复杂，依据三个选择将产生不同的语义：<br />
1）重发请求消息：客户端是否重发请求，直到收到应答或者认定服务器故障为止<br />
2）过滤重复消息：当客户端重发请求时候，服务器是否过滤重复的请求<br />
3）重传结果：服务器是否保存结果消息的历史，以便服务器不用重新执行操作就能重传结果。<br />
<br />
对这三个选择的不同组合将产生三种可能的远程调用语义：<br />
重发请求消息 过滤重复消息 重传结果&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 语义<br />
<br />
否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不适用&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不适用&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 或许<br />
是&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 重新执行操作&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 至少一次<br />
是&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 重传结果&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 至多一次<br />
<strong><br />
或许调用语义</strong>：远程方法可能执行一次，或者根本不执行（在消息遗漏或者服务器崩溃的情况下）<br />
<br />
<strong>至少一次调用语义</strong>：远程方法要嘛至少执行一次并返回结果，要嘛返回一个异常。因为启用了重发请求消息，服务器也重新执行操作，因此远程调用至少执行一次，除非服务器崩溃；但是，由于服务器重新执行操作，如果调用不是幂等的，那么多次重复执行将产生副作用叠加，可能不符合预期需求。对于幂等操作，至少一次调用语义是可以接受的。<br />
<br />
<strong>至多一次调用语义</strong>：在此语义下，服务器会过滤重复的请求，并且缓存执行的结果重传而非重新执行。因此远程调用同样也是返回调用结果，或者一个异常。在返回结果的情况下，可以确认服务器恰好执行一次，与本地调用语义一样，不会有副作用叠加。如果返回异常，就是通知调用者没有返回结果，远程调用要嘛执行了一次，要嘛根本没有执行。总之，远程调用至多执行一次。<br />
<br />
Java RMI的调用语义是至多一次。<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/223133.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-08-19 23:47 <a href="http://www.blogjava.net/killme2008/archive/2008/08/19/223133.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TCP的TIME_WAIT状态</title><link>http://www.blogjava.net/killme2008/archive/2008/06/23/209961.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sun, 22 Jun 2008 17:25:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/06/23/209961.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/209961.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/06/23/209961.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/209961.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/209961.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 主动关闭的Socket端会进入TIME_WAIT状态，并且持续2MSL时间长度，MSL就是maximum segment lifetime(最大分节生命期），这是一个IP数据包能在互联网上生存的最长时间，超过这个时间将在网络中消失。MSL在RFC 1122上建议是2分钟，而源自berkeley的TCP实现传统上使用30秒，因而，TIME_WAIT状态一般维持在1-4分钟。<br />
&nbsp;&nbsp;&nbsp; TIME_WAIT状态存在的理由：<br />
1）可靠地实现TCP全双工连接的终止<br />
&nbsp;&nbsp;&nbsp; 在进行关闭连接四路握手协议时，最后的ACK是由主动关闭端发出的，如果这个最终的ACK丢失，服务器将重发最终的FIN，因此客户端必须维护状态信息允许它重发最终的ACK。如果不维持这个状态信息，那么客户端将响应RST分节，服务器将此分节解释成一个错误（在java中会抛出connection reset的SocketException)。因而，要实现TCP全双工连接的正常终止，必须处理终止序列四个分节中任何一个分节的丢失情况，主动关闭的客户端必须维持状态信息进入TIME_WAIT状态。<br />
<br />
2）允许老的重复分节在网络中消逝&nbsp; <br />
&nbsp;&nbsp;&nbsp; TCP分节可能由于路由器异常而&#8220;迷途&#8221;，在迷途期间，TCP发送端可能因确认超时而重发这个分节，迷途的分节在路由器修复后也会被送到最终目的地，这个原来的迷途分节就称为lost duplicate。在关闭一个TCP连接后，马上又重新建立起一个相同的IP地址和端口之间的TCP连接，后一个连接被称为前一个连接的化身（incarnation)，那么有可能出现这种情况，前一个连接的迷途重复分组在前一个连接终止后出现，从而被误解成从属于新的化身。为了避免这个情况，TCP不允许处于TIME_WAIT状态的连接启动一个新的化身，因为TIME_WAIT状态持续2MSL，就可以保证当成功建立一个TCP连接的时候，来自连接先前化身的重复分组已经在网络中消逝。<br />
<br />
新的SCTP协议通过在消息头部添加验证标志避免了TIME_WAIT状态。<br /><img src ="http://www.blogjava.net/killme2008/aggbug/209961.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-06-23 01:25 <a href="http://www.blogjava.net/killme2008/archive/2008/06/23/209961.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sicp4.1.1-4.1.5节部分习题尝试解答(update)</title><link>http://www.blogjava.net/killme2008/archive/2008/06/01/205155.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sun, 01 Jun 2008 07:51:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/06/01/205155.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/205155.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/06/01/205155.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/205155.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/205155.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 当将用scheme写的scheme求值器跑起来的时候，你不觉的兴奋是不可能的，真的太酷了，太magic了。<br />
习题4.2，如果将application？判断放在define?判断之前，那么求值(define x 3)将把define当作一般的procedure应用于参数x和3，可是define是特殊的语法形式，而非一般过程，导致出错。<br />
习题4.4，我的解答，eval增加两个判断：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&nbsp;((and</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;exp)<br />
&nbsp;&nbsp;&nbsp;(eval</span><span style="color: #000000;">-</span><span style="color: #000000;">and&nbsp;(and</span><span style="color: #000000;">-</span><span style="color: #000000;">exps&nbsp;exp)&nbsp;env))<br />
&nbsp;((or</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;exp)<br />
&nbsp;&nbsp;&nbsp;(eval</span><span style="color: #000000;">-</span><span style="color: #000000;">or&nbsp;(or</span><span style="color: #000000;">-</span><span style="color: #000000;">exps&nbsp;exp)&nbsp;env))</span></div>
实现谓词和各自的过程：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(and</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;exp)&nbsp;<br />
&nbsp;&nbsp;(tagged</span><span style="color: #000000;">-</span><span style="color: #000000;">list</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;exp&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">and))</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">(define&nbsp;(and</span><span style="color: #000000;">-</span><span style="color: #000000;">exps&nbsp;exp)<br />
&nbsp;&nbsp;(cdr&nbsp;exp))<br />
(define&nbsp;(eval</span><span style="color: #000000;">-</span><span style="color: #000000;">and&nbsp;exps&nbsp;env)<br />
&nbsp;&nbsp;(cond&nbsp;((</span><span style="color: #0000ff;">null</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;exps)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">true)</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((result&nbsp;(eval&nbsp;(car&nbsp;exps)&nbsp;env)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(not&nbsp;result)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(eval</span><span style="color: #000000;">-</span><span style="color: #000000;">and&nbsp;(cdr&nbsp;exps)&nbsp;env))))))<br />
(define&nbsp;(or</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;exp)<br />
&nbsp;&nbsp;(tagged</span><span style="color: #000000;">-</span><span style="color: #000000;">list</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;exp&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">or))</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">(define&nbsp;(or</span><span style="color: #000000;">-</span><span style="color: #000000;">exps&nbsp;exp)&nbsp;(cdr&nbsp;exp))<br />
(define&nbsp;(eval</span><span style="color: #000000;">-</span><span style="color: #000000;">or&nbsp;exps&nbsp;env)<br />
&nbsp;&nbsp;(cond&nbsp;((</span><span style="color: #0000ff;">null</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;exps)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">false)</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((result&nbsp;(eval&nbsp;(car&nbsp;exps)&nbsp;env)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;result<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(eval</span><span style="color: #000000;">-</span><span style="color: #000000;">or&nbsp;(cdr&nbsp;exps)&nbsp;env))))))</span></div>
<br />
如果用宏实现就简单了：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define</span><span style="color: #000000;">-</span><span style="color: #000000;">syntax&nbsp;and<br />
&nbsp; (syntax</span><span style="color: #000000;">-</span><span style="color: #000000;">rules&nbsp;()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((_)&nbsp;#t)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((_&nbsp;e)&nbsp;e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((_&nbsp;e1&nbsp;e2&nbsp;e3&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;e1&nbsp;(and&nbsp;e2&nbsp;e3&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />)&nbsp;#f))))<br />
(define</span><span style="color: #000000;">-</span><span style="color: #000000;">syntax&nbsp;or<br />
&nbsp;&nbsp; (syntax</span><span style="color: #000000;">-</span><span style="color: #000000;">rules&nbsp;()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((_)&nbsp;#f)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((_&nbsp;e)&nbsp;e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((_&nbsp;e1&nbsp;e2&nbsp;e3&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (let&nbsp;((t&nbsp;e1))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;t&nbsp;t&nbsp;(or&nbsp;e2&nbsp;e3&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />))))))</span></div>
<br />
习题4.5，cond的扩展形式，也不难，在else子句之外增加个判断，是否带有=&gt;符号，修改expand-clauses过程：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define (cond-extended-clauses? clause)<br />
&nbsp; (and (&gt; (length clause) 2) (eq? (cadr clause) '=&gt;)))<br />
(define (extended-cond-test clause)<br />
&nbsp; (car clause))<br />
(define (extended-cond-recipient clause)<br />
&nbsp; (caddr clause)<br />
(define&nbsp;(expand</span><span style="color: #000000;">-</span><span style="color: #000000;">clauses&nbsp;clauses)<br />
&nbsp;&nbsp;(</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">null</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;clauses)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">false</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((first&nbsp;(car&nbsp;clauses))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(rest&nbsp;(cdr&nbsp;clauses)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(cond&nbsp;((cond</span><span style="color: #000000;">-</span><span style="color: #0000ff;">else</span><span style="color: #000000;">-</span><span style="color: #000000;">clauses</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;first)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">null</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;rest)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(sequence</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">exp&nbsp;(cond</span><span style="color: #000000;">-</span><span style="color: #000000;">actions&nbsp;first))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(error&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">else&nbsp;clause&nbsp;is&nbsp;not&nbsp;LAST</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;clauses)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((cond</span><span style="color: #000000;">-</span><span style="color: #000000;">extended</span><span style="color: #000000;">-</span><span style="color: #000000;">clauses</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;first)&nbsp; ;判断是否扩展形式<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(make</span><span style="color: #000000;">-</span><span style="color: #0000ff;">if</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(extended</span><span style="color: #000000;">-</span><span style="color: #000000;">cond</span><span style="color: #000000;">-</span><span style="color: #000000;">test&nbsp;first)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(extended</span><span style="color: #000000;">-</span><span style="color: #000000;">cond</span><span style="color: #000000;">-</span><span style="color: #000000;">recipient&nbsp;first)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(extended</span><span style="color: #000000;">-</span><span style="color: #000000;">cond</span><span style="color: #000000;">-</span><span style="color: #000000;">test&nbsp;first))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(expand</span><span style="color: #000000;">-</span><span style="color: #000000;">clauses&nbsp;rest)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(make</span><span style="color: #000000;">-</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(cond</span><span style="color: #000000;">-</span><span style="color: #000000;">predicate&nbsp;first)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(sequence</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">exp&nbsp;(cond</span><span style="color: #000000;">-</span><span style="color: #000000;">actions&nbsp;first))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(expand</span><span style="color: #000000;">-</span><span style="color: #000000;">clauses&nbsp;rest)))))))</span></div>
<br />
习题4.6，let如果用宏定义，类似这样：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define</span><span style="color: #000000;">-</span><span style="color: #000000;">syntax&nbsp;let<br />
&nbsp;&nbsp;(syntax</span><span style="color: #000000;">-</span><span style="color: #000000;">rules&nbsp;()<br />
&nbsp;&nbsp;&nbsp;&nbsp;((_&nbsp;((x&nbsp;v)&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />)&nbsp;e1&nbsp;e2&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;(x&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />)&nbsp;e1&nbsp;e2&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />)&nbsp;v&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />))))</span></div>
求值器扩展，实现let-&gt;combination过程：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(let?&nbsp;exp)<br />
&nbsp;&nbsp;(tagged</span><span style="color: #000000;">-</span><span style="color: #000000;">list?&nbsp;exp&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">let))</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">(define&nbsp;(let</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">combination&nbsp;exp)<br />
&nbsp;&nbsp;(let&nbsp;((vars&nbsp;(map&nbsp;car&nbsp;(cadr&nbsp;exp)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(vals&nbsp;(map&nbsp;cadr&nbsp;(cadr&nbsp;exp)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(body&nbsp;(caddr&nbsp;exp)))<br />
&nbsp;&nbsp;(cons&nbsp;(make</span><span style="color: #000000;">-</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;vars&nbsp;(list&nbsp;body))&nbsp;vals)))</span></div>
我们做的仅仅是syntax transform，将let转成对应的lambda形式。<br />
<br />
习题4.7，这里的关键在于let*-&gt;netsted-lets要递归调用，从let*的宏定义可以看出：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define</span><span style="color: #000000;">-</span><span style="color: #000000;">syntax&nbsp;let</span><span style="color: #000000;">*</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(syntax</span><span style="color: #000000;">-</span><span style="color: #000000;">rules()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((_&nbsp;((var1&nbsp;val1))&nbsp;e1&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((var1&nbsp;val1))&nbsp;e1&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((_&nbsp;((var1&nbsp;val1)&nbsp;(var2&nbsp;val2)&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />)&nbsp;e1&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((var1&nbsp;val1))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;((var2&nbsp;val2)&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e1&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />)))))</span></div>
那么，let*-&gt;nested-lets可以定义为：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(let</span><span style="color: #000000;">*</span><span style="color: #000000;">?&nbsp;exp)<br />
&nbsp;&nbsp;(tagged</span><span style="color: #000000;">-</span><span style="color: #000000;">list?&nbsp;exp&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">let*))</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">(define&nbsp;(let</span><span style="color: #000000;">*-&gt;</span><span style="color: #000000;">nested</span><span style="color: #000000;">-</span><span style="color: #000000;">lets&nbsp;exp)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((pairs&nbsp;(cadr&nbsp;exp))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(body&nbsp;(caddr&nbsp;exp)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(null?&nbsp;(cdr&nbsp;pairs))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">let&nbsp;pairs&nbsp;body)</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">let&nbsp;(list&nbsp;(car&nbsp;pairs))&nbsp;(let*-&gt;nested-lets&nbsp;(list&nbsp;</span><span style="color: #800000;">'</span><span style="color: #000000;">let</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;(cdr&nbsp;pairs)&nbsp;body))))))</span></div>
测试一下：<br />
(let* ((x 1) (y (+ x 3))) (+ x y)) =》5<br />
<br />
习题4.8，命名let，修改let-&gt;combination过程，判断cadr是pair还是symbol，如果是前者，那就是一般的let，如果是symbol就是命名let语句，那么需要定义一个名为(cadr exp)的过程放在body里，注意，我们是在做语法转换，因此，这个定义也应该描述成符号，定义一个make-define过程来生成define语句：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(make</span><span style="color: #000000;">-</span><span style="color: #000000;">define&nbsp;var&nbsp;parameters&nbsp;body)<br />
&nbsp;&nbsp;(list&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">define&nbsp;(cons&nbsp;var&nbsp;parameters)&nbsp;body))</span></div>
然后修改let-&gt;combination过程，如上所述：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(let</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">combination&nbsp;exp)<br />
&nbsp;&nbsp;(</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(symbol?&nbsp;(cadr&nbsp;exp))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((var&nbsp;(cadr&nbsp;exp))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(vars&nbsp;(map&nbsp;car&nbsp;(caddr&nbsp;exp)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(vals&nbsp;(map&nbsp;cadr&nbsp;(caddr&nbsp;exp)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(pairs&nbsp;(caddr&nbsp;exp))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(body&nbsp;(cadddr&nbsp;exp)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(cons&nbsp;(make</span><span style="color: #000000;">-</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;vars&nbsp;(list&nbsp;(make</span><span style="color: #000000;">-</span><span style="color: #000000;">define&nbsp;var&nbsp;vars&nbsp;body)&nbsp;body))&nbsp;vals))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((vars&nbsp;(map&nbsp;car&nbsp;(cadr&nbsp;exp)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(vals&nbsp;(map&nbsp;cadr&nbsp;(cadr&nbsp;exp)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(body&nbsp;(caddr&nbsp;exp)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(cons&nbsp;(make</span><span style="color: #000000;">-</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;vars&nbsp;(list&nbsp;body))&nbsp;vals))))</span></div>
<br />
<br />
习题4.1.4，原生的map过程接受的procedure，是以scheme内在数据结构表示的procedure，而在我们的求值器中，procedure的内在数据结构取决于我们，与原生的结构不同，导致原生的map无法接受自制求值器的procedure，如果map也以求值器中的结构定义，那么就没有这个问题。因此，本质上的困难就在于两个求值器对procedure的数据结构表示的不同。<br />
<br />
习题4.1.5，著名的图灵停机问题，先是假设存在halts?过程可以正确地判断任何过程p和对象a是否p对a终止，定义了try过程：<br />
(define (try p)<br />
&nbsp;&nbsp; (if (halts? p p)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (run-forever)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'halted))<br />
当执行(try try),如果这个过程可终止，那么(halts? try try)应该返回false，也就是try过程对try不会终止，这与一开始的假设矛盾；如果这个过程将无穷运行下去，那么(halts? try try)应该返回true，也就是try对try终止，这也与(try try)将无穷运行的假设矛盾。因此，可以推论出，我们不可能写出一个过程halts?，使它能正确地判断任何过程p和对象a是否p对a终止。<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/205155.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-06-01 15:51 <a href="http://www.blogjava.net/killme2008/archive/2008/06/01/205155.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最近的工作</title><link>http://www.blogjava.net/killme2008/archive/2008/05/21/201865.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 21 May 2008 03:45:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/05/21/201865.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/201865.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/05/21/201865.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/201865.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/201865.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 转眼间，来广州快半年了，感觉还不错。广州如死鱼所说的那样，是个包容并且很有活力的城市，习惯了周末煲汤，去天河公园跑跑步，这生活还是挺舒适的，除了比较潮的天气。<br />
&nbsp;&nbsp;&nbsp; 最近跟公司闹了点不愉快，在转正时间上，其实不是多大的事，只是心里不舒服罢了，干起活来也没什么激情了，呵呵。当然，手头的工作咱还是要高效率地完成，做完两个游戏后，现在转到棋牌类，棋牌类游戏核心就两个算法：随机发牌和出牌判断。随机发牌算法，学习了云风的blog上提到的方法，感觉还可以接受；出牌规则判断，倒是没想象中的复杂，建立牌型的OO模型，一切都很简单了。另外一个发现，用jdk6跑jruby1.1.1，比用jdk5跑效率（包括内存和CPU）好上很多，例如我们一个游戏进程，在使用jdk5时，CPU稳定在15%，内存85M，而改用jdk6后，cpu降到了%5以下，内存也缩减到70多M。<br />
&nbsp;&nbsp;&nbsp; 搞完了之后，时间有点空闲，就想学点新东西，最后选择了Prolog。Yep，非常地有趣，真正的声明式编程语言。Prolog本质上就是两个东西：规则和事实，由事实和规则出发，Prolog的推理系统将回答你的查询（query）。有点类似现在流行中的规则引擎的概念，在对效率不是很考虑的场景中，嵌入一个Prolog引擎做规则引擎完全是可以的，java中有个tuProlog项目，可以关注一下。然后就是一直在读的sicp，延时求值模拟无穷级数实在是相当地cool，大开眼界。这两天一直在理解continuation这个概念，小有所得。一个表达式的求值可以分为两个阶段：&#8220;What to evaluate?&#8221;和&#8220;What to do with the value&#8221;，&#8220;What to do with the value&#8221;就是计算的Continuation。例如，scheme求值下列表达式：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">null</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;x)&nbsp;(quote&nbsp;())&nbsp;(cdr&nbsp;x))</span></div>
先求值表达式(null? x)，(null? x)就是&#8220;What to evaluate&#8221;，当(null? x)求值后，需要根据这个值来决定是执行(quote ())还是(cdr x)，这个根据值来决定的过程就是Continuation。如果在每次函数调用时，同时传入当前的continuation，那么就完全可以不要堆栈。call/cc就提供了这样的一个语法糖，call/cc全称就是call-with-current-continuation，要求参数是一个过程，调用这个过程，并且向这个过程传入当前的continuation（一般称为k,kont，或者Ruby中一般是c,cont)，这就是call/cc为我们做的。call/cc是实现Continuation的方式之一，coroutine/fiber/yield也是实现continuation的方式。《The Scheme Programming Language》给出的轻量级进程机制的例子比较有趣：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;lwp</span><span style="color: #000000;">-</span><span style="color: #000000;">list&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">())</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">(define&nbsp;(lwp&nbsp;thunk)<br />
&nbsp;&nbsp;(set!&nbsp;lwp</span><span style="color: #000000;">-</span><span style="color: #000000;">list&nbsp;(append&nbsp;lwp</span><span style="color: #000000;">-</span><span style="color: #000000;">list&nbsp;(list&nbsp;thunk))))<br />
(define&nbsp;start<br />
&nbsp;&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">()<br />
&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((p&nbsp;(car&nbsp;lwp</span><span style="color: #000000;">-</span><span style="color: #000000;">list)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set!&nbsp;lwp</span><span style="color: #000000;">-</span><span style="color: #000000;">list&nbsp;(cdr&nbsp;lwp</span><span style="color: #000000;">-</span><span style="color: #000000;">list))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(p))))<br />
(define&nbsp;pause<br />
&nbsp;&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">()<br />
&nbsp;&nbsp;&nbsp;&nbsp;(callcc&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">(k)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(lwp&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;()&nbsp;(k&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">f)))</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(start)))))<br />
(lwp&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;()&nbsp;(let&nbsp;f&nbsp;()&nbsp;(display&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">h</span><span style="color: #800000;">"</span><span style="color: #000000;">)&nbsp;(pause)&nbsp;(f))))<br />
(lwp&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;()&nbsp;(let&nbsp;f&nbsp;()&nbsp;(display&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">e</span><span style="color: #800000;">"</span><span style="color: #000000;">)&nbsp;(pause)&nbsp;(f))))<br />
(lwp&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;()&nbsp;(let&nbsp;f&nbsp;()&nbsp;(display&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">y</span><span style="color: #800000;">"</span><span style="color: #000000;">)&nbsp;(pause)&nbsp;(f))))<br />
(lwp&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;()&nbsp;(let&nbsp;f&nbsp;()&nbsp;(display&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">!</span><span style="color: #800000;">"</span><span style="color: #000000;">)&nbsp;(pause)&nbsp;(f))))<br />
(lwp&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;()&nbsp;(let&nbsp;f&nbsp;()&nbsp;(newline)&nbsp;(pause)&nbsp;(f))))<br />
(start)</span></div>
实现了代码级的进程调度。<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/201865.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-05-21 11:45 <a href="http://www.blogjava.net/killme2008/archive/2008/05/21/201865.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sicp3.5.2、3.5.3节部分习题尝试解答</title><link>http://www.blogjava.net/killme2008/archive/2008/05/13/200312.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Tue, 13 May 2008 15:52:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/05/13/200312.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/200312.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/05/13/200312.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/200312.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/200312.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 本节主要讲述无穷流。<br />
3.53，显然<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;s&nbsp;(cons</span><span style="color: #000000;">-</span><span style="color: #000000;">stream&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;(add</span><span style="color: #000000;">-</span><span style="color: #000000;">stream&nbsp;s&nbsp;s)))</span></div>
定义是2的n次方组成的无穷数列，2,4,8,16,32...<br />
<br />
3.54，定义阶乘组成的无穷序列：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(mul</span><span style="color: #000000;">-</span><span style="color: #000000;">streams&nbsp;s1&nbsp;s2)<br />
&nbsp;&nbsp;(stream</span><span style="color: #000000;">-</span><span style="color: #000000;">map&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;s1&nbsp;s2))<br />
(define&nbsp;factorials&nbsp;(cons</span><span style="color: #000000;">-</span><span style="color: #000000;">stream&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;(mul</span><span style="color: #000000;">-</span><span style="color: #000000;">streams&nbsp;factorials&nbsp;(stream</span><span style="color: #000000;">-</span><span style="color: #000000;">cdr&nbsp;integers))))</span></div>
<br />
3.55解答，比较有趣，也是不难的题目，列出来找出规律就成了，就是将(stream-car s)加到生成的序列中的每个元素上，通过stream-map，最后的结果就是每个元素都是前n个元素累积的结果，我的解答：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(partial</span><span style="color: #000000;">-</span><span style="color: #000000;">sums&nbsp;s)<br />
&nbsp;&nbsp;(cons</span><span style="color: #000000;">-</span><span style="color: #000000;">stream&nbsp;(stream</span><span style="color: #000000;">-</span><span style="color: #000000;">car&nbsp;s)&nbsp;(stream</span><span style="color: #000000;">-</span><span style="color: #000000;">map&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">(x)&nbsp;(</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;x&nbsp;(stream</span><span style="color: #000000;">-</span><span style="color: #000000;">car&nbsp;s)))&nbsp;(partial</span><span style="color: #000000;">-</span><span style="color: #000000;">sums&nbsp;(stream</span><span style="color: #000000;">-</span><span style="color: #000000;">cdr&nbsp;s)))))</span></div>
<br />
3.56，有了merge就好办了，根据条件合并起3种情况来就好：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define S (cons</span><span style="color: #000000;">-</span><span style="color: #000000;">stream&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;(merge&nbsp;(scale</span><span style="color: #000000;">-</span><span style="color: #000000;">stream&nbsp;s&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">)&nbsp;(merge&nbsp;(scale</span><span style="color: #000000;">-</span><span style="color: #000000;">stream&nbsp;s&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">)&nbsp;(scale</span><span style="color: #000000;">-</span><span style="color: #000000;">stream&nbsp;s&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">)))))</span></div>
<br />
3.57,略过<br />
<br />
3.58，观察到，num每次都与radix相乘并且radix保持不变，那么radix可以认为是一个基数，den也保持不变作为除数，那么这个序列就是以radix为基数对den求整数商的序列，不明白num为什么每次要变换成余数？这个序列有啥特别的用途呢？未解。<br />
<pre>(expand 1 7 10)<br />
=&gt; 1 4 2 8 5 7 1 4 2 8<br />
<br />
(expand 3 8 10)<br />
=&gt; 3 7 5 0 0 0 0 0 0 0</pre>
3.59解答：<br />
a)只要将序列通过前面定义的mul-streams与整数的倒数序列相乘：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(integrate</span><span style="color: #000000;">-</span><span style="color: #000000;">series&nbsp;s)<br />
&nbsp;&nbsp;(mul</span><span style="color: #000000;">-</span><span style="color: #000000;">streams (stream</span><span style="color: #000000;">-</span><span style="color: #000000;">map&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">(x)&nbsp;(</span><span style="color: #000000;">/</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;x))&nbsp;integers)&nbsp;s))</span></div>
<br />
b)照着定义来了，cons的级数注意使用scale-stream乘以-1：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define sine</span><span style="color: #000000;">-</span><span style="color: #000000;">series<br />
&nbsp;&nbsp;(cons</span><span style="color: #000000;">-</span><span style="color: #000000;">stream&nbsp;0&nbsp;(integrate</span><span style="color: #000000;">-</span><span style="color: #000000;">series&nbsp;cosine</span><span style="color: #000000;">-</span><span style="color: #000000;">series)))<br />
<br />
(define cosine</span><span style="color: #000000;">-</span><span style="color: #000000;">series<br />
&nbsp;&nbsp;(cons</span><span style="color: #000000;">-</span><span style="color: #000000;">stream&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;(scale</span><span style="color: #000000;">-</span><span style="color: #000000;">stream<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(integrate</span><span style="color: #000000;">-</span><span style="color: #000000;">series&nbsp;sine</span><span style="color: #000000;">-</span><span style="color: #000000;">series)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">)))</span></div>
<br />
3.64解答：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(stream</span><span style="color: #000000;">-</span><span style="color: #000000;">limit&nbsp;s&nbsp;tolerance)<br />
&nbsp;&nbsp;(define&nbsp;(stream</span><span style="color: #000000;">-</span><span style="color: #000000;">limit</span><span style="color: #000000;">-</span><span style="color: #000000;">iter&nbsp;stream&nbsp;current)<br />
&nbsp;&nbsp;&nbsp;&nbsp;(cond&nbsp;((</span><span style="color: #0000ff;">or</span><span style="color: #000000;">&nbsp;(stream</span><span style="color: #000000;">-</span><span style="color: #000000;">null?&nbsp;stream)&nbsp;(null?&nbsp;(stream</span><span style="color: #000000;">-</span><span style="color: #000000;">car&nbsp;stream)))&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">f)</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((next&nbsp;(stream</span><span style="color: #000000;">-</span><span style="color: #000000;">car&nbsp;stream)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;(abs&nbsp;(</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;next&nbsp;current))&nbsp;tolerance)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(stream</span><span style="color: #000000;">-</span><span style="color: #000000;">limit</span><span style="color: #000000;">-</span><span style="color: #000000;">iter&nbsp;(stream</span><span style="color: #000000;">-</span><span style="color: #000000;">cdr&nbsp;stream)&nbsp;next))))))<br />
&nbsp;&nbsp;(stream</span><span style="color: #000000;">-</span><span style="color: #000000;">limit</span><span style="color: #000000;">-</span><span style="color: #000000;">iter&nbsp;(stream</span><span style="color: #000000;">-</span><span style="color: #000000;">cdr&nbsp;s)&nbsp;(stream</span><span style="color: #000000;">-</span><span style="color: #000000;">car&nbsp;s)))</span></div>
<br />
习题3.65：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(ln</span><span style="color: #000000;">-</span><span style="color: #000000;">summands&nbsp;n)<br />
&nbsp;&nbsp;(cons</span><span style="color: #000000;">-</span><span style="color: #000000;">stream&nbsp;(</span><span style="color: #000000;">/</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1.0</span><span style="color: #000000;">&nbsp;n)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(stream</span><span style="color: #000000;">-</span><span style="color: #000000;">map&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;(ln</span><span style="color: #000000;">-</span><span style="color: #000000;">summands&nbsp;(</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;n&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)))))<br />
(define&nbsp;ln</span><span style="color: #000000;">-</span><span style="color: #000000;">stream&nbsp;(partial</span><span style="color: #000000;">-</span><span style="color: #000000;">sums&nbsp;(ln</span><span style="color: #000000;">-</span><span style="color: #000000;">summands&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)))<br />
(define&nbsp;ln</span><span style="color: #000000;">-</span><span style="color: #000000;">stream2&nbsp;(euler</span><span style="color: #000000;">-</span><span style="color: #000000;">transform&nbsp;ln</span><span style="color: #000000;">-</span><span style="color: #000000;">stream))<br />
(define&nbsp;ln</span><span style="color: #000000;">-</span><span style="color: #000000;">stream3&nbsp;(accelerated</span><span style="color: #000000;">-</span><span style="color: #000000;">sequence&nbsp;euler</span><span style="color: #000000;">-</span><span style="color: #000000;">transform&nbsp;ln</span><span style="color: #000000;">-</span><span style="color: #000000;">stream))</span></div>
经过欧拉变换加速过的级数收敛的很快，测测就知道<br /><img src ="http://www.blogjava.net/killme2008/aggbug/200312.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-05-13 23:52 <a href="http://www.blogjava.net/killme2008/archive/2008/05/13/200312.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>scheme解决约瑟夫环问题（续）</title><link>http://www.blogjava.net/killme2008/archive/2008/04/16/193331.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 16 Apr 2008 02:27:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/04/16/193331.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/193331.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/04/16/193331.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/193331.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/193331.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; sicp的习题3.22，也就是以消息传递的风格重新实现队列，我的解答如下：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(make</span><span style="color: #000000;">-</span><span style="color: #000000;">queue)<br />
&nbsp;&nbsp;(let&nbsp;((front</span><span style="color: #000000;">-</span><span style="color: #000000;">ptr&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">())</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(rear</span><span style="color: #000000;">-</span><span style="color: #000000;">ptr&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">()))</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;(define&nbsp;(set</span><span style="color: #000000;">-</span><span style="color: #000000;">front</span><span style="color: #000000;">-</span><span style="color: #000000;">ptr!&nbsp;ptr)&nbsp;(set!&nbsp;front</span><span style="color: #000000;">-</span><span style="color: #000000;">ptr&nbsp;ptr))<br />
&nbsp;&nbsp;(define&nbsp;(set</span><span style="color: #000000;">-</span><span style="color: #000000;">rear</span><span style="color: #000000;">-</span><span style="color: #000000;">ptr!&nbsp;ptr)&nbsp;(set!&nbsp;rear</span><span style="color: #000000;">-</span><span style="color: #000000;">ptr&nbsp;ptr))<br />
&nbsp;&nbsp;(define&nbsp;(empty</span><span style="color: #000000;">-</span><span style="color: #000000;">queue?)&nbsp;(null?&nbsp;front</span><span style="color: #000000;">-</span><span style="color: #000000;">ptr))<br />
&nbsp;&nbsp;(define&nbsp;(front</span><span style="color: #000000;">-</span><span style="color: #000000;">queue)<br />
&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(empty</span><span style="color: #000000;">-</span><span style="color: #000000;">queue?)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(error&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">FRONT&nbsp;called&nbsp;with&nbsp;an&nbsp;empty&nbsp;queue</span><span style="color: #800000;">"</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(car&nbsp;front</span><span style="color: #000000;">-</span><span style="color: #000000;">ptr)))<br />
&nbsp;&nbsp;(define&nbsp;(insert</span><span style="color: #000000;">-</span><span style="color: #000000;">queue!&nbsp;item)<br />
&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((new</span><span style="color: #000000;">-</span><span style="color: #000000;">pair&nbsp;(cons&nbsp;item&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">())))</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(cond&nbsp;((empty</span><span style="color: #000000;">-</span><span style="color: #000000;">queue?)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set</span><span style="color: #000000;">-</span><span style="color: #000000;">front</span><span style="color: #000000;">-</span><span style="color: #000000;">ptr!&nbsp;new</span><span style="color: #000000;">-</span><span style="color: #000000;">pair)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set</span><span style="color: #000000;">-</span><span style="color: #000000;">rear</span><span style="color: #000000;">-</span><span style="color: #000000;">ptr!&nbsp;new</span><span style="color: #000000;">-</span><span style="color: #000000;">pair))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set</span><span style="color: #000000;">-</span><span style="color: #000000;">cdr!&nbsp;rear</span><span style="color: #000000;">-</span><span style="color: #000000;">ptr&nbsp;new</span><span style="color: #000000;">-</span><span style="color: #000000;">pair)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set</span><span style="color: #000000;">-</span><span style="color: #000000;">rear</span><span style="color: #000000;">-</span><span style="color: #000000;">ptr!&nbsp;new</span><span style="color: #000000;">-</span><span style="color: #000000;">pair)))))<br />
&nbsp;&nbsp;(define&nbsp;(delete</span><span style="color: #000000;">-</span><span style="color: #000000;">queue!)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(cond&nbsp;((empty</span><span style="color: #000000;">-</span><span style="color: #000000;">queue?)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(error&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">DELETE!&nbsp;called&nbsp;with&nbsp;an&nbsp;empty&nbsp;queue</span><span style="color: #800000;">"</span><span style="color: #000000;">&nbsp;queue))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set</span><span style="color: #000000;">-</span><span style="color: #000000;">front</span><span style="color: #000000;">-</span><span style="color: #000000;">ptr!&nbsp;(cdr&nbsp;front</span><span style="color: #000000;">-</span><span style="color: #000000;">ptr)))))<br />
&nbsp;&nbsp;(define&nbsp;(dispatch&nbsp;m)<br />
&nbsp;&nbsp;&nbsp;&nbsp;(cond&nbsp;((eq?&nbsp;m&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">front-queue)&nbsp;(front-queue))</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((eq?&nbsp;m&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">empty-queue?)&nbsp;(empty-queue?))</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((eq?&nbsp;m&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">insert-queue!)&nbsp;insert-queue!)</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((eq?&nbsp;m&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">delete-queue!)&nbsp;delete-queue!)</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(error&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">Unknow&nbsp;method</span><span style="color: #800000;">"</span><span style="color: #000000;">&nbsp;m))))<br />
&nbsp;&nbsp;&nbsp;&nbsp;dispatch))<br />
(define&nbsp;(front</span><span style="color: #000000;">-</span><span style="color: #000000;">queue&nbsp;z)&nbsp;(z&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">front-queue))</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">(define&nbsp;(empty</span><span style="color: #000000;">-</span><span style="color: #000000;">queue?&nbsp;z)&nbsp;(z&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">empty-queue?))</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">(define&nbsp;(insert</span><span style="color: #000000;">-</span><span style="color: #000000;">queue!&nbsp;z&nbsp;item)&nbsp;((z&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">insert-queue!)&nbsp;item))</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">(define&nbsp;(delete</span><span style="color: #000000;">-</span><span style="color: #000000;">queue!&nbsp;z)&nbsp;((z&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">delete-queue!)))</span></div>
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 由此，我才知道自己竟然一直没有想到，scheme完全可以模拟单向循环链表，整整第三章都在讲引入赋值带来的影响，而我却视而不见。在引入了改变函数后，数据对象已经具有OO的性质，模拟链表、队列、table都变的易如反掌。首先，模拟节点对象，节点是一个序对，包括当前节点编号和下一个节点：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(make</span><span style="color: #000000;">-</span><span style="color: #000000;">node&nbsp;n&nbsp;next)&nbsp;(cons&nbsp;n&nbsp;next))<br />
(define&nbsp;(set</span><span style="color: #000000;">-</span><span style="color: #000000;">next</span><span style="color: #000000;">-</span><span style="color: #000000;">node!&nbsp;node&nbsp;next)&nbsp;(set</span><span style="color: #000000;">-</span><span style="color: #000000;">cdr!&nbsp;node&nbsp;next))<br />
(define&nbsp;(set</span><span style="color: #000000;">-</span><span style="color: #000000;">node</span><span style="color: #000000;">-</span><span style="color: #000000;">number!&nbsp;node&nbsp;n)&nbsp;(set</span><span style="color: #000000;">-</span><span style="color: #000000;">car!&nbsp;node&nbsp;n))<br />
(define&nbsp;(get</span><span style="color: #000000;">-</span><span style="color: #000000;">number&nbsp;node)&nbsp;(car&nbsp;node))<br />
(define&nbsp;(get</span><span style="color: #000000;">-</span><span style="color: #000000;">next</span><span style="color: #000000;">-</span><span style="color: #000000;">node&nbsp;node)&nbsp;(cdr&nbsp;node))</span></div>
<br />
&nbsp;&nbsp;&nbsp; 有了节点，实现了下单向循环链表：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(make</span><span style="color: #000000;">-</span><span style="color: #000000;">cycle</span><span style="color: #000000;">-</span><span style="color: #000000;">list&nbsp;n)<br />
&nbsp;&nbsp;(let&nbsp;((head&nbsp;(make</span><span style="color: #000000;">-</span><span style="color: #000000;">node&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">())))</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;(define&nbsp;(make</span><span style="color: #000000;">-</span><span style="color: #000000;">list&nbsp;current&nbsp;i)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((next</span><span style="color: #000000;">-</span><span style="color: #000000;">node&nbsp;(make</span><span style="color: #000000;">-</span><span style="color: #000000;">node&nbsp;(</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">())))</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(cond&nbsp;((</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;i&nbsp;n)&nbsp;current)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set</span><span style="color: #000000;">-</span><span style="color: #000000;">next</span><span style="color: #000000;">-</span><span style="color: #000000;">node!&nbsp;current&nbsp;next</span><span style="color: #000000;">-</span><span style="color: #000000;">node)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(make</span><span style="color: #000000;">-</span><span style="color: #000000;">list&nbsp;next</span><span style="color: #000000;">-</span><span style="color: #000000;">node&nbsp;(</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">))))))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(set</span><span style="color: #000000;">-</span><span style="color: #000000;">next</span><span style="color: #000000;">-</span><span style="color: #000000;">node!&nbsp;(make</span><span style="color: #000000;">-</span><span style="color: #000000;">list&nbsp;head&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)&nbsp;head)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;head))</span></div>
<br />
&nbsp;&nbsp;&nbsp; make-cycle-list生成一个有N个元素的环形链表，比如(make-cycle-list 8)的结果如下<br />
#0=(1 2 3 4 5 6 7 8 . #0#)<br />
&nbsp;&nbsp;&nbsp; Drscheme形象地展示了这是一个循环的链表。那么约瑟夫环的问题就简单了：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;(josephus</span><span style="color: #000000;">-</span><span style="color: #000000;">cycle&nbsp;n&nbsp;m)<br />
&nbsp;&nbsp;(let&nbsp;((head&nbsp;(make</span><span style="color: #000000;">-</span><span style="color: #000000;">cycle</span><span style="color: #000000;">-</span><span style="color: #000000;">list&nbsp;n)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(define&nbsp;(josephus</span><span style="color: #000000;">-</span><span style="color: #000000;">iter&nbsp;prev&nbsp;current&nbsp;i)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((next</span><span style="color: #000000;">-</span><span style="color: #000000;">node&nbsp;(get</span><span style="color: #000000;">-</span><span style="color: #000000;">next</span><span style="color: #000000;">-</span><span style="color: #000000;">node&nbsp;current)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(cond&nbsp;((eq?&nbsp;next</span><span style="color: #000000;">-</span><span style="color: #000000;">node&nbsp;current)&nbsp;(get</span><span style="color: #000000;">-</span><span style="color: #000000;">number&nbsp;current))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;i)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set</span><span style="color: #000000;">-</span><span style="color: #000000;">next</span><span style="color: #000000;">-</span><span style="color: #000000;">node!&nbsp;prev&nbsp;next</span><span style="color: #000000;">-</span><span style="color: #000000;">node)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(josephus</span><span style="color: #000000;">-</span><span style="color: #000000;">iter&nbsp;prev&nbsp;next</span><span style="color: #000000;">-</span><span style="color: #000000;">node&nbsp;m))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(josephus</span><span style="color: #000000;">-</span><span style="color: #000000;">iter&nbsp;current&nbsp;next</span><span style="color: #000000;">-</span><span style="color: #000000;">node&nbsp;(</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">))))))<br />
&nbsp;&nbsp;&nbsp;&nbsp;(josephus</span><span style="color: #000000;">-</span><span style="color: #000000;">iter&nbsp;head&nbsp;head&nbsp;m)))</span></div>
<br />
&nbsp;&nbsp;&nbsp; 从head节点开始计数，每到m，就将当前节点删除（通过将前一个节点的next-node设置为current的下一个节点），最后剩下的节点的编号就是答案。<br /><img src ="http://www.blogjava.net/killme2008/aggbug/193331.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-04-16 10:27 <a href="http://www.blogjava.net/killme2008/archive/2008/04/16/193331.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于binary search</title><link>http://www.blogjava.net/killme2008/archive/2008/04/02/190285.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 02 Apr 2008 02:08:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/04/02/190285.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/190285.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/04/02/190285.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/190285.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/190285.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 编程珠玑Column 4关于binary search的部分相当精彩，<font face="Courier New">1946年就有人发表binary search，但直到1962第一个正确运行的算法才写出来。尽管算法描述看起来简单明了，但是要写的正确却是有许多地方要仔细考虑。作者着重强调的是对程序正确性的分析方法，仔细分析方法的</font><font face="Courier New">pre-condition, invariant,和post-condition。</font>g9老大翻译过Joshua Bloch在google blog上的文章《<a href="http://blog.csdn.net/g9yuayon/archive/2006/06/04/772382.aspx">号外，号外，几乎所有的binary search和mergsort都有错</a>》，原文在<a href="http://feeds.feedburner.com/~r/blogspot/gJZg/~3/144582870/extra-extra-read-all-about-it-nearly.html">这里</a>。今天看了下原文，有更新，对于求中值索引的c/c++方法原文仍然是有错的，本来是这样：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;mid&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;((unsigned)&nbsp;(low&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;high))&nbsp;</span><span style="color: #000000;">&gt;&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">。</span></div>
<br />
但是在c99标准中，对于两个signed数值之和，如果溢出结果是未定义的(undefined)，也就是说与编译器实现相关。上面的代码应该修改为：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">mid&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;((unsigned&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">)low&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;(unsigned&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">)high))&nbsp;</span><span style="color: #000000;">&gt;&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;</span></div>
<br />
我查了下jdk6的java.util.Arrays的源码，joshua bloch说的这个问题已经解决，现在的binary search如下：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Like&nbsp;public&nbsp;version,&nbsp;but&nbsp;without&nbsp;range&nbsp;checks.</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;binarySearch0(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;a,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;fromIndex,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;toIndex,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;key)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;low&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;fromIndex;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;high&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;toIndex&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(low&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;high)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;mid&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(low&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;high)&nbsp;</span><span style="color: #000000;">&gt;&gt;&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;midVal&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;a[mid];<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(midVal&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;key)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;low&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;mid&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(midVal&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;key)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;high&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;mid&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;mid;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;key&nbsp;found</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">(low&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">);&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;key&nbsp;not&nbsp;found.</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<br />
&nbsp;&nbsp;&nbsp; 如原文所讨论的，采用了&gt;&gt;&gt;操作符替代除以2<img src ="http://www.blogjava.net/killme2008/aggbug/190285.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-04-02 10:08 <a href="http://www.blogjava.net/killme2008/archive/2008/04/02/190285.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>