六天不悟,七天就能悟么?意思意思得了 zz

六天不悟,七天就能悟么?意思意思得了【皆是虚妄,为何不能交媾?】【有本事自己寻缘。】【万法皆空,为何不能食肉?】【庙里没有闲钱。】【梦幻泡影,为何不能蓄发?】【你师娘摸不习惯。】【师傅,一切如梦幻泡影,可在梦里我还有哭有笑,甚至还有了一头长发,梦幻泡影虽易逝,也比这循环往复的无聊强太多了。】【你睡醒了再跟我说话。】如是我闻:时,佛见须菩提静坐莲台吃面,佛问,须菩提,何不就蒜?须菩提白佛言:世尊,我念经已经够臭了。如是我闻:须菩提庆生,佛告曰,此是一世,前有无穷世,后有无穷世,所谓生日只是来日,所谓死日只是去日,来去如烟,何必庆祝,你就别跟我要蛋糕了,乖,Happy
birthday to you 。须菩提白佛言:Are you fucking kidding me ?【师傅,你知道我在想谁么?】【昨天那个女施主。】【你怎么知道。】【我也在想。】【那你怎么睡得着?】【那是大方丈的闺女,想也白想。】【师傅,想必我在庙里呆不久了,我怕我控制不住自己。】【还想她呢?】【嗯。】【那就别控制了,为师传你一套迷魂经。】【你怎么不用?】【此经一生一念,一念一缘,我已经有你师娘了。】【我靠,那我还是等等看还有没有更合适的吧。】【操,没用,都会腻的。】【小和尚,听说你喜欢我?】【不好说喜欢,只是看见你会乱】【听说你还想娶我?】【不好说想娶,只是想永远和你在一起。】【妈逼,油嘴滑舌,你丫天秤座的吧?】【阿弥陀佛,心直口快,女施主别不是天蝎的吧?咱俩正合】【合你大爷,你们佛门弟子还信这个?我爹怎么带的队伍。】【师傅,为什么咱早上要敲钟啊?】【因为我们没养鸡。】【师傅,你什么时候教我武功?】【佛门中人,慈悲为怀,大方丈有令,我们这种清净小庙,不可学少林喊打喊杀。为师传你诸般经义,读懂念通,内心强大,见着那些花拳绣腿的,舌灿莲花,灭他们跟玩儿似的。】【师傅,我懂了,知识就是力量。】【咦?你怎么肿成了这个样子?又去调戏小北了?】【不是,少林的人打的。】【为什么?】【我跟他们舌灿莲花来着。】【唉,我说什么你都信,真可爱。】【师傅,《易筋经》听起来很牛逼啊,我想学。】【那是通过刺激经脉给自己带来快感的土办法,都是买不起大麻追不上姑娘的和尚才练的。】【我好像就是....】【可我不是,所以不会,哦耶。】【师傅,今天晚上我能不住庙里么?】【别装了,出去冻一夜回来和师兄弟们吹牛逼的事儿我也干过,想开点儿吧,色即是空。】【师傅,和尚有自杀的么?】【有,但各寺都封锁消息,佛门已是逃避现世之地,你来了还死,传出去这不显得我们不专业么?此世不乐,来世就乐么?这些人真痴。】【那来世就一定不乐么?】【嗬,跟我抬杠?那你死去吧。】【你看你,辩经嘛,小心眼儿样儿。】【师傅,那你相信西方极乐么?】【那都是骗施主们的。】【为师现赐你法号澈丹,取清清澈澈,圆润如丹之意。】【师傅,我又怎么着你了.....】【你知足吧,你师兄宨丹都没说啥。】【师傅,你法名为什么叫空舟?】【大方丈说我度不了人,也难自度,所以赐名空舟,由我自横。】【那我还跟着你干嘛....】【你执念太重,跟着谁也到不了彼岸,不如索性和我负负得正。】【为什么啊?】【你看,你总问为什么。】【师傅,其实我应该叫你师父才对吧?】【没事儿,输入法怎么默认的就怎么叫吧,随缘。】【师父,你师父是谁?】【大方丈。】【他的呢?】【他师父就是咱庙的创始人,据说当年是混的,后来路上捡了本儿经,就拉了一票弟兄,占山为王,广结善缘,干起了这普度众生的勾当。】【咱庙还有这背景?】【不然你以为为什么我们还没被少林吞并?】【师父,小北和她娘为什么不住庙里啊?】【大方丈怕影响不好。】【那我师娘为什么就能住庙里?】【我一个出家人,还在乎什么影响。】【一切如梦幻泡面,有蒜就蒜,没蒜就算,观自在,望远山,一切有为法,当做如是观】【师父,我爱吃米饭。】【.....好了,今天的早餐,啊不,早课就上到这里吧。】【撤丹,听说你偷鸡被人撞见了?大白天就去偷鸡,你可真有创意。】【师父,没事儿,我说我是少林的。】【嗯,好孩子,鸡呢?赶紧给你师娘送去,出家人不能杀生。】【再说咱也不会炖啊。】【阿弥陀佛,这孩子,真可爱。】【师父,人家别的寺都叫方丈,为什么咱们得叫大方丈?】【这不显得咱大气么。】【那我以后就管你叫大师父吧?】【嗬,你在这儿等着我呢!】都看的很明白,都活得很不明白————空舟禅师与诸君共勉。【师父,咱庙为什么叫遗寺啊?】【说来话长。本来叫义寺,就大方丈那黑社会师父取的,后来他死了,大方丈说这名儿太不禅了,就叫了疑寺。谁知那年起了瘟疫,正该是香火旺的时候,结果百姓都不来咱庙,就改成遗寺了。还有人提议叫逸寺,让大方丈否了,他说,蒙谁啊,你真那么逸还出什么家?】【小和尚,你到底喜欢我吗?】【喜欢】【出家人不打诳语?】【出家人连肉都不吃连姑娘都不泡,他们的话你也敢信?我师父说,出家人的话都是诳语。小北,这话不是出家人说的,这是我说的,我喜欢你。】【师父,今天怎么哪儿哪儿都这么黑啊?】【澈丹,我们佛门中人,不要学人家针砭时弊。晨鸡报晓,昏鸦鼓噪,都在红尘里闹,你以为黑白的红尘就不是红尘了?活着的人就不是死人了?唉,去叫你师娘吃饭。】【师父,其实那迷魂经你没给师娘念过吧?】【你怎么知道?】【我昨天听见师娘让你跪搓衣板儿来着】【...那是我们夫妻间的小游戏】【你怎么不念啊,念了师娘不就全听你的了么?】【这些伪科学的东西怎么能信,再说,她要是全听我的了,我们在一起还有什么意思。】【师父】【嗯?】【那你为什么让我给小北念迷魂经?】【反正你也追不上人家,死经当活经念呗。万一成功了,证了这经,那得造福多少比丘僧啊,你这可是大功德。】【师父,要不是打不过你我就跟你拼了】【师父啊,可是爱情本身不就是伪科学吗?】【谁说不是了,你看这些香客,求签,问八字,配星座,凡俗中人,贪恋的不就是这些个伪科学吗?他们要是都科学了我佛就没饭吃了。】【师父,那什么是科学?】【这孩子,我要懂我还跟这儿呆着?闹什么闹。不过据说大方丈是懂的,他说,科学就是一花一世界,就是无限的轮回无限的远,就是谁也说不清楚的东西,就是比伪科学还伪科学的东西。咱们还是别想这个了,省得一不小心再真给顿悟了。】【师父,好大风雨。】【澈丹,少做感慨。】【师父,澈丹公然追求大方丈之女,枉顾清规戒律,破坏寺内安定团结,请师父予以管教。】【行了吧,看你们这没出息的样儿,还学会给人扣大帽子了?还学会正义凛然了?还有没有一点儿出家人的样子!】【澈丹,和师兄弟们打架了?】【是。】【所为何事?】【他们说我不应该追小北,其实他们是嫉妒。】【嗯,既已看破是嫉妒,又何必跟他们争呢?】【我没争,他们争。】【唉,力的作用是相互的,你真的没争么?你还是执念太重啊。算了,来,为师传你一套女子防身术,省得你老吃亏。】【师父,我从小就在庙里,我的亲爹亲娘呢?】【你怎么问这么俗套的问题?难道为师要告诉你我其实就是你爹吗?】【师父,咱们出家人,可不许玩儿伦理哏。】【你还跟我玩儿八点档狗血剧呢。】【师父,你说大方丈知道我和小北的事儿吗?】【大方丈什么不知道。】【那他怎么不管?难道他看我还行?】【别臭美了,大方丈那是对自己的女儿有信心。】【澈丹,此番云游,有何感想?那儿好玩儿么?】【师父,你竟然也会问这种问题,用你的话说,这红尘里哪有什么好玩儿不好玩儿。】【唉,主要是你师娘想把蜜月补上。】【师父,寺里好安静啊。】【那你还说什么话。】【师父,我心里乱。】【去墙根蹭蹭去,没看我这儿入定呐嘛,别烦我。】【师父,你干嘛要入定?】【我心里乱。】【空舟!你那徒弟,叫什么撤丹的,怎么老不见影儿,是不是出去云游了?怎么也不跟我爹请假!好放肆!】【哈哈哈,小北,你动凡心了。】【师父,你说,我和小北,我是不是自作多情?】【自作虽苦,但看你这个贱兮兮很享受的样子,多情想必是快乐的,你还抱怨什么?】【别跟我打哈哈,我知道今天小北来找过我,她说什么了?】【别问,万一不是好话呢?】【小北,我觉得少林的素菜做的还不错啊,我请你去吃好么?】【不吃,就爱吃肉。】【小北,我觉得十里坡那个戏班子的青衣唱的还可以,我请你去听好么?】【不听,没我嗓子好。】【小北,你生我气了?】【不生.....哎?生!】【完了,小北,我们有分歧了,肯定是我错了,我决定听你的!】【真的?】【真的】【那我可唱了】【..........】【小北,你唱的真好,能教教我么?】【得了吧,你念经都跑调。】佛法不二,佛不分是非,不分喜悲,佛见有缘的教他度化,见无缘的教他轮回。后来佛见你了,佛二了,佛更不分是非了,你是便喜,你非便悲,从此你就是佛法了,佛不普度众生了,佛颓了,佛被你普度了,但是佛欢喜了。————空舟禅师当年的情书,引来给你。【澈丹,为师是为了让你哄小北才给你看我的情书,你自己用心研究就好了,干嘛到处嚷嚷啊?】【师父,你还挺不好意思。】【不是,那当年不是给你师娘写的.....】【我说你怎么有点儿肿.....】我师父和师娘早睡了,我师兄和师弟们也睡了,小北,你也已经睡了吧?我和想你也该睡了。【师父,你好久没给我讲经了。】【你不是最烦听经么?】【我觉得将来要和小北生活在一起,还是得有一技傍身,你看,你不就是靠经念得好才能留住师娘,才能做得禅师的吗?】【这孩子,这话别跟别人说,来,为师给你讲一段儿楞严,这活我熟。】【澈丹啊,念经只是基本功,做好和尚还得会解签,趋妖,看风水,做慈善,心理辅导,编造彼岸,装看得开,装悲天悯人,装笑口常开。佛法无涯,你慢慢学吧。】【师父,做和尚好难,要不咱们出家吧?】【这诸般经义,确实是安身立命之技,练到能随口占偈,指点迷津,越指越迷也就行了。但我就怕你动机太纯,一心执念,将来小北转身一走,水打飘萍,你别真的陷进经里,那就神佛难救了。】【没事儿,小北走我就跟着呗。】【得,这就已经没救了。】【澈丹,你喝酒了?】【嗯。】【啤的白的?】【要不我吐出来你尝尝?】【傻孩子,能吐出来的就不是酒了。】 【师父,你说我是不醉了?】【这你得问小北。】 【小北不理我。】【嗯,你没醉。】【师父,这次中原辩经大会咱庙派得你去吧?】【不是,当然是派你空响师叔。】【他?他念经还不如我呢吧?】【但他嗓门儿大啊,大会上好几百和尚,辩到最后,还能喊出来不破音儿的就算胜利。】【师父,我能跟去么?】【想见见世面?】【嗯】【算了吧,年年辩经大会都得打伤几个和尚,庙里今年派你空手道,啊不,空道师叔陪同保护。咳,上回要不是少林不要脸竟然带了家伙去,咱庙去年就是第一了,他们哪是空道的对手。】【咱庙得过第一么?】【建寺第一年,大方丈的师父为了闯名头想了个狠招,辩经当天故意迟到,待群僧辩至酣处,一脚踢碎大门,注意,是踢碎,立在大厅就喊了一句:大音希声。那帮和尚都傻了,没傻的看着那一地木头渣儿也都装傻了,第一就是咱的了。】【这招好,再用啊。】【别提了,后来确实有人模仿,同样动作,喊完正等鼓掌呢,那评委老和尚气得哆哆嗦嗦地骂,你们这行为艺术还有完没了?踢坏门不赔也就算了,还老拿《道德经》里的词儿冒充佛法,以后我们还能跟道士见面儿么!给我滚出去!】【哈哈哈这倒霉蛋是谁啊。】【咱们大方丈。】【大方丈还干过这事儿?】【谁没年轻过啊,回来痛定思痛,觉得脚疼不如嗓子疼,辩经还得拼硬功夫,就苦练声乐了。小北唱歌儿好听吧?遗传他爹的。你空响师叔就是那会儿进的庙,学的就是这本事。】【那大方丈后来还去辩过经么?】【去过几次再也不去了,自从他有了小北,就成了现在这副大彻大悟的样子,还给自己改了法名,叫南无,翻译过来好像就是皈依的意思。】【那大方站以前叫什么?】【南子,他那黑社会师父给起的,说是听着霸气。后来大方丈才知道他看过《论语》,起这名儿其实是糟践大方丈长的不够霸气。】【哈哈哈,就怕流氓有文化。】【师父,我怎么每次午觉醒来都觉着头沉啊?】【你执念太重。】【那怎么办啊。】【....以后就别午睡了吧。】【师父,咱们和尚又不干正经事,怎么还那么多人能当和尚啊。】【本朝尊佛,会念个阿弥陀佛就饿不死。再说,干正经事的人总要把钱花在这些不正经的事上,都是应运而生,你不用过意不去。】【那万一哪天本朝不尊佛了呢?】【出家人,不要学人家深谋远虑,深谋远虑,最后都净剩下虑了。当一日和尚撞一日钟,到时候实在不行咱就转型当道士呗,不就买个假发套的事儿嘛。】【师娘!快快,小北让我陪她去逛街,快给我找件儿干净好看的僧衣。】【傻孩子,这大热天儿,你还得拿那么多东西,穿什么僧衣啊,你师父上次陪我逛街就是臭美,还拿了禅杖,回来就中暑了。】【师父...】【澈丹,锻炼身体,磨砺耐性,也算修行,去吧去吧,唉,中午多吃点儿饭啊。】【师父,空响师叔回来了?怎么没见空道师叔?】【空响连辩三天三夜,直至群僧哑口无言,就听他一人儿喊了,当然第一。但是少林的辩手不服气,哑着嗓子指你空道师叔的头发,意思留发的不是佛门弟子,一大厅的哑巴和尚都盯着空道呜呜喊,空道顾全大局,当场剃度。回来就一直躲屋里哭,不见人】【对啊,空道师叔为什么能留头发?】【说来话长,空道是从日本偷渡来我中原求佛法的,结果这个笨蛋还赶时髦信儒家,身体发肤不损,这不倒霉催的么,哪个庙都不要他。大方丈看他一身武艺,性情朴质,就留下了,顺便学日语。】【大方丈还会日语?】【哈依。】【不行了,你空道师叔是咽不下这口气了,为师得跟他去趟少林。】【好!讨回公道!】【小点儿声,喊什么,讨什么公道,哪来那么多公道,佛门中人,不可争强好胜,能不声不响的给那个输了不服气的孙子来一闷棍就好。】【师娘,我师父呢?】【闭关七日,潜心佛法。】【那我修行怎么办?】【我教你呗。】【你?】【怎么着?不就普度众生那套嘛,别说普度众生了,大彻大悟咱也会啊。】【师娘,你还是教我点儿正经的吧,怎么才能讨姑娘喜欢啊?怎么才能让小北待见我?】【讨姑娘喜欢的道理我可以教你很多,但这就像你师父教你的那些大道理一样,具体到人和事上,道理都是没有用的。小北是一劫,凡是劫,都要自己去度。】【咳,我也不知道要你们两口子干嘛用。】【师父,你怎么出关了?悟道了么?】【没有。】【那你怎么六天就出关了,不是要闭关七日吗?】【六天不悟,七天就能悟么?意思意思得了。】【澈丹啊,你应该也闭闭关,减肥,美白,增加忧郁感和神秘感,还能变得沉默少言。哎呀,这么一说,真该让你师娘也闭闭关。】【你敢跟师娘说么?】【不敢。】【师父,小北彻底不理我了,怎么办啊。】【你问我我问谁。】【那那些施主有了烦恼,怎么都来问你。】【那不是问我,是问我佛。】【那我也问我佛。】【问我佛是要收费的。】【师父,今儿是佛诞日啊。】【那你孵去吧。】【师父,你这大不敬,今天是佛祖诞辰,佛祖生日!】【嗯。】【你嗯什么啊,咱们不表示表示?】【你跟佛祖熟吗?佛祖用的着你表示吗?为师过生日你表示了吗?师娘过生日你表示了吗?你们啊,就整这些虚的来劲。】小北,今天天气晴好,但过一会儿可能会下雨,我现在在想你,但过一会儿可能会更想。我师父说,世上其实并没有比天气更难测的东西。我觉得他说的对,他总是说的对,小北,不管下不下雨,过一会儿我都会更想你。【师父,刚那洋人来干嘛的?】【来传教的,说让咱们别信佛祖了,信耶稣,真可爱,好像咱们本来信佛祖似的。】【怎么不让人家进来啊?】【你can speak English
吗?为师也就是勉强能听懂,大方丈倒是会说,但是这些传教士都一根筋,你大方丈懒得费工夫开悟他,打他又不合适,就撵走了。】【不是一根筋吗?怎么能撵走?】【大方丈说,我中原大乘正宗佛法皆出自少林,少林如若改信耶稣,我等小庙没有不信之理。那洋人一听有道理,就去少林了。】【大方丈这是借刀杀人吗?】【呦,你还看上兵法了?心里明白就得了。】【空舟!你们遗寺太过分了,这传教的打也打不得,劝又劝不走,弄我们少林来让我们如何是好?】【阿弥陀佛,吵吵什么,你们不是爱接待外宾吗?拿出中原第一大寺的排场来,好生款待他,说不准哪天被感化了,就回西洋替我们传佛法了。】【师父,最近咱怎么不做早课净跑步啊?】【出家人,太胖不合适,影响信誉。保持身材,眼神空灵,头顶锃亮,僧袍整洁,都算职业道德。】【师父,今日山上好大雾啊,望不出去。】【没雾你就能望出去吗?瞎望什么,留神脚下。】【师父,昨夜雷声好大啊。】【嗯,也不光是雷,你空响师叔跟丫对着喊来着。】【喊什么啊?】【"你小点儿声!你小点儿声!"大概就这句吧。】【后来雨停了,雷歇了,你空响师叔就笑了,说了句阿弥陀都服,你不服?哦耶了一下儿,就睡了。】【我说他今儿怎么看谁都笑,得意洋洋的。】【那是嗓子喊哑了,要不早显摆上了。】【澈丹啊,你这心里老挂着小北,已成执迷不悟之势,长此以往,怕是影响修行。】【那怎么办啊?】【你还是得找小北求解脱。】【.....我要这么求,她非打死我。】【师父,空言道何以弘道?我得跟空道师叔学学空手道。】【嗯,这上联儿不错,你自己能对出下联儿来我就让你去学。】【靠!】【靠什么靠,你空道师叔倾心儒学,虽是武艺超群,但一身文人毛病,就爱对个对子,你早晚都得学】【佛理实相中,本来一切空,
无生无死无去无来,哪有个相对?师父,你竟然让我学这等有悖佛理的小技。】【哪儿那么些废话,让你学你就学,过年写写春联儿也能挣点儿零花钱】

