20100929

方舟子继续遭受网络暴民袭击 zz

方舟子继续遭受网络暴民袭击 zz

http://www.tianya.cn/publicforum/content/no01/1/422937.shtml


方舟子先生躲过锤击之后,近日继续遭受网络暴民的围剿。

谁是暴民呢?我在这里不是指某个"坏人",最坏的人可能也有偶尔和善的时候。我是说,你的某种情绪可能促使你在某个时候做出了一件非常错误的事。我下面要把暴民分成几种,我相信是他们内心的某种倾向性使他们失去了公正,我要对他们内心的倾向性予以猜测,并做适当的分类。符合这些猜测的网友,请您反思一下,你是否不自觉地受到了这些倾向性的影响,而在最近对方舟子先生做出了一些不那么理性也并非基于事实的指责。

思想在某些方面具有某种倾向性,这不是过错,相反,那很可能是自然的。但批评性言论本身有个公正性的问题。如果你批评某个人,这个人在某些方面具有与你不同的倾向性,你可以通过事先表明自己的这种倾向性来显得文质彬彬,这可能有助于你避免做出不公正的判断。我们中国人有句话,叫做"攻其恶,无攻人之恶",意思是说:因为这样做是错的,所以我才反对,而不是因为这是我所不喜欢的某个人做的,所以我才反对。这是我们的祖先为我们指出的君子之道。

当然,无论你的内心有何种倾向,言论就是言论,只要你的指责基于事实,你的推理可以被接受,你的评判准则被大家所认可,那么,你的批评性意见肯定会被很多人尊重。相反,如果您对于什么是事实并不是很清楚,您对此也并不感兴趣,但您仍然要出言诋毁方舟子这个人,我认为,您需要看一看自己是否受到了内心如下一些倾向性的影响。我认为,无须承担责任的、受到群体行为暗示的、情绪化的、缺乏事实依据的、不公正的指责,是一种错误的行为,这些行为看起来像一群暴民所为。

本文所针对的读者,完全排除那些为了经济利益而愿意发表任何言论的人,当然也不包括任何通过造假谋取利益的人。适合与他们谈论是非善恶的,应该是他们的妈妈,而不是其他人。以下是我归纳的思想倾向:

倾向一:神创论者、设计论者,他们反对人类自己创造新的生命形式。

这些人以前的说法是,世界是在七天之内被一个人格神所创造的,信这个神,可以得到拯救,不信这个神的异教徒,都会在末日审判中被区别对待。现在,这些人显得比较科学,毕竟科学太强大,他们现在只说这个世界是被创造或者被设计的,而做这件事的主体则被省略。最有趣的,他们说他们的理论应该与进化论一样,在(公立)学校中教授。虽然他们已经不怎么公开谈论创世的主体,但是,他们仍然认为,只有这个主体,才有创造生命的资格,任何改变基因、控制胚胎发育的行为,都是人类对这个创世主体的权力的僭越,这是由人类自己在创造新的生命形式,因此是不可接受的。

他们显然是对未知的世界比较悲观、比较恐惧的一部分人。因为方舟子先生被某些人塑造成了转基因食品的著名支持者,因此,这些神创论者或者设计论者,或者秉承某种原教旨主义的教徒,也就把他当成了著名的敌人。当然,方舟子先生可能确实也不喜欢某种西方的一神教。对于有此种思想倾向的网友,我认为您先亮出自己的宗教信仰,然后再参与讨论,更容易避免不公。

至于说对于转基因食品的立法,这是一个政治问题,我希望大家能够和平地予以讨论。我个人认为,按照是否支持对转基因食品施加某种法律限制,包括必须在包装上予以标注,这并不足于区分好人和坏人,大家不必因此而敌对。我们完全可以心平气和地讨论转基因食品的意义及其风险。即使你认为这挑战了你的教义,你可能仍然需要尊重他人的观点。

我个人还没有看到转基因食品可能对人类构成伤害的证据,这可能需要长期的实验。因此,我认为,在是否立法对转基因食品予以必要限制这个议题上,只能反映大家对未来的感受,这不大可能是一种理性的选择,这只能反应一个人更悲观或者更乐观的性格特点,这种观点上的差别不是一个严重的问题。至于有人说方舟子先生是转基因食品生产商的顾问,因此,他的结论可能是带有倾向性的,说这种话的人,您需要给出证据。


倾向二:相信某种超自然力量或者玄秘理论,但无法容忍别人说这"不科学"或"不够科学"的人。

汉语经常对"科学"一词有些古怪的用法,这些古怪用法的一个严重结果是,"科学"一词经常让人联想到"正确",而"不科学"则意味着"错误"、"落后",甚至"迷信"。某些愿意相信某种超自然力量或者玄秘理论的人,他们当然不愿意被人说成是"错误"、"落后"或者"迷信"的。因此,如果他们觉得方舟子先生是保卫"科学"、声讨"不科学"的一位"斗士",那么,方舟子先生也就成了他们的一个重要敌人。

其实,从较为狭义的角度说,科学只是一些得到知识、组织知识的系统性方法,这种方法最显著的特点是基于数学推理或者可控制、可重复的实验。一种理论被称为科学的,通常是这种理论的陈述符合科学家共同体对于什么是"科学方法"的认识,而一种理论被认为不那么"科学",这通常意味着这种理论的陈述很难满足科学家共同体对于"科学方法"的认识。举个例子,你可能觉得,"某人一发功,就治好了眼前这个人的病",这是很科学的。但科学家可能并不这么认为,他们需要知道,经过怎样一个可操作的、可重复的程序,就能以一定的概率治好某个病人,如果他们没法从"一发功"这个特殊现象研究出某种可操作、可重复、可检验的程序,他们就会认为自己一无所获,他们就没法承认"一发功就能治病"是个"科学"的理论。当然,这并不意味着他们打算否定什么,科学家们不知道的事情,肯定比他们知道的事情来得多。

我相信,无论您相信什么样的超自然力量或者玄秘理论,只要您不坚持要科学家共同体承认您的理论是"科学"的,您就不大可能与他们发生冲突。当然,据说也有人用魔术冒充"神功",这是另一回事,这可能涉及到法律问题,比如诈骗。如果这并不是魔术表演,而是一种牟利行为,甚至可能伤害他人的健康,这种行为值得戳穿。


倾向三:民科,但不希望别人指出这一点。

其实我也是民科。很多民科不知道的是,"教科书"与"学术界"是两码事,如果你念过大学本科,你肯定对教科书里的内容不陌生,但那通常不是"研究",而只是"结论"。打个比方,你可能读到过一本叫做《历史》的书,但《历史》不是"历史学",一个"历史学"的学者,他要发表"学术"著作,不能只写下几条结论、给出几个故事,他必须而且主要需要阐明的,是他所得到的结论的意义,以及得到这些结论的过程是否"科学"。因此,如果你只读过一本叫做《历史》的书,你很可能不知道什么是"历史学",你仿照这本书写下的东西,是不大可能被历史学家们所接受的。类似地,你读过几本叫做《数学》的书,也不意味着你了解什么是数学研究,因此,你对于哥德巴赫猜想的见解,数学家们可能只想把它扔进垃圾篓。

事实上,学者们确实生活于一个似乎隐秘的世界里,没有一本教科书能真正让你了解什么是"研究",你只能在很多年的时间里,通过阅读其他研究者的论文来逐渐"摸索"什么是"研究的方法",更重要的,尝试找到合适的研究问题,普通大众并不知道这个世界到底是什么样子,就如同很多人没有去过饭店的厨房,他们能看到的,只是厨师做好的菜。

我本人并不觉得方舟子先生以取笑民科为乐,虽然这样的人可能很多,当然,也许有些人不这样认为,他们觉得自己的自尊心受到了伤害。我觉得,民科们完全可以自得其乐,没必要去烦扰学术界。一个更自由、更有责任感的学术界,也应该关注与其他社会成员的交流,让他们尽可能多地了解学者们正在做什么。他们正在做什么?:-)


倾向四:自惭形秽的文科生,他们内心里认为"人文"并不是如同自然科学一样的"科学",没有那样显赫的地位,因此,谁在那大声谈论"科学",谁就是伤害了他们的感情。

可能普通大众不知道,写小说,不是"科学","研究"别人写的小说,才是"科学"。莎士比亚和曹雪芹都不是科学家,"研究"莎士比亚和曹雪芹的人才是各大学文学系的"科学家",而他们得到研究成果的过程,必须是满足科学家共同体对于"科学方法"的认识。因此,一个人成为某个大学文学系的教授,领到一份工资,这是因为他在"研究"和教学,至于他自己写小说,那完全是他的私人生活,与这份工资无关。类似地,哲学系的教授不是发明哲学的,而是研究别人发明的哲学的,历史系的教授不是记录今天历史的,而是研究他人在历史上留下的蛛丝马迹的。因此,"人文"确实不是科学,"研究人文"才是科学。创造"人文"是不可能在大学里领到工资的,研究并教授"人文"才能在大学里领到工资。文科生们应该再反思一下科学的概念。


倾向四:宣扬伪科学的科学共同体成员,他们曾经与方舟子一边的科学共同体成员直接论战。

有一些人,已经是科学共同体的成员,但可能有一些特殊的经历,比如曾经被训练来教授某种十九世纪的哲学,但他们必须得把这种哲学说成是科学之母。现在他们只能是哲学系的教师,但是,在习惯上,他们并不研究"别人"发明的哲学,而是向他人灌输某种哲学,这就是当初训练他们的人所要达到的目的。现在,他们当中的某些人,很想把"科学"里塞进一些他们自己喜欢的东西。他们相当有文化,因此,可以写出一些似是而非的东西,试图动摇传统上"科学"的概念。

