Search

4/25/2010

Crockford on JavaScript: A Public Lecture Series at Yahoo! - Volume One: The Early Years

Crockford on JavaScript: A Public Lecture Series at Yahoo! - Volume One: The Early Years

Weaving the Threads
- The people who should be the first to recognize the value of an innovation are often the last.
- Obsolete technologies fade away slowly.
- Sometimes forward, sometimes backward.
- The Myth of Inevitability.

Carriage Return & Linefeed (crlf)
the carriage return character would take the printed element and push over to the left
the linefeed character would roll the paper one line

http://en.wikipedia.org/wiki/Douglas_Engelbart
http://www.youtube.com/watch?v=JfIgzSoTMOs

An End to Innovation
We have a small set of CPU architecture
- Intel (computers)
- PowerPC (games)
- ARM (mobile)

ALOGOL 60
The best design-by-committee in the history of programming languages.

Atari 2600 VCS
- 6502 CPU
- There is no software or firmware in the console.
- A cartridge can hold 4K or 8K
- Console has 128 bytes of RAM. That has to hold all the game's dynamic states, including the subroutine stack.

ALGOL -> Simula (first object-oriented language, classes & objects) -> Smalltalk (for kids)

Object Oriented Programming
- 1967 Simula
- 1972 Kay begins Smalltalk
- 1980 Smalltalk released
- 1995 C++ Programming Language
- 1995 The Java Programming Language

Leaps
- Plugboards
- Symbolic Assembly Language
- High Level Languages
- Structured Programming
- Object Oriented Programming

Smalltalk -> Self (took the smalltalk idea, and took the classes out, one object inherited from other object.)

The Actor Model (from smalltalk)
What is "send a message" meant "send a message".
- desktop app all build around event loop, look very much like message queue, so application is an actor
- web server is an actor

LISP (AI language developed in MIT, 1958)
-> Scheme
The Actor Model

LISP
- tail recursion in order to allow you to keep calling things that never expect to return without running out of memory
- lexical closure if function is nested inside another function they get access of everything that outer function has, if the outer function has already returned.

The Actor Model -> Joule
-> E (The Object Capability Model)
Java

Caja is based on the work of E.

HyperCard types
- Stack: contains background and cards
- Background: an images and buttons and fields
- Card: a background and buttons and fields
- Button: text and/or image
- Field: text

on mouseUp
put "100, 100" into pos
repeat with x = 1 to th number of card buttons
set the location of card button x to pos
add 15 to item 1 of pos
end repeat
end mouseUp

HyprtCard
- Stacks of cards containing images, buttons, and text fields.
- Didn't anticipate color.
- Didn't anticipate text links.
- Didn't anticipate networking.
- A decade alter ,cards would become disappear

Java ->
Scheme -> JavaScript
Self ->
(you just can't do scheme, too weired-looking, people don't like it, make it more look like java)
took syntax form java, take the function model of scheme (doug: best idea of history of programming language), took prototypal object from Self

4/24/2010

histroy.length

History length Property

The length property returns the number of URLs in the history list.
Note: Internet Explorer and Opera start at 0, while Firefox, Chrome, and Safari start at 1

Use the history.length property to count the items in the history list. Unfortunately, this nugget of information is not particularly helpful in scripting navigation relative to the current location because your script cannot extract anything from the place in the history queue where the current document is located. If the current document is at the top of the list (the most recently loaded), you can calculate relative to that location. But users can use the Go/View menu to jump around the history as they like. The position of a listing in the history does not change by virtue of navigating back to that document. A history.length of 1, however, indicates that the current document is the first one the user loaded since starting the browser software.

4/23/2010

lisp

The Little JavaScripter
kuangjc5566 - 你是如何成為Lisp程序員的?

問題之:你是如何成為Lisp程序員的?

答:我成為Lisp程序員的道路曲折而漫長。我曾於2007年10月3日在自己的日記中總結了自己的學習經歷,現抄錄於此。

最早在2000年5月,斯托曼院士訪華時告訴我,Lisp (或者它的現代變種Scheme)是功能最強大的編程語言,他本人就是一位高級的Lisp程序員,他還精通C ,GNU Emacs就是採用C和Lisp兩者開發的。我當時已經掌握了C,但不會用Lisp,但是我完全相信他說的都是真的。於是,一心想成為編程高手的我,決定學習和掌握這門編程語言。我從2000年下半年開始學習Lisp。下面總結的學習經歷大致按照時間先後順序排出:

有必要先說明一點,在我遇到斯托曼院士之前,我在上大學時曾經閱讀過一本關於人工智能的著作,《Artificial Intelligence --- Making machines "think"》,
作者是Neill Graham,這本書的最後一章(第14章)是關於Lisp語言的簡介,
所以我對人工智能和Lisp的概念並不完全陌生。這本書前面的章節都很好理解,但是在這最後一章,我遇到了很大困難。我花了許多時間試圖明白其中的道理,不過最後成效不彰,現在回想起來,究其緣故,最主要的就是我沒有一個適當的上機練習環境,在讀了許多書中的東西後,當時我感覺似乎明白了其道理,但是實際上並沒有真正理解清楚。不過,有兩點在我看來無疑是確定的:一、Lisp早已經成為人工智能研究項目的首選(或者說是默認的)編程工具,在人工智能領域沒有其他語言能撼動其領導地位。二、對於具有表結構的數據操作,對於列表(list)頭元素(pair的car的部分)的處理採用遞歸方式比較好,而對於眾多的體元素(pair的cdr的部分)則採用迭代的方式處理效率更好。

