Is there a good way to write code like this in Erlang ?
A == B ? X : Y
below is ruby-style code
Is there a good way to write code like this in Erlang ?
A == B ? X : Y
below is ruby-style code
The reason the ternary operator _ ? _ : _
exists in many languages is due to the fact that they have two syntactic classes: Statements and Expressions. Since if-then-else constructions usually belong the the statement-class, there is no way to get that working for when you are entering an expression. Hence you add the _ ? _ : _
operator to the expression class.
As another post states, you can take a == b ? true : false
and just write a == b
, but that does not explain the general case where we may have a == b ? X : Y
for arbitrary expressions X
and Y
. Also note that a == b
is always false
in Erlang, so you could argue that the real thing to do is to replace the whole expression with false
.
Luckily, Erlang, as is the case for most functional languages, have one syntactic class only, expressions. Hence you can use case a == b of X -> ...; Y -> ... end
in any place in a function, other expressions included. In other words, the ternary _ ? _ : _
operator is redundant in Erlang since the case
already works.
Suppose we are to return a simple proplist and we have some computation we need to do
f() ->
case a == b of
true ->
[{a, 3},
{b, <<"YE">>},
{c, 7}];
false ->
[{a, 3},
{b, <<"YE">>},
{c, "HELLO!!!"}];
end.
But since the case
construction is an expression, we can just inline it:
f() ->
[{a, 3},
{b, <<"YE">>},
{c, case a == b of
true -> 7;
false -> "HELLO!!!"
end}].
and be done with the thing.
the if .. end
construction in Erlang is usually not what you want. You want to scrutinize a value a == b
in this case and it can yield one of two outputs true
or false
. In that case the case
-expression is more direct. The if
is better used if you have to check for multiple different tests and pick the first matching, whereas we only have a single test to make here.
We use macro like this:
-define(IF(Cond,E1,E2), (case (Cond) of true -> (E1); false -> (E2) end)).
Then in your code you write:
io:format("~s~n", [?IF(a==b, "equal", "not equal")]).
If you're asking how to write something like A == B ? X : Y
as an if
expression, it's
if
A == B ->
X;
true -> % "true" means "else" here
Y
end
You can also write it as a case
expression:
case A == B of
true ->
X;
_Else ->
Y
end
or
case A == B of
true ->
X;
false ->
Y
end
Since a == b ? true : false
maps to a == b
, you can use a == b
in Erlang also.
You can use 'if' like that
foo(A,B) ->
[1,
2,
(if A == B -> 3; true -> 4 end), % A == B ? 3 : 4
5,
6].
special ?: form seems to be not necessary. You can of course use true/false as return value but I think you meant more general form, as that one would be useless (A == B does the same job).
@Gabe's answer is the most concise, and (as far as I can tell) idiomatic. The C expression ((A==B) ? X : Y)
maps directly to the Erlang expression
case A == B of
true -> X;
false -> Y
end
However, this is vastly more code than the C version. You should probably wrap it up into a convenience function — and someone should tell me if this already exists in the Erlang standard libraries!
iff(true, X, Y) -> X;
iff(false, X, Y) -> Y.
Then your C expression becomes simply iff(A == B, X, Y)
. However, beware! that just like C, Erlang eagerly evaluates function arguments. If X
or Y
have side effects or are expensive to evaluate, then iff
will not be equivalent to an in-line case
expression.