It is so nice to program in a sane language!

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?

  • Yes
  • No
  • I don’t care

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}:

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.

1 Like

The discussion of Tau has arrived numerous times on here!

There is a package for it :smiley:

1 Like

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:

  • 1e2Float64 literal
  • 1E2 — means the same thing
  • 1f2Float16 literal
  • 1F2 – nope, that is NOT a float literal syntax
  • no syntax for Float16 literals
  • no syntax for Float128 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.

1 Like

Fwiw, there’s an extensive discussion of this point (from 2014-2017) on the issue tracker.

1 Like

I suggest to rename this thread to Julia: WAT! :wink:


Thanks, I am aware of that, but also that it is unlikely to be changed in the foreseeable future, so I was just venting :wink:

1 Like

No idea :man_shrugging:

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...)


let a = literal
    f(a, b, c...)

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.

1 Like

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


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> () + []

julia> () + ()

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?

1 Like

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.