Today I realized by chance that in the Julia programming language, like in C/C++, assignment returns the assigned value.
To be more precise, assignment returns the right-hand side of the assignment expression. This doesn’t appear to be documented in the current (as of December 2017) stable version of the manual, but a FAQ has been added to its development version. Be aware of this subtlety, because you can get unexpected results if you rely on the type of the returned value of an assignment:
julia> let a
a = 3.0
end
3.0
julia> let a
a::Int = 3.0
end
3.0
In both cases the let
blocks return 3.0
, even though in the former case a
is really 3.0
and in the latter case it’s been marked to be an Int
.
Assignment in the REPL
The fact that assignment returns the assigned value is a very handy feature. First of all, this is probably the reason why in the Julia’s REPL the assigned value is printed after an assignment, so that you don’t have to type again the name of the variable to view its value:
julia> x = sin(2.58) ^ 2 + cos(2.58) ^ 2
1.0
Instead in Python, for example, assignment returns None
. Thus, in the
interactive mode of the interpreter you have to type again the name of the
variable to check its value:
>>> from math import *
>>> x = sin(2.58) ** 2 + cos(2.58) ** 2
>>> x
1.0
Using assignment as condition
Another useful consequence of this feature is that you can use assignment as
condition in, e.g., if
and while
, making them more concise. For example,
consider this brute-force method to compute
the Euler’s number
stopping when the desired precision is reached:
euler = 0.0
i = 0
while true
tmp = inv(factorial(i))
euler += tmp
tmp < eps(euler) && break
i += 1
end
By using this feature the while
can be simplified to:
euler = 0.0
i = 0
while (tmp = inv(factorial(i))) >= eps(euler)
euler += tmp
i += 1
end
Can this feature be a problem in Julia?
A common objection against having this feature in Python is that it is error-prone. Quoting from a Python tutorial:
Note that in Python, unlike C, assignment cannot occur inside expressions. C programmers may grumble about this, but it avoids a common class of problems encountered in C programs: typing
=
in an expression when==
was intended.
This is indeed an issue because in C and Python conditions can be pretty much anything that can be converted to plain-bit 0 and 1, including, e.g., characters.
Consider the following C program:
#include <stdio.h>
int main()
{
char a = '\0';
if (a = 0)
printf("True\n");
else
printf("False\n");
if (a == 0)
printf("True\n");
else
printf("False\n");
return 0;
}
which prints
False
True
Mistyping the condition (=
instead of ==
or vice-versa) in this language can
lead to unexpected results.
Instead, this is mostly a non-issue in Julia because conditions can only be
instances of Bool
type. Therefore, problems may arise only when dealing with
Bool
objects. One way to make an error in Julia is the following:
julia> a = false
false
julia> if (a = false)
println("True")
else
println("False")
end
False
julia> if a == false
println("True")
else
println("False")
end
True
but it is kind of useless to test equality with a Bool
as a condition, since
you can use the Bool
itself. The only other possible error you can make in
Julia I came up with is the following:
julia> a = false
false
julia> b = false
false
julia> if (a = b)
println("True")
else
println("False")
end
False
julia> if a == b
println("True")
else
println("False")
end
True
For this case I don’t have an easy replacement that could prevent you from an error, but this is also an unlikely situation. The Julia style guide suggests to not parenthesize conditions. Following this recommendation is a good way to catch the error in this case because the assignment requires parens:
julia> if a = b
println("True")
else
println("False")
end
ERROR: syntax: unexpected "="