You mean for generic code where n could also be an array?
This is my most common typo bug. I also wish it was an error…
You mean for generic code where n could also be an array?
This is my most common typo bug. I also wish it was an error…
I don’t think you can catch this at the syntax level, since n
might as well be an iterable.
The fundamental problem is that numbers are iterable. That would have to be fixed so that this can just error.
Just curious about others:
If you could, would you remove Numeric Literal Coefficients in Julia 2.0?
0 voters
One thing that I am sure catches out many new users are the ambiguities caused by the use of white space in parsing matrices and how these ambiguities also splatter into the parsing of vectors (but not tuples).
julia> v = [ 1 - 2, 3 + 4 ]
2-element Array{Int64,1}:
-1
7
julia> m = [ 1 - 2 3 + 4 ]
1×2 Array{Int64,2}:
-1 7
julia> m = [ 1 - 2 3 +4 ]
1×3 Array{Int64,2}:
-1 3 4
julia> v = [ 1 - 2, 3 +4 ]
ERROR: syntax: missing separator in array expression
julia> v = [ 1 -2, 3 + 4 ]
ERROR: syntax: unexpected comma in matrix expression
julia> t = ( 1 -2, 3 + 4 )
(-1, 7)
I really hope something like this proposal in #7128 makes it into Julia 2.0
I actually think the current system is fine, just requires a little effort to get used to. I understand it maybe a little tricky initially.
Perhaps the pain of all these is to encourage people to use loop comprehensions instead.
The discussion of Tau has arrived numerous times on here!
There is a package for it https://github.com/JuliaMath/Tau.jl
Rather than removing numeric literal coefficients, I might prefer the more radical move of changing the engineering syntax for floating point literals to something that (a) doesn’t clash with numeric literal coefficients and (b) is more extensible to different floating point sizes. Currently we have:
1e2
— Float64
literal1E2
— means the same thing1f2
— Float16
literal1F2
– nope, that is NOT a float literal syntaxFloat16
literalsFloat128
literals (and we don’t have those… yet)Space-sensitive parsing is a real pain. Unfortunately, it also applies to macro calls, so even if we got rid of it for array concatenation, we’d still have it there.
Could you elaborate a bit on how such a new syntax could look like? I find the current one quiet convenient and can’t really think of any syntax that’s neither taken already nor awkward to write.
I suggest to rename this thread to Julia: WAT!
Thanks, I am aware of that, but also that it is unlikely to be changed in the foreseeable future, so I was just venting
No idea
I would like it if 1.0*10^30
were parsed as a floating point literal (instead of evaluating to 5.077e18 due to integer overflow).
How would you suggest the above is parsed instead? Why not just use 1e30
?
I would, instead, prefer if in general
f(literal, b, c...)
and
let a = literal
f(a, b, c...)
end
were indistinguishable everywhere and the parser refrained from clever tricks without being asked explicitly.
That is already violated with literal integer powers (as pointed out above). When that was introduced I thought it was an especially neat trick, now I don’t think it was worth the confusion.
My parsing rule would be that [literal float] * [literal integer] ^ [literal integer]
would evaluate in arbitrary precision, and then yield a literal Float64
if the result would fit, and a literal BigFloat
otherwise.
Yes, this would be confusing sometimes, but so is 1.0*10^30 ≈ 5.07694427030e18
.
Now that I think about it, maybe [literal integer] ^ [literal integer]
should always be evaluated at parse time, and yield Int128
or BigInt
as necessary, just as integer literals with many digits do.
(Then you’d have to write e.g. 2^127 % Int64
if you wanted the current behavior, which I think is fair, because that is a very confusing way to write 0
.)
It think this would be best handled by a literal macro, eg
literal"1.0*10^30"
Perhaps a package is the best place to experiment with the semantics.
With some help
Base.:(+)(::typeof([ ]), ::typeof([ ])) = nothing
Base.:(+)(::typeof([ ]), ::typeof(())) = ["object" "Object"]
Base.:(+)(::typeof(()), ::typeof([])) = 0
Base.:(+)(::typeof(()), ::typeof(())) = NaN
we can get:
julia> [] + []
julia> [] + ()
1×2 Array{String,2}:
"object" "Object"
julia> () + []
0
julia> () + ()
NaN
This is good for experimenting. But this issue is something you are likely to stumble into. If you are aware enough to use a literal macro, it’s probably not an problem anyway.
Could a linter catch this?
Yes, a linter would be great for this too.
You are right that this is one of the problems people newbies stumble into, but Julia made a decision very early not to be clever about this.
It is tempting to expect the parser to figure out the “right” type of numeric values behind the scenes, but I imagine that would (1) either have no effect (for non-broadened values), (2) make code slower beause the parser decided that BigFloat
or BigInt
is the right type and propagate that.
A lot of examples in this topic demonstrate gotchas that even relatively experienced users stumble into. I don’t think that integer arithmetic is one of those though, it is just part of the language design.