他们是文化人,可能还自诩为哲学家,因此,我想,他们大概既不会参与铁锤事件,也不会为此叫好。但他们可能有一定的影响力。比如,他们给方舟子这边的人按上了一个"科学主义"的帽子,据说持有这种观点的人认为科学能够解释一切以及解决一切,而且只能由科学来解释和解决。但是,就像人们所嘲笑的,除了他们自己(他们当中的某些人说自己曾经是"科学主义"者),尚未在世界上发现持有如此愚蠢观点的人。


倾向五:认为方舟子打假不够专业的专业人士。

对于这些人,我不想多说,谁说方舟子不够专业,你专业?你专业你来打!总不至于说学术界没有假可打吧?其实,方舟子在学术界能打的假,都是一些最不入流的,比如,明显抄袭论文的,招摇撞骗过分生猛的,等等。这根本不是今天学术界的主要问题,这是一台机器都能判断的不端行为。至于那些需要高度专业知识和崇高职业道德才能做出的判断,你根本听不到,没本事的都在琢磨着怎么应付论文数量的要求,有本事的都在琢磨着怎么申请经费、花掉经费,最有本事的自己立项、自己拿。而在这些人背后,是一些终于认识到提高知识分子待遇的好处的人,利出于一孔之后,上下同钱同德:-)


倾向六:认为方舟子代表了要消灭中医的力量。

我不知道方舟子先生是否真的这样认为。但是,"中医"与"西医"这种并列方式,肯定遮蔽了问题的实质。问题是,什么是"现代"的、可以接受的医学?我们是否需要立法规定任何人要取得行医执照,都必须满足同样的、"现代"的训练标准?而诊断和治疗的过程,是否也要满足某种必需的标准?无论你怎样看待中医,你不可能禁止别人提出这样的问题,哪怕你觉得他们仅仅是出于一种文化上的自卑感,因此要竭力消灭"祖国的传统文化"。

理论上说,医学是实践性很强的学科,西医并不足以否定中医,但是,如果要所有学生接受相同强度的西医训练,而学习中医的学生还要额外接受中医训练,这可能在事实上导致没有人去学中医了。当然这只是猜测。没准事实相反,中西医两个学位会让你更受欢迎,既接受过相同强度的现代西医训练,又懂得"祖国传统文化",你可能看起病来更有"文化底蕴"?:-)
没准中医院因此很火?:-) 结果,"祖国的传统文化"被你更好地发扬光大了。


倾向七:其他认为科学或者严谨的理性是他的绊脚石的人。


至此,以上七种倾向分析完毕。我认为,每一种倾向都不应该导致铁锤或者为铁锤叫好,指责他人应该基于事实,而且保持公正。现在我们讨论一下什么是一个好的社会?

首先,我相信,你会承认,普遍的诚实对于我们这个社会的意义。一个互相撒谎的社会不可能是一个好的社会,在这样的社会里,好人没有机会,只有那些最寡廉鲜耻的人才能如鱼得水。你不可能认为,普遍的欺诈能导致一个好的社会。因此,你肯定会认为,保卫诚实、反对欺诈对于我们的社会意义重大。

其次,科学是人类有史以来最伟大的发明之一,它在今天直接给我们带来利益。科学的存在和发展依赖于科学家,而自由和诚实是科学家之所以能够成为科学家的前提。一群被包养的不诚实的精英对于科学的发展是零价值的,他们创造不了任何东西,他们甚至学不会别人的东西。如果一个国家的科学界已经堕落到只会点数经费,那么,哪怕是一点批评性的意见,即使这种意见只能针对那些最不入流的造假者,这也是非常珍贵的。这是为在这个国家中保卫人类最有价值的精神财产而战。有些不了解科学界的人士可能觉得自己也被归为造假者的行列,我认为,如果你没有伤害任何人,你不必感到可耻,当然,如果你指望"科学"这个概念能够变得像你希望的那样,你也可能会遭到批评。

最后,法律对于我们来说很重要,如果没有法律,你可能一天也活不过去。我们必须明白,雇凶杀人或者伤人,这是一个非常严重的法律问题。这种行为,不会仅仅伤害一个你所不喜欢的人,也会伤害你赖以生存的法律,就如同伤害你周围的空气。如果抽走我们身边的空气,不是只有方舟子会窒息而死,我们也无法生存。你作为这个社会的一员,你有义务在必要的时候重申法律对于我们的意义,而不是相反,对于极其恶劣的谋杀行为幸灾乐祸,如果你这样做了,你只是在伤害你自己,那不是任何其他人的耻辱,那只是你自己的耻辱。

你内心怎样看待方舟子,这不重要。我也很多年没有去过方舟子的网站了,我的浏览器总是告诉我他的网站无法连接,可能受到防火墙的阻挡,要我与网络管理员联系。我一般没有与网络管理员联系的勇气。更重要的问题是,你怎样看待上面的几个问题?我们需要保卫诚实吗?我们需要爱护和保卫科学吗?我们需要保卫法律吗?如果你的回答是:是!那很好,我相信,你与你观点不同的人会因此达成很多共识。

因此,我建议,在最近一段时间,讨论与方舟子有关的问题时,大家都来表明自己的观点,告诉大家,你知道诚实很珍贵,你认为科学应该被爱护、被保卫,你认为法律必须得到尊重。我相信,有了这些表达,很多分歧容易解决。方舟子没有做到的,你可以去做到,他没有做好的,你可以做得更好。你也可以做一名"打假斗士":-)
而且更货真价实。但你肯定不是希望这个世界一片黑暗,方舟子作为一个"打假斗士"的符号,很可能是这个黑暗世界上的最后一盏灯,或许你不这样认为,或许你认为你不需要光明,但是,如果你想熄灭他,我还是希望你能慎重考虑,你真的能把你的理由在下面写清楚吗?

实际上,你可以选择,你可以说:"这个世界是我们的"。你也可以觉得自己就是一个过客,一个每天被人操纵的人,因此你愤世嫉俗,有一种要做暴民的冲动,拿出你指尖的小铁锤,用言词砸烂任何听起来比你更勇敢的故事,好让自己相信,你自己平凡而怯懦的人生,已经是这个黑暗世界里最光荣、最勇敢的人生了。但你其实什么也没有改变!

写给我的暴民同胞们:-)

2010-09-27

20100917

谜语答案

谜语答案

1. Invoking heap(20) in heap(int *a,int size), at line 2,
an instance of heap is created
(which can be a local variant to be referenced) without being named as
an variant.
Let's call it heap_drop.

2. root[i] in heap(int *a,int size), at line 5, is a member of the instance that
will be created by heap(int *a,int size), just this constructor
itself.
root[i] in heap(int *a,int size) is NOT a member of heap_drop mentioned above,
therefore it has not been allocated memory yet.


1 heap(int *a,int size){
2 heap(20);
3 cout<<"hhh";
4 for(int i = 0;i<size;i++){
5 root[i] = a[i];
6 }
7 heapSize = size;
8 build_Heap();
9 }
10 heap(int maxSize){
11 root = new int [maxSize];
12 }

典典一句话评论:
heap(20) 不是调用构造函数初始化当前对象,而是分配了一个临时对象然后立刻销毁。

感谢某用功同学提供代码示例。

20100916

猜谜活动

猜谜活动。

人生艰难,听来个谜语给大家讲讲,娱乐一下。

话说某同学整了以下C++代码,运行就崩溃。

问:为啥?

等级考试以后公布答案。

#include<iostream>

using namespace std;

struct heap{

private:

int *root;

int heapSize;

int maxSize;

void build_Heap(){

int n = (heapSize+1)/2 -1;

for(int i = n;i>=0;i--){

max_Heapify(i);

}

}

public:

heap(int *a,int size){

heap(20);

cout<<"hhh";

for(int i = 0;i<size;i++){

root[i] = a[i];

}

heapSize = size;

build_Heap();

}

heap(int maxSize){

root = new int [maxSize];

}

heap(){

root = new int [20];

}

void copyBuild(int *a,int size){

cout<<"hhh";

for(int i = 0;i<size;i++){

root[i] = a[i];

}

heapSize = size;

build_Heap();

}

void max_Heapify(int i){

int leftChild = i*2+1;

int rightChild = i*2+2;

int max = root[i];

int maxLoc = i;

if(leftChild<heapSize&&root[leftChild]>max){

max = root[leftChild];

maxLoc = leftChild;

}

if(rightChild<heapSize&&root[rightChild]>max){

max = root[rightChild];

maxLoc = rightChild;

}

if(maxLoc!=i){

root[maxLoc] = root[i];

root[i] = max;

max_Heapify(maxLoc);

}

}

int pop_top(){

if(0==heapSize){

cout<<"error!!! this is an empty heap\n";

return -9999999;

}

if(1==heapSize){

heapSize = heapSize-1;

return root[0];

}

else {

int max = root[0];

root[0] = root[--heapSize];

max_Heapify(0);

return max;

}

}

void output(){

for(int i = 0;i<heapSize;i++){

cout<<root[i]<<" ";

if((i+1)%10==0) cout<<endl;

}

cout<<endl;

}

};

int main(){

int *a = new int [20];

for(int i = 0;i<9;i++){

a[i] = i;

cout<<a[i]<<" ";

}

int ss = 9;

heap *p = new heap(a,9);

cout<<"build heap\n";

p->output();

cout<<"pop_top "<<p->pop_top()<<endl;

}

20100915

通往奴役之路 笔记

