* 匯出全部
Erlang允許個模組將自己的函數全部匯出:
-compile(export_all)
REBOL雖然沒有這樣的作法。但是REBOL模組中沒有被匯出者,依然可以透過explicit的方式,被外部使用,例如:
my-module/non-expoted-func
* Arity
對Erlang來說,Arity(引數的個數)是函數的一部份,函數area/1表示函數名為area,且具有一個引數。而area/1可能又有許多個clause。同一個Erlang模組內,即使函數名稱一樣,但Arity不同,那麼就是完全不同的函數。Erlang常常會使用相同名稱但不同Arity的函數,當作輔助函數(helper)。
REBOL函數不具有clause,也不強調Arity。
* 匿名函數
Erlang和REBOL都支援匿名函數。
Erlang:
fun(x) -> x * 2 end.
REBOL:
func[x] [x * 2]
但是Erlang的匿名函數可以有多個clause,REBOL則不行。
* 較高次方函數
Erlang和REBOL也都支援「較高次方」函數(higher-order function),也就是「以函數為引數或傳出值」的函數。較高次方函數是Function Programming很重要的特色。
Erlang大量使用「較高次方」函數,但REBOL卻很少使用「較高次方」函數。
* 把函數當引數用
Erlang有相當多list-at-a-time函數,可以將對整個list的操作,當作單一個概念。簡化我們的思考,也簡化我們的程式。REBOL也可以做到這一點,設計出block-at-a-time函數,只是目前好像這樣的函數並不多(但MAP是個例外)。而且許多時候,REBOL都是利用block來當作函數(不像函數那麼有彈性)。這一點,我比較喜歡Erlang。
Erlang:
> Double = fun(x) -> x * 2 end.
> L = [1,2,3,4]
> list:map(Double, L).
[2,4,6,8]
* 把函數當傳出值用
Erlang可以將函數當傳出值,例如:
> Fruit = [apple,pear,orange].
> MakeTest = fun(L) -> (fun(X) -> lists:member(X, L) end) end.
> IsFruit = MakeTest(Fruit).
> IsFruit(apple).
true
> IsFruit(beef).
false
REBOL必須透過closure,才能做到這件事:
>> Fruit: [apple pear orange]
>> Make-Test: closure [L] [ func[X] [found? Find L X] ]
>> Is-Fruit: Make-Test Fruit
>> Is-Fruit 'apple
== true
>> Is-Fruit 'beef
== false
不管是Erlang或REBOL,「把函數當傳出值用」都很少見。但是利用這種方式建立自己的流程控制,可以相當有效地減少程式體積,有時候甚至會讓程式更清晰易讀。
沒有留言:
張貼留言