Emacs开发VC程序 zz

[http://emacser.com/dev-vc.htm]Emacs开发VC程序
背景
前些日子,微软宣布Visual studio 2010的EMACS扩展。此前,Visual studio 2005
6.01已然引入了Emacs的键盘模拟,这次又将Visual studio
的Emacs化更进一步,这种事发生在Microsoft这样无利不起早的企业,原因呢,你懂得。
话说,武功再高,也怕菜刀。Emacs玩的再溜,也保不齐哪天你要去开发Visual studio
程序。习惯了Emacs的高效,使用Visual studio
就是一个杯具1。这种情况,一般一颗红心,两手准备。一颗红心:cosplay,两手准备:1.Visual studio 扮Emacs
2Emacs扮Visual studio 。VC扮EMACS非官方扩展式visEMACS
官方的Emacs扩展2
不过,我对这种方式的经验总结:享受不到Emacs的周到体贴,却净受VS的大小姐脾气了。不给力啊,不给力。不过,作为出差旅行,远程登陆,客户服务时,没有Emacs可用时,让Visual
studio 模拟一把Emacs,也不失为一种没有办法的好办法了。这个方法不是本文的重点,所以不深入。EMACS扮VC配置EMACS为IDE
一个基本的IDE,必备功能:编辑,编译,调试。编辑应该很多人都很眼红Visual studio的销魂的插件visual assist
x吧。实时语法检查,快速打开文件,h,cpp文件,回到刚才编辑的地方,函数跳转,自动补全,插入模板。可以号称操作系统的Emacs怎么可能没有这些功能呢?尽管这些不在本文范围,但是稍稍提及功能在Emacs中的对应,有兴趣想深入的请Google,
Duckduckgo, Wikipedia.VXA功能 EMACS对应功能
实时语法检查 Flymake 3
快速打开文件 ECB, 快速打开文件
h,cpp跳转 CEDET 4
回到刚才编辑的地方 Recent-jump5
函数跳转 CEDET 4
自动补全 Auto-complete 6
插入模板 Yasnippet 7
快速打开文件
至于快速打开文件一项,我感觉ECB做的并不是特别好,如果C++程序的头文件和实现文件没有在一个文件夹,很难找到。所以我用了一个比较笨的方法,生成文件的列表到一个文件,使用Emacs的查找功能和打开当前光标下文件的功能
find-file-at-point,我把它编定到了C-c
C-f。这个过程还有两个副产物供cscope和etags用。确认你的机器上有cscope, find,
etags8,将以下代码成为uptags.bat,放到系统的pathz中的某个文件夹下。
%1
cd %2
rm TAGS
rm cscope.files
rm filelist.txt
rm cscope.in.out
rm cscope.out
rm cscope.po.out
if "%3" EQU "java" set PARAM=-name "*.java" -print
if "%3" EQU "c++" set PARAM=-name "*.cpp" -print -o -name "*.r" -print
-o -name "*.[hcrHs]" -print -o -name "*.hpp" -print -o -name "*.lua"
-print
echo %PARAM%
find . %PARAM% > cscope.files
less cscope.files | xargs etags -aR
cscope -bkq -i cscope.files
cp cscope.files filelist.txt
find . -name "*.txt" -print >> filelist.txt
假设我们的C++工程在d:mydocumentsworkspacecpp,那么调用方法9为:uptags d: d:mydocumentsworkspacecpp c++
java工程在d:mydocumentsworkspacejava, 那么调用方法为:uptags d: d:mydocumentsworkspacejava java
那么打开文件helloworld.cpp的操作就是:C-x b filelist.txt , C-s helloworld.cpp, C-c
C-f, RET。确实,稍显复杂,期待有更好的方法。编译编译的话基本上还是要靠Visual studio 自带的工具:nmake10,msdev。本文主要介绍msdev。使用msdev.exe
msdev.exe位于安装路径下的bin目录,如我本机使用Visual studio 6.0,目录为"C:Program
FilesMicrosoft Visual StudioVC98bin"。 直接调用msdev.exe,即启动Visual
studio的UI界面,同时msdev.exe也接受命令行调用。我们看其帮助。
msdev /?
Usage:
MSDEV [myprj.dsp|mywksp.dsw] - load project/workspace
[<filename>] - load source file
/? - display usage information
/EX <macroname> - execute a VBScript macro
/OUT <filename> - redirect command line output to a file
/USEENV - ignore tools.options.directories settings
/MAKE [<target>] [...] - build specified target(s)
[<project> - <platform> <configname>]
[[<project>|ALL] - [DEBUG|RELEASE|ALL]]
/CLEAN - delete intermediate files but don't build
/REBUILD - clean and build
/NORECURSE - don't build dependent projects
假设我们有这么一个工程,路径为d:Mydocumentsworkbench,工程目录结构,Configuration如下图
可以通过命令msdev.exe来编译工程test211。
C:Program FilesMicrosoft Visual StudioVC98binmsdev.exe test2.dsw
/Make "test2 - Win32 Debug" /NORECURSE
同样,使用clean,rebuild可以清除、重编译该工程。将test2 改为test21,test23,即改变编译对象。
总这样写也很麻烦,而且为了在Emacs中调用 ,我们将其写成一个批处理。d:
cd d:Mydocumentsworkbench
set project=%1
set target=%2
if "%1" == "" set project=test2
if "%2" == "no" set target=/NORECURSE
msdev test2.dsw /Make "%project% - Win32 Debug" %target%
保存为makTest2.bat。调用方式为:makeTest2 [工程 [目标]]
默认为编译test2 的 /NORECURSE。如果要编译test23的rebuild,调用方式为:makeTest2 test23 /REBUILD
调试实际上,如果有了编辑,编译,那么调试就不需要了。因为调试器是一切罪恶他妈12。哈哈,当然是开玩笑的了。作为一个有思想的程序员,要认清楚,编译器,调试器都只是恶魔,程序员本身,也就是我们,才是恶魔他妈(当然大部分是他爹^_^ )。哈哈,那么作为恶魔的产生者,我们当然要丰富自己的技能,而调试就是一个必杀技。我杀,bug闪……..cdb-gud
要用Emacs调试Visual studio 的程序,首先需要一个el – cdb-gud.el
。cdb-gud使用Microsoft的命令行调试器cdb来调试程序。
cdb-gud.el只需下载,然后在.emacs中使用下面语句,cdb-gud就随时待命了。
;;+cdb [[http://msdn.microsoft.com/en-us/vstudio/default.aspx][Visual studio ]]
(when (eq system-type 'windows-nt)
(load-file "~/.emacs.d/lisp/cdb-gud.el")
)
调用cdb-gud: M-x cdb RET。Microsoft命令行调试器cdb.exe
如果你是一个Windows程序员,Windbg听说过吗?如果没有听说过,我建议你去看看《软件调试》,这本书讲的非常的透彻。
注意,这是一本厚度为1000页的砖头书。如果你没有耐心去读这么厚的书,那么还有一个选择,《Windows用户态程序高效排错》,
内容236页,内容写的不多,但是书内提供的资源。
两本书排名不分先后。那么cdb就在Windbg的安装目录下。Windbg是Windows下的能用户态调试核心态调试的强大的图形界面的调试器。那么,简而言之,尽管不太准确13,cdb就是非图形界面的调试用户态程序的windbg。
简要介绍一下cdb:cdb就是一个命令行的调试器,over。深入探讨一学cdb: 我想很深入的探讨一下cdb,但是实在是没有如此深厚的内功,但是我可以推荐一些内容供有兴趣的去深入。WINDBG安装目录内的debugger.chm
windbg info
MSDN的帮助
强烈推荐将windbg info 打印出来在手边供不时查阅之需。现在,来启动cdb-gud吧:M-x cdb RETShowtime14!例子
建立一个Visual studio 的console典型的Hello world工程(比如刚才的test2),源代码如下15:
#include "stdafx.h"
#include <string.h>
void assign (int a[], int n)
{
for (int i = 0; i < n; ++i)
{
if (a[i] == 0)
{
a[i] = i;
}
}
}int main(int argc, char* argv[])
{ int a[100];
assign(a, 100);
for (int i = 0; i < 100; ++i)
{
printf("%dt", a[i]);
} return 0;
}
通过上边程序,我们期待打出所有0-99的数,每个数是间隔一个制表符,每十个数打出一个换行。我们编译运行代码,得到结果:-858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460
有点奇怪,为什么没有得到我们需要的东西呢??从代码中貌似看不到直接的证据证明我们的代码逻辑的错误。我们就祭出cdb。M-x cdb RETminibuffer: cdb d:Mydocumentsworkbenchtest2debugtest2.exe 会有以下界面提示。Microsoft (R) Windows Debugger Version 6.11.0001.404 X86
Copyright (c) Microsoft Corporation. All rights reserved.CommandLine: d:/Mydocuments/workbench/tmp/VCTest/test2/test/Debug/test.exe
Symbol search path is:
C:symbolsXpSp3;d:/Mydocuments/workbench/via/helios/coyote/Bin/MULTIMEDIA_PRO_240x320_Debug
Executable search path is:
*** WARNING: Unable to verify checksum for test.exe
ModLoad: 00400000 0042c000 test.exe
ModLoad: 7c900000 7c9b2000 ntdll.dll
ModLoad: 7c800000 7c8f6000 C:WINDOWSsystem32kernel32.dll
(a90.1eb8): Break instruction exception - code 80000003 (first chance)
eax=00241eb4 ebx=7ffd9000 ecx=00000000 edx=00000001 esi=00241f48 edi=00241eb4
eip=7c90120e esp=0012fb20 ebp=0012fc94 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
ntdll!DbgBreakPoint:
7c90120e cc int 3
0:000> cdb: Reading initial command 'l+*;l-s'
Source options are ffffffff:
1/t - Step/trace by source line
2/l - List source line at prompt
4/s - List source code at prompt
8/o - Only show source code at prompt
Source options are fffffffb:
1/t - Step/trace by source line
2/l - List source line at prompt
8/o - Only show source code at prompt
0:000>
0:000> bp main
bp 表示打断点,断点的方式有几种:函数名,文件行数,内存地址。但是我最喜欢的还是:当调试过程已经在运行,*在Emacs中打开文件,走到需要打断点的行,C-x space*,断点就打到该行,很给力啊。0:000> g
Breakpoint 0 hit
test!main:
0040d880 55 push ebp
0:000> p
test!main+0x1e:
0040d89e 6a64 push 64h
0:000> t
test!ILT+15(?assignYAXQAHHZ):
00401014 e907c80000 jmp test!assign (0040d820)
0:000> p
test!assign:
0040d820 55 push ebp
0:000> p
test!assign+0x18:
0040d838 c745fc00000000 mov dword ptr [ebp-4],0 ss:0023:0012fd8c=cccccccc
g==go,所以表示开始运行程序。p 单步跟踪,不进入子函数。t 单步跟踪,但是进入子函数。不出意外,当你使用p或者t跟踪程序的时候,源代码窗口已经打开,同时随着跟踪,相应的代码行也会高亮。0:000> dv
a = 0x0012fdf0
n = 100
i = -858993460
0:000> p
test!assign+0x32:
0040d852 8b55fc mov edx,dword ptr [ebp-4] ss:0023:0012fd8c=00000000
0:000> dv
a = 0x0012fdf0
n = 100
i = 0
0:000> dt a[0]
Local var @ 0x12fd98 Type a[ 100]
[0] 0x0012fdf0
-> -858993460
0:000> dt a[1]
Local var @ 0x12fd98 Type a[0]
[1] 0x0012fdf0
-> -858993460
0:000> dt a[i]
Local var @ 0x12fd98 Type a[1]
[0] 0x0012fdf0
-> -858993460
dv:显示当前的局部变量。dt: 显示指定的变量。当前发现为什么a数组的值怎么是负数,不是期待的0呢?0:000> k
ChildEBP RetAddr
0012fd90 0040d8ac test!assign+0x32
[D:MydocumentsworkbenchtmpVCTesttest2testtest.cpp @ 10]
0012ff80 00401209 test!main+0x2c
[D:MydocumentsworkbenchtmpVCTesttest2testtest.cpp @ 21]
0012ffc0 7c817077 test!mainCRTStartup+0xe9 [crt0.c @ 206]
WARNING: Stack unwind information not available. Following frames may be wrong.
0012fff0 00000000 kernel32!RegisterWaitForInputIdle+0x49
0:000> .frame 1
01 0012ff80 00401209 test!main+0x2c
[D:MydocumentsworkbenchtmpVCTesttest2testtest.cpp @ 21]
0:000> dv
argc = 1
i = -858993460
Type information missing error for a
0:000>
k:打印出当前的栈内容.frame:跳转到栈中的第几帧,当前为第0帧。在.frame 1后,我们注意到以下代码:int a[100];
assign(a, 100);
貌似a[ 100]没有初始化吧。0:000> q
然后修改代码后#include "stdafx.h"
#include <string.h>
void assign (int a[], int n)
{
for (int i = 0; i < n; ++i)
{
if (a[i] == 0)
{
a[i] = i;
}
}
}int main(int argc, char* argv[])
{ int a[100]={0};
assign(a, 100);
for (int i = 0; i < 100; ++i)
{
if (0 == (i % 10))
{
printf("n");
}
printf("%dt", a[i]);
} return 0;
}
编译运行,结果:testdebugtest.exe0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
50 51 52 53 54 55 56 57 58 59
60 61 62 63 64 65 66 67 68 69
70 71 72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87 88 89
90 91 92 93 94 95 96 97 98 99
那么cdb简单使用就介绍完了。然而,其实很多cdb的强大功能都没有介绍到:可以调试程序崩溃时留下的内存转储文件dump,调出其堆栈休息。
可以附挂到一个正在运行的程序。
远程调试
显示,执行代码
处理断点(支持复杂的条件断点)
读写内存地址
反汇编
多线程调试
Windows符号文件
对于一般的console程序,可能这样就够了。但是在调试广大的Windows程序时,哪能不接触Windows的API啊,调试这些个玩意儿,才是让人头痛的东西呢,没有源代码!!cdb的一个机制可以让你没有源代码的情况下看到很多Windows的公开数据结构。
首先,先查看自己的系统的版本,在我的电脑->右键->属性,我可以看到我的系统是Microsoft Windos XP
Professional Service Pace 3, 那么我就来这里下载Windows的相应的符号文件。将其安装到本机,比如:C:symbolsXpSp3。添加环境变量:_NT_ALT_SYMBOL_PATH,设其值为安装目录。经此设置,cdb在调试时就可以看到Windows API的符号文件。更多内容,还请参考帮助文档或者我推荐的两本书。Footnotes:
1 @木鱼指出 6.0中的Epsilon即为emacs模式。 可查到资料中最早的是2005, 来源猛击我。 但是有可能更早,如果有资料,麻烦请留言告之.2 此处没有贬低Visual studio 的意思,只是我中Emacs的毒已太深,用其它什么都不爽:)3 下载链接Visual studio Emacs emulation addon4 flymake配置见http://marcelotoledo.com/2007/07/11/emacs-flymake/5 CEDET配置见http://emacser.com/c-cedet.htm6 recent-jump 配置见http://liuminzhao.com/emacs/recent-jump-el-for-emacs/7 auto-complete 配置见http://emacser.com/auto-complete.htm8 yasnippet主页http://code.google.com/p/yasnippet/9 cygwin, mingw, msys, unixutils10 好吧,我承认这个调用方法很蛋疼,如果你的工程比较少的话,其实可以将路径,程序类型什么的写到文件里,多整几个文件即可。upCppProject1Tags.bat,
upCppProject2Tags.bat,upJavaPro1Tags.bat,upJavaPro2Tags.bat。11 此文 介绍了如何使用nmake,但是恕我直言,我在Visual studio 的安装目录里没有找到nmake。12 如果不成功,请注意检查大小写和空格。13 调试器,恶魔之母 http://stackoverflow.com/questions/602138/is-a-debugger-the-mother-of-all-evil14 其实,用户态的windbg是图形界面的cdb。15 谨以此名纪念我经历的一个软件项目:Showtime 0.7。16 请注意,这是实验代码,所以请忽略魔幻数,程序是否有意义等话题。15 请注意,这是实验代码,所以请忽略魔幻数,程序是否有意义等话题。

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

方舟子继续遭受网络暴民袭击 zz http://www.tianya.cn/publicforum/content/no01/1/422937.shtml
方舟子先生躲过锤击之后,近日继续遭受网络暴民的围剿。谁是暴民呢?我在这里不是指某个"坏人",最坏的人可能也有偶尔和善的时候。我是说,你的某种情绪可能促使你在某个时候做出了一件非常错误的事。我下面要把暴民分成几种,我相信是他们内心的某种倾向性使他们失去了公正,我要对他们内心的倾向性予以猜测,并做适当的分类。符合这些猜测的网友,请您反思一下,你是否不自觉地受到了这些倾向性的影响,而在最近对方舟子先生做出了一些不那么理性也并非基于事实的指责。思想在某些方面具有某种倾向性,这不是过错,相反,那很可能是自然的。但批评性言论本身有个公正性的问题。如果你批评某个人,这个人在某些方面具有与你不同的倾向性,你可以通过事先表明自己的这种倾向性来显得文质彬彬,这可能有助于你避免做出不公正的判断。我们中国人有句话,叫做"攻其恶,无攻人之恶",意思是说:因为这样做是错的,所以我才反对,而不是因为这是我所不喜欢的某个人做的,所以我才反对。这是我们的祖先为我们指出的君子之道。当然,无论你的内心有何种倾向,言论就是言论,只要你的指责基于事实,你的推理可以被接受,你的评判准则被大家所认可,那么,你的批评性意见肯定会被很多人尊重。相反,如果您对于什么是事实并不是很清楚,您对此也并不感兴趣,但您仍然要出言诋毁方舟子这个人,我认为,您需要看一看自己是否受到了内心如下一些倾向性的影响。我认为,无须承担责任的、受到群体行为暗示的、情绪化的、缺乏事实依据的、不公正的指责,是一种错误的行为,这些行为看起来像一群暴民所为。本文所针对的读者,完全排除那些为了经济利益而愿意发表任何言论的人,当然也不包括任何通过造假谋取利益的人。适合与他们谈论是非善恶的,应该是他们的妈妈,而不是其他人。以下是我归纳的思想倾向:倾向一:神创论者、设计论者,他们反对人类自己创造新的生命形式。这些人以前的说法是,世界是在七天之内被一个人格神所创造的,信这个神,可以得到拯救,不信这个神的异教徒,都会在末日审判中被区别对待。现在,这些人显得比较科学,毕竟科学太强大,他们现在只说这个世界是被创造或者被设计的,而做这件事的主体则被省略。最有趣的,他们说他们的理论应该与进化论一样,在(公立)学校中教授。虽然他们已经不怎么公开谈论创世的主体,但是,他们仍然认为,只有这个主体,才有创造生命的资格,任何改变基因、控制胚胎发育的行为,都是人类对这个创世主体的权力的僭越,这是由人类自己在创造新的生命形式,因此是不可接受的。他们显然是对未知的世界比较悲观、比较恐惧的一部分人。因为方舟子先生被某些人塑造成了转基因食品的著名支持者,因此,这些神创论者或者设计论者,或者秉承某种原教旨主义的教徒,也就把他当成了著名的敌人。当然,方舟子先生可能确实也不喜欢某种西方的一神教。对于有此种思想倾向的网友,我认为您先亮出自己的宗教信仰,然后再参与讨论,更容易避免不公。至于说对于转基因食品的立法,这是一个政治问题,我希望大家能够和平地予以讨论。我个人认为,按照是否支持对转基因食品施加某种法律限制,包括必须在包装上予以标注,这并不足于区分好人和坏人,大家不必因此而敌对。我们完全可以心平气和地讨论转基因食品的意义及其风险。即使你认为这挑战了你的教义,你可能仍然需要尊重他人的观点。我个人还没有看到转基因食品可能对人类构成伤害的证据,这可能需要长期的实验。因此,我认为,在是否立法对转基因食品予以必要限制这个议题上,只能反映大家对未来的感受,这不大可能是一种理性的选择,这只能反应一个人更悲观或者更乐观的性格特点,这种观点上的差别不是一个严重的问题。至于有人说方舟子先生是转基因食品生产商的顾问,因此,他的结论可能是带有倾向性的,说这种话的人,您需要给出证据。
倾向二:相信某种超自然力量或者玄秘理论,但无法容忍别人说这"不科学"或"不够科学"的人。汉语经常对"科学"一词有些古怪的用法,这些古怪用法的一个严重结果是,"科学"一词经常让人联想到"正确",而"不科学"则意味着"错误"、"落后",甚至"迷信"。某些愿意相信某种超自然力量或者玄秘理论的人,他们当然不愿意被人说成是"错误"、"落后"或者"迷信"的。因此,如果他们觉得方舟子先生是保卫"科学"、声讨"不科学"的一位"斗士",那么,方舟子先生也就成了他们的一个重要敌人。其实,从较为狭义的角度说,科学只是一些得到知识、组织知识的系统性方法,这种方法最显著的特点是基于数学推理或者可控制、可重复的实验。一种理论被称为科学的,通常是这种理论的陈述符合科学家共同体对于什么是"科学方法"的认识,而一种理论被认为不那么"科学",这通常意味着这种理论的陈述很难满足科学家共同体对于"科学方法"的认识。举个例子,你可能觉得,"某人一发功,就治好了眼前这个人的病",这是很科学的。但科学家可能并不这么认为,他们需要知道,经过怎样一个可操作的、可重复的程序,就能以一定的概率治好某个病人,如果他们没法从"一发功"这个特殊现象研究出某种可操作、可重复、可检验的程序,他们就会认为自己一无所获,他们就没法承认"一发功就能治病"是个"科学"的理论。当然,这并不意味着他们打算否定什么,科学家们不知道的事情,肯定比他们知道的事情来得多。我相信,无论您相信什么样的超自然力量或者玄秘理论,只要您不坚持要科学家共同体承认您的理论是"科学"的,您就不大可能与他们发生冲突。当然,据说也有人用魔术冒充"神功",这是另一回事,这可能涉及到法律问题,比如诈骗。如果这并不是魔术表演,而是一种牟利行为,甚至可能伤害他人的健康,这种行为值得戳穿。
倾向三:民科,但不希望别人指出这一点。其实我也是民科。很多民科不知道的是,"教科书"与"学术界"是两码事,如果你念过大学本科,你肯定对教科书里的内容不陌生,但那通常不是"研究",而只是"结论"。打个比方,你可能读到过一本叫做《历史》的书,但《历史》不是"历史学",一个"历史学"的学者,他要发表"学术"著作,不能只写下几条结论、给出几个故事,他必须而且主要需要阐明的,是他所得到的结论的意义,以及得到这些结论的过程是否"科学"。因此,如果你只读过一本叫做《历史》的书,你很可能不知道什么是"历史学",你仿照这本书写下的东西,是不大可能被历史学家们所接受的。类似地,你读过几本叫做《数学》的书,也不意味着你了解什么是数学研究,因此,你对于哥德巴赫猜想的见解,数学家们可能只想把它扔进垃圾篓。事实上,学者们确实生活于一个似乎隐秘的世界里,没有一本教科书能真正让你了解什么是"研究",你只能在很多年的时间里,通过阅读其他研究者的论文来逐渐"摸索"什么是"研究的方法",更重要的,尝试找到合适的研究问题,普通大众并不知道这个世界到底是什么样子,就如同很多人没有去过饭店的厨房,他们能看到的,只是厨师做好的菜。我本人并不觉得方舟子先生以取笑民科为乐,虽然这样的人可能很多,当然,也许有些人不这样认为,他们觉得自己的自尊心受到了伤害。我觉得,民科们完全可以自得其乐,没必要去烦扰学术界。一个更自由、更有责任感的学术界,也应该关注与其他社会成员的交流,让他们尽可能多地了解学者们正在做什么。他们正在做什么?:-)
倾向四:自惭形秽的文科生,他们内心里认为"人文"并不是如同自然科学一样的"科学",没有那样显赫的地位,因此,谁在那大声谈论"科学",谁就是伤害了他们的感情。可能普通大众不知道,写小说,不是"科学","研究"别人写的小说,才是"科学"。莎士比亚和曹雪芹都不是科学家,"研究"莎士比亚和曹雪芹的人才是各大学文学系的"科学家",而他们得到研究成果的过程,必须是满足科学家共同体对于"科学方法"的认识。因此,一个人成为某个大学文学系的教授,领到一份工资,这是因为他在"研究"和教学,至于他自己写小说,那完全是他的私人生活,与这份工资无关。类似地,哲学系的教授不是发明哲学的,而是研究别人发明的哲学的,历史系的教授不是记录今天历史的,而是研究他人在历史上留下的蛛丝马迹的。因此,"人文"确实不是科学,"研究人文"才是科学。创造"人文"是不可能在大学里领到工资的,研究并教授"人文"才能在大学里领到工资。文科生们应该再反思一下科学的概念。
倾向四:宣扬伪科学的科学共同体成员,他们曾经与方舟子一边的科学共同体成员直接论战。有一些人,已经是科学共同体的成员,但可能有一些特殊的经历,比如曾经被训练来教授某种十九世纪的哲学,但他们必须得把这种哲学说成是科学之母。现在他们只能是哲学系的教师,但是,在习惯上,他们并不研究"别人"发明的哲学,而是向他人灌输某种哲学,这就是当初训练他们的人所要达到的目的。现在,他们当中的某些人,很想把"科学"里塞进一些他们自己喜欢的东西。他们相当有文化,因此,可以写出一些似是而非的东西,试图动摇传统上"科学"的概念。他们是文化人,可能还自诩为哲学家,因此,我想,他们大概既不会参与铁锤事件,也不会为此叫好。但他们可能有一定的影响力。比如,他们给方舟子这边的人按上了一个"科学主义"的帽子,据说持有这种观点的人认为科学能够解释一切以及解决一切,而且只能由科学来解释和解决。但是,就像人们所嘲笑的,除了他们自己(他们当中的某些人说自己曾经是"科学主义"者),尚未在世界上发现持有如此愚蠢观点的人。
倾向五:认为方舟子打假不够专业的专业人士。对于这些人,我不想多说,谁说方舟子不够专业,你专业?你专业你来打!总不至于说学术界没有假可打吧?其实,方舟子在学术界能打的假,都是一些最不入流的,比如,明显抄袭论文的,招摇撞骗过分生猛的,等等。这根本不是今天学术界的主要问题,这是一台机器都能判断的不端行为。至于那些需要高度专业知识和崇高职业道德才能做出的判断,你根本听不到,没本事的都在琢磨着怎么应付论文数量的要求,有本事的都在琢磨着怎么申请经费、花掉经费,最有本事的自己立项、自己拿。而在这些人背后,是一些终于认识到提高知识分子待遇的好处的人,利出于一孔之后,上下同钱同德:-)
倾向六:认为方舟子代表了要消灭中医的力量。我不知道方舟子先生是否真的这样认为。但是,"中医"与"西医"这种并列方式,肯定遮蔽了问题的实质。问题是,什么是"现代"的、可以接受的医学?我们是否需要立法规定任何人要取得行医执照,都必须满足同样的、"现代"的训练标准?而诊断和治疗的过程,是否也要满足某种必需的标准?无论你怎样看待中医,你不可能禁止别人提出这样的问题,哪怕你觉得他们仅仅是出于一种文化上的自卑感,因此要竭力消灭"祖国的传统文化"。理论上说,医学是实践性很强的学科,西医并不足以否定中医,但是,如果要所有学生接受相同强度的西医训练,而学习中医的学生还要额外接受中医训练,这可能在事实上导致没有人去学中医了。当然这只是猜测。没准事实相反,中西医两个学位会让你更受欢迎,既接受过相同强度的现代西医训练,又懂得"祖国传统文化",你可能看起病来更有"文化底蕴"?:-)
没准中医院因此很火?:-) 结果,"祖国的传统文化"被你更好地发扬光大了。
倾向七:其他认为科学或者严谨的理性是他的绊脚石的人。
至此,以上七种倾向分析完毕。我认为,每一种倾向都不应该导致铁锤或者为铁锤叫好,指责他人应该基于事实,而且保持公正。现在我们讨论一下什么是一个好的社会?首先,我相信,你会承认,普遍的诚实对于我们这个社会的意义。一个互相撒谎的社会不可能是一个好的社会,在这样的社会里,好人没有机会,只有那些最寡廉鲜耻的人才能如鱼得水。你不可能认为,普遍的欺诈能导致一个好的社会。因此,你肯定会认为,保卫诚实、反对欺诈对于我们的社会意义重大。其次,科学是人类有史以来最伟大的发明之一,它在今天直接给我们带来利益。科学的存在和发展依赖于科学家,而自由和诚实是科学家之所以能够成为科学家的前提。一群被包养的不诚实的精英对于科学的发展是零价值的,他们创造不了任何东西,他们甚至学不会别人的东西。如果一个国家的科学界已经堕落到只会点数经费,那么,哪怕是一点批评性的意见,即使这种意见只能针对那些最不入流的造假者,这也是非常珍贵的。这是为在这个国家中保卫人类最有价值的精神财产而战。有些不了解科学界的人士可能觉得自己也被归为造假者的行列,我认为,如果你没有伤害任何人,你不必感到可耻,当然,如果你指望"科学"这个概念能够变得像你希望的那样,你也可能会遭到批评。最后,法律对于我们来说很重要,如果没有法律,你可能一天也活不过去。我们必须明白,雇凶杀人或者伤人,这是一个非常严重的法律问题。这种行为,不会仅仅伤害一个你所不喜欢的人,也会伤害你赖以生存的法律,就如同伤害你周围的空气。如果抽走我们身边的空气,不是只有方舟子会窒息而死,我们也无法生存。你作为这个社会的一员,你有义务在必要的时候重申法律对于我们的意义,而不是相反,对于极其恶劣的谋杀行为幸灾乐祸,如果你这样做了,你只是在伤害你自己,那不是任何其他人的耻辱,那只是你自己的耻辱。你内心怎样看待方舟子,这不重要。我也很多年没有去过方舟子的网站了,我的浏览器总是告诉我他的网站无法连接,可能受到防火墙的阻挡,要我与网络管理员联系。我一般没有与网络管理员联系的勇气。更重要的问题是,你怎样看待上面的几个问题?我们需要保卫诚实吗?我们需要爱护和保卫科学吗?我们需要保卫法律吗?如果你的回答是:是!那很好,我相信,你与你观点不同的人会因此达成很多共识。因此,我建议,在最近一段时间,讨论与方舟子有关的问题时,大家都来表明自己的观点,告诉大家,你知道诚实很珍贵,你认为科学应该被爱护、被保卫,你认为法律必须得到尊重。我相信,有了这些表达,很多分歧容易解决。方舟子没有做到的,你可以去做到,他没有做好的,你可以做得更好。你也可以做一名"打假斗士":-)
而且更货真价实。但你肯定不是希望这个世界一片黑暗,方舟子作为一个"打假斗士"的符号,很可能是这个黑暗世界上的最后一盏灯,或许你不这样认为,或许你认为你不需要光明,但是,如果你想熄灭他,我还是希望你能慎重考虑,你真的能把你的理由在下面写清楚吗?实际上,你可以选择,你可以说:"这个世界是我们的"。你也可以觉得自己就是一个过客,一个每天被人操纵的人,因此你愤世嫉俗,有一种要做暴民的冲动,拿出你指尖的小铁锤,用言词砸烂任何听起来比你更勇敢的故事,好让自己相信,你自己平凡而怯懦的人生,已经是这个黑暗世界里最光荣、最勇敢的人生了。但你其实什么也没有改变!写给我的暴民同胞们:-)2010-09-27