斯托曼院士回國後,我首先在計算機上嘗試用Emacs Lisp編程,
它是嵌入在GNU Emacs文本編輯器中的解釋器。在龐大的Lisp家譜中,
Emacs Lisp不是Common Lisp,而是早期的MacLisp的一個直系後代,
同時在一些方面作了簡化和強化。同時我開始閱讀Robert Chassell所著《Introduction to Emacs Lisp Programming》,Robert Chassell是斯托曼院士早年結識的戰友,也是自由軟件基金會的合創人之一,他很早就使用GNU Emacs,而且使用Emacs Lisp程序定制GNU Emacs,斯托曼友善地把Robert Chassell介紹給我認識。這本書既是自由文檔(可以從GNU的網站自由下載),又是自由軟件基金會出版社(GNU Press)的出版物。等我讀完了這本書之後,我覺得這本書實在太美妙了,作者的文筆十分了不起(即使對於想學習英文寫作的人,幫助也應該很大),把這本書介紹給其他人是完全值得的。我於是找了兩位翻譯人員(毛文濤博士和呂芳女士),把它譯成了中文,我則擔任了全書的編輯和審校工作。中文版質量很高,我很滿意,它作為一本很偉大的編程入門書籍十分適合廣大讀者自學(我認為讀者應該搞到一本閱讀)。我至今還想自己動手翻譯這本書的第三版,可惜如今我很難再找到當年那麼多的時間做編輯和審校之類的工作了。

閱讀完這本書之後,我意識到如果想使用Emacs Lisp開發非玩具級別的實際應用程序,那麼根據作者的推薦,自由軟件基金會出版的《GNU Emacs Lisp Reference Manual》是必不可少的工具書,我打印了這份文檔的第2.4版本,厚厚的共四本。後來這份文檔正式出版,從GNU網站上訂購的圖書升級到了2.6版本,針對的是GNU Emacs version 21。我不太認同Eric Raymond在他的名著《The Art of Unix Programming》中對Emacs Lisp的評論,他以為Emacs Lisp只能為Emacs編輯器本身編寫控製程序,而趕不上其他腳本語言全面。實際上,我認為只要熟悉了Emacs Lisp的細節,其他任何腳本語言能完成的工作,都可以使用Emacs Lisp程序完成。我親眼看見斯托曼院士在GNU Emacs內完成電子郵件的編輯、收發等工作,不用Eric Raymond開發的fetchmail程序一樣幹得很好。我自己也利用Emacs Lisp編寫過CGI應用程序,效果也不錯。

Bob Glickstein曾經寫過一本《Writing GNU Emacs Extensions》,可以配合Robert Chassell的書與《GNU Emacs Lisp Reference Manual》,作為補充讀物。

讀了Robert Chassell的書之後,我開始花時間閱讀David Touretzky博士所著的《Common Lisp: A Gentle Introduction to Symbolic Computation》,這本書可以從互聯網上自由下載,讀者可以自行在萬維網上google得到它。這也是一本偉大的Lisp著作,內容已經是基於 Common Lisp的,但是作者並沒有特意強調這一點。我把下載的PDF文件打印出來,自己動手把打印出的文檔紙張裝訂成了兩卷手冊。我從這本書中得到的最大收穫是我充分認識到Lisp中的一切都是對象:數字原子(numeric atoms)和符號原子(symbolic atoms)都是對象。數字原子求值返回它自身的值,而符號原子則有名稱(name)、類型(type)、值(value)、秉性表(plist)和綁定表(bindlist)。這五個字段可以放入一個數據結構中,並在實現中以C語言的struct表達。

在閱讀這些材料的同時,我又從網上找到了Gary Knott教授編寫的一份文檔,《Interpreting Lisp》,這份文檔篇幅不長,從來沒有正式出版成書。在這份文檔中,作者利用C語言編寫了一個微小的Lisp實現,非常接近於最初的Lisp實現。最可貴的是他將實現的源代碼和盤托出。從這本書中,我清晰地看到瞭如何構造Lisp對象的結構,我開始認識到內存垃圾收集算法的重要性。在理解了David Touretzky博士所著的《Common Lisp: A Gentle Introduction to Symbolic Computation》介紹的Lisp對象的結構基礎上,我明白了書中圖示的Lisp對像中若僅在結構設計時安排五個字段是不夠的,還需要有供垃圾回收(GC,Garbage CCollector)模塊操作的字段才行。

在2001-2002期間,我開始接觸Scheme。在此之前的2000年8月,Rorbert Chassell曾來中國訪問,我們在西安時,他向我介紹了Scheme是我應該關注的語言。 Scheme於1985年誕生於MIT,發明人有兩位:一位是Gerald Sussman教授,他是自由軟件基金會的董事會成員之一,另一位是Guy J.Steele博士,下面即將更多地提到。我首先使用了Dorai Sitaram所著的教材《Teaching Yourself Scheme in Fixnum Days》,這份文檔可以從網絡自由下載,不過坦率地說,這本書教材不太適合初學者,閱讀它的人至少應該具有很多基礎知識或者經驗才行。我並沒有從這本書從獲得太多的幫助,對Scheme的基本概念也沒有搞清楚,特別是連續(Continuation)之類的概念沒有理解。不過,收穫還是有很多,我意識到 Scheme是一個非常優美的Lisp變種,它繼承了源自Algol60和早期Lisp兩者的特點。這份教材的最後還列舉出了一個具體的編程實例,講授如何利用Scheme編寫CGI程序。現在我看來,在CGI編程等領域, Perl和PHP等腳本語言獲得廣泛應用簡直就是鑽了Lisp社團不善營銷的空子。

