Is this a bug (scalar+ranges) with the parser?

I want to add one scalar value with all value of a unitRange.

Naively, I would do the x = 1:5 .+ 0.5 code, but I realize that actually the parser is doing y=1:(5 .+ 0.5). Below a full example:

expected = [1,2,3,4,5] .+ 0.5

x = 1:5 .+ 0.5
y = 1:(5 .+ 0.5)
z = collect(1:5) .+ 0.5

@assert expected==x # not OK
@assert expected==y # not OK
@assert expected==z # OK

I achieve my intended solution with a collect. Case closed.
However, I expected that the y = 1:(5 .+ 0.5) case, to be valid only if the user don’t write the dot operator - y = 1:(5 + 0.5).

I am here to ask: is the parser doing, what it should be doing ?
:thinking:

x = (1:5) .+ 0.5

Don’t use collect.

3 Likes

Yes, + has higher precedence than :, so this is expected and correct.

Numbers are iterables (this is somewhat controversial, though), so it is also expected that 5 .+ 0.5 is 5.5.

2 Likes

1:5 .+ 0.5 is such a dangerous pattern, I’ve been bitten more than once (in more languages than Julia).

I’m going to add a warning coloring for this in my editor, there is no reason to not specify (1:5) .+ 0.5 or 1:(5 .+ 0.5) (and so on for */-)

edit: This is in my vim ftplugin for julia now. It will catch the simplest cases of this mistake.

syn match juliaRangeArithemticWarning "(\@<![^(,; ]\+:[^(,; ]\+\s*\.\?[+\-/*^]"
hi def link juliaRangeArithemticWarning ErrorMsg
1 Like

Linking this related post, where one danger is illustrated by:

v = (1:5) .- 1/7
length(v) == 4  # true  

v = collect(1:5) .- 1/7
length(v) == 5  # true  

NB: using Julia 1.7

2 Likes

Thanks I hate it

That’s just a bug. I think it may already be fixed.

Fixed in 1.7.0-rc2

https://github.com/JuliaLang/julia/issues/42291

julia> v = (1:5) .- 1/7
0.8571428571428572:1.0:4.857142857142858

julia> length(v)
5

julia> versioninfo()
Julia Version 1.7.0-rc2
Commit f23fc0d27a* (2021-10-20 12:45 UTC)
DEBUG build
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: Intel(R) Core(TM) i5-9400F CPU @ 2.90GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-12.0.1 (ORCJIT, skylake)

But …

julia> ( (1:5) .- 1/7 ) == ( collect(1:5) .- 1/7 )
false

julia> collect( (1:5) .- 1/7 ) == ( collect(1:5) .- 1/7 )
false

julia>  collect( (1:5) .- 1/7 )
5-element Vector{Float64}:
 0.8571428571428572
 1.8571428571428572
 2.857142857142857
 3.857142857142857
 4.857142857142858

julia> ( collect(1:5) .- 1/7 )
5-element Vector{Float64}:
 0.8571428571428572
 1.8571428571428572
 2.857142857142857
 3.857142857142857
 4.857142857142857

Interesting floating point numbers

julia> 1 - 1/7 + 4
4.857142857142858

julia> 1 + 4 - 1/7
4.857142857142857

julia> (1 - 1/7 + 4) == (1 + 4 - 1/7)
false

Do not have this latest release installed but could you confirm if the following is true?

v = (1:5) .- 1/7
length(v) == 5  # true

v = (1 - 1/7):(5 - 1/7)
length(v) == 5  # false
julia> v = (1:5) .- 1/7
0.8571428571428572:1.0:4.857142857142858

julia> length(v) == 5
true

julia>

julia> v = (1 - 1/7):(5 - 1/7)
0.8571428571428572:1.0:3.857142857142857

julia> length(v) == 5
false

julia> versioninfo()
Julia Version 1.7.0-rc2
Commit f23fc0d27a* (2021-10-20 12:45 UTC)
DEBUG build
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: Intel(R) Core(TM) i5-9400F CPU @ 2.90GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-12.0.1 (ORCJIT, skylake)

1 Like