Whitespace effects in x+1

Other than violating WYSIWYG here and there, Julia is awesome.
An example of this, to me is when
x +1
is broken, but
x + 1 works.
and
x+1 works
[ 1 +x for x in 1:3]

Adding in lots of blanks would be a good rule of thumb but leaving out all blanks seems to work also…confused…

You should really add parentheses to ambiguous expressions like that

[(1 + x) for x in 1:3]

I also recommend using JuliaFormatter or Runic

1 Like

The problem here is that + is both an infix and a prefix operator. So 1+x is legal, and +x is legal. Even 1 +x is legal, however in the construction

[1 +x for x in 1:3]

it isn’t obvious if the + should be infix or a prefix to the following generator x for x in 1:3 (I think):

julia> x = 3
3

julia> [ (1+x) for x in 1:3 ]
3-element Vector{Int64}:
 2
 3
 4

julia> [ 1 (+x for x in 1:3) ]
1×2 Matrix{Any}:
 1  Generator{UnitRange{Int64}, var"#29#30"}(#29, 1:3)

julia> [1 +x]
1×2 Matrix{Int64}:
 1  3

julia> [1+x]
1-element Vector{Int64}:
 4

julia> [1 2 
       3 4]
2×2 Matrix{Int64}:
 1  2
 3  4

julia> [(1 +x for x in 1:3)]
1-element Vector{Base.Generator{UnitRange{Int64}, var"#32#33"}}:
 Base.Generator{UnitRange{Int64}, var"#32#33"}(var"#32#33"(), 1:3)

julia> +(itr) = sum(itr)  # THIS WILL MESS UP YOUR julia SESSION!!
+ (generic function with 1 method)

julia> [1 +(x for x in 1:3)]
1×2 Matrix{Int64}:
 1  6

The parsing of array literals is special. It’s space sensitive. There are no clear precedence rules to guide the decision in your erroring example, and the parser gives up. The error message could have been clearer, though.

8 Likes

Maybe to be even a little more explicit about the prefix/infix:

julia> 1 + +2
3

julia> 1 + -2
-1

julia> 1 - +2
-1

julia> 1 - -2
3

julia> 1 - - -2 # I never knew you could keep going until now (also with + but less interesting)
-1

julia> 1 - - - -2
3

julia> 1 - - - - -2
-1

But I’ll concede it’s a touch weird that

julia> 1 +2
3

julia> (1 +2)
3

julia> [1 +2 for _ in 1]
ERROR: ParseError:

I expect there’s some other corner case that makes this useful, though I don’t know what it is.

The “corner case” is that

As in,

SQRTISWAP = [
    1  0    0   0
    0 1/√2 𝕚/√2 0
    0 𝕚/√2 1/√2 0
    0  0    0   1
]

And, by extension, also for comprehensions.

It makes it highly ambiguous whether a whitespace is a whitespace inside an expression for one of the matrix elements, or whether it’s a whitespace separating different elements. So, use parentheses! I should probably even put parentheses around 1/√2 in the above example… but everyone is lazy sometimes, or goes for “readability”, and it does work in this case.

2 Likes

And:

julia> collect(1 +2 for _ in 1)
0-dimensional Array{Int64, 0}:
3
1 Like