To me, (a = 1, b=2)
is literal, (;a, b)
or (; :a =>1 , :b => 2)
is kinda non-literal. And a bit weird to have ;
as prefix. This syntax is also not mathematical.
This syntax seems out of vacuum, not from mathematics.
struct
s are not from mathematics either. I donât see the problem.
To me, the ânon-literalityâ of (; a, b)
is why this works. Just like in function arguments, where the semicolon signals âordered arguments end here, from now on only specified, âextraâ informationâ, it means âthis tuple is not a normal, ordered, tupleâ.
The semicolon is used consistently to mark âhere begin keywordsâ throughout the language and have since Julia 0.2 (IIRC), so it certainly doesnât come out of nowhere.
Itâs even required by YASGuide and BlueStyle.
In argument lists, always separate positional arguments from keyword arguments using a semicolon (
;
).
When calling a function always separate your keyword arguments from your positional arguments with a semicolon. This avoids mistakes in ambiguous cases (such as splatting a
Dict
).
It doesnât come out of nowhere for a seasoned Julia programmer, but I imagine it is fairly surprising for people coming from most other languages. Which is a pity, because IMHO Julia does very well on that front otherwise.
You donât have to be that seasoned. Day three of reading the manual, tops.
Thatâs assuming you are in the privileged position where you can set aside three days just to read the manual of yet another programming language. My point was that if you know how to program in any language, then you probably can read most Julia code without referring to the manual at all. The (; foo) = bar
syntax is a major exception to this rule, and itâs one which is also potentially quite hard to google.
Iâm sorry, but why should Julia satisfy such a ridiculous requirement? Do you really think thereâs a language out there that does? Do you really think someone whoâs only ever done Common Lisp would be able to read most Python code without a manual? Or that someone who only knows Python would never need a manual to read Java?
Julia is its own language, and is under no obligation to be readable without a manual by someone âwho knows to program in another languageâ. As it is, Julia is very readable already, and moreover very consistent in its syntax, and you canât realistically expect more of a programming language.
I agree on the difficulties that ;
poses for beginners. But at the same time I think this:
is asking too much. A big part of what makes Julia appealing is its syntax being more expressive than say Matlab or Python. And you can hardly have both âmore expressive syntaxâ and âknowing Matlab/Python is enough to read the codeââŚ
I mean even basic array literals are un-understandable without reading the manual!
A = 1:3
B = [A A]
C = [A, 5:9]
D = [A; 5:9]
Maybe a Matlab/Python user thinks they understand this code, but theyâre probably wrong. Theyâre also unlikely to guess what
:x
means unless they happen to know Ruby or another language with symbols.
Then thereâs broadcasting:
x = 0:0.1:pi
A = cos.(x) .+ rand.()
Good luck understanding this without reading about loop fusionâŚ
Thereâs also chained comparisons:
1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
Or the convention-based difference between
filter(...)
# and
filter!(...)
and probably many more examplesâŚ
Iâm personally happy Julia offers some pleasant, original (or at least less common) syntax rather than a rehash of 2-3 dominant languages
Thanks for all the explanations. I can get the syntax design via take ;
as separator not prefix.
While as separator it surely make sense.
Sorry, poor choice of words on my end. When I said âyou should be able to read Julia without a manualâ, I meant âyou probably would be able to do thatâ. The point that I was trying to make is exactly the one you are raising, which is that Julia is very readable. Thus (;foo) = bar
is a bit of an odd one out.
I agree with you that there are some features of Julia which you will not be able to make sense of without a manual, but for most of them itâs hard to think of a better way. Personally, Iâm not convinced (;foo) = bar
falls into this category. Iâd argue the old-style @unpack foo = bar
is potentially easier to grasp, and if not then at least thereâs the obvious ?@unpack
to get help.
Having said that, I of course understand that many people way smarter than myself must have thought very carefully about why (;foo) = bar
is better than @unpack foo = bar
, and I imagine I will come to agree with them sooner or later. However, Iâm not there yet, and I assume others arenât either.
This is analogous to user asking, âwhat is a[3]
?â, and very few would think having getindex(a, 3)
everywhere is a good idea.
julia> Meta.@lower (;re) = a
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope`
1 â %1 = Base.getproperty(a, :re)
â re = %1
âââ return a
))))
in general, ?
doesnât help with syntax question, but @lower
does
If beginners donât know about this syntax, theyâre not very likely to know about Meta.@lower
either, or how to read it
well, but thatâs like saying user donât know how to use >?
, itâs one-time and universal enough I wonât worry about it.
Is it really that much more surprising or âoddâ than slurp/splat syntax or destructuring of general iterables?
(For the record, Iâm not a big fan of this syntax either, but not because you have to look it up in the manual.)
Could the help system be able to give nice help for something like a (;foo) = bar
expression?
Itâs a slightly weird syntax, but itâs a useful feature and this is the natural syntax for it. How did we get here?
Methods definitions
- Positional args:
f(x, y)
- Positional and keyword args with defaults:
f(x, y; a=1, b=2)
- Positional and keyword args without defaults:
f(x, y; a, b)
- Keyword args only with defaults:
f(; a=1, b=2)
- Keyword args only without defaults:
f(; a, b)
Tuple syntax
- Construction, like 1 without the function:
(x, y)
- Destructuring, like 7 but left of an assignment:
(x, y) = ...
Named tuple syntax
- Construction with explicit values, like 4 without the function:
(; a=1, b=2)
- Construction with implicit values, like 5 without the function:
(; a, b)
- Destructuring, like 10 but left of assignment:
(; a, b) = ...
The only thing thatâs new in Julia 1.7 is the last itemânamed tuple destructuring. Once you see it in the context of all these other syntaxes, perhaps it becomes clear why itâs the only syntax choice that fits in with all the rest.
Might I suggest a section of the manual devoted to the concept of destructuring and examples of these various syntaxes?
Thatâs a great idea and would be an excellent doc contribution if someone cares to take a crack at it.