通往奴役之路 笔记

2010-09-15 21:53:26

补录以前的,估计是2年前的

pp.73 法治

最能清楚地将一个自由国家的状态和一个在专制政府统治下的国家的状况区分开的,莫过于前者遵循着被称为法治的这一伟大原则。撇开所有技术细节不论,法治的意思就是指政府在一切行动中都受到事前规定并宣布的规则的约束--这种规则使得一个人有可能十分肯定地预见到当局在某一情况中会怎样使用它的强制权力,和根据对此的了解计划它自己的个人事务。虽然因为文法者以及那些受委托执行法律的人都是不可能不犯错误的凡人,从而这个理想也永远不可能达到尽美善尽美的地步,但是法治的基本点是清楚的:即留给执掌强制权力的执行机构的行动自由,应当减少到最低限度。虽则每一条法律,通过变动人们可能用以追求其目的的手段而在一定程度上限制了个人自由,但是在法治之下,却防止了政府采取特别的行动来破坏个人的努力。在已知的竞赛规则之内,个人可以自由地追求他人私人的目的和愿望,肯定不会有人有意识地利用政府权力来阻挠他的行动。

pp.77 道德

第二个方面,即道行的或政治方面的论证,与我们现在所要讨论的问题有更直接的关系。如果政府要精确地预见到其行动的影响,那就意味着它可以不让受影响的人有任何选择的任地。凡是当政府能够精确地预见其各种可能的行动对某种人的影响时,也恰恰是政府能够对各种目标进行选择。如果我们要创造新的对一切人都开放的机会,要给人们提供他们能随意加以利用的机会牟话,那么其精确的结果就是难以预见的。因此,普遍性的规则,有别于具体命令的真正法律,必须意在适用于不能预见其详情的情况,因而它对某一特定目标,某一特定个人的影响事前是无法知道的。只是在这种意义上,立法者才可能说得上是不偏不倚的。所谓不偏不倚的意思,就是指对一定的问题没有答案--如果我们一定要解决这类问题的话,就只能靠抛掷硬硬币来决定。在一个每一件事都能精确预见到的社会中,政府很难做一件事而仍然保持不偏不倚。只要政府政策对某种人的精确的影响是已知的,只要政府的直接目的是要达到那些特定影响,它就不能不了解这些影响,因而也就不能做到不偏不倚。它必定有所偏袒,把它的评价强加于人民,并且,不是帮助他们实现自己的目标,而是为他们选择目标。只要当制定法律的时候就已预见到这些特定影响,那提出,法律就不再仅仅是一个供人民使用的工具,反而成为立法者为了他的目的而影响人民的工具。政府不再是一个旨在帮助个人充分发展其个性的实用的机构,而成为一个"道德的"机构--这里的"道德的"一词不是作为"不道德的"反义词来使用的,而是指这样一种机构,它把它对一切道德问题的观点都强加于其成员,而不管这种观点是道德的或非常不道德的。在这种意义上,纳粹或其它任何集体主义的国家都是"道德的",而自由主义国家则不是。

pp.85 法治限制政府行为

20100914

沉默容易 不说谎很不容易 zz

◇◇新语丝(www.xys.org)(xys4.dxiong.com)(www.xinyusi.info)(xys2.dropin.org)◇◇

  沉默容易 不说谎很不容易

  作者:高新

  方舟子悬赏二十万找目击者,让我不知何感?这个政府不仅无脸还无能。二
十万可能可以找到50个杀手,却不一定能找到一个知情者。哪个的代价大谁都很
清楚,我甚至想:如果是悬赏杀手,会不会更容易找到答案?虽然抱着一丝希望
这案能破,但又对这丝希望隐隐不安,幕后黑手一旦大白天下,政府会怎么处理?
因为要拿到他的这种罪证基本不可能,更何况,这些疑似幕后黑手的人何其多也,
曝光了一个又会怎么样?所以这二十万只是政府脸面的一道口,不知道胡温一直
都要沉默下去吗?

  和一佛家居士好友长聊,她也承认佛家的戒条中,最不易的就是不说谎。我
们对"打酱油、做俯卧撑"一族很同情,是因为他们没有选择沉默的机会,更不
能说真话,只能说谎了。佛家思想教人修身养性,独善其身,对周围一切都抱着
宽容之心,包容一切恶的、丑的、贪婪的、无耻的,献完了左脸又献出右脸。诵
着佛经等着因果的轮回。我和朋友说起新加坡,这个岛国无文化底蕴、无地大物
博,何以现在有如此高的素质和文明?佛家的宽容是不是导致大陆现状的幕后推
手?居士好友彻夜解读,也没能让我参透一二,我甚至问:佛门弟子会做官吗?
能搞管理吗?

  居士好友仍会坚定地耕耘着,以其善去感动着身边非佛的众生们,而我却为
有那么多佛性同胞而感到难过。7月底,我和一个朋友带着孩子一行四人路途遥
遥地奔赴上海,在我的强权下,两个孩子坚持进了三次园。做为我这等草根,如
果不是为了让孩子见识一下国际大都市、世界博览会,有可能数十年也不会那么
长途一次的。虽然事前己打过预防针:要排很长时间的队进一场馆,但真轮着一
次次的三、四个小时换来一片片人海时,这已经不是热情,而是挑战流进密集人
堆的勇气了,如"世"子般的队伍不知道何处是头何处是尾,大家很快接受了来
世博园是练习排队,而我也只剩下了:每天进园四十多万人,那么多排队的都是
傻子,就你俩个聪明?!排吧,否则我们来这干吗来了?我不是佛家弟子,我却
教育着孩子们逆来顺受。是呀,我惊叹我们的同胞有这么多!更惊叹我们有如此
多良民!看了杨恒均先生的文章"世博亲历记:中国人的低素质让世博蒙羞?"
后,我更后怕这沉默的大多数,素质何其高、数量何其大!

  多么难能可贵的太平盛世,多么难能可贵的和谐安康呀!这么大的草根良民
群体,轮回后又会成为什么?

  昨天一个朋友在火车站发短信告诉我,她着急赶往车站,检票时才发现车票
没了,要求补票上车,结果检票员既不让补票更不让上车,她一急一气之下,伸
出了一拳,结果被一群工作人员围上。若不是一个当地的友人赶来解围,她就被
扣留在火车站了。我这朋友从我们读大学时就是一个吃苦耐劳、忍辱负重的典范,
曾在九十年代初期就获得过北京市劳模的称号,绝对是属于不会呐喊的沉默中的
良民。发生这样雷倒我的事,我竟然很开心,称赞她:总算有人味了!

  我身边的佛实在太多,他们作为个体真完美得无可挑剔,善良、勤奋、坚韧、
智慧、淡泊名利,他们为了善常常会撒点善意的小谎,或帮别人圆圆骗局,也经
常做点舍己利人的事,甚至牺牲生命也再所不惜,他们是道德的楷模!但他们基
本不除恶扬善,也不会拉起手来共同向恶呐喊一声,指望他们象领袖一样建立如
新加坡式惩罚分明、严明的法制更是没门!

  这是不是我们草根良民的佛性?

(XYS20100913)

◇◇新语丝(www.xys.org)(xys4.dxiong.com)(www.xinyusi.info)(xys2.dropin.org)◇◇

20100906

持续工作的方法 键盘

--
Sincerely,
YANG Guifu
School of Computer Science and Information Technology
Northeast Normal University
Changchun, P.R.China
----
杨贵福
无不大工。

20100905

持续工作的方法

笔记 The Little Schemer

笔记 The Little Schemer


MIT Press - The Little Schemer - Daniel P. Friedman.pdf
The Little Schemer - 4th Edition.pdf

[2010-08-17 周二 00:40]-
[2010-09-05 周日 20:06]

* define atom?

pp.5 [2010-08-17 周二]
> (define atom?
(lambda (x)
(and (not (pair? x))(not (null? x)))))
> (atom? (quote ()))
#f

* cdr

pp.13 [2010-08-17 周二]

cdr is a list.

What is (cdr (cdr l))
where
l is ((b) (x y) ((c)))

(((c)))

类似的

What is the cdr of l
where
l is ( a b c)

(b c)

* cons

What is the cons of s and l
where s is (banana and)
and
l is (peanut butter and jelly)

((banana and ) peanut butter and jelly)

* cons

What is (cons s l)
where a is ((a b c))
and
l is b

No answer,
since the second argument l must be a list.

* null list

What is (null? (quote ()))

* eq

Is (eq? l1 l2) true or false
where l1 is ()
and
l2 is (strawberry)

No answer, () and (strawberry) are lists.

* eq

Is (eq? n1 n2) true or false
where n1 is 6
and
n2 is 7

No answer,
6 and 7 are numbers.

* eq

Is (eq? (cdr l) a) true or false
where
l is (soured milk)
and
a is milk

No answer,
See The laws of Eq? and Cdr.
Young says, (cdr l) is (milk), which is not an atom.

* lat

True or false: (lat? l)
where l is ()

True,
because it does not contain a list.

* recursion

InsertR

(cons old (cons new (cdr lat)))

* recursion

pp. 62
在定义multinnsertL中,
需要在递归中改变条件。

* recursion

pp.81
We recur with a first argument from which we subtract the second
argument. When the function returns, we add 1 to the result.
=> division.

* recur with car

pp. 89
How are insertR* and rember* similar?

They both recur with the car, whenever the car is a list, as well as
with the cdr.

* 递归代替迭代

pp.94 leftmose的递归调用方法,是用函数的递归调用代替了迭代。
* S-expression

What is an S-expression?

An S-expression is either an atom or a (possibly empty) list of S-expressions.

