Posted by glhaynes 2 days ago
Pascal doesn’t do type inference at all.
I think OCaml meets both of the non-goals mentioned in the article:
“There are also two non-goals worth mentioning:
Removing overloading from the language. Without disjunction constraints, a constraint system can almost always be solved very quickly. However, this would be such a major change to the language, and break so many existing APIs, that it is not feasible to attempt at this point, even as a new language mode.
Removing bidirectional inference. We can also imagine a language design where expressions are type-checked in a strictly bottom-up fashion, starting from the leaves, like in many other C-family languages. This is another drastic simplification that essentially trivializes the whole problem. However, this would require giving up on language features such as polymorphic literals, leading-dot member syntax, closures with inferred types, and parts of generics. All of these are features that make Swift into the expressive language it is today.”
So, both are fast because they do less. Given that Apple hasn’t managed to make the Swift compiler even somewhat swift (pun intended) I think that partly is the right choice.
Great. Give me that with a modern toolchain and a good stdlib, and I’ll be one happy dev. Swift focused on solving the wrong problem. I don’t need overloading or bidirectional inference. I need fast compilation, good tooling, and a solid stdlib.
> The invalid expression from above, where + was applied to String and Int, is still rejected, however with the new algorithm, it only takes the compiler 2 seconds to reach the limit.
I think failing is okay, as the expression can then be explicitly typed. But if it would be solved slowly by the type checker, does Xcode show a slow compile warning for the line that this code should be optimized?
> However, an integer literal such as 123 actually has two default types, Int and Double, and the resulting disjunction has three choices. It might be worth considering a language change where floating point literals must be spelled with a decimal point. Today, expressions involving mixed integer and double literals can be particularly tricky to type check, for this reason.
The habit to write 123.0 for floats is second nature. I think this is a good idea, don’t know if other programmers would find that annoying? (aside the annoyance of changing existing code bases).
For your second point, this is mostly the case for Swift as well. 123 defaults to Int so if you wanted a floating point you'd have to write let x: Double = 123 or let x = 123.0. Most people will default to the latter because it is less typing.
I find that sometimes typedecls aid understanding, but they get in the way if they're the least bit complicated. I'm better off reading the program. I never had problems understanding Lisp programs for some reason.
Edit: I'm no expert in this topic, but Prolog interpreters (compilers?) have some fascinating machinery to solve complex constraints. Maybe a similar approach could help here?
Oh how I wish I could have a working Swift :(.
I've been doing some language work recently, and I'm quite sympathetic to bidirectional inferencing. I think, though, that modern PLs need better solutions for adhoc overloading. It's notorious for its complexity, blowing up algorithmically, and confusing users with surprising results (why oh why did the compiler select this function over the one I intended). That said, I haven't discovered a good alternative (for my purposes) yet.
So, something like "How to make ad-hoc polymorphism less ad hoc"?
Smells like “we made a poor architectural / design choice and ain’t walking it back”.
Type annotate everything. Don’t mix integers and doubles, be explicit. Most important of all, do not ever make a long chain of nested result building function calls with those stupid trailing untyped dangling {} closures, especially when the closure expects an implicit return of an opaque ‘some’ type.
What I’m saying is, don’t use SwiftUI. It’s a pee filled kiddie pool to attract JavaScript react devs with awful performance and semantics.
It’s actually 28% I just checked but it’s front and centre there if you scroll down.
And nobody’s mad.
I do agree that the language design has gone overboard in the last couple of years, expecially in the various approaches to parallelism.
However they are not alone, just look at any programming language sponsored by companies, you need features to justify team sizes and naturally old features don't go away.
(And while the past shouldn't necessarily be a shackle on the future, it is striking that such a radically different set of trade-offs was picked for Swift vs Obj-C.)
I think both Go and C# are pretty nice languages, to give you an idea of where I'm coming from. And Rust is very interesting -- as a user you see software that gets written in it exceed the previous state-of-the-art (e.g., ripgrep).
I don't see that w/ Swift. It seems like the opposite. E.g., the terrible Settings rewrite that rolled out a couple releases ago...
Confession, though, while I did a lot of ojbc back in the day, I've never done more than kick the tires on Swift, so I'm not critiquing from a position of deep knowledge -- more like talking shit from the sidelines. But I do think I'm right. ;-)
Just compare C# 14 with C# 1, laundry list of features, and BCL changes.
Go, has plenty of warts caused by ignoring the history of programming languages.
Rust async/await story isn't that great, as it is kind of half done.
We could also add others to the list, each year get a few more constructs, runtime changes, standard library changes, whatever is the package manager of the year, and so on.
All have issues, then again we can go back to the famous Bjarne Stroustoup quote
"There are only two kinds of languages: the ones people complain about and the ones nobody uses".
In practice obj-c apps were snappy, e.g., good perf on extremely limited hardware of original iPhone. SwiftUI (I assume) of MacOS settings app much slower than the old version it replaced -- too much heavy programmer framework magic resulting in slower final code? That's my diagnosis/guess from afar (I might be wrong ofc), a pitfall that objc did not tend to lead developers into.
> The Swift standard library has 17 overloads of + and 9 types adopting the ExpressibleByStringLiteral Protocol. This leads to an exponential combination of types and operators for the constraint solver to try.
I think the ExpressibleBy thing means that a string literal can be interpreted to mean any of those 9 types. Personally I agree with you; I would actually suggest that the compiler error out if there are anywhere near this many interpretations of an expression. Apparently the corrected expression compiles in 0.19s, which is unacceptable to me. I would much rather pay the cost once of adding a few type annotations or intermediate expressions than pay that fifth of a second over and over and over again for every recompile of that file. Since the types a pretty global constraint system, the expression is a landmine as well: you could fiddle with some distant overload which causes it to attempt the permutations in a different order and suddenly start timing out again.
I'm glad I'm not the only one wondering why this is not instant to type check.
I am very curious as to what you're running into where you're seeing wildly slow type checking times.
It could have been the library I was using (YoutubeTranscript) but I wasn't getting any type hints on the result from URLComponents either.
I just updated my app from Swift 5 to 6 and it seems a better.
Most of the time it’s a syntax error or typo.