到了2001夏天,我從美國獲得了《Structure and Interpretation of Computer Programs》的教師手冊,是我的朋友James Gray幫我買的,他是我一個很好的朋友,不過我這裡要善意地埋怨一下,他做事有些馬大哈,我原來希望他給我搞到這本書的學生用書,沒有想到他卻寄來了教師手冊,我想他在買書時沒有仔細區分一下,而此著作的教師手冊和學生用書的封面都採用了同一圖案,作者和MIT出版社的編輯的確很優秀,他們在營銷本書時非常成功,後來專門還開設了一個網站推廣本書和相關的教學材料,網上公佈了教材的全部內容,加上兩位作者課堂教學的視頻錄像。教師手冊價格比較便宜,James在購買時要么沒有仔細辨認清楚,要么就是幫我省錢,才寄來了這本教師手冊。我當時沒有學生手冊,也就沒有繼續學習Scheme。不過話說回來,James寄給我的教師手冊我一直都留在我手頭,後來對於我在黑客道教學中講授Scheme幫助極大,在這裡還是應該深深地感謝James Gray。

不久(2003年),我買了一本Patrick Winston教授所著的《Common Lisp》第三版,作者是麻省理工學院人工智能實驗室的主任(斯托曼早年就是他手下的兵),在美國的人工智能研究領域名氣很大,我就是衝著他的名氣才買此書的。閱讀完之後,我覺得這位教授名副其實,而不像我在國內見到的一些人徒有虛名,拿不出真東西。這是一本介紹Common Lisp的極好教材。後來Hans Hagen (ConTeXt排版軟件包的主要作者之一)告訴我這本書的合著者Berthold Klaus Paul Horn在TeX社團名氣也很大,的確如此,從本書的排版質量即可看出許多名堂來,排版樣式一看就是典型的TeX風格。作為中文TeX用戶俱樂部(CTUG)的主席,我已經知道,國內學術界(我指的是數學界和計算機科學技術界)很少有人精通TeX排版系統,鮮有人能使用它排版自己的講義或著作。

讀了這本書之後,我感覺自己必須閱讀Common Lisp的語言參考手冊,許多問題必須在看到語言規範(這是基本的尺度)之後才能搞清楚。 Guy L. Steele博士寫過這樣的手冊,而且他寫了兩次,第一個版本是在Common Lisp標準化之前完成的,第二個版本是在標準化完成之後寫成的,但是網上有人評論說有些該寫的東西沒有寫進去,此書是否會有第三版不得而知。 Guy L. Steele博士是非常著名的語言手冊的作者,他已經為C、Common Lisp、Java等編程語言都寫過的語言參考手冊,都非常成功,這些參考手冊都是一版再版,銷路極好,比位於瑞士的國家標準化組織(ISO)發布的非常昂貴的標准文檔銷路好許多。他寫的這些語言參考手冊已經成為編寫這些語言編譯器作者們的大救星。

大約在同時,我下載了《On Lisp》,這是Paul Graham博士編寫的一本優秀著作,從中我得到了許多Lisp概念的細節,特別是Lisp的macro機制,
以及黑客們如何利用Lisp思考問題。作者介紹的自底向上(bottom up)的方法論對我觸動很大,而作者的講解是非常富於啟發性的(作者曾專程赴意大利的美術學院學習過油畫創作,所以具有很高的藝術修養)。從那時開始,混合編程(Hybrid Programming)的思想在我頭腦中開始成型,我堅信Lisp將會成為一種非常長壽的編程語言,這使我聯想起斯托曼院士當年在四川九寨溝就GNU Emacs開發對我講過的話。在GNU Emacs和Lisp背後隱含的方法論是永遠不會過時的。

2004年,我真正找到了Lisp編程的感覺,覺得自己開始進入狀態,
並開始使用Scheme開發真正的應用程序,我編寫的程序是一個網絡應用程序,即一個網絡留言板(Web-based bulletin System),在萬維網上可以運行,
CGI的模塊是採用Scheme寫的,Apache在服務器上通過Scheme的CGI程序接上了PostgreSQL數據庫。我使用的是PLT Scheme的103版本,我非常喜歡這個版本,既簡單又很乾淨,我用C語言和PostgreSQL提供的libpg編寫了一個DA (database adaptor),讓Scheme程序可以訪問PostgreSQL數據庫。

完成了這個項目之後,好事成雙,我得到了渴望已久的《Structure and Interpretation of Computer Programs》(簡稱SICP,或者“紫皮書”),作者就是Harold Abelson教授和Gerald Sussman教授。正是這一年,我開始利用自己頭腦中形成的數學觀點,特別是在我的泛系尺度論中表達的思想,來認真學習Scheme,並且主動地從中國古代的陰陽太極圖模型來理解當今電子計算機系統上的計算模型。這一過程延續了很長時間,直到2005年的冬天才最終獲得成功!這期間的許多思想寫入了我的著作《自由軟件:新的遊戲規則》第三卷內篇的第二章“論尺度”。今後我還準備花更多的時間把它擴展開來,形成一部單行本的著作《泛系尺度論》,在這個單行本中,我將利用更長的篇幅把中國古代的哲理思想、現代數學思想和計算機編程融為一體,對整個計算理論提出自己完整的一家之言。在黑客道九個段位中,初段就是講“計算的本質”,裡面就納入了我的思想方法和編程經驗。

2004-2005年期間,我仔細地研究了R5RS文檔中除了第七章之外的所有內容,
收穫巨大。對於第七章的內容,當時仍然有些疑惑,因為這些材料需要理解大量的關於lambda calculi的細節和大量的預備知識,我當時還沒有找到充分的材料鑽研。另外,在研究PLT Scheme的源代碼時,內存垃圾回收算法對我而言,仍然是一大疑難問題,顯然,對於內存垃圾回收技術,我還需要學習更多的背景材料。