* lamda
pp.129

Now what is
(lambda (a)
(lambda (x)
(eq? x a)))

It is a function that, when passed an argument a, returns the function
(lambda (x)
(eq? x a))
where a is just that argument.

* lambda apply

pp.135

如何应用函数
(define multirember-f
(lambda (test?)
(lambda (a lat)
.....
)))

(multirember-f test?) a lat)

multirember-f是这样的函数,以test?作为参数,返回值是一个函数,
返回的函数以 a 和 lat 作为参数。

(multirember-f test?) a lat)
相当于
(foo a lat)

* lambda

应用一个过程
Applying a procedure of lamda

返回函数的函数 的应用语法

pp.130
Do we need to give a name to eq?-salad

No, we may just as well ask
((eq?-c x) y)
where
x is salad
and
y is tuna.

pp. 129
Now what is
(lamda (a)
(lamda (x)
(eq? x a)))

It is a function that, when passed an argument a, returns the function
(lambda (x)
(eq? x a))
where a is jsut that argument.

* closures

pp. 137开始。递归太复杂。

** [http://www.michaelharrison.ws/weblog/?p=34]
:
: (define multirember&co
: (lambda (a lat col)
: (cond
: ((null? lat)
: (col '() '()))
: ((eq? (car lat) a)
: (multirember&co a
: (cdr lat)
: (lambda (newlat seen)
: (col newlat
: (cons (car lat) seen)))))
: (else
: (multirember&co a
: (cdr lat)
: (lambda (newlat seen)
: (col (cons (car lat) newlat)
: seen)))))))


基于closures的解释,参见文献[1]。

** 文献[2]提到,可以用Dr.Scheme 语言Pretty Big的debug观察。

实验。定义multirember&co以后。Dr.Scheme, Pretty Big.
: >(define foo
: (lambda (x y)
: (length x)))
:
: > (multirember&co 'tuna '(tuna aa bb cc) foo)
: 3

** 尝试用drscheme"展开"闭包,不支持;求助刘典,用display显示变量,不够直观,只能显示应用求值,不能显示代换的过程。

** 手动

: (define multirember&co
: (lambda (a lat col)
: (cond
: ((null? lat)
: (col '() '()))
: ((eq? (car lat) a)
: (multirember&co a
: (cdr lat)
: (lambda (newlat seen)
: (col newlat
: (cons (car lat) seen)))))
: (else
: (multirember&co a
: (cdr lat)
: (lambda (newlat seen)
: (col (cons (car lat) newlat)
: seen)))))))
: (define foo
: (lambda (x y)
: (length x)))
:
: ultirember&co 'tuna '(tuna aa bb cc) foo)

substitute:

The arguments of calling multirember&co:
: | calling | current lat | col | col, substituted a and
lat | col, substituted lambda |
: | multirember&co | | |
| |
: |----------------+-----------------+-----+----------------------------+-------------------------|
: | 1st round | (tuna aa bb cc) | col | /
| lambda (x y)(length x) |


