Does it require a particular version of Erlang?
_______________________________________________
erlang-questions mailing list
erlang-q...@erlang.org
http://www.erlang.org/mailman/listinfo/erlang-questions
I think you can relax, Robert. This is not a problem.
In plain Erlang, you'd write
MyCons = fun cons/2,
MyCons(A,B)
In Core Erlang, you write it like this:
let MyCons = 'cons'/2 in apply MyCons(A, B)
Neither of these things mean that you'll necessarily get another
closure that will delegate the call - that's an old implementation
detail, which is not universally valid anymore. (E.g., with inlining
enabled, this will reduce to a direct call "cons(A, B)".) And in
particular, there is just a single variable namespace.
You're right that Core Erlang has no special notation ("fun f/N") for
referring to a function (as opposed to defining it) - that's because the
keyword "fun" is not needed. Core Erlang has two flavours of variables:
normal Erlang-style variables, and 'atom'/integer function names. (We
could actually have used only the first form, but then the Core Erlang
code would be harder to understand, and the export section would have to
look something like "export [ F17 as 'foo'/2, F32 as 'bar'/1, ... ]".)
You can only define function-name variables in letrec-expressions, not
in let-expressions, but this is no limitation in general, since you can
easily bind a plain variable to a function-name variable, as above.
The main point here is: when you see some expression "'f'/3" in Core
Erlang or "fun f/3" in Erlang, think of it as just a name, a variable.
Forget about how "fun f/3" was originally implemented. This is one of
the big things about Core Erlang: except for when you need to create
names of exported functions, that will be visible outside the module,
a variable is just a reference to some value, functional or not, and
it does not matter whether it was defined in a letrec or a let. This
makes it much easier to do transformations like inlining on the Core
language level.
/Richard
PS. I know that it's not easy to grok the full consequences of the Core
Erlang specification; one has to sort of clear one's mind and start from
scratch - if the spec doesn't prohibit something, then it should just
work (assuming that the compiler doesn't have a bug or is incomplete).
[http://www.it.uu.se/research/group/hipe/cerl/doc/core_erlang-1.0.3.pdf]
If you need human assistance to interpret some detail, just mail me.
Is there a particular reason for setting the linenumber to 6666 in
annotations where there is no associated Lisp source code ?
Roberto
--
Roberto Saccon
http://rsaccon.com
> I have finally released LFE, Lisp Flavoured Erlang, which is a lisp syntax
> front-end to the Erlang compiler.
Does it require a particular version of Erlang?
Well, since you asked for it, at a click of a button dialyzer reports
the following:
lfe_scan.erl:215: The pattern <Rest, Line, {'end_token', T}, Ts> can
never match the type <_,_,'error' | 'skip_token' | {'error',[32 | 97 |
99 | 101 | 103 | 104 | 105 | 108 | 114 | 116,...]},_>
lfe_scan.erl:164: The pattern <Rest, Line, {'end_token', T}> can never
match the type <_,_,'error' | 'skip_token' | {'error',[32 | 97 | 99 |
101 | 103 | 104 | 105 | 108 | 114 | 116,...]}>
lfe_scan.erl:118: The pattern <Rest, Line, {'end_token', T}, Ts> can
never match the type <_,_,'error' | 'skip_token' | {'error',[32 | 97 |
99 | 101 | 103 | 104 | 105 | 108 | 114 | 116,...]},[{atom(),_} |
{'number',_,_} | {'string',_,[any()]} | {'symbol',_,atom()}]>
lfe_scan.erl:255: The pattern <Rest, Line, {'end_token', _T}, Error> can
never match the type <_,_,'error' | 'skip_token' | {'error',[32 | 97 |
99 | 101 | 103 | 104 | 105 | 108 | 114 | 116,...]},_>
lfe_macro.erl:490: The pattern {'yes', _} can never match the type
'error' | {'ok',_}
lfe_macro.erl:489: The pattern {'yes', _} can never match the type
'error' | {'ok',_}
The first set is just dead clauses. The second set, is a mismatch of the
return value of a function.
Dialyzer also reports some more additional warnings which are also
reported by the BEAM compiler, so I am suppressing these.
Cheers,
Kostis
Dialyzer also reports some more additional warnings which are also
reported by the BEAM compiler, so I am suppressing these.
I have a couple of suggestions:
- it would be nice to have a preprocessor/parse transform that converts the form
(foo:bar baz ..)
to
(: foo bar baz ...)
I find the former much more readable.
- It would like to have an Erlang-style '=' operator for binding
instead of (let). The main difference is in the number of parentheses
and the scoping rules. So, instead of
(let ((a 1) (b 2)) (+ a b))
you could write
(= (a 1) (b 2))
(+ a b)
- String literals should be interpreted as literal lists rather than
sexps. It seems redundant to write a single quote before a string
literal.
- It would be great to have syntax for multi-line strings and binaries.
- Distributing LFE under a standard open source license would
encourage its adoption and foster community contributions.
lfe_scan.erl has this license notice:
%%% (C)Robert Virding. This stuff is mine, distributed without
%%% warranty "as is" and may not be used commercially without letting
%%% me know.
This wording is ambiguous. Is the only requirement to using LFE
commercially to let you know, or it it required to buy a license for
commercial use? What happens to user contributions? Etc.
Regards,
Yariv
2008/3/1 Robert Virding <rvir...@gmail.com>:
This I can agree with, as long as we're only talking about
literal module and function names, not general expressions.
> - It would like to have an Erlang-style '=' operator for binding
> instead of (let). The main difference is in the number of parentheses
> and the scoping rules. So, instead of
>
> (let ((a 1) (b 2)) (+ a b))
>
> you could write
>
> (= (a 1) (b 2))
> (+ a b)
NO! Absolutely no fricking way.
The way Erlang (ab)uses the '=' sign to do bindings is
IMNSHO one of the ugliest flaws in the language, in part
because it isn't structurally lexical scoped (bindings
flow /out/ of expressions, not just into them).
The point of Lisp/Scheme-like S-expression syntax is not
just using parenthesis for grouping, but also using the
structure to express scoping. LET-expressions do that,
your '=' abuse would not.
Robert, this is very cool. I already started playing with LFE and it's
great. Thanks a lot for sharing it.
I have a couple of suggestions:
- it would be nice to have a preprocessor/parse transform that converts the form
(foo:bar baz ..)
to
(: foo bar baz ...)
I find the former much more readable.
- It would like to have an Erlang-style '=' operator for binding
instead of (let). The main difference is in the number of parentheses
and the scoping rules. So, instead of
(let ((a 1) (b 2)) (+ a b))
you could write
(= (a 1) (b 2))
(+ a b)
- String literals should be interpreted as literal lists rather than
sexps. It seems redundant to write a single quote before a string
literal.
- It would be great to have syntax for multi-line strings and binaries.
- Distributing LFE under a standard open source license would
encourage its adoption and foster community contributions.
lfe_scan.erl has this license notice:
%%% (C)Robert Virding. This stuff is mine, distributed without
%%% warranty "as is" and may not be used commercially without letting
%%% me know.
This wording is ambiguous. Is the only requirement to using LFE
commercially to let you know, or it it required to buy a license for
commercial use? What happens to user contributions? Etc.
Regards,
Yariv
Then why not simply put it at code.google.com with a GPL license
attached to it?
--Tobbe
BSD license is much shorter and nicer :)
--
vlm
If LFE were made GPL, it essentially makes any distribution of Erlang
using it GPL. The wxWidgets license (basically LGPL with static linkage
exception) is a better fit, if GPL is a must, given that you only need
to distribute the source of the library (i.e. LFE) and not the
applications linked to & depending on it.
Regards,
B.J.Tolputt
Lev Walkin wrote:
> Torbjorn Tornkvist wrote:
>
>> Robert Virding wrote:
>>
>>> As for LFE I am giving it away. If somebody has a nice, short license
>>> notice expressing this then let me know. I would, however, become
>>> disappointed if someone else started selling it. :-)
>>>
>> Then why not simply put it at code.google.com with a GPL license
>> attached to it?
>>
>
> BSD license is much shorter and nicer :)
>
>
_______________________________________________
I usually stay out of the licensing flame-wars, and hoepfully this won't
result in one. I agree that BSD, MIT, or even Apache are better licenses
than GPL "for the stated purpose" (which as I understand it is simply to
prevent people taking credit for the work, though Robert can correct me
if I am wrong here).
I created the following macro:
(define-syntax bar
(macro
((vals)
(: lists map (lambda (x) (: io format '"~p~n" x)) vals) ())))
and the following function:
(define (foo)
(bar (1 2 3)))
When I call '(foo)' I get the following error:
** exception error: lfe_eval:'-eval_lambda/2-fun-0-'/2 called with one argument
in function lists:map/2
in call from lfe_eval:eval_body/2
in call from lfe_macro:macro/3
in call from lfe_macro:expand_tail/3
in call from lfe_macro:expand/2
in call from lfe_macro:expand_top_forms/2
in call from lfe_macro:expand_top_forms/2
in call from lfe_macro:expand_file/2
Also, can you please explain the difference between 'macro' and
'syntax-rules'? 'macro' seems to do what I expect and I'm not sure
when syntax-rules would be a better option.
Thanks,
Yariv
2008/3/1 Robert Virding <rvir...@gmail.com>:
Hi, I think I found a bug in lfe_eval.
I created the following macro:
(define-syntax bar
(macro
((vals)
(: lists map (lambda (x) (: io format '"~p~n" x)) vals) ())))
and the following function:
(define (foo)
(bar (1 2 3)))
When I call '(foo)' I get the following error:
** exception error: lfe_eval:'-eval_lambda/2-fun-0-'/2 called with one argument
in function lists:map/2
in call from lfe_eval:eval_body/2
in call from lfe_macro:macro/3
in call from lfe_macro:expand_tail/3
in call from lfe_macro:expand/2
in call from lfe_macro:expand_top_forms/2
in call from lfe_macro:expand_top_forms/2
in call from lfe_macro:expand_file/2
Also, can you please explain the difference between 'macro' and
'syntax-rules'? 'macro' seems to do what I expect and I'm not sure
when syntax-rules would be a better option.
Thanks,
Yariv
Karol
> I am thinking of changing the names to defsyntax and defmacro :
>
> (defsyntax let*
> (pat1 exp1)
> ... )
>
> (defmacro let*
> (pat1 . body1)
> ... )
>
> What does the "user community" feel about that? Having both under one
> define-syntax maybe a clearer way to express the intention though.
> Robert
I want currying... :-)
--Tobbe
> trapexit.org <http://trapexit.org>,
> http://forum.trapexit.org/viewtopic.php?p=40268#40268.
Perhaps a stupid question. Do LFE implement currying?
If not, why?
I want currying... :-)
--Tobbe
>
> Perhaps a stupid question. Do LFE implement currying?
> If not, why?
>
> I want currying... :-)
>
Here's something I threw together in a couple minutes:
%% F({a,b}) -> F'(a,b)
curry(F, Arity) ->
if
Arity =:= 1 -> fun(A) -> F({A}) end;
Arity =:= 2 -> fun(A,B) -> F({A,B}) end;
Arity =:= 3 -> fun(A,B,C) -> F({A,B,C}) end;
Arity =:= 4 -> fun(A,B,C,D) -> F({A,B,C,D}) end;
Arity =:= 5 -> fun(A,B,C,D,E) -> F({A,B,C,D,E}) end;
true -> throw(unsupported_arity)
end.
%% F(a,b) -> F'({a,b})
uncurry(F) ->
fun(Tuple) -> apply(F, tuple_to_list(Tuple)) end.
A gross hack, to be sure, although I can't see how you could have any
hope to avoid having to specify an Arity to curry(). Maybe there's a
way to implement it less horribly, though.
BTW, did you actually mean that you want partial application? Via a
similar process:
papply(F, Arity, Arg) ->
if
Arity =:= 1 -> fun() -> F(Arg) end;
Arity =:= 2 -> fun(A) -> F(Arg,A) end;
Arity =:= 3 -> fun(A,B) -> F(Arg,A,B) end;
Arity =:= 4 -> fun(A,B,C) -> F(Arg,A,B,C) end;
Arity =:= 5 -> fun(A,B,C,D) -> F(Arg,A,B,C,D) end;
true -> throw(unsupported_arity)
end.
-kevin
>
> On Mar 10, 2008, at 2:11 PM, Torbjorn Tornkvist wrote:
>
>>
>> Perhaps a stupid question. Do LFE implement currying?
>> If not, why?
>>
>> I want currying... :-)
>>
>
> Here's something I threw together in a couple minutes:
>
> %% F({a,b}) -> F'(a,b)
> curry(F, Arity) ->
> if
> Arity =:= 1 -> fun(A) -> F({A}) end;
> Arity =:= 2 -> fun(A,B) -> F({A,B}) end;
> Arity =:= 3 -> fun(A,B,C) -> F({A,B,C}) end;
> Arity =:= 4 -> fun(A,B,C,D) -> F({A,B,C,D}) end;
> Arity =:= 5 -> fun(A,B,C,D,E) -> F({A,B,C,D,E}) end;
> true -> throw(unsupported_arity)
> end.
>
Should do slightly more browsing of the docs before posting :-). This
is a slight improvement:
%% F({a,b}) -> F'(a,b)
curry(F) ->
{arity, Arity} = erlang:fun_info(F, arity),
if
Arity =:= 1 -> fun(A) -> F({A}) end;
Arity =:= 2 -> fun(A,B) -> F({A,B}) end;
Arity =:= 3 -> fun(A,B,C) -> F({A,B,C}) end;
Arity =:= 4 -> fun(A,B,C,D) -> F({A,B,C,D}) end;
Arity =:= 5 -> fun(A,B,C,D,E) -> F({A,B,C,D,E}) end;
true -> throw(unsupported_arity)
end.
_______________________________________________
_______________________________________________
erlang-questions mailing list
erlang-q...@erlang.org
http://www.erlang.org/mailman/listinfo/erlang-questions
Yup, I realized that later as well. That change works for papply, but
not for curry. (This shortcoming is not restricted to Erlang, one
should note. For example, in Haskell, curry and uncurry only operate
on binary functions.)
-kevin
As an example, look at my little Haskell-to-Erlang experiment:
http://blog.tornkvist.org/blog.yaws?id=1190846785574003
As you can see, it is also possible to make user-defined guards
when you're rolling your own language on top of Erlang core.
Cheers, Tobbe
curry(F,Arg) ->
case erlang:fun_info(F,arity) of
{_,1} -> fun() -> F(Arg) end;
{_,2} -> fun(A) -> F(A,Arg) end;
{_,3} -> fun(A,B) -> F(A,B,Arg) end;
{_,4} -> fun(A,B,C) -> F(A,B,C,Arg) end
end.
mats
(*) I Am Not A Computer Scientist
-kevin
On Mar 11, 2008, at 2:49 PM, Mats Cronqvist wrote:
> Kevin Scaldeferri wrote:
>>>> No, that's partial application. Or, sort of reverse partial
>>>> application. Compare to the papply function I wrote.
>>>>
>>>>
>>>> -kevin
>>>
>>> like i said, i really have no idea what i'm talking about. but i
>>> found several descriptions like this;
>>>
>>> http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52549
>>>
>>> "In functional programming, currying is a way to bind arguments with
>>> a function and wait for the rest of the arguments to show up later.
>>> You "curry in" the first few parameters to a function, giving
>>> you a function that takes subsequent parameters as input and
>>> calls the original with all of those parameters."
>>>
>>> i'm so confused...
>>
>> So is the author of that paragraph :-). Here's a better
>> explanation from wikipedia: http://en.wikipedia.org/wiki/Currying
>>
>> "Given a function f of type f : (X x Y) -> Z , then currying it
>> makes a function curry(f) : X -> (Y -> Z) . That is, curry(f) takes
>> an argument of type X and returns a function of type Y -> Z . "
>>
>> So, what you see here is that in some sense currying is a precursor
>> to partial application.
>
> i guess you just can't trust random web pages these days... i found
> a better source of info on the haskell web (surprise!)
>
>> Part of the confusion in talking about this is that this is all in
>> the context of theories of computation where all functions are
>> unary (like the lambda calculus). In languages with arbitrary
>> arity of functions, it's a little less clear what currying means.
>> I made the choice to interpret it as converting a unary function
>> expecting a tuple into a multi-ary function. You could argue,
>> though, that maybe it should be this instead:
>>
>> curry(F) when is_function(F,2)->
>> fun(X) ->
>> fun(Y) -> F(X,Y) end
>> end.
>>
>>
>> Notice, though, that curry() doesn't actually apply any arguments,
>> it just returns a function which naturally allows partial
>> application.
>
> i see... thanks a lot for your time!
>
>>
>> -kevin
>>
>> P.S. Did you intentionally only send this to me? I think there's
>> frequent confusion about this, so it seems to be like valuable
>> discussion for the list
>>
> i did "reply all" in my trusty old thunderbird; i think your
> previous mail was sent to me only (at least it looked like that to
> thunderbird). feel free to forward any/all of this to the list. i'm
> pretty sure i'm not the only one confused by this (though i might be
> the only one that cares, of course.)
>
> mats
> <mats_cronqvist.vcf>
your_curried_func( A ) -> fun( B, C ) -> your_curried_func( A, B, C ) end.
your_curried_func( A, B ) -> fun( C ) -> your_curried_func( A, B, C ) end.
your_curried_func( A, B, C ) -> ...
One extra line for each curring case. For me it's completely ok, but
you can define macro to hide this stuff if it bothers you. You'll get
something like this:
?curried_3( your_curried_func )
your_curried_func( A, B, C ) -> ...
Currying is the act of taking a function of multiple arguments and,
without binding any, returning a function that takes them one at a time.
For example,
curry(F) ->
case erlang:fun_info(F, arity)
of 0 -> fun (_) -> F() end
; 1 -> F
; 2 -> fun (X1) -> fun (X2) -> F(X1,X2) end end
; 3 -> fun (X1) -> fun (X2) -> fun (X3) -> F(X1,X2,X3) end end
end
% continue as long as you have patience or use
end.
Partial application is the act of taking a function of multiple
arguments and, by some means, supplying some but not all of them,
returning a function, not necessarily unary, awaiting the rest.
The British AI language Pop-2 supported partial application but not
currying. If I remember correctly, f(% ... %) provided *trailing*
arguments for f, leaving it still awaiting its leading arguments.
With a curried function, it is easiest to provide leading arguments,
but it is often useful to supply others.
For example, in Haskell a binary operator like > is curried:
> :: Ord a => a -> a -> Bool
We might want to supply *either* of the arguments:
x_exceeds = (x >)
returns \y -> x > y
exceeding_x = (> x)
returns \y -> y > x
Working on binary functions, we might have
apply_left(X, Op) -> fun (Y) -> Op(X, Y) end.
apply_right(Op, Y) -> fun (X) -> Op(X, Y) end.