到了2005年的年底,我把R5RS翻譯成了中文。在完成翻譯的過程中,我知道瞭如何利用形式語言和擴展的巴科斯-勞爾範式(EBNF)來定義一門編程語言的形式句法和語義規則,以及如何正確理解和讀懂它。

2005-2006期間,我學習了其他許多關於Lisp編程的書籍,包括Paul Graham博士的《ANSI Common Lisp》、 Matthew Flatt等人合著的《How to Design
Programs》, Brian Harvey和Matthew Wright合著的《Simply Scheme ---
Introducing Computer Science》(此書的封面設計別出心裁,非常值得回味)、
Daniel Friedmann和Matthias Felleisen合著的《The Little Schemer》和
《The Seasoned Schemer》。另外我花了相當多的時間仔細閱讀《The Scheme Programming Language, 3e》,這是R. Dybvig教授的代表作,他是Chez Scheme實現的設計大師。年底我得到了《Hackers and Painters》(“黑客和畫家”),這是Paul Graham博士所著的散文集,與Robert Chassell一樣,他也是一位偉大的作家,他的行文非常容易閱讀,而且這本書中的內容如同其書名副標題一樣,的確收入了許多偉大的想法,這些想法對於創新公司利用Lisp開發創新項目是非常富有啟發性的。

2006年7月15日,我的學生千俊哲從南韓的漢城大學帶來了他學習的兩本著作的複印件:George Springer和Daniel P. Friedman合著的《Scheme and the Art of Programming》,以及Mark Watson的《Programming in Scheme: Learn Scheme through Artificial Intelligence Programs》。前一本的難度在紫皮書之下,比較好讀,其中許多程序如同棋譜一樣,展現了許多高級編程技巧,值得反复思考,我立即在PLT Scheme實現上驗證了書中的大部分代碼;後一本則介紹如何使用MIT Scheme來設計人工智能程序,非常精彩。

2006年7月送走了千俊哲之後的夏天,我一直在瑞士蘇黎世度假(八月下旬我還去了西班牙馬德里參加了國際數學家大會),蘇黎世中央圖書館(ZB,Zentralbibliothek Zuerich)是一所了不起的圖書館,現有藏書一百二十萬種。據說列寧當年在歐洲流亡時曾來到蘇黎世,就睡在這個圖書館裡讀書學習。八月份時,大多數瑞士人也在休假,圖書館的人不多,非常安靜。我在這段時間從圖書館中找到了非常多的背景材料,包括HP Barendregt所著的數學經典教材《The Lambda Calculus --- Its Syntax and Semantics》,這本書於1981年由North Holland出版社出版,對這一數學分支作了詳盡的介紹,我認為對於這一主題,今後再也無人可以寫得比這本著作更好了。另外,我找到了第一本關於 lambda calculus的著作,是由這個理論的創始人Alonzo Church教授創作的,《The Calculi of Lambda-conversion》簡直是無價之寶,在這本小冊子中,作為數學家,作者清晰而精煉地闡明了lambda calculi的全部內容。任何一位想掌握lambda calculus的人都應該仔細閱讀本書。在圖書館中還找到了《An Introduction to Lmabda Calculi for Computer Scientists》,作者是Chris Hankin。 Matthias Felleisen和Matthew Flatt合寫的《Programming Language and Lambda Calculi》也打印出來了,並仔細閱讀了兩遍,這兩人是PLT Scheme研發小組的核心成員。在蘇黎世中央圖書館的書架上,我還看到了SCIP紫皮書的第一版的德文本,書中的內容與英文版第二版大同小異,但是我敏銳地發現,第一版的第四章中沒有收入eval和apply兩個高階算子構成的太極推手圖,第二版中則出現了。

我花時間研究了《Lisp 1.5 Programmer's Manual》,這是世界上第一份真正意義上正式發布過的Lisp穩定實現版本的手冊,作者就是John McCarthy等人,極具學術權威性,我認為任何一位Lisp程序員都應該閱讀這本手冊。時隔多年後,我又開始閱讀關於人工智能方面的著作,《Lisp, Lore and Logic》是W. Richard Stark寫的,《Artificial Intelligence, theory and practice》是Thomas Dean等人寫的,他們都已經使用Common Lisp來說明問題。閱讀時,我參考了前面已經提到的Partrick Winston教授編寫的經典教材《Artificial Intelligence, 3e》。

2007年初,我開始關注Scheme社團中尚處於起草狀態中的R6RS,這個文件將成為新的Scheme語言規範。我現在仍然認為Common Lisp太複雜、太龐大,回廠大修似乎也不太可能,因為工業界已經很好地接受了Common Lisp,而Scheme將是未來的主流。我開始按照這一規範來開發自己的Scheme實現版本,這一實現版本稱為MNM Scheme。

2007年6月至7月間,我在瑞士蘇黎世的Campus Zollikerberg打印了R5.97RS,
我花了許多時間理解這一新的規範,特別是它與前一個版本(R5RS)的差異。
同時,我重新思考了PLT Scheme實現的源代碼和涉及模塊(modules)、名稱空間(namespaces)、盒子(box)類型、define-values和其他附加在R5RS規範之上的特性與實現風格。