The arguments of calling multirember&co:
: | calling | current lat | col, before substitution
| col, substituted a and lat
| col, substituted lambda
|
: | multirember&co | |
|
|
|
: |----------------+-----------------+---------------------------------------------------------+----------------------------------------------------------------------+-------------------------------------------------------------------------------------------|
: | 2nd round | (tuna aa bb cc) | lambda (newlat seen) (col
newlat (cons (car lat) seen)) | lambda (newlat seen) (col newlat (cons
(car '(tuna aa bb cc)) seen)) | lambda (newlat seen) ((lambda (x
y)(length x)) newlat (cons (car '(tuna aa bb cc)) seen)) |

Note:

In the expression
: lambda (newlat seen) (col newlat (cons (car lat) seen))
lat is (tuna aa bb cc), insetead of (aa bb cc).
The substitution happens before multirember&co is called,
so the lat is the original one without cdr applying.
Sic passim.

End of the note.

The col
lambda (newlat seen) ((lambda (x y)(length x)) newlat (cons (car
'(tuna aa bb cc)) seen))
is from:
lambda (newlat seen)
((lambda (x y)(length x))
newlat
(cons (car '(tuna aa bb cc)) seen))

The arguments of calling multirember&co:
: | calling | current lat | col, before substitution
| col, substituted a and lat
| col, substituted lambda

|
: | multirember&co | |
|
|

|
: |----------------+-------------+---------------------------------------------------------+-----------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------|
: | 3rd round | (aa bb cc) | lambda (newlat seen) (col (cons
(car lat) newlat) seen) | lambda (newlat seen) (col (cons (car '(aa bb
cc)) newlat) seen) | lambda (newlat seen) ((lambda (newlat seen)
((lambda (x y)(length x)) newlat (cons (car '(tuna aa bb cc)) seen)))
(cons (car '(aa bb cc)) newlat) seen) |

The col
lambda (newlat seen) ((lambda (newlat seen) ((lambda (x y)(length x))
newlat (cons (car '(aa bb cc)) seen))) (cons (car '(bb cc)) newlat)
seen)
is from:
lambda (newlat seen)
((lambda (newlat seen) ((lambda (x y)(length x)) newlat (cons (car
'(aa bb cc)) seen)))
(cons (car '(aa bb cc)) newlat)
seen)

The arguments of calling multirember&co:
: | calling | current lat | col, before substitution
| col, substituted a and lat
| col, substituted lambda


|
: | multirember&co | |
|
|


|
: |----------------+-------------+---------------------------------------------------------+--------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
: | 4th round | (bb cc) | lambda (newlat seen) (col (cons
(car lat) newlat) seen) | lambda (newlat seen) (col (cons (car '(bb
cc)) newlat) seen) | lambda (newlat seen) ((lambda (newlat seen)
((lambda (newlat seen) ((lambda (x y)(length x)) newlat (cons (car
'(tuna aa bb cc)) seen))) (cons (car '(aa bb cc)) newlat) seen)) (cons
(car '(bb cc)) newlat) seen) |

The col
lambda (newlat seen) ((lambda (newlat seen) ((lambda (newlat seen)
((lambda (x y)(length x)) newlat (cons (car '(tuna aa bb cc)) seen)))
(cons (car '(aa bb cc)) newlat) seen)) (cons (car '(bb cc)) newlat)
seen)
is from:
lambda (newlat seen)
((lambda (newlat seen) ((lambda (newlat seen) ((lambda (x y)(length
x)) newlat (cons (car '(tuna aa bb cc)) seen))) (cons (car '(aa bb
cc)) newlat) seen))
(cons (car '(bb cc)) newlat)
seen)

The arguments of calling multirember&co:
: | calling | lat | col, before substitution
| col, substituted a and lat
| col, substituted lambda |
: | multirember&co | for multirember&co |
|
| |
: |----------------+---------------------+---------------------------------------------------------+-----------------------------------------------------------+-------------------------|
: | 5th round | (cc) | lambda (newlat seen) (col
(cons (car lat) newlat) seen) | lambda (newlat seen) (col (cons (car
'(cc)) newlat) seen) | |


The col
lambda (newlat seen) ((lambda (newlat seen) ((lambda (newlat seen)
((lambda (newlat seen) ((lambda (x y)(length x)) newlat (cons (car
'(tuna aa bb cc)) seen))) (cons (car '(aa bb cc)) newlat) seen)) (cons
(car '(bb cc)) newlat) seen)) (cons (car '(cc)) newlat) seen)
is from:
lambda (newlat seen)
((lambda (newlat seen) ((lambda (newlat seen) ((lambda (newlat seen)
((lambda (x y)(length x)) newlat (cons (car '(tuna aa bb cc)) seen)))
(cons (car '(aa bb cc)) newlat) seen)) (cons (car '(bb cc)) newlat)
seen))
(cons (car '(cc)) newlat)
seen)

There is no 6th round of calling multirember&co, because of cond fullfilled.

: ((null? lat)
: (col '() '()))

Current lat is (cdr '(cc)), as '().

The procedure col has been subsitituted in the previous steps to be
: lambda (newlat seen) ((lambda (newlat seen) ((lambda (newlat seen)
((lambda (newlat seen) ((lambda (x y)(length x)) newlat (cons (car
'(tuna aa bb cc)) seen))) (cons (car '(aa bb cc)) newlat) seen)) (cons
(car '(bb cc)) newlat) seen)) (cons (car '(cc)) newlat) seen)

Eval (applying '() '() as arguements on col);

(col '() '())
=>
((lambda (newlat seen) ((lambda (newlat seen) ((lambda (newlat seen)
((lambda (newlat seen) ((lambda (x y)(length x)) newlat (cons (car
'(tuna aa bb cc)) seen))) (cons (car '(aa bb cc)) newlat) seen)) (cons
(car '(bb cc)) newlat) seen)) (cons (car '(cc)) newlat) seen))
'()
'()
)

* 图灵机停机

pp. 153
will-stop? 无法定义,因为有的函数不会停止。

* Y-combinator

[http://www.catonmat.net/blog/derivation-of-ycombinator]
解决在函数中应用匿名函数的问题。

1. 使用???替换函名函数,如果执行不到,这代码是可以执行的。

: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (
:
: (lambda (list) ; the
: (cond ;
: ((null? list) 0) ; function
: (else ;
: (add1 (??? (cdr list)))))) ; itself
:
: (cdr list))))))

2. 以length为参数以后,下面这段代码需要修正后执行,否则报错 "reference to undefined identifier: ???"

: ((lambda (length)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (length (cdr list)))))))
: ???)

??? 被改为 length 后可执行。
??? 被改为 '(???) 也可以被执行。
??? 被改为 '() 也可以被执行。
看起来,只要???是个可以被引用的东西就行,但是不能是未定义的。
事实上,lambda (length)的参数不管是什么,都会返回 (lambda (list) 这个函数。

如下实验:

: (((lambda (length)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (willnot_run_here (cdr list)))))))
: 'place_holer) '() )

下面的代码

: ((lambda (f)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (f (cdr list)))))))
: ((lambda (g)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (g (cdr list)))))))
: ((lambda (h)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (h (cdr list)))))))
: ???)))

"ince the argument names f, g,h in (lambda (f) ...), (lambda (g) ...),
(lambda (h) ...) are independent, we can rename all of them to length,
to make it look more similar to the length function:"

以上并非可以替换名字的原因。
真正的原因是,lamda(f)中的参数f,是lamda(g);
lamda(g)中的参数g,是lambda(h);
而h只是占位符,对程序的求值没有任何作用。
以下代码是上面代码的变形,帮助理解。

: (((lambda (lambda_lambda_place_holder)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (lambda_lambda_place_holder (cdr list)))))))
: ((lambda (lambda_place_holder)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (lambda_place_holder (cdr list)))))))
: ((lambda (place_holder)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (willnot_run_here (cdr list)))))))
: 'place_holder))) '(a b))

下面的代码中,
把lambda(length)作为参数传给lambda (mk-length)
lambda (mk-length) 的执行是以参数作为函数,给这个函数的参数是占位符???;
这个参数此时是 lambda (length)。
lambda (length)的占位符参数没有被求值,函数就结束了。
所以,以下代码能求 '()

: ((lambda (mk-length)
: (mk-length ???))
: (lambda (length)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (length (cdr list))))))))

下面的代码中
lambda (mk-length)的执行是,
向mk-length传递参数 (mk-length ???)。
这一参数的解释上面已经提到,执行一次lambda (length)。
执行lambda (length),最后返回的是 length (cdr list)。
即,以lambda (length)作为lambda (length)的参数。
一共执行两次。

: ((lambda (mk-length)
: (mk-length
: (mk-length ???)))
: (lambda (length)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (length (cdr list))))))))

既然???是占位符,不会被求值,所以可以

: ((lambda (mk-length)
: (mk-length mk-length))
: (lambda (length)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (length (cdr list))))))))

所有的length改在mk-length。
传进来的参数确实是它。
代码略去。

然后,length (cdr list) 换成 (mk-length mk-length) (cdr list)。
这样,(mk-length mk-length) 递归地返回 原来的lambda (length) 应用在 (cdr list) 上

: ((lambda (mk-length)
: (mk-length mk-length))
: (lambda (mk-length)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 ((mk-length mk-length) (cdr list))))))))

其实mk-lenth只执行了一次,然后mk-length参数就是占位符了。
但是,"The function works because it keeps adding recursive uses by passing
mk-length to itself, just as it is about to expire."

递归的跳出条件是(null? list)。

把(lambda (length)移出作为lambda (le)的参数,
(lambda (x)作为le的参数。
代码如下。

: ((lambda (le)
: ((lambda (mk-length)
: (mk-length mk-length))
: (lambda (mk-length)
: (le (lambda (x)
: ((mk-length mk-length) x))))))
: (lambda (length)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (length (cdr list))))))))

Y-combinator如下。

: (define Y
: (lambda (le)
: ((lambda (f) (f f))
: (lambda (f)
: (le (lambda (x) ((f f) x)))))))

匿名函数的应用如下。

: ((Y (lambda (length)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (length (cdr list))))))))
: '(a b c d e f g h i j))

另一种Y-combinator的写法,
[http://www.mactech.com/articles/mactech/Vol.07/07.05/LambdaCalculus/]
and [http://www.stanford.edu/class/cs242/readings/vocabulary.html]
"When applied to a function, returns its fixed point."
: (define y
: (lambda (f)
: ((lambda (x) (f (x x)))
: (lambda (x) (f (x x))))))

参见TLS书(非pdf页码)pp.171,
如何把lambda (length)移出,从而形成了Y-combinatior的框架。

*关键:applying arguemnt lambda on precedure lambda, and eval the
augument lambda in precedure lambda.*

另,参考[http://blog.vazexqi.com/2006/07/13/y-combinator]

原来看不懂的一个原因是,这本电子书有缺页。
[The Little Schemer - 4th Edition.pdf]是个更完整的版本。

* value

pp.185
What is (value e)
where
e is (quote nothing)

nothing.

What is (value e)
where
e is nothing.

nothing has no value.

* value
Where is (value e)
where
e is ((lambda (nothing)
(cons nothing (quote ())))
(quote
(from nothing comes something)))

((from nothing comes something))

以 '(from nothing comes something) 作为 lambda(nothing)的参数

实验,Pretty Big
>'(nothing)
(nothing)
> (cons '(nothing) '())
((nothing))

* interpreter

pp. 189
Have we used the table yet?
No, but we will in a moment.

Why do we need the table?
To remember the values of identifiers.

pp. 188
(define value
(lambda (e)
(meaning e (quote ()))))
(define meaning
(lambda (e table)
((expression-to-action e) e table)))
* What is the Value of All of This?

第10章,略读了。
这一部分应该是用 apply & eval 构造解释器。
准备细读《计算机程序的构造和解释》的相应部分。

* laws

** car

The primitive car is defined only for non-empty lists.
Young says: the result is a atom.

** cdr

The primitive cdr is defined only for non-empty lists.
The cdr of any non-empty list is always another list.

** cons

The primitive cons takes two arguments.
The second argument to cons must be a list. The result is a list.

** null?

The primitive null? is defined only for lists.

** eq?

The primitive eq? takes two arguments.
Each must be a non-numeric atom.

** lat

[http://objectmix.com/scheme/186190-newbie-problem-understanding-lat-atom-little-schemer.html]
I bet, they use lat as short for "List of-AToms".

** S-expression

[http://objectmix.com/scheme/186190-newbie-problem-understanding-lat-atom-little-schemer.html]
The S in S-expression stands for symbolic. The word S-expression is
older than Scheme.

** The First Commandment

When recurring on a list of atoms, lat, ask two questions about it:
(null? lat) and else.
When recurring on a number, n, ask two questions about it: (zero? n) and else.
When recurring on a list of S-expressions, l, ask thress question
about it: (null? l), (atom? (car l)), and else.


[以下前面的版本]
Always ask null? as the first question in expression any function.

When recurring on a list of atoms, lat, ask two questions about it:
(null? lat) and else.
When recurring on a number, n, ask two questions about it: (zero? n) and else.


** The Second Commandment

Use cons to build lists.

** The Third Commandment

When building a list, describe the first typical element,
and then cons it cons onto the natural recursion.


** The Fourthe Commandment

Always change at least one argument while recurring.
When recurring on a list of atoms, lat, use (cdr lat).
When recurring on a number, n, use (sub1 n).
And when recurring on a list of S-expressions, l, use (car l) and (cdr l)
if neither (null? l) nor (atom? (car l)) are true.

If must be changed to be closer to termination. The changing argument
must be tested in the termination condition:

when useing cdr, test termination with null? and
when using sub1, test termination with zero?.

[以下前面的版本]
Always change at least one argument while recurring. It must be
changed to be closer to termination. The changing argument must be
tested in the termination condition:
when using cdr, test termination with null? and
when using sub1, test termination with zero?.

** The Fifth Commandment

When building a value with +, always use 0 for the value of the
terminating line, for adding 0 does not change the value of an
addition.

When building a vluae with X, alwyas use 1 for the value of the
termination line, for multiplying by 1 does not change the value of a
multiplication.

When building a vluae with cons, always consider () for the value of
the terminating line.


** The Sixth Commandment

Simplify only after the function is correct.

** The Seventh Commandment

Recur on the subparts that are of the same nature:
- On the sublists of a list.
- On the subexpressions of an arithmetic expression.

** The Eight Commandment

Use help functions to abstract from representations.

** The Ninth Commandment

Abstract common patterns with a new function.

** The Tenth Commandment

Build functions to collect more than one value at a time.

* 参考文献

[1] [http://www.michaelharrison.ws/weblog/?p=34]

Unpacking multirember&co from TLS The purpose of The Little Schemer,
its authors profess, is to teach you to think recursively, and to do
so without presenting too much math or too many computer science
concepts. The book is a ball to read. However, from the perspective of
this reader, who is fairly new to functional programming and totally
new to Scheme, the book gets almost asymptotically more difficult and
complicated towards the end of chapter 8, when we hit the function
multirember&co. Looking around on the web, I noticed quite a few
people had also hit this speed bump and were scratching their heads
about how to go on. I think I can offer some assistance. So, as
threatened yesterday, I now unveil my initial contribution to the wild
world of Lisp, my explication of multirember&co and the concept of
currying. Here's hoping I don't embarrass myself too much.


The Little Schemer, (hereafter "TLS") is the latest iteration of The
Little LISPer, and is presented as a dialogue between teacher and
student. If you take the roll of the student, and try to answer the
teacher's questions, especially those of the form "define this
function whose behavior we've been describing," you can really flex
your neurons. Each chapter is a little more complicated than the
previous, and within each chapter the questions get slightly harder as
you go. It's like walking up a steadily graded hill. Until you get to
page 137 and they hit you with a long function definition, for a
function you've never seen before, and they ask, "What does this do?"

Yikes!

Here is the code for the function. (Thank you, Geoffrey King, for
transcribing it in your post.)

(define multirember&co
(lambda (a lat col)
(cond
((null? lat)
(col '() '()))
((eq? (car lat) a)
(multirember&co a
(cdr lat)
(lambda (newlat seen)
(col newlat
(cons (car lat) seen)))))
(else
(multirember&co a
(cdr lat)
(lambda (newlat seen)
(col (cons (car lat) newlat)
seen)))))))

The first clue to dealing with this function is its context. The
previous pages of TLS deal with currying, in which you define a
function like (lambda (x) (lambda(y) (eq? x y) )) — it takes one
argument, parameter x, and then returns the inner function, which also
takes one argument, parameter y. The value you pass as x acts to
customize the inner function by binding the occurance of variable x in
the inner function to the value you passed in. So chapter 8 is about
the practice of wrapping functions in this way.

The chapter is also about passing functions as arguments. The first
line of multirember&co, (lambda (a lat col) defines three
parameters. The variables 'a' and 'lat' are by convention used for an
atom and a list of atoms. But 'col' is a function–you have to pass
multirember&co a function that it uses inside its own definition.

TLS admits that multirember&co is complicated. "That looks really
complicated!" says the student. But it seeks to simplify the function
by defining functions to stand in for a) the function that will be
passed as 'col'; b) the first inner function defined in the cond
branch (eq? (car lat) a); and c) the inner function defined in the
cond else branch. To try to make you feel better about being up to
your eyelids in deep water, the TLS authors give their functions
friendly names, like "a-friend" and "next-friend." But I prefer names
that tell me what roll the functions play, so here are my renamed
functions:

a) the function that will be passed initially as 'col' (and will be
executed last):

(define last-function
(lambda(x y) (length x)))

b) the function called when a matches (car lat):

(define when-match
(lambda (newlat seen) (col newlat (cons (car lat) seen)))

c) the function called when the cond else branch executes:

(define when-differ
(lambda (newlat seen) (col (cons (car lat) newlat) seen))

TLS walks you through an execution of multirember&co, and so will
I. To further simplify things, and reduce the amount of typing I have
to do, I'll change the example in the book. Instead of a four-word lat
with some longer words, let's use (berries tuna fish) for our list,
and we'll keep tuna as our atom argument.

Here's multirember&co, with the two inner functions replaced by the
pre-defined helper functions:

(define multirember&co
(lambda (a lat col)
(cond
((null? lat)
(col '() '()))
((eq? (car lat) a)
(multirember&co a
(cdr lat)
(when-match)))
(else
(multirember&co a
(cdr lat)
(when-differ))))))

When the function is called the first time, a is tuna, lat is (berries
tuna fish), and col is last-function. (car lat) is berries, which does
NOT eq tuna, so the else branch executes: multirember&co is called
with tuna as a, (tuna fish) as lat because we pass (cdr lat) and so we
lose the berries atom at the front of the list, and when-differ as
col.

But wait. Actually, we're not just passing the when-differ function we
defined above. Here is that definition:

(lambda (newlat seen) (col (cons (car lat) newlat) seen))

This definition contains a variable, lat, that has a value at the time
multirember&co is called recursively: (berries tuna fish). So (car
lat) is (quote berries). What we've got here is a version, or an
instance, of when-differ that has a value bound to one of its
variables.

This is like currying, this binding of values to the variable of a
function and then using this altered function to do something. I think
that currying, however, refers to wrapping functions so that only one
variable at a time is given a value. What this apparent creation of a
specific instance of the function when-differ DOES have in common with
currying is this: both use closures to encapsulate the instance of the
function with bound variables, or, to be precise, to make a copy of
the function with its own scope that will persist so long as there are
references to the closure. I didn't realize this on my own, of
course. I owe this insight to Richard P. Gabriel's essay The Why of Y,
which you can read in this Dr. Dobb's article or download as a PDF.

There's something else in when-differ that will bind to a value:
col. The function passed, remember, is last-function. So we can (and
should) substitute that in for col.

Let's give a unique name to the instance (technically the closure) of
the function when-differ that has these two values bound to it:
when-differ-1. Let's write it out, and set it aside for later use:

(define when-differ-1
(lambda (newlat seen) (last-function (cons (quote berries) newlat) seen))
)

Now, on to iteration two, which we can summarize like this:

(multirember&co (quote tuna) (tuna fish) when-differ-1)

OK, so this time, (eq? (car lat) a) yields true, and the other branch
of the condexecutes: multirember&co is called with tuna as a, (fish)
as lat, and when-match as col. Once again, thanks to currying, the
definition of when-match contains expressions to which values are
bound:(car lat), which becomes (quote tuna) , and col, which becomes
when-differ-1. Remember, we just recurred by calling multirember&co
with when-differ-1 as the function argument for the parameter col. So
now let's define the resulting instance of when-match as when-match-1:

(define when-match-1
(lambda (newlat seen) (when-differ-1 newlat (cons (quote tuna) seen)))
)

On on to iteration three–we're nearly there–which we can summarize
like this:

(multirember&co (quote tuna) (fish) when-match-1)

This time, tuna and fish don't match, which means we're going to recur
with another version of when-differ, when-differ-2:

(define when-differ-2
(lambda (newlat seen) (when-match-1 (cons (quote fish) newlat) seen))
)

Finally, iteration four:
(multirember&co (quote tuna) () when-differ-2)

This time lat is an empty list, which means (null? lat) is true, and
the terminating line (col (quote()) (quote())) is executed. Yay! We're
done!

Except…

The result of the completed execution (col (quote()) (quote())) has to
be evaluated. Here's where everything turns inside out, or rightside
out if you like.

First of all, the value of col in the final iteration was
when-differ-2. So we'll start there.

(when-differ-2 (quote()) (quote()))

Now, look back up and get the definition of when-differ-2 and
substitute it.

((lambda (newlat seen) (when-match-1 (cons (quote
fish) newlat) seen)) (quote()) (quote()))

OK, so the parameters newlat and seen both get assigned the value of
an empty list:

(when-match-1 (cons (quote fish) (quote())) (quote()))

We can simplify this by consing fish onto the empty list:

(when-match-1 (fish) (quote()))

We have a definition for when-match-1 too. Let's substitute that in now.

((lambda (newlat seen) (when-differ-1 newlat (cons (quote tuna)
seen))) (fish) (quote())) )

And again assign values, this time (fish) and () to newlat and seen:
(when-differ-1 (fish) (tuna))

We're getting somewhere now. Do you see how at each step we're consing
a value onto either seen or newlat? seen has gotten the instance of
tuna, which was the atom we passed to multirember&co at the start,
whereas newlat has gotten the other atom, fish. Guess where berries is
going to go when we get to it.

Now, let's substitute our definition of when-differ-1:

((lambda (newlat seen) (last-function (cons (quote berries) newlat)
seen)) (fish) (tuna))

Which becomes….
(last-function (berries fish) (tuna) )

And now we're back where we started, with last-function.

( (lambda(x y) (length x)) (berries fish) (tuna) )

(length (berries fish) )

2

So that's how multirember&co works. What does it accomplish? It seems
to separate occurrences of the atom a in the list of atoms lat from
the other atoms in lat, and then it executes last-function using the
list of occurrences and the list of other atoms.

In an imperative language like C or Java, you would probably define
two variables, one for each list, and then loop through the list of
atoms, testing each element in the list for equality with a, and then
pushing the element onto either of the two lists. Finally, you would
call the final function with the two lists you built.

Consider the differences in this approach. Throughout the loop, you
have several variables remaining in scope, which means you have an
opportunity to munge one of them accidentally. Also, how modular is
this hypothetical code? In C, you could pass the last-function
function as an argument to a procedure that encapsulates the loop, but
try it in Java. No sir, in Java you'd have to call a method to get the
two lists (which would have to come back wrapped into one object,
probably a String[] array) and then call last-function with returnval[
0 ] and returnval[ 1 ]. Not terrible, but not elegant either.

That's just scratching the surface, I'm sure. If the example were more
complicated, other implications of the recursive approach might become
clear, at least to smarter people than me. But there is one other
thing to point out.

As TLS points out, the function you supply for use with the two lists
is assigned to a parameter names col because "col" stands for
"collector" by convention. What is this function collecting? The two
lists, of course. But more than that each use of col, as it changes
from when-differ to when-match, is persisting the values of the lists
from one step to the next. And that's important because as of page
136, there has been no mention in TLS of an assignment operator. So
even if we wanted to define variables to reference while looping
through the list, we could not. Not yet. After all, such code would
produce what functional programmers refer to, with a sniff, as side
effects.

[2] [http://www.rhinocerus.net/forum/lang-scheme/100568-how-why-did-they-do.html]

中国城市化进程考验城市管理 人治模式亟待转变 zz

中国城市化进程考验城市管理 人治模式亟待转变
来源:瞭望新闻周刊2010年09月04日18:56
我来说两句(716)复制链接打印大中小
  《瞭望》文章:不断突破城市管理瓶颈
  进入城市大国的新时代,我们再一次面临"赶考"的挑战:如何在快速推进的城市化过程中管理好城市?
  文/韩保江
  随着城市化进程的快速推进和越来越多的人口向城市聚集,中国正在从农村人口占大多数的国家向城市居民占大多数的国家转变。这是一个巨变,它宣告传统以控制乡村、限制农民流动为特征的"城乡分治"模式将退出历史舞台,昭示以鼓励农村人口流动、放开城市限制为特征的"城乡一体化"治理模式将隆重登场。这个巨变,既会给城市带来新的发展机遇、发展动力和经济繁荣,也会给城市稳定和社会秩序带来巨大压力。因此,如何适应这一巨变,如何在城乡一体化加速推进的过程中管理好城市,如何突破制约城乡一体化发展的各种管理瓶颈等问题,亟待回答。
  早在1949年新中国成立前夕,毛泽东是用进京"赶考"来形容我们党从领导农村革命和夺取政权到执掌政权与开展城市建设这一时代转换的。如今,进入新的城市大国的时代,我们将再一次面临"赶考"的挑战。这次"赶考"的主要题目就是如何在快速推进的城市化过程中管理好城市。这需要认真研究现代城市发展规律,虚心借鉴发达国家管理城市的经验,深入检讨我国城市管理中的不足甚至缺陷。
  客观地讲,我国在过去几十年的城市管理中积累了不少经验。正因如此,城市化进程不仅快速推进,而且城市内部的经济和社会实现了发展和稳定。但也必须看到,我国的城市管理尚有诸多不足。具体表现在:一是刚性有余,柔性不足。现有城市管理方式多是沿袭计划经济体制和战争年代的管理观念,过于强调整齐划一。然而,城市应是丰富多彩的,城市人的生活应是更有个性的,特别是"市民社会"追求"自由和自治",由此要求城市管理要更富有柔性,要更有人情味,而绝非简单的"命令与服从"、"违规与惩罚",甚至"围追堵截"。
  二是重人治,轻法治。当前我国的城市管理过程中仍偏重领导重视和领导批示,以会议落实会议的现象普遍存在,重部署,轻落实,进而使许多法律法规流于形式。甚至由于长官意志而更改法律的现象也仍然存在。由于忽视法律法规严肃性及其在城市管理中的作用,城市中的许多违规主体或是采取"上有政策,下有对策"的办法来应付管理,或采取贿赂手段来逃避法律制裁。
  三是重政府,轻中介。城市管理主体是政府,但面对纷繁复杂的城市经济和社会生活,什么都要政府事必躬亲,是不可能的。许多发达国家都非常重视发挥"非政府组织"在城市管理中的作用。由于非政府组织的"民间性"、"中立性",可帮助政府解决民间政府不能解决的许多矛盾和问题。而这一点在我国城市管理过程中常常被忽视。
  四是重运动,轻制度。在我国城市管理过程中,无论是针对城市卫生、食品安全、假冒伪劣、黄赌毒、还是社会治安,都喜欢搞"战役式"的运动。不仅有五花八门的"大检查"、"严打月(年)",而且有形形色色的专项治理"领导小组"。这种治理城市的方式不仅容易劳民伤财,引起民怨,而且其效果也不甚理想。许多丑恶现象经常在轰轰烈烈的"战役"之后"死灰复燃"。
  五是政出多门,缺乏协调。在我国,专司城市管理的部门可谓不少,不仅有城管部门,而且有工商、卫生防疫、质量监督、食品安全、安全生产、公共安全等众多部门。城市管理水平不高,主要是因为部门之间职能交叉、缺乏协调。每个部门都容易从自身利益出发来制定政策,实施管理。有利的事大家争着管,无利的事易相互推诿,逃脱责任。由于这种"群龙治水"的管理方式效率很低,有的甚至越管问题越多,加上执法和管理过程中还存在着某些腐败或执法不公的现象,久而久之,管理部门的公信力每况愈下。
  针对不足和问题,我们应在研究中国城市发展规律的基础上,尝试用"法治"来管理和治理城市。为此,首先要深化城市管理体制改革,精简和整合城市管理机构,加快建立公共服务型政府。全新的城市管理应是刚柔并济、管理与服务并重、把管理寓于服务之中,并以此来缓解管理者与被管理者的"对立情绪"。有效的管理是政令统一的管理,为此需要整合诸多的城市管理部门职能,合理分工,努力形成城市管理合力,提高城市管理效率。
  其次,要加快完善我国城市管理的制度和法规,提高管理执法水平,最大限度减少管理执法过程的随意性。"公生明,廉生威",城市管理只有有法可依、执法必严,才能有利于城市居民形成"遵纪守法"的良好预期,进而提高政府执法部门的公信力。
  再有,要充分发展和利用中介组织,学会用社会力量管理社会。在城市管理过程中既要不遗余力地打击非法或黑社会组织,也要重视发展合法的非政府中介组织,充分发挥非政府中介组织在城市管理中的积极作用。
  同时,要大力提高城市管理人员的素质和能力,克服城市管理人员的"本领恐慌"。正所谓"事在人为",再好的制度、法规和政策都得通过城市管理人员来落实。因此,加强城市管理人员的培训,增强城市管理人员的素质,是落实好各项制度、法规、政策的根本保障。□
(责任编辑:曾安能)

20100904

自动pull全部git工程:技术选择和放弃-故障定位

自动pull全部git工程:技术选择和放弃-故障定位


** git mail
*** mail list
**** http://sourceforge.net/apps/trac/sourceforge/wiki/Git
无动作.配置成本地git也未收到邮件.
**** http://pkill.info/b/1473/setting-up-git-commit-email-notification/
[hooks]
mailinglist = "email1@example.com email2@example.com"
senderemail = "owner@exmaple.com"
**** http://source.winehq.org/git/tools.git/?a=blob_plain;f=git-notify;hb=HEAD
wine开发组用的。执行后停住不动。
** 邮件通知一直失败,做了个脚本,以后每天执行一次,pull更新GIT本地repository。
: echo ------------------------
: echo ec
: cd ec
: git pull .
: cd ..
:
: echo ------------------------
: echo gitadmin/gitosis-admin
: cd gitadmin/gitosis-admin
: git pull origin
: cd ../..
:
: echo ------------------------
: echo gittest/gittest
: cd gittest/gittest
: git pull .
: cd ../..
:
: echo ------------------------
: echo movie
: cd movie
: git pull .
: cd ..
:
: echo ------------------------
: echo patent_monkeyking
: cd patent_monkeyking
: git pull .
: cd ..
:
: echo ------------------------
: echo spr
: cd spr
: git pull .
: cd ..
:
: echo ------------------------
: echo story9000s
: cd story9000s
: git pull .
: cd ..
:
: echo ------------------------
: echo uv
: cd uv
: git pull .
: cd ..
:
: echo web程序设计_网络课程
: cd web程序设计_网络课程
: git pull .
: cd ..
:
: echo ------------------------
: echo 马赛克人名.自动调节曝光时间和电压时间
: cd 马赛克人名.自动调节曝光时间和电压时间
: git pull .
: cd ..


** git pull remote?? config
CLOCK: [2010-09-04 周六 17:20]--[2010-09-04 周六 20:33] => 3:13
*** git bash & gui 不能pull,而tortoise 能
*** git pull -v repository branch ?
*** git remote -v
*** git config -l
*** 找到原因,是因为putty自动载入了[C:\Users\ibm\.ssh\]下的 private key [2010-09-04 周六 19:36]
gittest & gitadmin 是用 aa 的账号连接的。
*** tried to copy young.ppk to user ibm's home .ssh directory. failed
for different format.
*** bash uses ssh, not Putty

: $ ssh -v git@[马赛克_服务器的IP]
: OpenSSH_4.6p1, OpenSSL 0.9.8e 23 Feb 2007
: debug1: Connecting to [马赛克_服务器的IP] [[马赛克_服务器的IP]] port 22.
: debug1: Connection established.
: debug1: identity file /c/Users/ibm/.ssh/identity type -1
: debug1: identity file /c/Users/ibm/.ssh/id_rsa type -1
: debug1: identity file /c/Users/ibm/.ssh/id_dsa type -1
: debug1: Remote protocol version 2.0, remote software version OpenSSH_4.3
: debug1: match: OpenSSH_4.3 pat OpenSSH*
: debug1: Enabling compatibility mode for protocol 2.0
: debug1: Local version string SSH-2.0-OpenSSH_4.6
: debug1: SSH2_MSG_KEXINIT sent
: debug1: SSH2_MSG_KEXINIT received
: debug1: kex: server->client aes128-cbc hmac-md5 none
: debug1: kex: client->server aes128-cbc hmac-md5 none
: debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent
: debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP
: debug1: SSH2_MSG_KEX_DH_GEX_INIT sent
: debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY
: debug1: Host '[马赛克_服务器的IP]' is known and matches the RSA host key.
: debug1: Found key in /c/Users/ibm/.ssh/known_hosts:1
: debug1: ssh_rsa_verify: signature correct
: debug1: SSH2_MSG_NEWKEYS sent
: debug1: expecting SSH2_MSG_NEWKEYS
: debug1: SSH2_MSG_NEWKEYS received
: debug1: SSH2_MSG_SERVICE_REQUEST sent
: debug1: SSH2_MSG_SERVICE_ACCEPT received
: debug1: Authentications that can continue: publickey,gssapi-with-mic,passwor
: debug1: Next authentication method: publickey
: debug1: Trying private key: /c/Users/ibm/.ssh/identity
: debug1: Trying private key: /c/Users/ibm/.ssh/id_rsa
: debug1: Trying private key: /c/Users/ibm/.ssh/id_dsa
: debug1: Next authentication method: password
: git@[马赛克_服务器的IP]'s password:

*** convert young.ppk into young_openssh as OpenSSH Key
:
: ibm@IBM-THINK c:/Users/ibm/Documents/git/ec (master)
: $ ssh -v git@[马赛克_服务器的IP]
: OpenSSH_4.6p1, OpenSSL 0.9.8e 23 Feb 2007
: debug1: Connecting to [马赛克_服务器的IP] [[马赛克_服务器的IP]] port 22.
: debug1: Connection established.
: debug1: identity file /c/Users/ibm/.ssh/identity type -1
: debug1: identity file /c/Users/ibm/.ssh/id_rsa type -1
: debug1: identity file /c/Users/ibm/.ssh/id_dsa type -1
: debug1: Remote protocol version 2.0, remote software version OpenSSH_4.3
: debug1: match: OpenSSH_4.3 pat OpenSSH*
: debug1: Enabling compatibility mode for protocol 2.0
: debug1: Local version string SSH-2.0-OpenSSH_4.6
: debug1: SSH2_MSG_KEXINIT sent
: debug1: SSH2_MSG_KEXINIT received
: debug1: kex: server->client aes128-cbc hmac-md5 none
: debug1: kex: client->server aes128-cbc hmac-md5 none
: debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent
: debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP
: debug1: SSH2_MSG_KEX_DH_GEX_INIT sent
: debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY
: debug1: Host '[马赛克_服务器的IP]' is known and matches the RSA host key.
: debug1: Found key in /c/Users/ibm/.ssh/known_hosts:1
: debug1: ssh_rsa_verify: signature correct
: debug1: SSH2_MSG_NEWKEYS sent
: debug1: expecting SSH2_MSG_NEWKEYS
: debug1: SSH2_MSG_NEWKEYS received
: debug1: SSH2_MSG_SERVICE_REQUEST sent
: debug1: SSH2_MSG_SERVICE_ACCEPT received
: debug1: Authentications that can continue: publickey,gssapi-with-mic,password
: debug1: Next authentication method: publickey
: debug1: Trying private key: /c/Users/ibm/.ssh/identity
: debug1: Trying private key: /c/Users/ibm/.ssh/id_rsa
: debug1: read PEM private key done: type RSA
: debug1: Remote: Forced command: gitosis-serve young_ssh
: debug1: Remote: Port forwarding disabled.
: debug1: Remote: X11 forwarding disabled.
: debug1: Remote: Agent forwarding disabled.
: debug1: Remote: Pty allocation disabled.
: debug1: Authentication succeeded (publickey).
: debug1: channel 0: new [client-session]
: debug1: Entering interactive session.
: debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
: ERROR:gitosis.serve.main:Need SSH_ORIhGINAL_COMMAND in environment.
: debug1: channel 0: free: client-session, nchannels 1
: Connection to [马赛克_服务器的IP] closed.
: debug1: Transferred: stdin 0, stdout 0, stderr 38 bytes in 0.6 seconds
: debug1: Bytes per second: stdin 0.0, stdout 0.0, stderr 62.3
: debug1: Exit status 1
:
: ibm@IBM-THINK c:/Users/ibm/Documents/git/ec (master)
: $ git remote show origin
: * remote origin
: Fetch URL: ssh://git@[马赛克_服务器的IP]/ec
: Push URL: ssh://git@[马赛克_服务器的IP]/ec
: HEAD branch: master
: Remote branch:
: master new (next fetch will store in remotes/origin)
: Local ref configured for 'git push':
: master pushes to master (up to date)


*** 总结

Convert young.ppk (created by PuTTYGen) as OpenSSH Key;
Copy it into .ssh directory under home directory (of windows ) ;
Name it as id_rsa;
In bash, ssh -v git@[马赛克_服务器的IP];

config中的remote被 git pull 忽略了,使用了ssh。
原因不明。可能是安装git时,选择SSH客户端一步,我选择了PuTTY(plink.exe)。当时的屏幕说明中提到,"PuTTY has
better integration with Windows."

脚本的最终版本

echo ------------------------
echo ec
cd ec
git pull ec master
cd ..

echo ------------------------
echo gitadmin/gitosis-admin
cd gitadmin/gitosis-admin
git pull origin master
cd ../..

echo ------------------------
echo gittest
cd gittest
git pull gittest master
cd ..

echo ------------------------
echo movie
cd movie
git pull movie master
cd ..

echo ------------------------
echo patent_monkeyking
cd patent_monkeyking
git pull patent_monkeyking master
cd ..

echo ------------------------
echo spr
cd spr
git pull spr master
cd ..

echo ------------------------
echo story9000s
cd story9000s
git pull story9000s master
cd ..

echo ------------------------
echo uv
cd uv
git pull uv master
cd ..

echo web程序设计_网络课程
cd web程序设计_网络课程
git pull web_programming_cai master
cd ..

echo ------------------------
echo 马赛克人名.自动调节曝光时间和电压时间
cd 马赛克人名.自动调节曝光时间和电压时间
git pull monkeyking_code master
cd ..

20100902

Y-combinator

* Y-combinator

[http://www.catonmat.net/blog/derivation-of-ycombinator]
解决在函数中应用匿名函数的问题。

1. 使用???替换函名函数,如果执行不到,这代码是可以执行的。

: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (
:
: (lambda (list) ; the
: (cond ;
: ((null? list) 0) ; function
: (else ;
: (add1 (??? (cdr list)))))) ; itself
:
: (cdr list))))))

2. 以length为参数以后,下面这段代码需要修正后执行,否则报错 "reference to undefined identifier: ???"

: ((lambda (length)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (length (cdr list)))))))
: ???)

??? 被改为 length 后可执行。
??? 被改为 '(???) 也可以被执行。
??? 被改为 '() 也可以被执行。
看起来,只要???是个可以被引用的东西就行,但是不能是未定义的。
事实上,lambda (length)的参数不管是什么,都会返回 (lambda (list) 这个函数。

如下实验:

: (((lambda (length)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (willnot_run_here (cdr list)))))))
: 'place_holer) '() )

下面的代码

: ((lambda (f)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (f (cdr list)))))))
: ((lambda (g)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (g (cdr list)))))))
: ((lambda (h)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (h (cdr list)))))))
: ???)))