谜语答案

谜语答案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) 不是调用构造函数初始化当前对象,而是分配了一个临时对象然后立刻销毁。感谢某用功同学提供代码示例。

猜谜活动

猜谜活动。人生艰难,听来个谜语给大家讲讲,娱乐一下。话说某同学整了以下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 heapn"; 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 heapn"; p->output(); cout<<"pop_top "<<p->pop_top()<<endl;}

通往奴役之路 笔记

通往奴役之路 笔记2010-09-15 21:53:26补录以前的,估计是2年前的pp.73 法治最能清楚地将一个自由国家的状态和一个在专制政府统治下的国家的状况区分开的,莫过于前者遵循着被称为法治的这一伟大原则。撇开所有技术细节不论,法治的意思就是指政府在一切行动中都受到事前规定并宣布的规则的约束--这种规则使得一个人有可能十分肯定地预见到当局在某一情况中会怎样使用它的强制权力,和根据对此的了解计划它自己的个人事务。虽然因为文法者以及那些受委托执行法律的人都是不可能不犯错误的凡人,从而这个理想也永远不可能达到尽美善尽美的地步,但是法治的基本点是清楚的:即留给执掌强制权力的执行机构的行动自由,应当减少到最低限度。虽则每一条法律,通过变动人们可能用以追求其目的的手段而在一定程度上限制了个人自由,但是在法治之下,却防止了政府采取特别的行动来破坏个人的努力。在已知的竞赛规则之内,个人可以自由地追求他人私人的目的和愿望,肯定不会有人有意识地利用政府权力来阻挠他的行动。pp.77 道德第二个方面,即道行的或政治方面的论证,与我们现在所要讨论的问题有更直接的关系。如果政府要精确地预见到其行动的影响,那就意味着它可以不让受影响的人有任何选择的任地。凡是当政府能够精确地预见其各种可能的行动对某种人的影响时,也恰恰是政府能够对各种目标进行选择。如果我们要创造新的对一切人都开放的机会,要给人们提供他们能随意加以利用的机会牟话,那么其精确的结果就是难以预见的。因此,普遍性的规则,有别于具体命令的真正法律,必须意在适用于不能预见其详情的情况,因而它对某一特定目标,某一特定个人的影响事前是无法知道的。只是在这种意义上,立法者才可能说得上是不偏不倚的。所谓不偏不倚的意思,就是指对一定的问题没有答案--如果我们一定要解决这类问题的话,就只能靠抛掷硬硬币来决定。在一个每一件事都能精确预见到的社会中,政府很难做一件事而仍然保持不偏不倚。只要政府政策对某种人的精确的影响是已知的,只要政府的直接目的是要达到那些特定影响,它就不能不了解这些影响,因而也就不能做到不偏不倚。它必定有所偏袒,把它的评价强加于人民,并且,不是帮助他们实现自己的目标,而是为他们选择目标。只要当制定法律的时候就已预见到这些特定影响,那提出,法律就不再仅仅是一个供人民使用的工具,反而成为立法者为了他的目的而影响人民的工具。政府不再是一个旨在帮助个人充分发展其个性的实用的机构,而成为一个"道德的"机构--这里的"道德的"一词不是作为"不道德的"反义词来使用的,而是指这样一种机构,它把它对一切道德问题的观点都强加于其成员,而不管这种观点是道德的或非常不道德的。在这种意义上,纳粹或其它任何集体主义的国家都是"道德的",而自由主义国家则不是。pp.85 法治限制政府行为

