Python, Java and Scala have ternary operators. What is the equivalent in Julia?
You may be referring to this.
a = true
b = 1
c = 2
julia>a ? b : c
1
a = false
julia>a ? b : c
2
For inline use, a ? b : c exists, as mentioned by the previous answer. However it is worth noting that if-else-end in Julia works just like (if cond expr1 expr2) in most Lisp dialects which acts both as the if-clause and as the ternary operator. As such, if-then-else returns the return value of the expression that gets executed.
Meaning that you can write things like
function abs(x)
if x > 0
x
else
-x
end
end
and this will return what you want. You do not have to use a return statement to break the function block, you just return the value returned by the if-block.
Inline, you can write
if (x > 0) x else -x end
which will return the same thing as the ternary operator expression (x > 0) ? x : -x , but has the benefit of avoiding perl-ish ?: symbols and is generally more readable, but less chainable.
Most languages have a ternary operator separate from if-then-else because if clauses are statements, while in lisp-like languages they are expressions just like everything else and have a return value.
Yes! Julia has a ternary operator. Here is a quick example from the Julia documentation:
The so-called "ternary operator", ?:, is closely related to the if-elseif-else syntax, but it is used where a conditional choice between single expression values is required, as opposed to conditional execution of longer blocks of code. It gets its name from being the only operator in most languages taking three operands:
a ? b : c
The expression a, before the ?, is a condition expression, and the ternary operation evaluates the expression b, before the :, if the condition a is true or the expression c, after the :, if it is false. Note that the spaces around ? and : are mandatory: an expression like a?b:c is not a valid ternary expression (but a newline is acceptable after both the ? and the :).
The easiest way to understand this behavior is to see an example. In the previous example, the println call is shared by all three branches: the only real choice is which literal string to print. This could be written more concisely using the ternary operator. For the sake of clarity, let's try a two-way version first:
julia> x = 1; y = 2;
julia> println(x < y ? "less than" : "not less than")
less than
julia> x = 1; y = 0;
julia> println(x < y ? "less than" : "not less than")
not less than
Related
Consider the following R input:
if(TRUE){1}else{0} + if(TRUE){1}else{0}
The result is 1, but I was expecting 2. If I enclose each if-else statement in parentheses,
(if(TRUE){1}else{0}) + (if(TRUE){1}else{0})
then the result is 2.
Can someone explain this behaviour?
The else clause doesn't end till R can identify the end of the expression. In R the {} aren't part of the syntax for if/else statements. The {} can be used anywhere you want to possibly put multiple statements. You can also do
if(TRUE) 1 else 0 + if(TRUE) 1 else 0
The {} aren't really meaningful. And since
0 + if(TRUE) 1 else 0
is a valid expression, R just assumes you wanted all of that for your else clause. Normally R will end the else clause when it encounters a newline after a completed expression. This means that
if(TRUE){1}else{0} +
if(TRUE){1}else{0}
will also return the same value because the + at the end of the first line indicates that there's more to come because a valid expression can't end in +.
Note you can see how the expression is turned into the abstract syntax tree with the help of the lobstr package if you are really curious.
#lobstr::ast(if(TRUE){1}else{0} + if(TRUE){1}else{0})
o-`if`
+-TRUE
+-o-`{`
| \-1
\-o-`+`
+-o-`{`
| \-0
\-o-`if`
+-TRUE
+-o-`{`
| \-1
\-o-`{`
\-0
Here we see that everything is nested in the first if. The + is not the main operator.
As you've done, you can use () or {} to end the expression blocks explicitly
{if(TRUE){1}else{0}} + {if(TRUE){1}else{0}}
Consider also the case of
x <- 5
if(FALSE) x+1 else x+2
# [1] 7
if(FALSE) x+1 else {x}+{2}
# [1] 7
Note how the x+2 is taken all together for the else expression. It doesn't end at the first symbol x.
Is has something to to with operator affinity which determines the order of evaluation. Like math, parenthesis have a higher priority than multiplications with have a higher priority than plus and minus. The second part of the expression will never get evaluated and thus ignored resulting in 1 e.g. if(TRUE){1}else{0} + message("I'll never get printed"). Including the parenthesis will force to first evaluate both parts seperatley and then do the plus resulting in 2.
Javascript's comma operator is useful for inserting commands within code without it breaking the workflow. The preceding expression is executed but otherwise ignored (e.g. if embedded in a function that is expecting a different object):
> x = 5, 4
< 4
> x
< 5
Is there any way to implement this in R? I've tried following
',' = function(x, y) { x; y }
but R seems to have locked comma down:
> 4, 5
Error: unexpected ',' in "4,"
Is there any workaround to this?
(Un)fortunately , is one of the very few things in R that cannot be overloaded/redefined. It’s not an operator in the language, unlike e.g. `{` and `(`.
In a similar vein, while you can overload `=` and `(`, you cannot change their meaning indiscriminately; in a function call with parameters (e.g. f(a = 1, b = 2)), neither ( nor = can be made to change their meaning because, once again, they’re not operators in this context).
As noted in the comments, for your purpose, ; seems to be a very close equivalent, though.
I've written a prlog recursive factorial clause which is:
factorial(X,Y):-
(X>1)
-> factorial(X-1,X*Y)
; write(Y).
The problem is, for any valid call[for example, factorial(5,1). ], it is giving an expression rather than a value[(5-1-1-1)* ((5-1-1)* ((5-1)* (5*1)))]. How can I get a value rather than an expression.
The comment by #lurker is a bit simplistic. Comparison operators do evaluate expressions. So, your code could be made to work:
factorial(X,Y):- X>1 -> factorial(X-1,F), Y=X*F ; Y=1.
?- factorial(5,X),F is X.
X = 5*((5-1)*((5-1-1)*((5-1-1-1)*1))),
F = 120.
In Julia, I might want to write a function that returns 0 if the input is less than 1, or returns 2 if the input is greater than or equal to 1. This is a pretty simple function, and the verbosity of a five-line if else construct is probably excessive. So I'm trying to turn it into a one-line function. The best I can come up with is as follows:
f(x::Number) = begin (x < 1) && return(0); return(2); end
or
f(x::Number) = begin x < 1 ? (y=0) : (y=2); return(y); end
Are there any simpler ways to define this function?
julia> f(x::Number) = x < 1 ? 0 : 2
f (generic function with 1 method)
julia> f(0)
0
julia> f(1)
2
julia> f(0.99)
0
Alternative solution:
f(x::Number) = if (x < 1) 0 else 2 end
The if-elseif-else syntax in Julia will return the value of the expression that gets executed, which imho makes the C-like ternary operator rather superfluous. As in, all of its functionality is encompassed by a more readable alternative.
Looking at your previous attempts, I think it is worth mentioning that unlike in say Python, you rarely need to explicitly use return(). Often you can just return whatever your if-elseif-else blocks return, much like you would in most lisp dialects. Explicit return is like goto or break, something that you use to break control flow in exceptional cases.
I have a similar recursion function:
fillTable(X0,Y0,Yn,Yh):-
checkPoint(X0,Y0),
Ynext = Y0+Yh,
Ynext=<Yn,
fillTable(X0,Ynext,Yn,Yh).
checkPoint(X,Y):-
(-X-1)<Y,
X<0, Y<0,
write(X), writeq(' '), write(Y),write(' in 1 area'),
nl,
!
;
(-X+1)>Y, X>0, Y>0,
write(X),write(' '), write(Y),write(' in 2 area'),
nl,
!
;
write(X),write(' '),write(Y),write(' not in area'),nl.
Where X, Y and other var's are float, but when it's written by write(), it prints -1+0.2+0.2+0.2+... not -0.8, -0.6 or other.
How can I fix it?
This is a common beginner's issue in Prolog to confuse "unification" with "assignment".
Your expression:
Ynext = Y0+Yh,
Does not assign the value of Y0+Yh to the variable Ynext. The predicate =/2 is the unification predicate, which will take the expressions on both sides and unify them. These expressions are Ynext, a variable, and Y0+Yh, which is the functor +/2 applied to two other variables (which in your case, are instantiated). In other words, it unifies Ynext with +(Y0,Yh) and does not evaluate it.
Let's suppose then you have Y0 instantiated as -1 and Yh as 0.2. Then, the unification expression above will be:
Ynext = -1+0.2,
Which will result in Ynext having the value -1+0.2 (which is, in prolog, the same as +(-1,0.2).
If you want to evaluate the arithmetic expression and assign it, you'd use is/2:
Ynext is Y0 + Yh,
Note that the inequalities </2, >/2, etc do evaluate. So the expression:
(-X+1)>Y
Will do what you expect it to, which is to succeed or fail depending upon whether the value of the arithmetic expression (-X+1) is less than the value of Y or not.