Making Numeric Literals More Intuitive (DWIM) #49251
Replies: 22 comments 1 reply
-
Are functions going to specialize on that? Seems annoying that if you pass a |
Beta Was this translation helpful? Give feedback.
-
Let's also not forget your request to me for opening an issue after I proposed the original idea, which I didn't do because I felt the idea wasn't thought through yet, alright? Taking credit for other peoples ideas is not cool. Not to mention that the discussion then continued with the unresolved issue of what As I understood it, we pretty much came to the conclusion that making
As discussed on Slack, no, not really. The original idea behind making integer literals not immediately the same as a |
Beta Was this translation helpful? Give feedback.
-
As I mentioned in the relevant Slack thread, this is an idea I independently thought of about a year ago. I apologize for not mentioning you; the chat left me confused as to whether you were proposing the idea outlined in this post or the very different idea of having |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
I don't mean to "take credit" for the idea, since as I mentioned on Slack, that initial idea of a "ParsedInt" came from me reading about how Go does things (which we can't replicate due to us wanting to preserve referential transparency). I just wanted to point out that there's a whole lot more context & prior art here than your initial post suggests. Some of that prior art is Haskell requiring typeclasses to do the same thing, which we don't have.
I haven't seen you mention that on Slack and your questions about why it can't be an unparametrized
You're leaving out the fact that This is also what @KristofferC is referring to above - by making that type visible (and potentially doubling the number of integer types), it's very likely to produce A LOT of recompilation and code churn if the fact that an integer came from a literal value finds its place in the type system as its own type. Regardless, I took the last comment mentioned ("you can get away with just making At the very least, such a change in promotion behavior of literals is breaking, since currently |
Beta Was this translation helpful? Give feedback.
-
To clarify, when I said "I would like that, but [...]" I was responding to tecosaur's message, not Stefan's. I considered the question solved in support of just always parsing integer literals as
Ohhhh, I understand what you mean now. I thought your suggestion was just that One caveat is I think this should also include a |
Beta Was this translation helpful? Give feedback.
-
That is pretty much spot on with what I'm suggesting, yes. The only frontend change would be to actually emit julia> Meta.@dump f() = 1
Expr
head: Symbol =
args: Array{Any}((2,))
1: Expr
head: Symbol call
args: Array{Any}((1,))
1: Symbol f
2: Expr
head: Symbol block
args: Array{Any}((2,))
1: LineNumberNode
line: Int64 1
file: Symbol REPL[2]
2: Int64 1 would become this julia> Meta.@dump f() = 1
Expr
head: Symbol =
args: Array{Any}((2,))
1: Expr
head: Symbol call
args: Array{Any}((1,))
1: Symbol f
2: Expr
head: Symbol block
args: Array{Any}((2,))
1: LineNumberNode
line: Int64 1 # it's fine to track these as Int64, since they are an artifact from the host system
file: Symbol REPL[2]
2: Int 1 # this is the only change Note the This is consistent with the current behavior of
Floats luckily don't have the same ambiguity as |
Beta Was this translation helpful? Give feedback.
-
Well, the difficulty is in using literal floats non-disruptively. In general, literals tend to be pretty disruptive, and it would be better if it was easier to preserve types. The syntax for specifying floats of a specific type is fine, but it’s just like how |
Beta Was this translation helpful? Give feedback.
-
The difference to integers is that there isn't a "platform specific" floating point size. You either explicitly use 32 bit, or explicitly use 64 bit (or 16 bit on specialized hardware), because both of those are already extensions to the underlying architecture and writing |
Beta Was this translation helpful? Give feedback.
-
Re floats, things like There was a proposal (not mine) that the promotion rule in such cases should be that the non-default type wins, rather than the larger type as now. It seems rare to accidentally contaminate your Float64 calculation with one Float32. But the reverse is common (and an extreme performance bug on most GPUs). |
Beta Was this translation helpful? Give feedback.
-
Right--what I'm saying is that literals, including things like (In cases where a strong |
Beta Was this translation helpful? Give feedback.
-
That's more an argument for having
If anything, this suggests that things like |
Beta Was this translation helpful? Give feedback.
-
To me the trade-off here is not worth it: the upside is some cases give a better answer, while the downside is more complexity, more specialization, and more potential for type instability (*). I frankly don't consider this design intuitive, since nobody knows what a (*) I see that one of the goals here is to increase type stability, for example giving |
Beta Was this translation helpful? Give feedback.
-
Right, but any kind of numeric constant will cause the same problems. Trying either (Also, I just realized as I was typing this out that I probably messed up the type-propagation for some code I wrote in a package elsewhere 😅 I've been writing Julia for years, so that probably says something about the ease with which the current design lets bugs up.) I get what you mean by not wanting to turn Julia into a CAS, but I don't think this goes much further in a CAS-y direction than including |
Beta Was this translation helpful? Give feedback.
-
Maybe I should explain the new proposal, which does not involve Literal integers will always have type This adds exactly 1 extra type (since |
Beta Was this translation helpful? Give feedback.
-
That's basically the same thing, just with a better (albeit less descriptive) name. |
Beta Was this translation helpful? Give feedback.
-
No, that is NOT what I'm proposing! I'm not proposing to add a new type. I'm proposing to assign
|
Beta Was this translation helpful? Give feedback.
-
To add to the feeling of pickiness,
it should be "what they really meant is But I too wouldn't change this. This seems like a job to delegate to a linter or your favorite AI coding assistant, rather than adding more complexity to the language. We're in an era where coding details like this seem likely to be of diminishing concern. |
Beta Was this translation helpful? Give feedback.
-
Since this discussion revolves mostly around changing the actual type that's being emitted, I've opened a seperate issue to discuss my proposal for only changing what the parser emits, without introducing new types #49223 |
Beta Was this translation helpful? Give feedback.
-
I think that's backwards. Both from and from talking to people experienced in how coding assistants work, we're entering an era where coding details are likely to be the only concern left for humans. What coding assistants are good at is understanding high-level abstractions. When I tried out GPT-4, I asked it to implement a mixed integer linear programming algorithm in Julia from scratch. It was able to generate mathematically/conceptually correct code on the first try. But the code had lots of bad behavior for high-performance or production code, e.g.:
In other words, if you want to know "What kinds of mistakes will coding assistants make?" you should be asking yourself, "What kinds of mistakes would a brand-new user make?" This is likely to remain the case for the foreseeable future, because LLMs are trained on real code, most of which:
The only part of coding that LLMs can't automate is debugging of minor details like preserving types. That means that Julia code needs to either "Just work" even if poorly written, or it needs to aggressively throw errors (preferably at compile time). |
Beta Was this translation helpful? Give feedback.
-
In a sense, the ideal language for an LLM is Rust (throw lots of errors at compile time that catch mistakes), but more readable (so I can verify the code is correct). |
Beta Was this translation helpful? Give feedback.
-
I see things differently especially w.r.t. the "only" part of your statement, but perhaps it's not worth hashing out here as it's a bit off-topic. Even supposing you're right about the limitations of the AIs, this is certainly the kind of thing that can be analyzed & caught in a linter. Anyway, it seems the proposal is still a bit in flux. #49207 (comment) has its own downsides: suppose I'm trying to calculate the mean intensity in an 8-bit grayscale image. I might use an accumulator to first sum the pixels, and |
Beta Was this translation helpful? Give feedback.
-
Quoting Stefan Karpinski on an idea I proposed to him on Slack today:The proposal is, specifically, that we create a new parametric type,Weak{<:Number}
, that promotes differently from current behavior. So,x::Weak{Int64} + y::Int32
will returnz::Int32
. When combined with other weak types, weak types will promote as usual.EDIT: @Seelengrab has come up with a better version of this idea later in the thread, where
Int
always means a weak integer. Whenever a weak number comes into contact with a non-weak number, the weak type will "Give way," and all integer literals are parsed asInt
.The goal here is to make literals as non-disruptive as possible, by parsing all literals as weak literals. Usually, when someone types
y = x + 1
, what they really meant isy = x + one(x)
. This would avoid type-instabilities or type disruption when using literals, avoiding one of the more common pitfalls for new users learning Julia.Beta Was this translation helpful? Give feedback.
All reactions