沉默容易 不说谎很不容易 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)◇◇

笔记 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* cdrpp.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)* consWhat 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)* consWhat is (cons s l)
where a is ((a b c))
and
l is bNo answer,
since the second argument l must be a list.* null listWhat is (null? (quote ()))* eqIs (eq? l1 l2) true or false
where l1 is ()
and
l2 is (strawberry)No answer, () and (strawberry) are lists.* eqIs (eq? n1 n2) true or false
where n1 is 6
and
n2 is 7No answer,
6 and 7 are numbers.* eqIs (eq? (cdr l) a) true or false
where
l is (soured milk)
and
a is milkNo answer,
See The laws of Eq? and Cdr.
Young says, (cdr l) is (milk), which is not an atom.* latTrue or false: (lat? l)
where l is ()True,
because it does not contain a list.* recursionInsertR(cons old (cons new (cdr lat)))* recursionpp. 62
在定义multinnsertL中,
需要在递归中改变条件。* recursionpp.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 carpp. 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-expressionWhat is an S-expression?An S-expression is either an atom or a (possibly empty) list of S-expressions.* lamda
pp.129Now 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 applypp.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?-saladNo, 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.* closurespp. 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]是个更完整的版本。* valuepp.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))* interpreterpp. 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** carThe primitive car is defined only for non-empty lists.
Young says: the result is a atom.** cdrThe primitive cdr is defined only for non-empty lists.
The cdr of any non-empty list is always another list.** consThe 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 CommandmentWhen 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 CommandmentUse cons to build lists.** The Third CommandmentWhen building a list, describe the first typical element,
and then cons it cons onto the natural recursion.
** The Fourthe CommandmentAlways 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 CommandmentWhen 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 CommandmentSimplify only after the function is correct.** The Seventh CommandmentRecur on the subparts that are of the same nature:
- On the sublists of a list.
- On the subexpressions of an arithmetic expression.** The Eight CommandmentUse help functions to abstract from representations.** The Ninth CommandmentAbstract common patterns with a new function.** The Tenth CommandmentBuild 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) )2So 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]