"ince the argument names f, g,h in (lambda (f) ...), (lambda (g) ...),
(lambda (h) ...) are independent, we can rename all of them to length,
to make it look more similar to the length function:"

以上并非可以替换名字的原因。
真正的原因是,lamda(f)中的参数f,是lamda(g);
lamda(g)中的参数g,是lambda(h);
而h只是占位符,对程序的求值没有任何作用。
以下代码是上面代码的变形,帮助理解。

: (((lambda (lambda_lambda_place_holder)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (lambda_lambda_place_holder (cdr list)))))))
: ((lambda (lambda_place_holder)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (lambda_place_holder (cdr list)))))))
: ((lambda (place_holder)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (willnot_run_here (cdr list)))))))
: 'place_holder))) '(a b))

下面的代码中,
把lambda(length)作为参数传给lambda (mk-length)
lambda (mk-length) 的执行是以参数作为函数,给这个函数的参数是占位符???;
这个参数此时是 lambda (length)。
lambda (length)的占位符参数没有被求值,函数就结束了。
所以,以下代码能求 '()

: ((lambda (mk-length)
: (mk-length ???))
: (lambda (length)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (length (cdr list))))))))

下面的代码中
lambda (mk-length)的执行是,
向mk-length传递参数 (mk-length ???)。
这一参数的解释上面已经提到,执行一次lambda (length)。
执行lambda (length),最后返回的是 length (cdr list)。
即,以lambda (length)作为lambda (length)的参数。
一共执行两次。