從蘇黎世中央圖書館借到的另外一本具有重大價值的著作就是Richard Jones和Rafael Lins合著的《Garbage Collection》,這本書極大地幫助我理解了內存垃圾回收算法設計的細節。我從此開始真正明白了Scheme實現工作中的最後一個陰暗角落。對於一切Lisp對象,內存垃圾收集的算法設計時其實不存在理論上的最優算法,算法的效率受到多種因素的影響,而Lisp的設計者可以根據自己的設計思想來決定應該怎樣回收內存垃圾。

這時的我已經成長為熟練的C++程序員,站在C++程序員的立場看,一切Lisp對像都有類型,我可以用C++語言內置的類(class)來刻畫它們(即聲明各種用戶自定義的類),一切Lisp對像從存儲空間分配和回收的角度來看具有共性,所以,這可以利用C++的模板來表達Lisp對象的存儲管理結構,而各個Lisp對象佔有的存儲空間大小,則可以利用類的構造函數(constructor)和析構函數(destructor)對內存分配和內存垃圾回收在模板的支持下進行統一的操作。

源自Lisp發展起來的GC是一項“古老”的技術,實際上它已經廣泛地被採用了,Java這門當今新的商業編程語言中就有,而且Java的GC算法設計得非常好,我決定在我的Scheme實現中參考它。 2007年9月,我在從香港飛往蘇黎世的飛機上,我閱讀了美國著名的程序員Bruce Eckel所著的《Thinking in Java》的第四版原著,從作者的介紹中,我結合從《 Garbage Collection》中獲得的知識,我理解了Java的內存垃圾回收算法的總體思路,並構思瞭如何利用他們的算法來改進我的設計。而在我離開蘇黎世回國的同一天(2007年9月26日),R6RS技術委員會的全體編輯成員決定凍結對草案的討論,正式發布了這一規範,從那一天起,我實現MNM Scheme的步伐也大大加快了。(不過,請讀者留意在委員會舉辦的投票時,也有許多人投了反對票,並給出了反對意見,這些意見與支持的意見一起,都是極有研究價值的。)

Scheme的實現版本非常多,而且自己能否動手實現一個是考驗一個計算機專業人士學術修養深淺的好指標(這也是我在黑客道中把第五段的教學內容定為“解釋器的原理與構造”的原因之一)。迄今優秀的Scheme實現有: PLT Scheme、MIT Scheme、Chez Scheme等等。我認為PLT Scheme是非常優秀的實現版本,它是按照GPL發布的自由軟件,值得在這裡推薦給廣大讀者。毫不客氣地講,我的MNM Scheme也應該算一個。

Common Lisp的實現版本很多,拋開Franz Lisp等商業版本不談,自由軟件社團中最有名的兩個實現分別是:Bruno Haible等人從1992年以來一直維護和開發的CLISP,以及卡耐基梅隆大學的小組開發CMU Common Lisp。這兩個Common Lisp實現都很好,我個人比較喜歡使用CLISP。目前最好的Common Lisp編程著作可推薦Peter Seibel寫的《Practical Common Lisp》,這位作者的天分顯然比我高,他原來是Java和Perl程序員,2004年才開始學習Common Lisp,他花了一年的時間學習它,就完全學會了,而且在學習的同時,邊練習、邊寫書,結果很豐碩,寫出的這本書就是讀者能看到的結果,這本書得到了廣泛的認可,它出版後獲得了美國出版界計算機圖書創作的震撼大獎。他在一次採訪中提出了一個新的說法:時代的發展需要“第二代Lisp程序員”,而且每個程序員都應該學習Lisp。 (讓我再次回憶起斯托曼院士在2000年時對我說過的話。)

正如讀者在上面所讀到的,成為一位了解Lisp一切內幕的程序員可真不容易,但是我很高興,因為我已經成功地逾越過了這個初看起來曾經非常高的門檻,我現在已經是這樣一位程序員了。學習Lisp給我帶來了巨大的樂趣,如果沒有這種在編程中產生的樂趣相伴,我絕對不會花這麼長的時間來學習它。今天,我由衷地自豪,因為如果按照Peter Seibel的說法和衡量標準,我已經是第二代優秀的Lisp程序員群體中的一分子。

上面羅列的學習經歷對於一般人而言顯然太長了,黑客道學員們則可以站在我的肩膀上,借鑒我的經驗和教訓,少走許多彎路、避免走死胡同。值得慶幸的是,我已經在黑客道的課程設計中自覺地做了許多工作,凡是參加了黑客道的初段課程學習的學員(S1:“計算的本質”),即可在較短的時間內學會掌握 Lisp。

4/22/2010

Fillano's Learning Notes | 用Google App Engine跑php

Fillano's Learning Notes | 用Google App Engine跑php


* Run PHP on the Google App Engine(額外的jar可以從他這裡下載)
* Quercus on the Google App Engine(他提供了php存取datastore的範例)
* Using the Datastore with JDO(Google的官方教學,上述的guestbook範例是從這裡來的)

上了resin的官網仔細看了一下,resin-4.0.0裡面可以找到resin.jar,這裡面就有GoogleQuercusServlet(如同 blog上說的)。另外測試了一下,建議使用resin.jar而不是quercus.jar + resin-util.jar + script-10.jar + jetty-util-6.1.0.jar這個solution。這樣使用foreach也不會出現錯誤訊息。

Fillano's Learning Notes | 實驗-用Google App Engine跑CodeIgniter
Quercus有一個很方便的地方,就是可以自己寫QuercusModule,QuercusModule的公有方法就會成為php函數。使用自訂的函數,配合Google App Engine的datastore服務,就有可能把datastore當作檔案系統來使用。

HM2K.com » Getting started with Quercus in Google App Engine
If you get this error:

