论面向组合子程序设计方法 之 oracle
生活随笔
收集整理的這篇文章主要介紹了
论面向组合子程序设计方法 之 oracle
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
不少朋友說我的闡述很蒼白無力。這讓我很苦惱。我確實是拚了命地想把問題說清楚,我也有實際non-trivial的項目經驗,怎么就說不明白呢?哎!?
所以,還是不能不多羅嗦一下,希望能夠再闡述得明白一點。?
其實,所謂co,有心的朋友也許能夠感覺到,它很象是設計一門語言。?
它有順序/分支,有函數調用,異常處理,基本上一個程序設計語言有的東西它都有了。這些順序/分支作為語言的基礎設施,而一些應對具體需求的原子操作,(比如WriterLogger,比如NeptuneExceptionLogger)則可以看作是語言的擴展或者庫。?
只不過,c/c++/java是有編譯器來把源代碼轉化成目標代碼。而co的組合子則是利用了宿主語言(比如java)本身的能力來實現各個組合子的語義。可以說,co是在設計一門語言中的語言。?
最近這段時間,流行過一陣LOP(language oriented programming),就是用domain-specific-language來處理一些特定的domain需求。?
為什么會有這種說法呢?還是因為domain的需求多變靈活,不容易琢磨,所以人們發現用一個靈活的語言比用一些功能相對死板的庫更容易對付。?
但是dsl的實現不是那么容易的。而co是不是可以說給我們提供了一個相對廉價的創建自己的domain specific language的途徑呢??
我們雖然不能說?
Java代碼??if?level?>?1?then?logger1?else?logger2??
至少可以退而求其次,寫出?
Java代碼??ignore(1,?logger1,?logger2);;??
當然,這種子語言相比于宿主語言,缺乏調試器的幫助,缺乏編譯器的優化,缺乏各種ide的支持,可用性程度是大大不如的。?
但是,它也有它的好處,那就是,不用額外進行一次編譯;寫出來的東西和宿主語言無縫集成;可以自動利用宿主語言里面的一切設施。等等。?
那么如果把co作為一個語言來考慮,是不是會給我們一些別的啟示呢??
oz曾經質疑,所謂的co,怎樣決定基本的組合子?怎么樣才知道組合子夠用了??
那么,設計語言的時候,怎么設計基本的語言設施?怎么樣知道這個設施是不足,還是太多呢??
這是個大話題,語言設計非常有爭議性和主觀性。但是,也仍然是有些共性的。比如,幾乎所有的語言都支持順序,if/else,遞歸/循環,函數定義等。相當多我們熟悉的語言還支持異常處理,字符串,整數等。?
我們難道不能從這里借鑒一些東西?如果我們把基本的nop, 順序,分支作為啟動co的基本要求,這算不算是一個可以遵循的guidline呢??
另外,不同的語言,根據它所面向的領域,還有一些不同的內建操作,比如perl,面向文本處理,所以內建了regexp,而c/c++因為直接面對機器硬件模型,所以提供了指針。?
那么,根據我們的組合子所要面對的應用類型,我們也可以預先定義一些內建的原始組合子,比如那個WriterLogger。?
一般來說,對general purpose的語言,設計的基礎設施都是非常”基礎“的,基礎到幾乎不會有什么設施是多余的。同時,也基礎到一般人都可以沒有什么困難地掌握基本的語法語義。?
那么這些語言用這么有限的聊聊幾個設施怎么對應它不可能預見的各種現實中的需求呢??
我們平時對可以用簡單的if-else,順序,循環就可以做幾乎任何我們能想到的事情感到驚訝了嗎?對某個語言能否處理復雜的需求擔憂了嗎??
為什么沒有呢?就在于”組合“的威力。就是那么幾個簡單的設施,組合起來卻可以具有巨大的力量。?
同樣,在設計組合子的時候,如果我們遵循這些共性,同時在和具體需求磨合的時候積極改進組合子本身,應該就可以達到一個可以滿意的組合子系統。?
說到這里,可能有人問:你不是說組合子系統是脫離需求自己發展的嗎??
這個,怎么說呢?還是說語言。設計一個語言,原則上是設計一些和具體需求沒有耦合的基礎設施,然后讓寫具體應用的人組合這些基礎設施達到我們語言設計者不可能都預見到的某些具體效果。?
但是,在語言設計和逐漸發展過程中,仍然會從用戶(就是程序員)那里得到反饋,什么樣的需求是他們需要的,什么樣的設施不好用,然后設計者再進行改進。?
一個語言,一般不會是某個具體需求通過劃分責任,自頂向下的設計,最后作為這個需求的附屬模塊被開發出來。更多的情況,是語言的設計者對可能面對的需求有一個大致了解,并且知道這種可能的需求是變化的,不確定的,于是才會從基本設施開始設計這個語言,最后交付給開發具體應用的人來使用。?
組合子系統也遵循一樣的規律。組合子的設計需要來自具體需求的靈感和糾正。但是,基本組合子本身卻不能耦合于這些具體需求。?
組合子的設計者應該對可能面對的需求有大致的了解,但是并不需要完整地預測這種多變的需求。?
當然,組合子這種語言中的語言,還有不容易理解的弱點。當組合層次增多,邏輯變得復雜,這個復雜的組合子可不象寫在一般的程序設計語言里面的代碼那樣簡明,java繁瑣的語法讓這種語言中的語言對一些程序員也許就象是神廟里面的神諭一樣難以理解,甚至讓人望而生畏。?
這一半是因為java本身沒有提供對這種高階邏輯的直接支持,組合的語法相對繁瑣。如果用haskell,使用語言提供的do-notation,形式上的復雜程度就沒了。?
另一方面,高階邏輯都是有這種弱點的。?
其實,就算是oo,相比于po,它的多態也是降低可理解性的。?
因此,就象我們也不能在oo中到處override虛函數一樣,組合子的使用也要有一定的度,過猶不及。?
好了,沒有實際例子的論述已經太長了。肯定已經有人昏昏欲睡了。?
做個調查,我下面的例子有幾個選擇:?
[list]1。簡單的predicate。就是一個具有bool is(Object v);方法的接口。?
2。ant的FileSelector。一個predicate的變體。?
3。swing提到的jdbc的action。負責數據庫操作的組合子。?
4。yan container的component。負責從任意的構造函數,工廠方法,java bean以及它們的任意組合來產生和注射組件。比pico/spring靈活很多。?
5。neptune的command,負責調用任何ant task以及其它的可能返回一個java對象的函數。是一個一般化了的ant task。[/list:u]?
所以,還是不能不多羅嗦一下,希望能夠再闡述得明白一點。?
其實,所謂co,有心的朋友也許能夠感覺到,它很象是設計一門語言。?
它有順序/分支,有函數調用,異常處理,基本上一個程序設計語言有的東西它都有了。這些順序/分支作為語言的基礎設施,而一些應對具體需求的原子操作,(比如WriterLogger,比如NeptuneExceptionLogger)則可以看作是語言的擴展或者庫。?
只不過,c/c++/java是有編譯器來把源代碼轉化成目標代碼。而co的組合子則是利用了宿主語言(比如java)本身的能力來實現各個組合子的語義。可以說,co是在設計一門語言中的語言。?
最近這段時間,流行過一陣LOP(language oriented programming),就是用domain-specific-language來處理一些特定的domain需求。?
為什么會有這種說法呢?還是因為domain的需求多變靈活,不容易琢磨,所以人們發現用一個靈活的語言比用一些功能相對死板的庫更容易對付。?
但是dsl的實現不是那么容易的。而co是不是可以說給我們提供了一個相對廉價的創建自己的domain specific language的途徑呢??
我們雖然不能說?
Java代碼??
至少可以退而求其次,寫出?
Java代碼??
當然,這種子語言相比于宿主語言,缺乏調試器的幫助,缺乏編譯器的優化,缺乏各種ide的支持,可用性程度是大大不如的。?
但是,它也有它的好處,那就是,不用額外進行一次編譯;寫出來的東西和宿主語言無縫集成;可以自動利用宿主語言里面的一切設施。等等。?
那么如果把co作為一個語言來考慮,是不是會給我們一些別的啟示呢??
oz曾經質疑,所謂的co,怎樣決定基本的組合子?怎么樣才知道組合子夠用了??
那么,設計語言的時候,怎么設計基本的語言設施?怎么樣知道這個設施是不足,還是太多呢??
這是個大話題,語言設計非常有爭議性和主觀性。但是,也仍然是有些共性的。比如,幾乎所有的語言都支持順序,if/else,遞歸/循環,函數定義等。相當多我們熟悉的語言還支持異常處理,字符串,整數等。?
我們難道不能從這里借鑒一些東西?如果我們把基本的nop, 順序,分支作為啟動co的基本要求,這算不算是一個可以遵循的guidline呢??
另外,不同的語言,根據它所面向的領域,還有一些不同的內建操作,比如perl,面向文本處理,所以內建了regexp,而c/c++因為直接面對機器硬件模型,所以提供了指針。?
那么,根據我們的組合子所要面對的應用類型,我們也可以預先定義一些內建的原始組合子,比如那個WriterLogger。?
一般來說,對general purpose的語言,設計的基礎設施都是非常”基礎“的,基礎到幾乎不會有什么設施是多余的。同時,也基礎到一般人都可以沒有什么困難地掌握基本的語法語義。?
那么這些語言用這么有限的聊聊幾個設施怎么對應它不可能預見的各種現實中的需求呢??
我們平時對可以用簡單的if-else,順序,循環就可以做幾乎任何我們能想到的事情感到驚訝了嗎?對某個語言能否處理復雜的需求擔憂了嗎??
為什么沒有呢?就在于”組合“的威力。就是那么幾個簡單的設施,組合起來卻可以具有巨大的力量。?
同樣,在設計組合子的時候,如果我們遵循這些共性,同時在和具體需求磨合的時候積極改進組合子本身,應該就可以達到一個可以滿意的組合子系統。?
說到這里,可能有人問:你不是說組合子系統是脫離需求自己發展的嗎??
這個,怎么說呢?還是說語言。設計一個語言,原則上是設計一些和具體需求沒有耦合的基礎設施,然后讓寫具體應用的人組合這些基礎設施達到我們語言設計者不可能都預見到的某些具體效果。?
但是,在語言設計和逐漸發展過程中,仍然會從用戶(就是程序員)那里得到反饋,什么樣的需求是他們需要的,什么樣的設施不好用,然后設計者再進行改進。?
一個語言,一般不會是某個具體需求通過劃分責任,自頂向下的設計,最后作為這個需求的附屬模塊被開發出來。更多的情況,是語言的設計者對可能面對的需求有一個大致了解,并且知道這種可能的需求是變化的,不確定的,于是才會從基本設施開始設計這個語言,最后交付給開發具體應用的人來使用。?
組合子系統也遵循一樣的規律。組合子的設計需要來自具體需求的靈感和糾正。但是,基本組合子本身卻不能耦合于這些具體需求。?
組合子的設計者應該對可能面對的需求有大致的了解,但是并不需要完整地預測這種多變的需求。?
當然,組合子這種語言中的語言,還有不容易理解的弱點。當組合層次增多,邏輯變得復雜,這個復雜的組合子可不象寫在一般的程序設計語言里面的代碼那樣簡明,java繁瑣的語法讓這種語言中的語言對一些程序員也許就象是神廟里面的神諭一樣難以理解,甚至讓人望而生畏。?
這一半是因為java本身沒有提供對這種高階邏輯的直接支持,組合的語法相對繁瑣。如果用haskell,使用語言提供的do-notation,形式上的復雜程度就沒了。?
另一方面,高階邏輯都是有這種弱點的。?
其實,就算是oo,相比于po,它的多態也是降低可理解性的。?
因此,就象我們也不能在oo中到處override虛函數一樣,組合子的使用也要有一定的度,過猶不及。?
好了,沒有實際例子的論述已經太長了。肯定已經有人昏昏欲睡了。?
做個調查,我下面的例子有幾個選擇:?
[list]1。簡單的predicate。就是一個具有bool is(Object v);方法的接口。?
2。ant的FileSelector。一個predicate的變體。?
3。swing提到的jdbc的action。負責數據庫操作的組合子。?
4。yan container的component。負責從任意的構造函數,工廠方法,java bean以及它們的任意組合來產生和注射組件。比pico/spring靈活很多。?
5。neptune的command,負責調用任何ant task以及其它的可能返回一個java對象的函數。是一個一般化了的ant task。[/list:u]?
這些東西都是基于組合子的。大家覺得對哪一個更有興趣呢?我有些拿不定主意哪個更合適。
from:?http://ajoo.iteye.com/blog/23309
總結
以上是生活随笔為你收集整理的论面向组合子程序设计方法 之 oracle的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 面向组合子程序设计方法 之 新约
- 下一篇: 论面向组合子程序设计方法 之 重构