星期六, 10月 04, 2008

Haskell Learning Note(3) - 前傳

我本來想要參考和Josh Ko的MSN對話紀錄來這一篇的,但是發現MSN對話紀錄竟然不見了...Orz

funciton interface如何改變

一個function,會有0個至多個不等的argument,而function只有一個signal output(當然也不一定是signal output,你可以說傳一個list出來,說我傳了一堆東西,但是就整體而言,你還是傳了一個符合某一個type的東西出來),這對 functional programming更是如此,基本上就算是function name相同但是arguments 個數不同的話,我們仍視為不同的function

先跳回C/C++,眾所皆知,C++有著function overloading機制(靠著compile-time決定呼叫那一個function,為一個static-linking),基本上靠著這樣子的機制,避免非常多的name collision。

題外話,C++靠著三種機制來避免name collision,一種是name scope,一種是funciton overloading,一種是polymorphism,不過很可惜的是,沒有類似Java裡的inner class來避免一次性的class使用,但是到了boost,有提供lambda calculus來解決部分的問題。

或許換個角度來想,程式碼複用性一直是一個很重要很重要的問題,以function層面而言,最常見的wrapper function

int add(int a, int b){
return add(a, b, 0);
}

int add(int a, int b, int c){
return a+b+c;
}
當然,這個程式在C++中可以更簡單的寫成
int add(int a, int b, int c=0){
return a+b+c;
}
這些都是程式撰寫上的技巧,不足以掛齒,在寫程式的單純呼叫function時,引數是不足以構成問題的,可是call-back function上呢,在STL algorithm的比較呢,以STL的find_if為例。
template<lass InputIterator, class Predicate>
InputIterator find_if(InputIterator first, InputIterator last,
Predicate pred);
其中的Predicate要求傳入一個value type的變數,傳回bool,也就是說,如果你的function不是一個引數,是不符合Predicate的要求,那麼就無法變成find_if所能使用的function object。

STL所提供的解決方法有二,如果你要求剛好是function object adaptor和predefined function object組合起來可解決,那麼就使用組合技,第二個方法為,自行撰寫一個較為general function object ,再使用funciton object adaptor來改變一個function object的interface。舉個簡單的例子
std::find_if(u.begin(), u.end(), std::bind2nd(std::less<int>(), 0)); //尋找某個區間第一個小於0的數字。
我不能不說,我當初看到這樣子的寫法,我以為找到了救星,funciton可以玩組合技耶,而且這樣子的確解決了call back function的問題。

利用wrapper function或者是STL裡面的function object adapter或種種程式語言的技能的確可以改變一個function原本的interface,但是有沒有更好的方法? 有啊,不然我就白寫了,看到Haskell的方法之後,以前的我好傻好天真(大誤)~XD。

---
還沒進入正題XD

張貼留言