> let.
* 1:1: syntax error before: 'let'
OTP25 and OTP27 on windows
what’s this, I can’t find any document about it.
> let.
* 1:1: syntax error before: 'let'
OTP25 and OTP27 on windows
what’s this, I can’t find any document about it.
Quoting the documentation:
Note:
condandlet, while reserved, are currently not used by the language.
thanks and I found erlang doc upgraded ![]()
Yes, we were thinking about scoping variables but couldn’t really make up our minds so we just made let a reserved word just in case. Same with cond.
I write some rust code too.
let a = 1;
let a = 2;// bind 'a' again
println!("{}", a);// print 2
then I write a parse_transform to try it.
Surprisingly, it is very easy to implement.
-define(LET(X), {'__let_var__', X}).
main(_) ->
A = 1,
?LET(A) = 2,
io:format("~p~n", [A]).
then transform into
main(_) ->
A = 1,
A___0 = 2,// rename
io:format("~p~n", [A___0]).// replace with new name
it’s an interesting exploration ![]()
How about making cond into the ternary operator? It’s one of the few things I really miss in Erlang.
How do you mean a “ternary operator”? What we were thinking about with cond was something similar to if but with general expressions as test
cond test-expr –> body ;
test-expr –> body ;
. . . ;
else –> body
end
We couldn’t really get that far so we decided to reserve the keyword cond
Languages like Algol 60, Algol 68, Lisp,Ml, Haskell, R, and Erlang don’t need a “ternary operator” because with IF they already have it. ?: i. C has aleays struck me as an unsayisfactory ersatz for IF. It’s IF without the eordIF. Yoy get halfway through the expression before you reLise you’ve been tricked about what kind of expression it is.
I’m talking about the ? : operator from C. I just love how compact it is, and it chafes a bit that in Erlang I have to write so much more code to achieve the same thing. But as @nzok points out, IF is not that far from the ternary operator, I hadn’t thought of that before… if X > Y -> blap; X =< Y -> blop end. It’s clunkier, but also more expressive.
But the intent of cond looks pretty much like what I had in mind. An “effortless” else (as opposed the true in the IF statement that trips everyone up). But at the same time it’s very close to what case already is, so I understand why it was left out.
I guess my (admittedly half-baked) wish would be to replace the if-statement with a cond that works on guards and with else instead of true as catch-all.
And others wish for a cond that takes full expressions (not guard expressions) and evaluates them until one is true then that body. Then writing true for a catch-all would be perfectly logical in some sense, and having another way i.e else for the same thing could be considered redundant and confusing.
Yet others wish to not have to write a catch-all clause so they could use cond as a neater way for the andalso trick. Then an arbitrary catch-all value would have to be defined. ok, true, false, …, but any chosen value would interfere with the values from the other clauses as in if any of them return that value it would be indistinguishable from the catch-all.
The present state of the matter is to me starting to seem adequate, and a cond we could agree on would not contribute enough.
For what it’s worth,
If p then q else r fi
(p | q | r)
are the same thing in Algol 68. Compact isn’t always better.
Untested code warning:
-define(IF(P,Q,R), case P of true → Q ; false → R)).
should give you an if-then-else both compact and similar in style to Clean.
This doesn’t work due to a spello. This is one of the reasons I hate Erlang’s if – the fact that you have to write true for what is logically the false branch. Every sane language I know of spells that else or perhaps default but not I-know-better Erlang. I know its Prolog background motivates this, but that’s BS IMO.
Don’t get me wrong, I love many aspects of Erlang, but it does get some things very wrong, expecially where “guard expressions” are involved. IMNSHO there is only one construct where the limitations of guard expressions makes sense, and that is receive, everywhere else they serve no purpose whatsoever. Please let us use general expressions and remote calls in if and where.
What about use _
-define(IF(P,Q,R), case P of true → Q ; _ → R)).
I much prefer
-define(IF(P,Q,R), case P of true → Q ; true → R)).
as Erlang has proper boolean values, either true or false, so they should be explicitly used.
Yes, if wasn’t a very smart choice. It was just meant as a replacement for case when there wasn’t any expression to evaluate and no patterns to match, just the guard expressions. We found these irritating so we added our if. Not very smart but nothing much to do about it so just get over it.
Guard expressions are necessary in all clause forms to evaluate variables from the match. We saw other languages where these tests were included in the pattern itself but they quickly became very confusing which is why we broke them out. They are limited because if they could be any expression you would quickly arrive at totally weird and confusing cases. E.g. you could have programs where all the work is done in guards and no clauses are chosen.
This would be pretty easy to implement, and I think they make sense for receive too, but for those in particular there’s a problem in that a general expression could itself have a receive internally, and defining semantics for that is not going to be fun.
Not that it’s unsolvable. I’d probably argue for similar semantics to filters in list comprehensions if we were hell-bent on adding this (nested receive could then be an exception so we won’t need to bother), but we haven’t found sufficient reason to open this can of worms.
-define(IF(P,Q,R), (fun() -> (case P of true -> Q; false -> R end) end)()). ?
I don’t believe it’s a good idea to add this, but people are always going to write weird things and if they want to lick the proverbial lightpole in the dead of winter we’re powerless to stop them. They can already do weird and confusing things in e.g. list comprehension filters, but it hasn’t been a problem in practice so I’m not convinced that this would be much worse.
What “spello” would that be? I have now tested that macro, and it works as intended.
You did notice that ?IF(P,Q,R) expands to a “case”, not an “if”, right?
I can think of several programming languages where ‘else’ is spelled ‘otherwise’,
a couple where it’s spelled ‘sinon’, and several where it doesn’t exist.
It’s one of several differences between Lisp and Scheme: ‘cond’ has an ‘else’
keyword in Scheme, but in Lisp you use T, which is Lisp’s name for “true”.
Of course in both Lisp and Scheme you use (if P Q R) with no ‘else’ at all.
Prolog’s conditional form goes back to Lisp 1.6 M-expressions:
[ C1 → B1
; C2 → B2
…
; Cn → Bn
]
where all of C1 … Cn are expressions to be evaluated in turn until one of them
comes out true, and if none of them comes out true the result is undefined. The
practice of ending with “; true → …” (actually T, not true) goes back to 1960ish.
This is very similar to
if C1 => B1
C2 => B2
…
Cn => Bn
fi
in Dijkstra’s notation, except that in Dijkstra’s notation, the order of testing is
undefined, and it is definitely an error if none of the Ci comes out true.
Please don’t. Guard expressions with side effects can create extremely non-obvious control flows. If they are allowed, humans must think about side effects from dead branches, and compilers must either generate less efficient code or introduce undefined behavior a la C++. Since Erlang cannot guarantee that an arbitrary expression doesn’t have side effects, not having them in guards is the right choice.
I know only one language that does it right, that is Haskell. In Haskell functions with side effects can’t return boolean type, so suspicious programs are rejected by the type system.
You did notice that ?IF(P,Q,R) expands to a “case”, not an “if”, right?
No I missed that, sorry. I guess one shouldn’t check forums late at night.