: ((lambda (mk-length)
: (mk-length
: (mk-length ???)))
: (lambda (length)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (length (cdr list))))))))

既然???是占位符,不会被求值,所以可以

: ((lambda (mk-length)
: (mk-length mk-length))
: (lambda (length)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (length (cdr list))))))))

所有的length改在mk-length。
传进来的参数确实是它。
代码略去。

然后,length (cdr list) 换成 (mk-length mk-length) (cdr list)。
这样,(mk-length mk-length) 递归地返回 原来的lambda (length) 应用在 (cdr list) 上

: ((lambda (mk-length)
: (mk-length mk-length))
: (lambda (mk-length)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 ((mk-length mk-length) (cdr list))))))))

其实mk-lenth只执行了一次,然后mk-length参数就是占位符了。
但是,"The function works because it keeps adding recursive uses by passing
mk-length to itself, just as it is about to expire."

递归的跳出条件是(null? list)。

把(lambda (length)移出作为lambda (le)的参数,
(lambda (x)作为le的参数。
代码如下。

: ((lambda (le)
: ((lambda (mk-length)
: (mk-length mk-length))
: (lambda (mk-length)
: (le (lambda (x)
: ((mk-length mk-length) x))))))
: (lambda (length)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (length (cdr list))))))))

Y-combinator如下。

: (define Y
: (lambda (le)
: ((lambda (f) (f f))
: (lambda (f)
: (le (lambda (x) ((f f) x)))))))

匿名函数的应用如下。

: ((Y (lambda (length)
: (lambda (list)
: (cond
: ((null? list) 0)
: (else
: (add1 (length (cdr list))))))))
: '(a b c d e f g h i j))

另一种Y-combinator的写法,
[http://www.mactech.com/articles/mactech/Vol.07/07.05/LambdaCalculus/]
and [http://www.stanford.edu/class/cs242/readings/vocabulary.html]
"When applied to a function, returns its fixed point."
: (define y
: (lambda (f)
: ((lambda (x) (f (x x)))
: (lambda (x) (f (x x))))))

参见TLS书(非pdf页码)pp.171,
如何把lambda (length)移出,从而形成了Y-combinatior的框架。

*关键:applying arguemnt lambda on precedure lambda, and eval the
augument lambda in precedure lambda.*

另,参考[http://blog.vazexqi.com/2006/07/13/y-combinator]

原来看不懂的一个原因是,这本电子书有缺页。
[The Little Schemer - 4th Edition.pdf]是个更完整的版本。