java.lang.IllegalStateException: Found a jar file too large to upload: “…\WEB-INF\lib\resin.jar”. Consider using –enable_jar_splitting.

Using the suggested option fixed this, which looks like this:

C:\appengine-java-sdk\bin\appcfg.cmd --enable_jar_splitting update war

4/17/2010

Visual Guide to NoSQL Systems

Visual Guide to NoSQL Systems



As you can see, there are three primary concerns you must balance when choosing a data management system: consistency, availability, and partition tolerance.
* Consistency means that each client always has the same view of the data.
* Availability means that all clients can always read and write.
* Partition tolerance means that the system works well across physical network partitions.

One of the primary goals of NoSQL systems is to bolster horizontal scalability. To scale horizontally, you need strong network partition tolerance which requires giving up either consistency or availability. NoSQL systems typically accomplish this by relaxing relational abilities and/or loosening transactional semantics.

In addition to CAP configurations, another significant way data management systems vary is by the data model they use: relational, key-value, column-oriented, or document-oriented
* Relational systems are the databases we've been using for a while now. RDBMSs and systems that support ACIDity and joins are considered relational.
* Key-value systems basically support get, put, and delete operations based on a primary key.
* Column-oriented systems still use tables but have no joins (joins must be handled within your application). Obviously, they store data by column as opposed to traditional row-oriented databases. This makes aggregations much easier.
* Document-oriented systems store structured "documents" such as JSON or XML but have no joins (joins must be handled within your application). It's very easy to map data from object-oriented software to these systems.
Now for the particulars of each CAP configuration and the systems that use each configuration:

Consistent, Available (CA) Systems have trouble with partitions and typically deal with it with replication. Examples of CA systems include:

* Traditional RDBMSs like Postgres, MySQL, etc (relational)
* Vertica (column-oriented)
* Aster Data (relational)
* Greenplum (relational)

Consistent, Partition-Tolerant (CP) Systems have trouble with availability while keeping data consistent across partitioned nodes. Examples of CP systems include:

* BigTable (column-oriented/tabular)
* Hypertable (column-oriented/tabular)
* HBase (column-oriented/tabular)
* MongoDB (document-oriented)
* Terrastore (document-oriented)
* Redis (key-value)
* Scalaris (key-value)
* MemcacheDB (key-value)
* Berkeley DB (key-value)

Available, Partition-Tolerant (AP) Systems achieve "eventual consistency" through replication and verification. Examples of AP systems include:

* Dynamo (key-value)
* Voldemort (key-value)
* Tokyo Cabinet (key-value)
* KAI (key-value)
* Cassandra (column-oriented/tabular)
* CouchDB (document-oriented)
* SimpleDB (document-oriented)
* Riak (document-oriented)

4/15/2010

L‧Seven 城氏空間 - [食記] 高麗亭 韓式料理(台北永和)

L‧Seven 城氏空間 - [食記] 高麗亭 韓式料理(台北永和) (大嘴巴懷秋 媽媽指導的店)

地址 台北縣永和市信義路5巷4號
電話 02-89236366

yui connect


// If the specified HTTP method is GET, setForm() will return an
// encoded string that is concatenated to the uri to
// create a querystring.
if(method.toUpperCase() == 'GET'){
if(this._sFormData.length !== 0){
// If the URI already contains a querystring, append an ampersand
// and then concatenate _sFormData to the URI.
uri += ((uri.indexOf('?') == -1)?'?':'&') + this._sFormData;
}
}
else if(method.toUpperCase() == 'POST'){
// If POST data exist in addition to the HTML form data,
// it will be concatenated to the form data.
postData = postData?this._sFormData + "&" + postData:this._sFormData;
}

vim tips

http://www.study-area.org/tips/vim/Vim-6.html#open

多檔編輯會有兩種情形,一種是在進入 vim 前所用的參數就是多個檔(這種情形稱為 argument list)。另一種情形是進入 vim 後另外再開其它的檔(稱為 buffer list)。不過都可以統稱為 buffer。

:n 編輯下一個檔案。
:2n 編輯下二個檔案。
:N 編輯前一個檔案。

* 注意,這種用法只能用於 argument list 的情形。

:e 檔名 這是在進入 vim 後,在不離開 vim 的情形下再開其它檔
案。只要您要編輯的檔案是在目前目錄,Tab 補全鍵還是
可以使用。
:e# 或 Ctrl-^ 編輯前一個檔案,用於兩檔互相編輯時相當好用。

* 這種用法不管是 argument list 或 buffer list 檔案間皆可使用。
* 還記得嗎? # 代表的是前一次編輯的檔案。

Windows in VIM

4/13/2010

button style for ie


overflow-x:visible /* cancel extra padding in x , if do overflow-x will cause button height exceed constraint */
overflow:hidden /* constraint height of button in ie6 */
position:relative; top: 2px /* shift text down a little bit if contains Chinese character in the button */

Download details: IE App Compat VHD

Download details: IE App Compat VHD
Microsoft Virtual PC: Virtual PC 2007
The Administrator and IETest passwords are Password1 .


* IE6-on-XP-SP3.exe contains a Windows XP SP3 with IE6 VHD file. Expires July 1, 2010
* IE7-on-XP-SP3.exe contains a Windows XP SP3 with IE7 VHD file. Expires July 1, 2010
* IE8-on-XP-SP3.exe contains a Windows XP SP3 with IE8 VHD file. Expires July 1, 2010
* IE7-VIS1.exe+IE7-VIS2.rar+IE7-VIS3.rar contain a Vista Image with IE7 VHD file. Expires 120 days after first run.
* IE8-VIS1.exe+IE8-VIS2.rar+IE8-VIS3.rar+IE8-VIS4.rar contain a Vista Image with IE8 VHD file. Expires 120 days after first run.

