I understand the expression will be evaluated to a value. So
a = 1
will be evaluated to 1 where as a=1; will not
However, I expect
begin a = 1; end
to evaluate to nothing as well. Why does it evaluate to 1? Intuitively I would expect the value of begin ... end expression be value of the last expression in the block.
The ; just supresses showing the value in the REPL, it doesn’t affect evaluation:
julia> (a = 1;)
1
That’s the same thing as begin a = 1 end. Actually, begin ... end is not much different that just using parentheses, except in readability. These are the same:
Yeah. The trailing semicolon at the end of an expression doesn’t affect semantics (except in different contexts, such as in a call with keyword arguments). It serves merely to supress display in the REPL, nothing to do with evaluation semantics.
I guess, to answer my own question, there are a few “theories of semicolons” you could have. We’re all on the same page that semicolons can be used to separate multiple expressions on the same line (instead of a newline) or optionally terminate complete expressions before the newline.
One theory is that they don’t change the meaning or behavior of the surrounding expressions or insert any invisible expressions. This is the way Julia works. There’s a heuristic in the REPL that if the input expression ends with a semicolon, we suppress printing, but that’s just a heuristic, the behavior of expressions doesn’t change.
Another theory is the “Matlab theory”, which is that statements (Julia doesn’t really have statements, so this would already start to strain the theory) are implicitly surrounded by a print call and putting a semicolon at the end either removes that print call, or maybe causes the statement to evaluate to a value like Julia’s nothing that doesn’t output anything when printed. Of course, Julia doesn’t have this—things are not printed by default.
This question seems to be coming from an intermediate theory where a semicolon at the end of an expression implicitly inserts nothing after the semicolon, turning an expression that would evaluate to some value into a chain that evaluates to nothing instead. If we wanted to bake the “semicolon to suppress printing” thing into the language deeper than being a REPL feature, we could have done this. However, that’s not how it works.
I think a common “misfeature” to this design would be
julia> if (a = true) print("true!") else print("false!") end
true!
Such “typo” would be errored in language like Rust where a=true evaluates to () and cannot be used as a condition.
I feel this weird because I am more mentally inclined to Rust’s design where adding an ; to the end of expression makes the expression evaluate to (), so it’s more than a surgar at REPL level
This is not very common in practice, I think. If you want to test whether a variable is true, you would normally do simply if a rather than if a == true, so there is less danger of accidentally typing if a = true. I’ve never seen the latter mistake in real code.
(Contrast this with C, where almost anything can be used as a conditional value, and accidental assignments in branches are such a common error that most compilers have a warning for this.)
Yeah, it’s a separate issue where the assignment returns the value assigned instead of nothing. But here even with semicolons, one couldn’t suppress this side-effect.
I agree it’s not very common and probably easy to spot. I am just in general not very satisfied with the side-effect on these expression evaluation (and not able to disable them with ;)
Julia, like Lisp (and most functional programming languages), is an expression-oriented language and doesn’t have statements. You’ll note that in Python, assignment is a statement. But then they eventually felt compelled to add the := operator just so that you can do an assignment that is an expression. Of course, why have assignment be a statement in the first place? So that you can’t accidentally do if x = 123 and have it evaluate to true. But Julia doesn’t have truthiness, which is a fundamentally broken concept, so this isn’t a big issue in the first place.
A few years ago I wrote a blog post about the return value of assignment and consideration of possible problems in conditionals (coming to similar conclusions as above): Returned value of assignment in Julia