To make it short; I don't want Erlang to be like C, it seems you got so tangled up in your own agenda so I don't think you care anymore what I am talking about. What I would like is Erlang to be able to do what it does with nested cases in a better and non-nested syntax, like the proposed "cond" that Jay is talking about. Then the programmer could decide for them selfs if they want to use it or not.<br>
<br>BR,<br>Daniel<br><br><div class="gmail_quote">2008/11/25 Richard O'Keefe <span dir="ltr"><<a href="mailto:ok@cs.otago.ac.nz">ok@cs.otago.ac.nz</a>></span><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="Ih2E3d"><br>
On 25 Nov 2008, at 9:56 pm, Daniel Rönnqvist wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Richard, I understand and to a great extent agree with your will to stay in the functional language domain and don't adapt to much other paradigms.<br>
</blockquote>
<br></div>
That's not exactly what my attitude/will is.<br>
I've forgotten who said "A language that doesn't change the way you<br>
think isn't worth learning", but there's a lot of wisdom in it.<br>
<br>
Can you hear the sound of panting? That's me trying (and failing)<br>
to keep up with how the typeful FP crowd think. Clean and Haskell 98<br>
I can get my head around, but dependent types are starting to enter<br>
what passes for the mainstream in FP, and while I know perfectly well<br>
what they are, I don't yet know how to use them effectively. The only<br>
way will be to find some time and *try*.<br>
<br>
Constraint logic programming: I know *what* it is and to a moderate<br>
extent how it works, what I don't know yet is how to use it effectively.<br>
The only way to really get my head around it will be to spend some time<br>
trying on realistic problems *without* all the time trying to pretend<br>
CLP is something else.<br>
<br>
I'm an enthusiastic Smalltalker. My own Smalltalk compiler has<br>
finally reached the point where I can run tests (finding bug of course)<br>
and benchmarks (which look pretty good actually, despite doing no<br>
optimisation at all). The way to master Smalltalk was to try very<br>
hard to do things in a Smalltalk style, and not try to pretend it's C.<br>
<br>
When I was in the happy position of being able to get a free copy<br>
of GNAT for my el cheapo and long off the market but still working<br>
just fine thank you SunBlade 1000, I used Ada, and the way to do<br>
that effectively is to stop trying to think like a C or Pascal or<br>
Fortran programmer and try to think like an Ada programmer and make<br>
really effective use of its type system.<br>
<br>
I would love to spend some time playing with APL again, but Haskell<br>
gives me a surprisingly similar programming style if I want it. But<br>
it was APL that taught me about *calculating* programs.<br>
<br>
In short, it's *always* a good idea to try to work a language for<br>
all it's worth *on its own terms* before trying to make it like some<br>
other language. (As witness the serious mess that exceptions have<br>
made of Haskell's semantics. Many obvious natural and useful<br>
equalities aren't, thanks to exceptions.)<div class="Ih2E3d"><br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
All I'm saying is that theoretically it can be inefficient to have to run _all_ tests (expressions), tag the results and then pattern match on this tag, especially when the tests take a long time.<br>
</blockquote>
<br></div>
So what? I for one have never proposed anything even remotely like<br>
that and am not proposing it now.<br>
<br>
The point at issue is this:<br>
The *precise* equivalent (linear source code expansion ratio,<br>
linear object code expansion ratio, linear run time expansion<br>
ratio, same semantics up to when types are checked) of<br>
if E1 then E2 else E3<br>
in say SML is<br>
case E1 of true -> E2 ; false -> E3 end<br>
in Erlang.<br>
<br>
That is, Erlang *HAS* if-expressions, they are just *spelled* 'case'.<br>
The only significant difference is thussyntactic style.<br>
Three magic tokens are replaced by eight.<br>
This is admittedly clumsy.<br>
However, in well written Erlang code it should also be rare,<br>
so it should not matter that much.<div class="Ih2E3d"><br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
This seem to me to be one of the two general thoughts on how to do it the Erlang-way. The other one with pattern matching but that's sometimes not an option, or at least it takes a lot more code (I.E your example in a previous post).<br>
</blockquote>
<br></div>
But "if-is-case" is done with pattern matching, so anything that<br>
can be done with "if _ then _ else _" in Algol 60 or SML or "_ ? _ : _"<br>
in C can be done with pattern matching in Erlang and so pattern<br>
matching is *always* an option.<br>
<br>
I have provided several examples. I cannot tell which you are<br>
referring to.<div class="Ih2E3d"><br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
<br>
One last thing; how am I refusing to discuss "a key reason why the present (or rather, the pre-Great Blunder) state of affairs is a Good Thing." by not wanting to use full blown application as an example?<br>
</blockquote>
<br></div>
Because the question at issue is whether the (more apparent than real)<br>
lack of an analogue of if _ then _ else _ in Erlang is a good thing or<br>
a bad thing. If it stops people writing good code, it is a bad thing.<br>
If it encourages them to write better code, it is a good thing. The<br>
only way to tell is to try real examples where someone *thinks* that<br>
if _ then _ else would be appropriate. If we can readily find better<br>
code without it, then Erlang does not have a problem.<br>
<br>
By the way, nobody has asked for a "full blown application",<br>
only for *some* real code. In the absence of real code, all the<br>
debate amounts to is<br>
X. I think Erlang needs to be like C.<br>
Y. I don't.<br>
Stalemate. With a real example, we can make progress.<div class="Ih2E3d"><br>
<br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Maybe you misunderstood me, what I wanted to know with my question was if there's a way to do this (elseif) in Erlang in a syntactically short and easy way without getting nested expressions.<br>
</blockquote>
<br></div>
You have two issues here: brevity and nesting.<br>
Brevity matters for frequent things, and in Erlang, this should<br>
not be a frequent problem.<br>
<br>
There's an important reason why it shouldn't be a frequent problem.<br>
Since not very long after Pascal came out, books and articles about<br>
how to be a good programmer started saying "DO NOT OVERUSE Boolean".<br>
Classic examples go something like this:<br>
<br>
function switch(S: SwitchNumber): Boolean;<br>
<br>
If switch(17) is true, does that mean switch 17 is on, or that it is off?<br>
Better to do<br>
<br>
type SwitchStatus = (Off, On);<br>
function switch(S: SwitchNumber): SwitchStatus;<br>
<br>
and then instead of<br>
<br>
if switch(17) then begin<br>
...<br>
end else begin<br>
...<br>
end<br>
<br>
do<br>
case switch(17) of<br>
On: ...;<br>
Off: ...;<br>
end<br>
<br>
The character classification example was a textbook instance of this<br>
design antipattern. Instead of a bunch of Boolean tests<br>
is_restricted_upper(C) -> true | false<br>
is_restricted_lower(C) -> true | false<br>
is_restricted_digit(C) -> true | false<br>
there should be a single classification function<br>
restricted_character_class(C) -> upper | lower | digit | other<br>
<br>
I repeat, this is a classic antipattern going back over 30 years.<br>
<br>
So much for the brevity of what should be rare.<br>
Now to nesting.<br>
<br>
Algol 60 (but not Algol 68), C, C++, Java, Haskell, Clean, and SML<br>
all require nested expressions if you want more than one 'if' in<br>
an expression. Let's just take determining the sign of an integer.<br>
<br>
Algol 60 if x < 0 then -1 else (if x > 0 then 1 else 0)<br>
Algol 68 if x < 0 then -1 elif x > 0 then 1 else 0 fi<br>
or (x < 0 | -1 |: x > 0 | 1 | 0)<br>
BCPL x < 0 -> -1, (x > 0 -> 1, 0)<br>
C x < 0 ? -1 : (x > 0 ? 1 : 0)<br>
Clean if (x < 0) -1 (if (x > 0) 1 0)<br>
Haskell if x < 0 then -1 else (if x > 0 then 1 else 0)<br>
Erlang case x < 0 of true -> -1 ; false -><br>
case x > 0 of true -> 1 ; false -> 0 end end<br>
Lisp (if (< x 0) -1 (if (> x 0) 1 0))<br>
or (cond ((< x 0) -1) ((> x 0) 1) (T 0))<br>
<br>
The parentheses in the Algol 60, BCPL, C, and Haskell examples<br>
are there to point out that the expressions are in fact nested,<br>
you don't really need them. All other parentheses are required.<br>
Does it really matter that much that only Algol 68 and Lisp in<br>
this list off non-nested multi-armed if (cond)? Why?<br>
<br>
Again, how-to-be-a-good-programmer textbooks have been warning<br>
for decades that complex ifs are probably wrong.<div class="Ih2E3d"><br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
I ran some benchmarks on the examples I provided with lists of 30 elements and there was no consistent efficiency winner in any of my examples but it seemed that elseif1 (andalso & orelse) and the elseif5 (using exceptions) was the slowest. I know micro-benchmarks is close to completely useless but I just couldn't help myself.<br>
</blockquote>
<br></div>
No, micro-benchmarks can tell you useful things.<br>
I'm not surprised by the exception handling approach coming last.<br>
<br>
I will say that on today's machines lists of 30 elements are probably<br>
far too short to get useful timings from, unless you are using hardware<br>
performance counters.<br>
<br>
<br>
</blockquote></div><br>