4/12/2010

JavaScript: The Good Parts

JavaScript: The Good Parts


Bad Parts
* Global Variable
* + adds and concatenates
* Semicolon insertion - when compiler gets an error, it backs up, looks around for a line feed, turns it into a semicolon, and then tries again.
* typeof
* with and eval
* phony arrays - In JavaScript, arrays are essentially hash tables, in which the keys are turned into strings and then hashed to locate the buckets. This has a terrible performance penalty. But it has an advantage in that it makes the programming model quite a bit easier. 'cause you don't ever have to dimension an array. Dimensions don't exist in this language.
* == and !=
* false, null, undefined, NaN

for in is troublesome
* Design question: Should for..in do a shallow skim or a deep dredge?
* Decision: deep dredge. The programmer must explicitly filter out the deep members.
* Except: They didn't tell anybody!
* Consequence: Lots of confusion about how to use for..in

Good Parts
* Lambda
* Dynamic Objects - you can take any object and at any time, you can add a new property to it or remove a property from it. You don't have to go to some class and make another derived class in order to have an object.
* Loose Typing
* Object Literals

Prototypal Inheritance
* Class-free
* Objects inherit from objects
* An object contains a link to another object: Delegation. Differential Inheritance.

var newObject = Object.create(oldObject);

newObject
__proto__ => oldObject

Each object contains only what makes it different from the object it inherits from, and that allows for objects to be much smaller. For a long time, the language was ambivalent about its prototypal nature, so never included an operator for actually making new objects which inherit from other objects. We're correcting that oversight in the next edition of the language with object.create, which will make a new object which inherits from an old one.


if (typeof object.create !== 'function') {
object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
}
}


Global

var names = ['zero', 'one', 'two', 'three'];
var digit_name = function (n) {
return names[n];
}
alert(digit_name(3));


Slow

var digit_name = function (n) {
var name = 'zero', 'one', 'two', 'three'];
return names[n];
};
alert(digit_name(3));

The problem with this is that every time this function gets called, we're going to reinitialize the names array. Now in theory, an optimizing compiler could detect this case and factor that out. But today, nobody does that.

Closure

var digit_name = function () {
var name = 'zero', 'one', 'two', 'three'];
return function (n) {
return names[n];
}
}();
alert(digit_name(3));


So here I've got a function which is going to return another function and the outer function gets executed immediately. The inner function has access to the properties of the outer function or to the variables of the outer function. It will continue to enjoy access to them even after the outer function has returned. So when it returns, the function goes into digit_name and that function will have names bound to the original array and will continue to have it for as long as it lives.


Power Constructor
1. Make an object - Object literal, Object.create, call another power constructor

function myPowerConstructor(x) {
var that = otherMaker(x);
}

2. Define some variables and functions - These become private members.

function myPowerConstructor(x) {
var that = otherMaker(x);
var secret = f(x);
}


3. Augment the object with privileged methods.

function myPowerConstructor(x) {
var that = otherMaker(x);
var secret = f(x);
that.priv = function () {
... secret x that ....
};
}


4. Return the object

function myPowerConstructor(x) {
var that = otherMaker(x);
var secret = f(x);
that.priv = function () {
... secret x that ....
};
return that;
}


Closure
* A function object contains
- A function (name, parameters, body)
- A reference to the environment in which it was created (context).

Style Isn't Subjective

return
{
ok: false
};

SILENT ERROR

It turns out that curly brace can mean "start an object literal", or it could mean a block. Now it turns out, in this language, we don't have block scope. So having an empty block is not useful.
Okay, so "ok" doesn't look like a statement. Well, actually it does. It looks like a statement label. Well, "false" doesn't look like any kind of statement. But remember, we have those useless expression statements that we inherited from C. So we'll evaluate "false" and go, "Yep, that's false", and ignore it.

return {
ok: true
}

Woks well in JavaScript

Why does JSON require quotes around the property names?
1. To align it with Python. In Python, the quotes are required.
2. it makes the grammar of the standards much easier to specify and I like simplicity.
3. JavaScript has a stupid reserved word policy. There are certain words that you cannot use in the key position of an object literal.

吃錯了,當然會生病!都是慢性食物過敏惹的禍!

吃錯了,當然會生病!都是慢性食物過敏惹的禍!

在免疫學的學理上,過敏可分為四類,但這裡我們只介紹其中兩類,即第一類的立即性過敏反應與第三類的延遲性過敏反應。以食物過敏為例,立即性食物過敏就是有些東西一吃下去,很快或馬上就會出現全身發癢等立即性的反應,例如有些人吃到海鮮、花生、芒果會全身發癢等等。它的過敏反應,是靠免疫球蛋白 E (IgE) 這種抗體在負責,一般醫院診所檢測過敏都是檢查 IgE,其實這種檢測遠不如慢性食物過敏檢測的IgG來得重要,因為幾乎所有有急性過敏症的人,都清楚會引起自己的過敏是什麼,而會主動避開。

 至於第三類的延遲性食物過敏的情況又是如何?譬如我們常吃的麵條、天天喝的牛奶,吃了、喝了,會產生疲倦、頭痛、鼻塞、咳痰等等問題,但症狀常會在幾個小時甚至兩三天後才發作,發作時你也很難聯想到是幾天前吃麵條或牛奶所引起的,所以你就繼續吃這些東西,症狀也持續著,慢慢地,症狀就變得不明顯,你也就更不會知道身體不舒服的原因在哪裡。

