Currying and Laziness in Erlang

Currying is a general feature in functional programming languages. It means that any function can be used by receiving an argument and evaluated as a partial-evaluated function. In Erlang, by using the following a function curry/2, currying is ready for use.

curry(F) when is_function(F, 2) ->
    fun(X) -> fun(Y) -> F(X, Y) end end.

I made another version of carrying function that it accepts zero or many arguments.

curry(F, N) ->
    curry(F, N, []).
curry(F, 0, Args) ->
    apply(F, lists:reverse(Args));
curry(F, N, Args) when N > 0 ->
    fun(X) ->
	    curry(F, N-1, [X|Args])

These currying functions are eager. I would like them being as lazy as possible for ease purpose. Laziness in Erlang should be used by describing it explicitly. Then I made a one-step lazy function by defining macros. (Thanking for John Hughes: )

-define(DELAY(E), fun()-> E end).
-define(FORCE(F), F()).

curryl(F, N) ->
    curryl(F, N, []).
curryl(F, N, Args) ->
    ?DELAY(curry(F, N, Args)).

It’s no problem that once calling curryl/2 or curryl/3 it is slightly lazy. However what I want is a lazy and lazy currying function because most functions are recursive. Thus I wrote a really lazy version: curryll/2.

curryll(F, N) ->
    curryll(F, N, []).
curryll(F, 0, Args) ->
    fun() -> apply(F, lists:reverse(Args)) end;
curryll(F, N, Args) when N > 0 ->
    fun() -> fun(X) ->
	    curryll(F, N-1, [X|Args])
    end end.

Then usage seems that troublesome.

> G1 = stdlib:curryll(fun lists:append/2, 2).
> G2 = (G1())([a,b]).
> G3 = (G2())([c]).
> G3().

It’s too lazy that I need force it work step-by-step. I’m not yet sure if it helps automation. I will use this lazy currying to write a parser, which will contain many recursive and recursive grammar that laziness is strongly recommended to be used, and partial evaluation is also important for it that most parsing combinators receives some arguments and are still functions waiting for more arguments.


本篇發表於 Erlang, Problem。將永久鏈結加入書籤。


在下方填入你的資料或按右方圖示以社群網站登入: Logo

您的留言將使用 帳號。 登出 /  變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )


您的留言將使用 Facebook 帳號。 登出 /  變更 )


連結到 %s