[erlang-questions] Funargs: Ruby-like blocks for Erlang

57 переглядів
Перейти до першого непрочитаного повідомлення

Tony Arcieri

не прочитано,
21 лип. 2011 р., 03:39:4521.07.11
Кому: Erlang Questions
This is an idea that's been bouncing around in my head for awhile now
and I thought I'd just bust it out:

https://gist.github.com/1096711

Raw patch available here (I just grabbed the latest source code off
Github to make this):

https://raw.github.com/gist/1096711/ec763d3440fe1e1c07579e8ff78b3cdbc04e87e0/funargs.patch

--

There's lots of cases where you just want to pass a single fun as an
argument to a function. By convention this fun is typically passed as
the first argument. However, the problem with Erlang's fun syntax is,
well, it isn't fun. It's kind of noisy, and passing a fun as an
argument makes it even noisier.

Ruby has this really nifty feature called blocks which, to put not too
fine a point on it, provides some awesome syntactic sugar for passing
an anonymous function as an argument to another function. In Ruby,
blocks look like this:

    [1,2,3,4,5].map do |n|
        n * 2
    end

(there are other forms, but this is the one I'm focusing on)

Ask any Rubyist and they'll tell you blocks are the bee's knees. They
are constantly trotted out as one of the most awesome and amazing
features of Ruby. Many attempts have been made to add blocks to
languages like Python (e.g.
http://tav.espians.com/ruby-style-blocks-in-python.html) but it
doesn't work in Python due to quirks in its indent-based grammar.

However, I'd rather ask: can Erlang have something like Ruby like
blocks? Yes, yes it can.

--

The linked patch implements a feature I'm tentatively calling
"funargs" (yes, I know, this name has prior usage in the funarg
problem. If you don't like it suggest a better one!)

The patch adds a new 'do' keyword and otherwise copies the Ruby syntax
outright. Let's compare what Erlang lets you do now with what the
syntax this patch provides allows.

Before:

mnesia:transaction(fun() ->
   mnesia:write(#thing{foo=1, bar=2, baz=3})
end).

After:

mnesia:transaction do
   mnesia:write(#thing{foo=1, bar=2, baz=3})
end.

That's marginally better. How about some more examples?

Before:

lists:map(fun(N) ->
N * 2
end, [1,2,3,4,5]).

After:

lists:map([1,2,3,4,5]) do |N|
N * 2
end.

Again, it's marginally better. What if there are more arguments?

Before:

lists:foldl(fun(Octec, Acc) ->
Acc bsl 8 bor Octet
end, 0, [127,0,0,1]).

After:

lists:foldl(0, [127,0,0,1]) do |Octet, Acc|
Acc bsl 8 bor Octet
end.

In this case I definitely prefer the latter form. Try to imagine
functions with much more expressions in the fun body.

So I'll admit so far none of these examples are *particularly* more
compelling than their equivalent "fun" forms. Where blocks get really
interesting is when you nest them, particularly when building what
Rubyists refer to as DSLs. Below is a hypothetical example I think
could actually be implemented using this syntax, perhaps with a custom
error handler, which I admit would be a complete hack, but I think
it'd be pretty interesting. I tried to translate an example builder
template from Ruby available here:

http://danengle.us/2009/05/generating-custom-xml-for-your-rails-app/

Let's imagine we have a custom error handler and a parameterized
module "Xml" which is thunking to a process that's building an XML
document for us on the fly. We could build XML in Erlang as follows:

Xml:posts do
lists:each(Posts) do |Post|
Xml:post do
Xml:title(Post#post.title),
Xml:body(Post#post.body),
Xml:published_at(Post#post.published_at),
Xml:comments do
lists:each(Post#post.comments) do |Comment|
Xml.comment do
Xml:body(Comment#comment.body)
end
end
end
end
end
end

And voila, you have a fairly decent DSL for building XML from Erlang.

Thoughts?

--
Tony Arcieri
_______________________________________________
erlang-questions mailing list
erlang-q...@erlang.org
http://erlang.org/mailman/listinfo/erlang-questions

Tony Arcieri

не прочитано,
21 лип. 2011 р., 03:54:1421.07.11
Кому: Erlang Questions
> And voila, you have a fairly decent DSL for building XML from Erlang.

For comparison, here's the hypothetical XML "DSL" in regular Erlang
syntax versus the block form:

https://gist.github.com/1096754

Vlad Dumitrescu

не прочитано,
21 лип. 2011 р., 04:58:2921.07.11
Кому: Tony Arcieri, Erlang Questions
Hi!

On Thu, Jul 21, 2011 at 09:39, Tony Arcieri <tony.a...@gmail.com> wrote:
> There's lots of cases where you just want to pass a single fun as an
> argument to a function. By convention this fun is typically passed as
> the first argument. However, the problem with Erlang's fun syntax is,
> well, it isn't fun. It's kind of noisy, and passing a fun as an
> argument makes it even noisier.
>
> Ruby has this really nifty feature called blocks which, to put not too
> fine a point on it, provides some awesome syntactic sugar for passing
> an anonymous function as an argument to another function.

I think it is useful to investigate this area. The verbosity of
function definitions is not pleasant, but I would argue that it is
mostly necessary (give or take a few tokens). The reason for that is
that we also have guards and multiple clauses. Your new syntax helps
for the simple cases, but the general case won't be much less verbose
than the current syntax. Or at least I can't see how it could be
simplified, maybe you can. An argument can be made that the simple
cases should be easier to type and read, but then there are two ways
to express the same thing. Also, if a code modification leads to the
function being no longer a 'simple case', then the whole expression
needs to be rewritten to use the full syntax.

How do you handle guards and multiple clauses in Reia?

One could just as well instead of "do |X, Y|" write "fun (X, Y) ->"
and keep the existing syntax for the fun. This will allow guards and
multiple clauses. In that case, the proposed change will be that we
could write
Mod:Fun(Arg1, Arg2) fun(X) -> foo(X) end,
instead of
Mod:Fun(Arg1, Arg2, fun(X) -> foo(X) end),
which is not really a big difference...

For your XML builder example, the lack of parentheses is the most
compelling advantage, in my opinion. Having "do |X, Y|" instead of
"fun (X, Y) ->" doesn't feel like a big deal. I'm not sure the "less
parentheses" argument is enough - there are other aspects with Erlang
that make in-language DSLs a less than pretty sight.

regards,
Vlad

Jesper Louis Andersen

не прочитано,
21 лип. 2011 р., 08:34:3721.07.11
Кому: Tony Arcieri, Erlang Questions
On Thu, Jul 21, 2011 at 09:39, Tony Arcieri <tony.a...@gmail.com> wrote:

> Ruby has this really nifty feature called blocks which, to put not too
> fine a point on it, provides some awesome syntactic sugar for passing
> an anonymous function as an argument to another function. In Ruby,
> blocks look like this:
>
>     [1,2,3,4,5].map do |n|
>         n * 2
>     end

Most of the trouble stems from

a) No currying in Erlang
b) A long anonymous function notation
c) No sectioning

In Haskell, your example is

map (*2) [1..5]

and if written without sectioning:

map (\x -> x * 2) [1..5]

and in SML which doesn't have a list constructor convenience notation:

List.map (fn x => x * 2) [1,2,3,4,5]

.

Ruby blocks is a weak implementation of anonymous functions in every
way. The problems from using lots of anonymous functions in Erlang
programs is mainly because the notational overhead of using them is
too big. But then again, I don't find

lists:map(fun(X) -> X * 2 end, [1,2,3,4,5]),

much harder to read. Yes, there is more clutter in there due to the
function object. But it has a distinct advantage over the block in
ruby which is that it is not statement-syntax but an expression. I can
write

foo(F) ->
lists:map(F, [1,2,3,4,5]).

and get away with it. In Ruby you have to do something more here to
turn the do-block, which is a statement, into some kind of value you
can then pass around. When I looked at Ruby in 2002 they had some
"proc" objects to do this with. I am sure it is better today. My main
gripe with the kind of notation you propose is that it doesn't
*compose* in the sense of a mathematical algebra. It is also why I
like currying, and why I absolutely *love* Agda 2 for its infix
operator definitions. In Agda, you can do:

data List (A : Set) : Set where
[] : List A
_∷_ : A -> List A -> List A

which defines that we have a list and that the notation of the cons
is: x ∷ l, where x has type A and l has type List A. You can even do
more advanced stuff like if_then_else to build if-then-else statements
yourself. These tools allow you to construct algebraic solutions to
nearly any problem statement syntax will help with.

TL;DR I don't think we need a new kind of syntax for certain kinds of
lambda sections (see the 'cut' proposal a couple of days ago from
SRFI-26 in Scheme-land). But I do agree the notation is heavier than
it could be. A more convenient notation would encourage people to use
anonymous functions more.

--
J.

Dhananjay Nene

не прочитано,
21 лип. 2011 р., 10:29:4421.07.11
Кому: Tony Arcieri, Erlang Questions
On Thu, Jul 21, 2011 at 1:24 PM, Tony Arcieri <tony.a...@gmail.com> wrote:
>> And voila, you have a fairly decent DSL for building XML from Erlang.
>
> For comparison, here's the hypothetical XML "DSL" in regular Erlang
> syntax versus the block form:
>
> https://gist.github.com/1096754

I couldn't but help being reminded of
http://redmine.ruby-lang.org/issues/5054 when reading the gist of
either version :) :)

Dhananjay
--
----------------------------------------------------------------------------------------------------------------------------------
http://blog.dhananjaynene.com twitter: @dnene google plus:
http://gplus.to/dhananjaynene

Tristan Sloughter

не прочитано,
21 лип. 2011 р., 12:21:1521.07.11
Кому: Dhananjay Nene, Tony Arcieri, Erlang Questions
How about doing that 'do' addition to make Erlando's use of Monads (especially the error monad that I love) look nicer. Instead of having a list.

error_m do
  ...
end

?

Tim Watson

не прочитано,
21 лип. 2011 р., 15:13:2721.07.11
Кому: Jesper Louis Andersen, Tony Arcieri, Erlang Questions
> SRFI-26 in Scheme-land). But I do agree the notation is heavier than
> it could be. A more convenient notation would encourage people to use
> anonymous functions more.

Interestingly, Haskellers are encouraged not to over-do anonymous
functions is possible. This is probably because using sections and
point-free style is more concise and arguably easier to follow.
Currying and decent support for function composition would come way
higher on my list of "want to have" stuff.

Deryk Barker

не прочитано,
21 лип. 2011 р., 15:29:1221.07.11
Кому: erlang-questions
Before the Ruby-istas get too boastful, arent' Ruby blocks essentially
the same as Smalltalk blocks?

deryk

Tristan Sloughter

не прочитано,
21 лип. 2011 р., 16:01:0721.07.11
Кому: Jesper Louis Andersen, Tony Arcieri, Erlang Questions
A reason I end up with far more anonymous functions in my Erlang than Haskell code (and end up with longer functions in Erlang) is the lack of 'let' and 'where'.

In Erlang I'd do:

-spec area_of_circles(record(circle)) -> [float()]
area_of_circles(Circles) ->
  lists:map(fun(C) -> 
                              math:pi() * math:pow(C#circle.radius, 2) 
                end, Circles).

While in Haskell:

area_of_circles :: [Shape] -> [Float]
area_of_circles circles =
  L.map (area_of_circle) circles
  where
    area_of_circle (Circle radius) = pi * radius^2

Not a great example, but I don't have time to come up with a better one... But maybe portrays what I mean about Erlang making me less likely to name anonymous functions and less likely to break things into smaller functions.

Tristan

Tony Arcieri

не прочитано,
21 лип. 2011 р., 16:43:4421.07.11
Кому: Deryk Barker, erlang-questions
On Thu, Jul 21, 2011 at 12:29 PM, Deryk Barker <dba...@camosun.bc.ca> wrote:
Before the Ruby-istas get too boastful, arent' Ruby blocks essentially the same as Smalltalk blocks?

There are definitely similarities between Ruby and Smalltalk blocks and the former was inspired by the latter, however the syntax is different. I implemented the Ruby syntax here, hence the comparison to Ruby. Obviously what I've implemented here doesn't have the same semantics as either Ruby or Smalltalk blocks. It's just syntactic sugar (or syntactic vomit, depending on your opinion)

--
Tony Arcieri

Richard O'Keefe

не прочитано,
21 лип. 2011 р., 18:48:5821.07.11
Кому: Tony Arcieri, Erlang Questions
Ruby blocks are a crippled perversion of Smalltalk blocks.
And Smalltalk blocks are practically the same as the way
functions were written in Wirth's language Euler.

> [1,2,3,4,5].map do |n|
> n * 2
> end

in Smalltalk this is just

(1 to: 5) collect: [:n | n * 2]

The Smalltalk collection classes provide *oodles* of opportunities
to use them, and no few of the methods require *two* blocks.
For example,

aCollection
do: [:each | Transcript print: each]
separatedBy: [Transcript space]

which doesn't really fit well into Ruby syntax.
Another example would have been try-catch, which _could_ have been
a function:

try(Set_Up, % () -> Info
Tear_Down, % (Info) -> ()
Body, % (Info) -> Answer
Handler_List) % [(Info, Exception) -> Answer]

> However, I'd rather ask: can Erlang have something like Ruby like
> blocks? Yes, yes it can.

Well yes, it does. They are called funs.


>
> The linked patch implements a feature I'm tentatively calling
> "funargs" (yes, I know, this name has prior usage in the funarg
> problem. If you don't like it suggest a better one!)

Almost ANYTHING, up to and including "tinklebats", would be
better than twisting existing words into incompatible meanings.
Since the Latin word "fungor" means "to occupy oneself with
anything", "perform", "execute" (Cassell's Latin Dictionary),
why not call them "fungors"?

> The patch adds a new 'do' keyword and otherwise copies the Ruby syntax
> outright.

> Let's compare what Erlang lets you do now with what the
> syntax this patch provides allows.
>
> Before:
>
> mnesia:transaction(fun() ->
> mnesia:write(#thing{foo=1, bar=2, baz=3})
> end).
>
> After:
>
> mnesia:transaction do
> mnesia:write(#thing{foo=1, bar=2, baz=3})
> end.
>
> That's marginally better.

It's a very small margin, and possibly a negative one.
Should it not be

<function>([<exprs>]) do [<pats> ->] <body> end
=>
<function>(fun () -> <body> end[, <exprs]>)
or <function>(fun <pats> -> <body> end[, <exprs]>)
?
So should it not be
mnesia:transaction() do


mnesia:write(#thing{foo=1, bar=2, baz=3})
end

for consistency?

> How about some more examples?
>
> Before:
>
> lists:map(fun(N) ->
> N * 2
> end, [1,2,3,4,5]).
>
> After:
>
> lists:map([1,2,3,4,5]) do |N|
> N * 2
> end.
>
> Again, it's marginally better.

This is where the margin turns negative.
What has mapping to do with "DO"?

And YEEK! The argument list here
looks like nothing else in Erlang whatever!
Surely surely surely Erlang should look like Erlang!

lists:map([1,2,3,4,5]) do (N) -> N*2 end

(As a Smalltalk programmer, I really wish that Ruby
hadn't taken Smalltalk's syntax for *local variables*
and twisted it to mean block parameters.)

The vertical bar notation here is NOT a good fit for
a language where function arguments involve pattern
matching, and patterns can involve vertical bars.

> What if there are more arguments?
>
> Before:
>
> lists:foldl(fun(Octec, Acc) ->
> Acc bsl 8 bor Octet
> end, 0, [127,0,0,1]).
>
> After:
>
> lists:foldl(0, [127,0,0,1]) do |Octet, Acc|
> Acc bsl 8 bor Octet
> end.
>
> In this case I definitely prefer the latter form. Try to imagine
> functions with much more expressions in the fun body.

Try to imagine function calls with many more funs in their arguments!

By the way, it's now a couple of years since I proposed syntax like

(Acc where Acc = 0 then Acl bsl 8 bor Octet
for Octet <- [127,0,0,1])

the three patterns being

'(' <expr> <opt-where> opt-generators-and-guards ')'
'[' <expr> <opt-where> opt-generators-and-guards ']'
'{' <expr> where <do-bindings> opt-generators-and-guards '}'

opt-where = 'where' <do-binding> {',' <do-binding>}... | <empty>
<do-binding> = <pattern> '=' <expr> ['then' <expr>]
opt-generators-and-guards = {'for' | '||'} {generator|guard}
{',' {generator|guard}}... | <empty>

This has roots in ISWIM, Scheme, Clean, and Erlang.

> So I'll admit so far none of these examples are *particularly* more
> compelling than their equivalent "fun" forms. Where blocks get really
> interesting is when you nest them, particularly when building what
> Rubyists refer to as DSLs.

They did not invent the idea. I think Erick Sandewall may have been
the first to write about embedded DSLs (in Lisp) back in the 70s.
There have been two USENIX conferences about DSLs.

I have serious trouble reading this,
and part of the reason is that I see <thing> do <thunk>
and cannot help but read that as "do <thunk> for every element of <thing>".
This is reinforced by the fact that in
Erlang *everything* that is a function call has a pair of parentheses;
"Xml:posts" looks far more like a variable than like a function call.

The thing is, we already _have_ a way of writing XML in Erlang:

{posts, [
{post, [
{title, [Post#post.title]},
{body, [Post#post.body]},
{published_at, [Post#post.published_at]},
{comments, [
{comment, [Comment#comment.body]}
|| Comment <- Post#post.comments]}}
|| Post <- Posts]}

which is 9 lines to your 16 with no language extensions whatever.

Give me a data structure, bursting with the seeds of its own
transformation, rather than a tangle of commands.

Ruby is an imperative language working by side effects.
What works well for Ruby doesn't work so well for Erlang.

Richard O'Keefe

не прочитано,
21 лип. 2011 р., 19:11:4521.07.11
Кому: Jesper Louis Andersen, Tony Arcieri, Erlang Questions

On 22/07/2011, at 12:34 AM, Jesper Louis Andersen wrote:
> TL;DR I don't think we need a new kind of syntax for certain kinds of
> lambda sections (see the 'cut' proposal a couple of days ago from
> SRFI-26 in Scheme-land). But I do agree the notation is heavier than
> it could be. A more convenient notation would encourage people to use
> anonymous functions more.

The whole of Erlang syntax is "heavier" than it might be.
I once devised a revised syntax which I called "hErlang".
For example, this is a hErlang module:

-module predict
-export (predict/2)
-import math:(pi/0 sqrt/1)
-author "Richard A. O'Keefe"
-date {2002,08,14}
-sccs "08/16/02"

predict X0 Ns =
let {Xs,Ys} = odds_and_evens Ns,
Np = length Xs,
XBar = if Np == 0 => 0.0 else sum Xs / Np fi,
YBar = if Np == 0 => 0.0 else sum Ys / Np fi,
Beta1 = sum [(X-XBar)*(Y-YBar) for X,Y in Xs,Ys] /
sum [(X-XBar)*(X-XBar) for X in Xs],
Beta0 = YBar - Beta1*XBar,
S = sqrt((sum [(Y-Beta1*X-Beta0)^2 for X,Y in Xs,Ys])/(Np-2)),
R = sqrt((Np+1)/Np + (X-XBar)^2/sum [(X-XBar)^2 for X in Xs]),
T70 = S * R * tfun 0.85 (Np-2),
T90 = S * R * tfun 0.95 (Np-2),
Y0 = Beta1*X0+Beta0
in {Y-T90,Y-T70,Y,Y+T70,Y+T90}

odds_and_evens [X,Y|XYs] = let {Xs,Ys} = odds_and_evens XYs in {[X|Xs],[Y|Ys]}
odds_and_evens _ = {[],[]}

tfun Goal N =
let G = (Goal-0.5) * (gam N / gam (N+1)) * sqrt (pi() * N),
F = \X. (1+X*X/N)^(-0.5*(N+1))
in bsearch F G 1.0 8.0

gam 1 = sqrt (pi())
gam 2 = 1.0
gam (K+2) = (K/2.0) * gam K

bsearch F G Lo Hi | Hi-Lo <= 0.5e-6 = (Lo+Hi)*0.5
= let M = (Lo + Hi) * 0.5,
S = simpson F 0 M 1.0e-5 10 0.0
in if S < G => bsearch F G M Hi
or S >= G => bsearch F G Lo M fi

simpson F X0 X1 Eps N R0 = % 2 'where' lines shorter.
let W = (X1 - X0) / (2 * N),
R = ( 4.0 * sum [F(X0 + W * (2*I-1)) for I in [1..N]]
+ 2.0 * sum [F(X0 + W * (2*I) ) for I in [1..N-1]]
+ F X0 + F X1 ) * (W/3.0)
in if abs (R-R0) <= Eps => R else simpson F X0 X1 Eps (N*2) R fi

It looks a lot like Haskell, but it's Erlang semantics all the way.
Not unlike LFE, in fact.

I never bothered finishing this, so don't ask for the code.
I just took it far enough to determine that the thing *could* be
done and *did* produce a useful payoff (my test files were about
1/3rd shorter than normal Erlang). But incorporating records and
binary patterns and all the other things seemed too much like work.

So a syntactically leaner Erlang *is* possible. The one thing I
found in that experiment that's really important here is that you
CAN'T get there from here one step at a time. To make a really
lean Erlang, you *have* to take a great big jump to a coherently
designed whole.

Tim Watson

не прочитано,
21 лип. 2011 р., 19:19:0721.07.11
Кому: Richard O'Keefe, Tony Arcieri, Erlang Questions

That actually looks really nice.

Richard O'Keefe

не прочитано,
21 лип. 2011 р., 19:19:1521.07.11
Кому: Dhananjay Nene, Tony Arcieri, Erlang Questions

On 22/07/2011, at 2:29 AM, Dhananjay Nene wrote:

> On Thu, Jul 21, 2011 at 1:24 PM, Tony Arcieri <tony.a...@gmail.com> wrote:
>>> And voila, you have a fairly decent DSL for building XML from Erlang.
>>
>> For comparison, here's the hypothetical XML "DSL" in regular Erlang
>> syntax versus the block form:
>>
>> https://gist.github.com/1096754
>
> I couldn't but help being reminded of
> http://redmine.ruby-lang.org/issues/5054 when reading the gist of
> either version :) :)

BCPL:
$(tag $( $( $( $( $)tag
PL/I:
L: do; do; do; do; end L;
Interlisp:
[foo (bar (ugh (zap]

and that's just three languages I've used that had some way of
abbreviating a lot of "end"s. Occam, Python, Haskell, and
Clean are four languages that eliminate the ends in the first
place.

This is another example where you cannot patch your way to
improvement, a whole new front end being needed.

(The hErlang example in my previous message looks as though
it relies on indentation, but it doesn't.)

Tim Watson

не прочитано,
21 лип. 2011 р., 19:20:0021.07.11
Кому: Richard O'Keefe, Tony Arcieri, Erlang Questions
> Almost ANYTHING, up to and including "tinklebats", would be
> better than twisting existing words into incompatible meanings.
> Since the Latin word "fungor" means "to occupy oneself with
> anything", "perform", "execute" (Cassell's Latin Dictionary),
> why not call them "fungors"?

No no, I think "tinklebats" is a rocking name! :)

Tim Watson

не прочитано,
21 лип. 2011 р., 19:21:2721.07.11
Кому: Richard O'Keefe, Tony Arcieri, Erlang Questions
> and that's just three languages I've used that had some way of
> abbreviating a lot of "end"s.  Occam, Python, Haskell, and
> Clean are four languages that eliminate the ends in the first
> place.
>
> This is another example where you cannot patch your way to
> improvement, a whole new front end being needed.
>
> (The hErlang example in my previous message looks as though
> it relies on indentation, but it doesn't.)
>

I actually rather like Python and Haskell's use of indentation - god
forbid I don't want to start a debate about it though.

Richard O'Keefe

не прочитано,
21 лип. 2011 р., 19:28:5121.07.11
Кому: Tristan Sloughter, Tony Arcieri, Erlang Questions

On 22/07/2011, at 8:01 AM, Tristan Sloughter wrote:

> A reason I end up with far more anonymous functions in my Erlang than Haskell code (and end up with longer functions in Erlang) is the lack of 'let' and 'where'.
>
> In Erlang I'd do:
>
> -spec area_of_circles(record(circle)) -> [float()]
> area_of_circles(Circles) ->
> lists:map(fun(C) ->
> math:pi() * math:pow(C#circle.radius, 2)
> end, Circles).
>

Wouldn't you write

area_of_circles(Circles) ->
[math:pi()*math:pow(C#circle.radius, 2) || C <- Circles].

> While in Haskell:
>
> area_of_circles :: [Shape] -> [Float]
> area_of_circles circles =
> L.map (area_of_circle) circles
> where
> area_of_circle (Circle radius) = pi * radius^2

Wouldn't you write

area_of_circles circles = [pi*r^2 | Circle r <- circles]

The problem isn't a lack of 'let' and 'where'.
That's solved just by making names distinct.
The problem is that normal function definitions don't nest;
while you can do

area_of_circles(Cs) ->
Area = fun (C) -> math:pi()*math:pow(C#Circle.radius, 2) end,
lists:map(Area, Cs).

you still have to use a 'fun' to do it.

Tony Arcieri

не прочитано,
21 лип. 2011 р., 19:34:3521.07.11
Кому: Richard O'Keefe, Erlang Questions
On Thu, Jul 21, 2011 at 3:48 PM, Richard O'Keefe <o...@cs.otago.ac.nz> wrote:
> However, I'd rather ask: can Erlang have something like Ruby like
> blocks? Yes, yes it can.

Well yes, it does.  They are called funs.

This sort of sentiment lacks any sense of aesthetics. It is akin to saying that a potato sack is the same thing as a suit coat because both provide the same basic function of covering your torso.

Let me call out explicitly what is ugly about Erlang fun syntax: it combines a symbolic token "->" with a keyword token "end" instead of a matching pair of symbolic tokens (e.g. "{" ... "}" or even "->" ... ".") or a matching pair of keywords (e.g. "do" ... "end").

I think there are a lot of people in the Erlang community who are either completely oblivious to how that sort of thing harms the aesthetics of the language or willfully choose to ignore it. This makes the Erlang "fun" syntax awkward and clumsy and not particularly "fun", when really anonymous functions are a powerful concept and should be a pleasure to use.
 
--
Tony Arcieri

Tristan Sloughter

не прочитано,
21 лип. 2011 р., 19:47:2721.07.11
Кому: Richard O'Keefe, Tony Arcieri, Erlang Questions
Yes, I said it was a poor example :)

Tony Arcieri

не прочитано,
21 лип. 2011 р., 19:58:2421.07.11
Кому: Richard O'Keefe, Erlang Questions
On Thu, Jul 21, 2011 at 3:48 PM, Richard O'Keefe <o...@cs.otago.ac.nz> wrote:
And YEEK!  The argument list here
looks like nothing else in Erlang whatever!
Surely surely surely Erlang should look like Erlang!

   lists:map([1,2,3,4,5]) do (N) -> N*2 end

The "end" keyword, in all other cases in Erlang, is paired with a corresponding keyword, like "if", or "case", or "receive", or "try". Only in funs is "end" paired with the stabby symbol. If anything Erlang's fun syntax is inconsistent.
 
--
Tony Arcieri

Tony Arcieri

не прочитано,
21 лип. 2011 р., 20:17:3521.07.11
Кому: Richard O'Keefe, Erlang Questions
On Thu, Jul 21, 2011 at 3:48 PM, Richard O'Keefe <o...@cs.otago.ac.nz> wrote:

And YEEK!  The argument list here
looks like nothing else in Erlang whatever!
Surely surely surely Erlang should look like Erlang!

   lists:map([1,2,3,4,5]) do (N) -> N*2 end

And to address your point a little more here, no I don't think "|" isn't Erlangy anymore than I feel it isn't Ruby-like. The "|" ... "|" syntax in Ruby looks like nothing else in Ruby whatsoever, but it's still aesthetically pleasing. Certainly much more so than "(" ... ")" "->" ... "end"

Nor do I feel the stabby is necessary here any more than I feel the "def" token is needed when defining an anonymous function in Ruby. The "do" token alone signifies you're defining an anonymous function and matches to the corresponding "end" token. I don't believe it should be any problem to add Erlang guard syntax into the grammar as-is, I just omitted it because I knew this patch is admittedly a bit of a joke.

This is where the margin turns negative.
What has mapping to do with "DO"?

The do is what the mapping does. The "do" keyword is completely intuitive to me in that what follows is a function which does something. I suppose the only cognitive dissonance here is that functional programmers go out of their way to not think of their programs as actually doing something, which may make sense in a lazy language like Haskell where your program may indeed never actually do anything, but if you feel that way about a language with strict evaluation like Erlang you're just kidding yourself.

--
Tony Arcieri

Jachym Holecek

не прочитано,
21 лип. 2011 р., 20:25:2121.07.11
Кому: Tony Arcieri, Erlang Questions
# Tony Arcieri 2011-07-22:

> On Thu, Jul 21, 2011 at 3:48 PM, Richard O'Keefe <o...@cs.otago.ac.nz> wrote:
>
> And YEEK!  The argument list here
>
> looks like nothing else in Erlang whatever!
> Surely surely surely Erlang should look like Erlang!
>
>    lists:map([1,2,3,4,5]) do (N) -> N*2 end
>
>
> The "end" keyword, in all other cases in Erlang, is paired with a corresponding keyword, like "if",
> or "case", or "receive", or "try".

Please define what kind of correspondence you have in mind, and if you're
going to mention presence of some symbols in Latin alphabet please explain
why that matters at all. To me they're just syntactic items. I don't care
what characters they're made of as long as those are on my keyboard and
the result is easy to read and write (by me).

> Only in funs is "end" paired with the stabby symbol.

Let's have a look:

fun (X) -> X end
^^^ ^^^

One more look:

fun (X) -> X; (Y) -> Y end
^^^ ^^^

See? Happy now? :-)

Have fun,
-- Jachym

Tony Arcieri

не прочитано,
21 лип. 2011 р., 21:01:3521.07.11
Кому: Jachym Holecek, Erlang Questions
On Thu, Jul 21, 2011 at 5:25 PM, Jachym Holecek <fr...@circlewave.net> wrote:
Please define what kind of correspondence you have in mind, and if you're
going to mention presence of some symbols in Latin alphabet please explain
why that matters at all.

I mean honestly, are you trolling me?

Tokens like "do" and "end" are words, or more specifically keywords. Tokens like "->" are symbols. Believe it or not for most people groupings of letters, as opposed to symbolic characters, actually has a significant meaning.

To me they're just syntactic items.

Can you think like a human instead of a lexer?

Let's have a look:

 fun (X) -> X end
 ^^^          ^^^

One more look:

 fun (X) -> X; (Y) -> Y end
 ^^^                    ^^^

See? Happy now? :-)

No. Clause bodies are delimited by "->" and "end" with ";" as an optional clause separator. The "fun" keyword is not the delimiter and can be used in contexts where a fun has no clause body, such as fun module:function/arity.

--
Tony Arcieri

Amy Lear

не прочитано,
21 лип. 2011 р., 22:02:2421.07.11
Кому: Tony Arcieri, Erlang Questions
On Thu, Jul 21, 2011 at 6:01 PM, Tony Arcieri <tony.a...@gmail.com> wrote:
>> To me they're just syntactic items.
>
> Can you think like a human instead of a lexer?

This appears a little antagonistic. Jachym's responses appeared to be
in good faith and serious to my perspective.

I also don't make any kind of distinction between keywords with
letters and keywords that are symbols, and I'm not clear on why this
is important to change, at least in isolation. As Richard pointed out,
if you're going to make syntax cleaner, you need to do it
comprehensively.

And I personally don't see any readability improvement, nor anything
this permits us to do we couldn't before.

Tony Arcieri

не прочитано,
21 лип. 2011 р., 22:19:5021.07.11
Кому: Amy Lear, Erlang Questions
On Thu, Jul 21, 2011 at 7:02 PM, Amy Lear <octopu...@gmail.com> wrote:
This appears a little antagonistic. Jachym's responses appeared to be
in good faith and serious to my perspective.

I also don't make any kind of distinction between keywords with
letters and keywords that are symbols, and I'm not clear on why this
is important to change, at least in isolation. As Richard pointed out,
if you're going to make syntax cleaner, you need to do it
comprehensively.

And I personally don't see any readability improvement, nor anything
this permits us to do we couldn't before.

Well, my apologies, but I'm having a bit of trouble wrapping my brain around the lack of aesthetic sense here. So forgive me for overreacting.

Here are some strategies to delimiting tokens that make sense to me:

"{" ... "}" - the oft reviled curly brace approach. These are a paired set of tokens that match.

"beginningtoken" ... "endingtoken" - these match at least in that they're words, and perhaps their meaning describes how they represent the beginning and end of a block of code

"->" ... "." - these don't do a great job of matching up but they're kind of acceptable because they're both symbols. The "->" character looks like an arrow and makes a decent enough beginning token. The "." token has a long history as the period character at the end of a sentence and imparts this is where a function ends.

Now compare this to:

"->" ... "end"

Seriously. WTF is that? Those two tokens do not match up whatsoever.

The "->" token, elsewhere in Erlang, is found in "forms", which are statements in that they do not return a value. They define functions and can't be used from things which only comprehend Erlang expressions, such as eshell.

The "end" token, elsewhere in Erlang, is only found in expressions, like "case", "if", "receive", and "try". Expressions return a value.

Erlang fun syntax jams together the "->" token and the "end" token in Erlang's lambda expression. In my opinion "->" does not belong in this context. All of the other Erlang expressions are delimited by keywords. "->" and "end" just don't match up as beginning and ending tokens.

--
Tony Arcieri

Jachym Holecek

не прочитано,
21 лип. 2011 р., 22:28:3521.07.11
Кому: Tony Arcieri, Erlang Questions
# Tony Arcieri 2011-07-22:

> On Thu, Jul 21, 2011 at 5:25 PM, Jachym Holecek <fr...@circlewave.net> wrote:
>
> Please define what kind of correspondence you have in mind, and if you're
> going to mention presence of some symbols in Latin alphabet please explain
> why that matters at all.
>
> I mean honestly, are you trolling me?

No -- there was an attempt at humor later on, but overall I'm serious.

> Tokens like "do" and "end" are words, or more specifically keywords. Tokens like "->" are symbols.
> Believe it or not for most people groupings of letters, as opposed to symbolic characters, actually
> has a significant meaning.

Are you sure you'd convince a Chinese programmer with little to no English skills
here? I remember that when I was starting programming the language had an UNLESS
statement (some dialect of BASIC I think, too tired to be sure ATM) -- didn't know
what that word meant, but that hardly stopped me... Sure, it was nice that it was
in Latin alphabet instead of Greek or something, but it (= it's word-y nature)
wasn't terribly significant either.

> Let's have a look:
>
>  fun (X) -> X end
>  ^^^          ^^^
>
> One more look:
>
>  fun (X) -> X; (Y) -> Y end
>  ^^^                    ^^^
>
> See? Happy now? :-)
>
> No. Clause bodies are delimited by "->" and "end" with ";" as an optional clause separator. The
> "fun" keyword is not the delimiter and can be used in contexts where a fun has no clause body, such
> as fun module:function/arity.

Wait. This was in response to:

The "end" keyword, in all other cases in Erlang, is paired with a corresponding keyword, like "if",

or "case", or "receive", or "try". Only in funs is "end" paired with the stabby symbol. If anything
Erlang's fun syntax is inconsistent.

Which is wrong like I say, to quote lib/stdlib/src/erl_parse.yrl:

fun_expr -> 'fun' fun_clauses 'end' : build_fun(?line('$1'), '$2').

fun_clauses -> fun_clause : ['$1'].
fun_clauses -> fun_clause ';' fun_clauses : ['$1' | '$3'].

The "fun M:F/A" is an atomic thing, no need for pairing there as there's no
expression to enclose. And "->" has nothing to do with ";" -- the former
separates pattern from clause body, the latter separates clauses from one
another.

If you're really talking just about the aesthetical aspects of code seen as
sequence of characters (regardless of the abstract structure it encodes) than
well, you're surely free to, I just don't see the point -- and actually it's
possibly counterproductive too: it's this clear underlying structure that
(when done right) makes code feel intuitive and easy to work with.

For example, in your proposal, can I pattern-match on arguments? Use guards?
If so, will they look the same they usually look? Can I do multi-clause "do"s?
How comes you're depriving functions of bits of their arity (this kind of
implicit trickery doesn't happen anywhere else in Erlang)? Is this proposal
limited to cases that have a Fun as first argument? That again is a new
thing in the language.

So: why replace perceived inconsistency in the language by actual hardcore
one (seems that way so far)? More importantly: aren't there more significant
aspects of the language to focus on instead of something that's already
handled pretty well? (Sure, your call, just saying)

BR,

Richard O'Keefe

не прочитано,
21 лип. 2011 р., 22:39:1721.07.11
Кому: Erlang Questions

On 22/07/2011, at 11:34 AM, Tony Arcieri wrote:

> On Thu, Jul 21, 2011 at 3:48 PM, Richard O'Keefe <o...@cs.otago.ac.nz> wrote:
> > However, I'd rather ask: can Erlang have something like Ruby like
> > blocks? Yes, yes it can.
>
> Well yes, it does. They are called funs.
>
> This sort of sentiment lacks any sense of aesthetics.

On the contrary, it is motivated by a very strong sense of fitness.

> It is akin to saying that a potato sack is the same thing as a suit coat because both provide the same basic function of covering your torso.

No, it's like saying that a family sedan is pretty much the same
thing as a sports car with lots of extra chromium, several more
wheels spinning idly, and a red plastic nose on the front,

except that the family sedan is more useful.

It has been pointed out several times in this thread that funs
(or Smalltalk-style blocks) can be used easily in far more contexts
than Ruby "blocks".

> Let me call out explicitly what is ugly about Erlang fun syntax: it combines a symbolic token "->" with a keyword token "end" instead of a matching pair of symbolic tokens (e.g. "{" ... "}" or even "->" ... ".") or a matching pair of keywords (e.g. "do" ... "end").

The phrase "symbolic token" as used here is new to me.
One reason I don't like that phrase is that "->" "{" and "}"
are precisely *NOT* symbolic in any useful sense. They are
just punctuation.

In PL/I, x->y means "follow untyped pointer x to typed field y".
In C, x->y means "follow typed pointer x to typed field y".
In Strudel, x->y->z means "add an edge from x to z labelled y".
In Dot, x->y means "add an edge from x to y".
In logic, x->y means "y or not x".
In Pop-2 and S, x->y means "assign the value of y to the variable x".
In a Scheme library I have, (-> x y z...) means "send message y to
the value of x with the values of z... as arguments."
In Prolog, P->Q;R means "if P then Q else R".

I could go on. And don't get me started on possible meanings of {
and }. (Take a look at J...)

You can *call* the punctuation marks "symbolic tokens" all you want,
the problem is that they aren't symbolic *OF* anything in particular,
except by arbitrary convention in a specific system of notation.

By the way, Erlang funs ***DON'T*** "combine a symbolic token with a
keyword token". They use two keywords for brackets.
The opening bracket is 'fun'.
The closing bracket is 'end'.
The arrow is NOT a bracket. You say it would be better to use "a
matching pair of keywords"? Well, that's *EXACTLY* what Erlang does.

Funs use "->" to separate argument patterns and guards from bodies.
This is *consistent* throughout the whole of Erlang:
top level functions, if, case, receive, ...
EVERYTHING uses "->" to separate patterns-and-guards from bodies.

If you want to separate some patterns-and-guards from a body,
you use "->". Nothing else.

If you see a "->", it is separating some patterns-and-guards from
a body. Nothing else.

One of the things that is horrible about the proposal to add
funs-crippled-in-the-Ruby-manner to Erlang is that it BREAKS THIS
CONSISTENCY.
foobar do |X Y|
<body>
end
*FAILS* to
- enclose the arguments in parentheses, like ordinary functions
- separate the arguments-and-guards from the body with "->",
like ordinary functions.

This makes the language
MORE complicated
LESS consistent
for no real gain.

> I think there are a lot of people in the Erlang community who are either completely oblivious to how that sort of thing harms the aesthetics of the language or willfully choose to ignore it. This makes the Erlang "fun" syntax awkward and clumsy and not particularly "fun", when really anonymous functions are a powerful concept and should be a pleasure to use.

Smalltalk:
[ :x :y | some expression involving x and y]
Erlang:
fun (X, Y) -> some expression involving X and Y end

Erlang uses matching keywords 'fun' 'end' instead of '[' ']'.
Erlang uses '(' and ',' instead of ':'.
Erlang uses ')' where Smalltalk has nothing, but then
Erlang has pattern matching to fit in here.
Erlang uses '->' where Smalltalk has '|'.

OK, suppose we take advantage of Unicode,
and suppose we lose the argument parentheses.

fun (X, Y) -> e(X, Y) end
=>
〖X, Y ↣ e(X, Y)〗

We could do that easily, while still allowing the old syntax.

In a major revision of Erlang syntax, we should certainly give
serious thought to taking advantage of Unicode (without requiring it).

But just how much of a change is this, really?
Would that be enough to satisfy the Aubrey Beardsleys in the Erlang mailing list?

I've said it before: Erlang syntax *is* clunky, but what merits reconsideration
(which might well ratify the existing syntax as a workable compromise) is the
*whole* language, not this part or that part.

This is a textbook example of a change that would make the language WORSE
by adding fragile support for a special case in a way that makes the language
*AS A WHOLE* less consistent, without adding ANY extra power, and very little
in the way of convenience.

As for me, I find fun ... end *clunky* but *tasteful*.
I know it could be done with fewer characters in other languages,
but it has been done in a way that is coherent with the rest of
the language, and such coherence is an aesthetic (and mnemonic!)
virtue not to be sacrificed lightly.

just one thing. We can add new syntax for things we could not do easily
before, but

Richard O'Keefe

не прочитано,
21 лип. 2011 р., 22:41:3221.07.11
Кому: Erlang Questions
I just _had_ to include this quotation from today's
"Haskell Weekly Newsletter":

PenguinOfDoom: Being enlightened gentlemen, we split all
programming languages into two groups, sucks and doesn't-suck and
put all of them into the first group.

Richard O'Keefe

не прочитано,
21 лип. 2011 р., 22:43:1121.07.11
Кому: Tony Arcieri, Erlang Questions

On 22/07/2011, at 11:58 AM, Tony Arcieri wrote:
>
> The "end" keyword, in all other cases in Erlang, is paired with a corresponding keyword, like "if", or "case", or "receive", or "try". Only in funs is "end" paired with the stabby symbol.

Wrong. In funs, "end" is paired with "fun" and "fun" ONLY.

Richard O'Keefe

не прочитано,
21 лип. 2011 р., 22:54:5121.07.11
Кому: Tony Arcieri, Erlang Questions

On 22/07/2011, at 12:17 PM, Tony Arcieri wrote:

> On Thu, Jul 21, 2011 at 3:48 PM, Richard O'Keefe <o...@cs.otago.ac.nz> wrote:
>
> And YEEK! The argument list here
> looks like nothing else in Erlang whatever!
> Surely surely surely Erlang should look like Erlang!
>
> lists:map([1,2,3,4,5]) do (N) -> N*2 end
>
> And to address your point a little more here, no I don't think "|" isn't Erlangy anymore than I feel it isn't Ruby-like. The "|" ... "|" syntax in Ruby looks like nothing else in Ruby whatsoever, but it's still aesthetically pleasing. Certainly much more so than "(" ... ")" "->" ... "end"

The "|" ... "|" notation really does NOT mesh very well with pattern
matching, something Ruby is, um, deficient in. Overloading punctuation
marks with too many meanings is not a good idea in any language.

>
> Nor do I feel the stabby

Why do you call the right arrow "stabby"? To me that

> is necessary here any more than I feel the "def" token is needed when defining an anonymous function in Ruby. The "do" token alone signifies you're defining an anonymous function and matches to the corresponding "end" token.

Just *precisely* as the "fun" token alone signifies that you are defining an anonymous
function and matches the corresponding "end" token in Prolog.

*Some* token is needed to separate the arguments from the body.
Since the arrow is used for that everywhere else in Erlang,
it would be inconsistent not to use it here.

> =This is where the margin turns negative.


> What has mapping to do with "DO"?
>
> The do is what the mapping does.

No. "do" is a VERB. Mapping is about computing *values*.
Mapping is not about side effects. "DO" is about as imperative
a keyword as you could expect to find; it really does not belong
in a mostly functional language. If you want to talk about
aesthetics, "do" has got to go.

Smalltalk gets this right:

container do: aBlock DOES something for each element.
container collect: aBlock COLLECTS a value for each element (it's map).
container select: aBlock SELECTS elements (it's filter)
container count: aBlock COUNTS matching elements
container sortedBy: aBlock SORTS container BY a comparison block

Ruby seized on one special case, "do:", emptied it of all meaning,
and shifted the burden of saying what result to compute elsewhere.
Not an improvement.

> The "do" keyword is completely intuitive to me in that what follows is a function which does something. I suppose the only cognitive dissonance here is that functional programmers go out of their way to not think of their programs as actually doing something, which may make sense in a lazy language like Haskell where your program may indeed never actually do anything, but if you feel that way about a language with strict evaluation like Erlang you're just kidding yourself.

What has strict evaluation to do with it?
It's perfectly possible to have a pure functional language
(that is, no mutable data structures and no side effects anywhere
in the semantics) that is strict. It is also possible to have a
lazy language that *does* have side effects, see S for an example.
Purity and laziness are logically and practically independent.

To imply *EVERY* time that a function works by side effects is no kindness.

Richard O'Keefe

не прочитано,
21 лип. 2011 р., 23:10:2421.07.11
Кому: Tony Arcieri, Erlang Questions

On 22/07/2011, at 1:01 PM, Tony Arcieri wrote:

> On Thu, Jul 21, 2011 at 5:25 PM, Jachym Holecek <fr...@circlewave.net> wrote:
> Please define what kind of correspondence you have in mind, and if you're
> going to mention presence of some symbols in Latin alphabet please explain
> why that matters at all.
>
> I mean honestly, are you trolling me?

No, he pretty obviously wasn't.


>
> Tokens like "do" and "end" are words, or more specifically keywords.

And in Algol 60, which pretty much invented the concept,
keywords counted as single characters in the abstract alphabet
and could be freely replaced by other words or even actual characters
in implementations. (This also applied in Algol 68.)

> Tokens like "->" are symbols. Believe it or not for most people groupings of letters, as opposed to symbolic characters, actually has a significant meaning.

OK, so what's the significant meaning of

An bhfuil an fear tromchúiseach?

without looking it up?

>
> To me they're just syntactic items.
>
> Can you think like a human instead of a lexer?

I don't know Jachym Holecek at all, but with that name, I'm guessing
he might be from the Czech Republic. We might all, from time to time,
try thinking like a human being whose native language is not English
and isn't particularly English-like. To such a person, a keyword
like SML's "fn" or Erlang's "bsl" has no more significant meaning
than Haskell's "\" or C's "<<".

>
> Let's have a look:
>
> fun (X) -> X end
> ^^^ ^^^
>
> One more look:
>
> fun (X) -> X; (Y) -> Y end
> ^^^ ^^^
>
> See? Happy now? :-)
>
> No. Clause bodies are delimited by "->" and "end" with ";" as an optional clause separator. The "fun" keyword is not the delimiter and can be used in contexts where a fun has no clause body, such as fun module:function/arity.

This is so wrong an understanding of Erlang syntax that I don't know where to start.
Consider this:
_____________ ______________
fun (true) -> f() ; (false) -> g() end
| |_____ |_____ |
|____________________________________|

The "fun" matches the "end".
NEITHER "->" matches the "end".
Neither "->" has ANY matching token at the right.
If the rightmost "->" matched the "end", what would the leftmost one be doing?
If the leftmost "->" matched the "end", what kind of thing would
(body ; arguments -> body) be?
You need an understanding of Erlang syntax that works with legal Erlang examples.

It's
lambda
: FUN fun_clauses END
| FUN fun_name
;
fun_clauses
: fun_clause
| fun_clauses SEMI fun_clause
;
fun_clause
: fun_head ARROW body
;
fun_head
: arguments WHEN guard
| arguments
;

The fact that "fun" can be used without arguments or body or "end"
can in no way be taken to mean that it is not the delimiter when
there _is_ an end, just as the fact that "-" can be used without
a left operand means that it isn't an infix operator when it
_does_ have a left operand.

In this case, ";" and "->" *look* like and *act* like infix operators.
Neither of them is a bracket, here or anywhere else.

Tony Arcieri

не прочитано,
21 лип. 2011 р., 23:49:0721.07.11
Кому: Richard O'Keefe, Erlang Questions
On Thu, Jul 21, 2011 at 7:43 PM, Richard O'Keefe <o...@cs.otago.ac.nz> wrote:
Wrong.  In funs, "end" is paired with "fun" and "fun" ONLY.

Okay, conceded (and Jachym made the same point)

I'll revert to my other point, which is that the '->' token in Erlang is only found in forms outside of funs, which are expressions. No other expression in Erlang uses the '->' token.

I'd also ask what you feel about the people who responded to this thread who find the Erlang fun syntax awkward. I certainly find it awkward.

--
Tony Arcieri

Richard O'Keefe

не прочитано,
21 лип. 2011 р., 23:35:0721.07.11
Кому: Tony Arcieri, Erlang Questions

On 22/07/2011, at 2:19 PM, Tony Arcieri wrote:
> Here are some strategies to delimiting tokens that make sense to me:
>
> "{" ... "}" - the oft reviled curly brace approach. These are a paired set of tokens that match.

Who reviles it? Nobody in Erlang. We use those for tuples.
(And SETL uses them for sets, and Smalltalk uses them for arrays, and ...)


>
> "beginningtoken" ... "endingtoken" - these match at least in that they're words, and perhaps their meaning describes how they represent the beginning and end of a block of code

Hey, I'm an Ada fan.


>
> "->" ... "." - these don't do a great job of matching up

AND IN ERLANG NOBODY EVER DREAMED THAT THEY MIGHT BE THOUGHT OF AS MATCHING UP.
They do not.

Consider

max(X, Y) when X >= Y -> X;
max(X, Y) when X < Y -> Y.

Think of ";" as an infix operator:

『max(X, Y) when X >= Y -> X』
;
『max(X, Y) when X < Y -> Y』.

I've put the corner brackets in to show clearly what the "operands" of ";" are.
You will notice that the "->" tokens are INSIDE the corner brackets.
There is no sense whatever in which they can be said to match the ".".
The "." is outside the corner brackets.
NO token matches it.

Now think of "when" and "->" as infix operators.

『『『max(X, Y)』 when 『X >= Y』』 -> 『X』』
;
『『『max(X, Y)』 when 『X < Y』』-> 『Y』』.

"when", "->", and ";" look like infix operators and in many ways act
like infix operators. They can certainly be parsed as infix operators.
NONE of these three tokens "matches" any other token, EVER.
Not "." and not "end".

One hypothesis occurs to me, and that is that you have formed a mental model
of Erlang based on functions and funs with only one clause, where you might
see a parallel between
[](int x, int y) { return x + y; } // C++
^(int x, int y) { return x + y; } // Objective C
fun ( X, Y) -> X + Y end

and think that "fun" is like "[]" or "^", "->" is like "{",
and "end" (or ".") is like "}".

But that is a false analogy which breaks down horribly when you have
multiple clauses. If it's not your analogy, my apologies, but it is
the only way I can imagine someone coming up with the crazy idea
that "->" *ever* matches "end" or ".".

> Now compare this to:
>
> "->" ... "end"
>
> Seriously. WTF is that?

It is a radical misunderstanding of Erlang syntax, that's what it is.
There is *NO* syntactic unit in Erlang *anywhere* that has the
form "->" ... "end". None.

> Those two tokens do not match up whatsoever.
>
> The "->" token, elsewhere in Erlang, is found in "forms", which are statements in that they do not return a value.

Wrong. There are no "forms" in Erlang which do not return values.
"if", "case", "receive", and "try" are *ALL* of them *expressions*
with well defined values.

It's true that in C/C++/ObjC/JavaScript/Java/C# "if" and "case" and "try"
are statements. So much the worse for them. Erlang is not any of those
languages. (If you want to compare it with any imperative language, try
Algol 68, in which also "if" and "case" were expressions, not statements.)

Come to think of it, according to
http://www.ruby-doc.org/docs/ProgrammingRuby/
the "if" construct in Ruby is also an expression, it returns a value,
and so does "case".

> They define functions and can't be used from things which only comprehend Erlang expressions, such as eshell.
>
> The "end" token, elsewhere in Erlang, is only found in expressions, like "case", "if", "receive", and "try". Expressions return a value.

"funs" are no exception.
The pattern that is common to all of them is

<opening keyword> <head> '->' <body> {';' <head> '->' <body>}... 'end'

There is nothing whatsoever exceptional about funs in this regard.

Tony Arcieri

не прочитано,
22 лип. 2011 р., 00:10:4922.07.11
Кому: Richard O'Keefe, Erlang Questions
All right so yeah, I take this back too.

I guess the real way of looking at it is:

    fun
        [clauses]
    end

And if you look at it like that, funs are consistent with other expressions. Funs are not consistent with other forms.

Mea culpa. Perhaps I could re-evaluate this patch with a different syntax, one that works like:

   function(...) do
       [clauses]
    end

So apologies there Mr. Richard O'Keefe. You had it right and I was mistaken.
--
Tony Arcieri

Amy Lear

не прочитано,
22 лип. 2011 р., 00:12:5222.07.11
Кому: Tony Arcieri, Erlang Questions
On Thu, Jul 21, 2011 at 8:49 PM, Tony Arcieri <tony.a...@gmail.com> wrote:
> I'd also ask what you feel about the people who responded to this thread who
> find the Erlang fun syntax awkward. I certainly find it awkward.

Sure, it's awkward. So are records. There's awkward stuff in lots of languages.

The key here is, from my (and possibly others') perspective your
suggestion isn't less awkward, or more readable, or enable constructs
that were previously difficult, cumbersome, or impossible.

When you re-approach it, try to determine what exactly you gain for
the effort of changing a well-established syntax. If it doesn't
actually let anyone do anything new, it's likely to meet quite a bit
of resistance.

Tony Arcieri

не прочитано,
22 лип. 2011 р., 00:15:0322.07.11
Кому: Amy Lear, Erlang Questions
On Thu, Jul 21, 2011 at 9:12 PM, Amy Lear <octopu...@gmail.com> wrote:
Sure, it's awkward. So are records.

The difference is I think Richard O'Keefe feels my pain on the issue of records.

--
Tony Arcieri

Amy Lear

не прочитано,
22 лип. 2011 р., 00:18:3022.07.11
Кому: Tony Arcieri, Erlang Questions

EVERYONE feels the pain on the issue of records.

Tony Arcieri

не прочитано,
22 лип. 2011 р., 00:26:5722.07.11
Кому: Amy Lear, Erlang Questions
On Thu, Jul 21, 2011 at 9:18 PM, Amy Lear <octopu...@gmail.com> wrote:
EVERYONE feels the pain on the issue of records.

Except Scumbag Ericsson:

Richard O'Keefe

не прочитано,
22 лип. 2011 р., 00:28:0222.07.11
Кому: Tony Arcieri, Erlang Questions

On 22/07/2011, at 3:49 PM, Tony Arcieri wrote:

> On Thu, Jul 21, 2011 at 7:43 PM, Richard O'Keefe <o...@cs.otago.ac.nz> wrote:
> Wrong. In funs, "end" is paired with "fun" and "fun" ONLY.
>
> Okay, conceded (and Jachym made the same point)
>
> I'll revert to my other point, which is that the '->' token in Erlang is only found in forms outside of funs, which are expressions. No other expression in Erlang uses the '->' token.

I am totally confused here.
Erlang constructs "->" if and only if they have patterns-and-guards
(well, patterns-and-or-guards, to be picky) to separate from bodies.

That's it. No exceptions.

I have just revised the Expressions chapter of the reference manual,
and I cannot find one single example of a kind of expression that
_should_ use "->" but doesn't.

So what kind of expression do _you_ think ought to use "->" but doesn't?

> I'd also ask what you feel about the people who responded to this thread
> who find the Erlang fun syntax awkward. I certainly find it awkward.

Oh dear, this is going to sound insulting, but it's not meant that way.

I am more impressed by people who demonstrate that they understand how
the current syntax actually *works* before they complain about it.

I myself have said that I find Erlang syntax "clunky but tasteful".
It uses more tokens than Haskell does.

But then, Haskell syntax is surprisingly tricky, and I'm not sure
how many Haskell parsers actually get it 100% right.

For reference, it took a huge amount of fighting in the ISO Prolog
committee to agree on an unambiguous syntax, and in the revision mailing
list there are continuing, um, strong disagreements. I think the
restrictions compared with classic Prolog were and are too severe. But
a correspondent who has done a heck of a lot more work on standards issues
in recent years than I have points out with a great deal of justice that
the various Prolog implementations out there STILL don't agree on syntax,
not as much as their authors fondly imagine. He'd like to see them get
what's in the standard right before adding anything else.

Do not despise a simple syntax that implementors can actually get RIGHT.

It is *HARD* to come up with a clean coherent syntax for the whole of a
programming language. And it is triply hard to patch your way there,
and outright impossible to do it by adding inconsistencies.

Yes, "fun ... end" is not as pretty as it could be, but for something
that was added years after Erlang was shipping, it's nearly as close
to the rest of the language as anyone could wish for. (The thing I
don't like is the scope rules for variables shared between "fun" heads
and their contexts, which has nothing to do with keywords or
punctuation.)

If you don't like funs in Erlang, try Objective C or JavaScript for a while.

Tony Arcieri

не прочитано,
22 лип. 2011 р., 00:29:3222.07.11
Кому: Richard O'Keefe, Erlang Questions
On Thu, Jul 21, 2011 at 9:28 PM, Richard O'Keefe <o...@cs.otago.ac.nz> wrote:
It is *HARD* to come up with a clean coherent syntax for the whole of a
programming language. 

Dude, I know! I mean, I tried to make my own language and all. Maybe I'll try again. But it won't be on the Erlang VM.

--
Tony Arcieri

Richard O'Keefe

не прочитано,
22 лип. 2011 р., 00:30:0122.07.11
Кому: Tony Arcieri, Erlang Questions

On 22/07/2011, at 4:26 PM, Tony Arcieri wrote:

> On Thu, Jul 21, 2011 at 9:18 PM, Amy Lear <octopu...@gmail.com> wrote:
> EVERYONE feels the pain on the issue of records.
>
> Except Scumbag Ericsson:

You pay them how much for support?

Tony Arcieri

не прочитано,
22 лип. 2011 р., 00:38:1622.07.11
Кому: Richard O'Keefe, Erlang Questions
On Thu, Jul 21, 2011 at 9:28 PM, Richard O'Keefe <o...@cs.otago.ac.nz> wrote:
I am more impressed by people who demonstrate that they understand how
the current syntax actually *works* before they complain about it.

My complaint came in the form of a patch to Erlang's yecc grammar. I think that demonstrates a degree of understanding that most Erlang programmers don't have. I admit I made mistakes in some of my follow-up responses because I wasn't referencing the grammar at the time I made the response. Mea culpa.

Did I mention I implemented an entire language to the point of borderline usability on the Erlang VM?

> On Thu, Jul 21, 2011 at 9:18 PM, Amy Lear <octopu...@gmail.com> wrote:
> EVERYONE feels the pain on the issue of records.
>
> Except Scumbag Ericsson:

You pay them how much for support?

LOL okay dude. Are you happy with the rejection of your records proposals?

--
Tony Arcieri

Richard O'Keefe

не прочитано,
22 лип. 2011 р., 01:37:5622.07.11
Кому: Tony Arcieri, Erlang Questions

On 22/07/2011, at 4:38 PM, Tony Arcieri wrote:

>
> LOL okay dude. Are you happy with the rejection of your records proposals?

No. Any more than I imagine Joe Armstrong is happy that his proposal
for pretty much the same thing has come to nothing. Actually, there is
no *rejection*. It's just that nobody has got around to deciding
anything either way yet.

For Erlang's audience, I think
- fixing the major system integrity weakness of too many atoms blowing
Erlang out of the water
- a logging system that deals with all the issues recently mentioned
- line numbers in exception reports
- better tracing/monitoring tools
are probably more urgent.

There is a qualitative difference between things that are an irritation
when coding and things that can bring your system down or things that
help you fix systems while customers are screaming at you.

I've made one proposal in the "things that can bring your system down"
area, and whatever my tastes in language design, I would *hope* that that
issue would treated as more urgent. (And I'm quite disappointed that it
has apparently not been treated as very urgent, because it has quite a
warping effect on data structure design.)

If you've got a language nearly to the point of usability on the Erlang
VM, presumably you understand that VM far better than I do. I never did
manage to get my head around the Beam instruction set, so if you want to
do something extremely helpful, writing the Beam manual that should
always have existed but doesn't would be close to the top of the list.

Joe Armstrong

не прочитано,
22 лип. 2011 р., 03:55:0822.07.11
Кому: Richard O'Keefe, Tony Arcieri, Erlang Questions

Now you've set me off ...

If you think Erlang funs are problematic you should take a look
at javascript. Javascript closures are truly horrible

NOTE in what follows "$$" means the javascript shell prompt

$$ x = 10;
10

Now let's make a function y that adds x to its argument
Pretty simply, eh,

In Erlang I'd write fun(Y) -> Y + X end

In Javascript I write:

$$ f = function(y){return(x+y);};
function (y){return(x+y);}

Test it:

$$ f(5);
15

Hooray - great - but wait a moment

Now change x

$$ x=20;
20

Now if the force was with javascript I'd rather hope that
I had not accidentally broken f. What happens?

Now what was f(5), let's take a look:

$$ f(5);
25

Oh dear - maths is broken. f(5) is not what it was earlier

Try again:

$$ x = 10;
10

Add an extra level of indirection and throw in some semicolons

$$ f = (function(z){return function(y){return y+z;};})(x);

(( F = fun(Y) -> Y + X end, in Erlang :-))


function (y){return y+z}
$$ f(5);
15

So far so good.

Now lets change x

$$ x=20;
20

Have we broken f?

$$ f(5);
15

No f still works.

No Lets' go back to Erlang and repeat the argument as it were.
Let's pretent Erlang is javascript

> X = 10;
> F = fun(Y) -> X + Y end;

Now ask the javascript question "what happens if I now change X"
Erlang answer - you can't

Now if you think horrible incantations like

f = (function(z){return function(y){return y+z;};})(x);

in Javascript solved all your problems with closures think again. What you
do inside the {...} bits of a function depends crucially on the semantics
of assignment in javascript.

I have three javascript books at home - I looked up assignment in all three.
But none of them said anything sensible ...

What does

x = y;

mean in javascript?

If I say

x = y;

In javascript and then change y, is x changed? Or if I change x is
y changed.

Is x a deep or shallow copy of y - well the answer is of course "it depends"
Now in Erlang X = Y behaves as if you'd made a deep copy of Y.
Of course you don't actually make a deep copy of Y - you just think you have,
and the question "what happens to X if we subsequently change Y?" is
easy to answer "You can't change Y"

(actually - non of the three Erlang books mention this, if you come
from javascript
you have to worry about the semantics of assignment, and the deep and
shallow copying implied by assignment)

Erlang fun syntax might have the odd wart (variable bindings can sometimes
seem strange to the unaccustomed eye) but at least things bound in closures
are actually bound in the closure and cannot be changed later - this
means no nasty surprises later.

Cheers

/Joe

Nahuel Greco

не прочитано,
22 лип. 2011 р., 12:10:2822.07.11
Кому: erlang-questions
On Fri, Jul 22, 2011 at 4:55 AM, Joe Armstrong <erl...@gmail.com> wrote:
> On Fri, Jul 22, 2011 at 6:28 AM, Richard O'Keefe <o...@cs.otago.ac.nz> wrote:
>
> I have three javascript books at home - I looked up assignment in all three.
> But none of them said anything sensible ...
>
> What does
>     x = y;
> mean in javascript?
> If I say
>     x = y;
> In javascript and then change y, is x changed? Or if I change x is
> y changed.
>

Javascript books are terrible, you really need to study the ECMA-262
document to get it. Closures in JS doesn't bind the values of the
outer lexical context variables when they are created. Instead, they
keep a reference to the outer scope frame. So when you execute the
closure, there is a level of indirection to the value not present in
Erlang. Inside the closure you are really doing something like
outer_scope['x'] = y;


Saludos,
Nahuel Greco

Robert Virding

не прочитано,
22 лип. 2011 р., 14:15:5422.07.11
Кому: Joe Armstrong, Tony Arcieri, Erlang Questions
Just a quick comment on Erlang fun syntax, without getting into a discussion on Tony's suggestion. This is how I remember it.

The fun syntax was chosen to look like the syntax for "normal" functions. This because they basically have the same properties and features: multiple clauses, patterns, guards, etc. Seeing they basically behave in the same way they should look the same way. Now a choice was made to start them with the reserved word 'fun' and not to repeat it for every clause. I can't remember why we chose not to repeat the "function name" (fun) for each clause but my guess is that we considered it redundant so we chose not to include it. Another choice we made was that all variables occurring in the head of a fun clause is a new variable which inside the fun clause shadows variables with the same name outside the fun. This means, of course, that any comparison with variables outside has to be done explicitly in the guard. This is, of course, un-Erlangy but I guess we thought it fitted better into the "standard" way of the fun. We couldn't, of course, end a fun definition with a '.' as this would really screw up the syntax handling so we ended a fun in the same was as we end everything, except a catch (this was a mistake, it would have been better to have catch ... end), with an 'end'.

I know the syntax is a bit wordy but at least both the syntax and semantics are consistent. (And at my age I value consistency)

The handling of variables was then "imported" into list comprehensions, so that there now are two things which treat variables differently.

I very much like the idea of a proper let (or a where) and I think it would make variable handling clearer. Variables are handled in a consistent way but it is not always easy to work out what should happen. Most people never ave problems with this as most people write pretty "simple" code (from the compiler point of view). Adding local functions, which I think would be a Good Thing, in the same way as variables are handled today would be very confusing so some form of 'let' construct would be necessary, at least for them. Then we might as well have for variables as well.

Sorry for digressing a little here.

Robert

----- "Joe Armstrong" <erl...@gmail.com> wrote:

> On Fri, Jul 22, 2011 at 6:28 AM, Richard O'Keefe <o...@cs.otago.ac.nz>
> wrote:
> >

> > On 22/07/2011, at 3:49 PM, Tony Arcieri wrote:
> >

> I have three javascript books at home - I looked up assignment in all
> three.
> But none of them said anything sensible ...
>
> What does
>
> x = y;
>
> mean in javascript?
>
> If I say
>
> x = y;
>
> In javascript and then change y, is x changed? Or if I change x is
> y changed.
>

> Is x a deep or shallow copy of y - well the answer is of course "it
> depends"
> Now in Erlang X = Y behaves as if you'd made a deep copy of Y.
> Of course you don't actually make a deep copy of Y - you just think
> you have,
> and the question "what happens to X if we subsequently change Y?" is
> easy to answer "You can't change Y"
>
> (actually - non of the three Erlang books mention this, if you come
> from javascript
> you have to worry about the semantics of assignment, and the deep and
> shallow copying implied by assignment)
>
> Erlang fun syntax might have the odd wart (variable bindings can
> sometimes
> seem strange to the unaccustomed eye) but at least things bound in
> closures
> are actually bound in the closure and cannot be changed later - this
> means no nasty surprises later.
>
> Cheers
>
> /Joe
>
> >

Tim Watson

не прочитано,
22 лип. 2011 р., 14:23:4422.07.11
Кому: Robert Virding, Tony Arcieri, Erlang Questions
> I very much like the idea of a proper let (or a where) and I think it would make variable handling clearer. Variables are handled in a consistent way but it is not always easy to work out what should happen. Most people never ave problems with this as most people write pretty "simple" code (from the compiler point of view). Adding local functions, which I think would be a Good Thing, in the same way as variables are handled today would be very confusing so some form of 'let' construct would be necessary, at least for them. Then we might as well have for variables as well.
>

I like the idea of let bindings - I think someone has suggested this
before. It might have been Richard, although apologies if I've got
that wrong.

Tristan Sloughter

не прочитано,
22 лип. 2011 р., 14:35:4222.07.11
Кому: Tim Watson, Tony Arcieri, Erlang Questions
I think everyone has suggested let bindings at some point in time for Erlang :)

Tony Rogvall

не прочитано,
24 лип. 2011 р., 17:53:3024.07.11
Кому: Tristan Sloughter, Tony Arcieri, Erlang Questions
On 22 jul 2011, at 20:35, Tristan Sloughter wrote:

I think everyone has suggested let bindings at some point in time for Erlang :)

'let'  has been a 'reserved' word since at least 1998. I could not find any trace of it in the sources from 1994.
Maybe robert knows more about when this was first planned for ? And why it was never introduced :-) 

/Tony
"Have run Make so many times I dunno what's installed anymore"

Robert Virding

не прочитано,
24 лип. 2011 р., 18:02:5724.07.11
Кому: Tony Rogvall, Tristan Sloughter, Tony Arcieri, Erlang Questions
I can't remember when it was added. We/some-of-use/me thought it wood be a Good Thing so I added it to the reserved words, although we never got around to adding it. Not everyone was convinced. For info 'cond' is also a reserved word, another good idea we never got around to adding. :-) I have an extended 'cond' in LFE (can do pattern matching as a test) and it is useful.

Robert


Richard O'Keefe

не прочитано,
25 лип. 2011 р., 23:24:3925.07.11
Кому: Robert Virding, Tristan Sloughter, Tony Arcieri, Erlang Questions
There was once a proposal to have
begin
<bindings>
within
<expessions>
end
where the <bindings> would be visible within the <expressions> but not
outside. begin...end survives in the language, but 'within' never made it.

Joe Armstrong

не прочитано,
26 лип. 2011 р., 03:49:5226.07.11
Кому: Richard O'Keefe, Tristan Sloughter, Tony Arcieri, Erlang Questions
"let" I can do without - I've never thought this to be a problem
(and I don't want to re-iterate the pros and cons here).

"letrec" on the other hand I find sadly missing.

Choosing names for auxiliary functions ("helper" functions) is painful.


Suppose I want to define foo/2 and bar/3 which are mutually recursive
but which also call a number of private auxiliary functions. The only
encapsulation
mechanism available is the module.

I want to say:

letrec
foo(X,Y) ->
...
foo_1(...)


bar(A,B,C) ->
...
foo-1(...)
bar_26(...)

where
foo_1(...) ->

bar_26(...) ->
end.

Only the functions foo/2 and bar/3 would be visible from outside
the letrec.

The is already a mechanism for (almost) this. The module.
But there are two problems with modules - we can't in-line them
and we can't have "anonymous" modules. With a small sleight of hand we can
transform letrecs into a very Erlangly syntax.

-module().
-export[foo/2,bar/2]).

%% definitions of foo/2, bar/2 and anything else they call

-end().

Adding this to the language is a trivial exercise in pre-processing.

This would incidentally solve some other problems do do with the scope
of comments of macros. Analyzing source code is difficult because there is
no notion of the scope of a comment or the scope of a macro. Comments are not
attached to any particular function and so on. This makes refactoring tools
and IDEs messy to say the least.

Joe Williams

не прочитано,
13 вер. 2011 р., 17:32:3713.09.11
Кому: Tony Arcieri, Erlang Questions

Xml:posts do
lists:each(Posts) do |Post|
Xml:post do
Xml:title(Post#post.title),
Xml:body(Post#post.body),
Xml:published_at(Post#post.published_at),
Xml:comments do
lists:each(Post#post.comments) do |Comment|
Xml.comment do
Xml:body(Comment#comment.body)
end
end
end
end
end
end

Just happened across this thread, late to the party. Perhaps you could write your patch to do "ennnnnnd" rather than six "ends".

-Joe

Відповісти всім
Відповісти автору
Переслати
0 нових повідомлень