為什麼過敏症狀會變得不明顯?因為長期吃這些過敏食物,身體為了要適應這些食物 , 免疫系統內的「壓抑型 T 細胞」會冒出來,把慢性食物過敏反應壓抑住,使它症狀不明顯。因此,過敏患者就這樣渾渾噩噩,長期生活在健康時好時壞的狀況當中,很多人終其一生都不知道自己有慢性食物過敏 , 更不清楚自己的慢性食物過敏原到底是什麼。

什麼是「低敏飲食」呢?首先必須避開的食物包含︰所有的乳製品、小麥、玉米、蛋、柳橙,以及會干擾神經系統的咖啡跟糖。還有就是以前常吃的東西,現在先停吃一段時間。另外,培養讀標籤的習慣,徹底了解每種食物的內容成分。可以吃的食物有五穀雜糧 (小米、燕麥、蕎麥、薏仁)、豆類(黃豆、豌豆、豆腐、黑豆、敏豆、白腎豆……),以及小麥以外的麵粉類。而蔬菜類幾乎都可以吃。蛋白質的部分,新鮮魚類、家禽類、羊肉與堅果類還不錯。油脂的話則沒什麼限制,但記得只能吃所謂的「好油」。

  牛奶、小麥製品皆隱藏在許多食物裡面,吃東西的時候要特別注意。例如含有小麥製品的食物有啤酒、麵包、餅乾、喜瑞爾、水餃、包子、蛋餅等等。雞蛋製品也包羅萬象︰麵包、蛋糕、泡芙、蛋塔、可可亞、美乃滋、冰淇淋、酒類、感冒疫苗、緩瀉劑等等。

  不少人對蛋過敏,基本上,人類對於任何東西都可能過敏,而且越常吃的東西,就越容易過敏,這是我們身體裡面 IgG免疫球蛋白的特性。尤其當身體處在一個不健康的狀態,又常吃這個東西,你的免疫系統容易混亂,更容易對這個東西產生過敏。

4/09/2010

Randy Time Management UVa 2007

http://www.cs.virginia.edu/~robins/Randy_Time_Management_UVa_2007_slides.html

Important Advice
* Kill your television – 28 hours/week
* Turn money into time – especially important for people with kids
* Eat and sleep and exercise. Above all else!
General Advice
* Never break a promise, but re-negotiate them if need be.
* If you haven’t got time to do it right, you don’t have time to do it wrong.
* Recognize that most things are pass/fail.
* Feedback loops: ask in confidence.

Rex's blah blah blah » Time Management by Randy Pausch
* 將時間視為金錢一般的數字,管理它。我其實心中藏有一個小小地費率表,告訴自己作這件事情的時薪是多少,整件事情價值多少錢。
* 電話的使用方式,盡可能使談話簡短,宣告議題,站著講電話都是很有效的方法。
* 所有做的事情都有「機會成本」,你不為重要的事情「找」時間,必須透過放棄不重要的事情「製造」時間。
* 把握創造力與最佳思考時間,把剩下的時間拿去安排會議、電話跟處理其他瑣事。
* 降低造成你切入 flow (zone mode) 的干擾次數、時間。不要隨時檢查電子郵件信箱,電子郵件的目的是讓你可以晚點處理,有空做更重要的事情。
* 養成紀錄時間使用日誌 (Time Journal Data)的習慣。除了四五年前開始利用筆記本與試算表紀錄日誌外,我已經改用 Hamster 追蹤每分每秒的工作項目,因此可以追蹤分析每日、每週、每月的工作狀態。已經養成每月檢視工作目標與分析工時分配的習慣。我甚至開始有點偏執的裝 Sleep cycle alarm clock 來分析睡眠狀態,你知道,睡眠其實是我不在電腦前最長得活動之一,了解睡眠週期與品質當然也很重要。我甚至有點偏執希望有一套設備可以偵查我的腦波、血糖、血壓,這樣我就可以科學的分析自己在自己在何種生理狀態時,會產生最佳的思考效率與生產力。但我朋友鄙視的說我已經快變成 Borg 了。:-/
* 避免延宕行為。延宕 – 壓力或罪惡或緊急下所造成的生產力損失或失信行為,肇因緊張、非現實時間感或不確定目標。延宕時常造成更昂貴的代價。
o Procrastination is the thief of time by Edward Young, Night Thoughts, 1742
o Work expands so as to fill the time available for its completion, Parkinson’s Law, Cyril Parkinson, 1957
* 正確把工作委任給他人,而不是把工作傾倒 (dumping) 給他人。設定「目標」、「死線」、「後果」並施予其「尊重」、「責任」、「權力」與「挑戰」。
* 會議不要超過一小時、關掉電話、鎖住門。寫下會議紀錄,重點是工作項目、負責人與死線。
* 「碰」每封信、每張紙、每筆資訊一次!不要把他們積在桌上或收件夾。
* 殺掉電視。(我已經這樣做許久)
* 不要破壞陳諾,如果有必要,重新協商新的日期。(這點還要努力)
* 演講中的推薦書 《與成功有約》 (The Seven Habits of Highly Effective People), 《一分鐘經理人》(The One Minute Manager).

4/02/2010

御三家備長炭串料理

御三家備長炭串料理

地址:台中市西區精誠六街25號
電話:04 – 2329-2892
營業時間:18:00~01:00

ととや(TOTOYA)和道屋日式串燒專門~隱身巷弄的串燒名店

ととや(TOTOYA)和道屋日式串燒專門~隱身巷弄的串燒名店

地址:台中市北區健行路766巷2號
電話:04-2206-8853
營業時間:05:30PM~02: 00A M