It is so nice to program in a sane language!

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.

3 Likes

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
8 Likes

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.

2 Likes

I’m too curious now given the above examples. Can someone explain in the following:

f2=3
2f2

produces 200.0f0?

2f2 is parsed as a Float32 literal for 2 * 10^2, which equals 200.0. This happens before any variables are checked for values.

1 Like

ah, of course. thanks.

I ran into this recently - my reason for not doing the latter was that my exponent was stored in a variable (and x=30; 1.0ex) doesn’t work.

Edit: I don’t have a good suggestion to your first question though :woman_shrugging:

I think that’s an actual calculation, not a question of type widening for literals. See eg exp10.

1 Like

Yes, I ended up going with exp10, just offering another reason one might try eg 1.0*10^x and get bit. I’m not arguing for a change to the language though - all the design choices around this seem reasonable to me.

1 Like

I run in a similar issue, took a while to isolate this MEW from my code:
Seems like one has to copy all varaibles first before using them like this.

function ou(au::Number;logspaced::Bool=false)
    if logspaced
        transform = (x)->(10.0^x*sign(au))
        au = log10(abs(au)) # commenting this line makes the example work as expected,.
    else
        transform = (x) ->identity(x)
    end
    return transform
end

uu(21,logspaced=false)(42) # ->42  ✓
ou(23,logspaced=true)(42)  # ->1e42  ✓
ou(-21,logspaced=false)(42) # 42 ✓
ou(-21,logspaced=true)(42) # 1e42  𝙓   -1e42 expected
ou(1,logspaced=true)(42) # 0 𝙓   1e42 expected