9 ms·
Currently developing both in swift and go and i have the exact inverse feeling. Go seems to have been developped by true masters that really understand that le
by bsaul 3y ago
Currently developing both in swift and go and i have the exact inverse feeling.
Go seems to have been developped by true masters that really understand that less is more. They've also kept a laser sharp focus on working on things that really matters and took the time to do things right.
Swift on the other hand looks like more and more bloated every day, without adressing the main pain points of the experience of coding in swift in the real world.
- SubjectToChange 3y agoGo seems to have been developped by true masters that really understand that less is more. "The key point here is our programmers are Googlers, they're not researchers. They're typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They're not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt." - Rob Pike Ignoring complexity on the language level simply passes the buck to application code, and developers end up paying that price across the ecosystem in perpetuity. They've also kept a laser sharp focus on working on things that really matters and took the time to do things right. Go's async model is underspecified, its implementation of generics incurs runtime overhead, much of the "wonderful tooling" only exists because of severe shortcomings in the language design and/or compiler implementation, its FFI is... difficult, etc. To be blunt, the values that Go embraces are none of the values I seek in a programming language or community. And I feel sorry for anyone too heavily invested in Go to turn back.
- bsaul 3y agogolang concurrent programming is by far the best i've ever used for its application domain which is mainly infrastructure middlewares running in a connected environment. The tradeof between language features and maintainability is also IMHO the best in class. Never before have i ever looked at a stdlib sourcecode and told myself "hu, yeah i see how that works".
- jstimpfle 3y agoI'll offer a different take: Thinking that complexity can be offloaded into the language is not seeing the whole picture. Offloading complexity into the language works for the simple cases, but the more one is trying to fit a solution into a physical box with physical constraints, and the more flexibility is required from the business logic, the situation will change in such a way that more control about the specific of the solution becomes a requirement, and the language shortcuts will fit less and less, to the point where they become a liability. Doubly so if it is difficult or impossible to unwrap the layers of language features. Of course, many problems can be solved with just a few Python scripts, or even with a huge pile of them. On the other hand, we can find a possible explanation why it could make sense for some teams to code huge apps in low-level languages (C or C++) or languages with few language features (e.g. Golang), or even to try and control the whole stack by maintaining their own language infrastructure.
- SubjectToChange 3y agothe situation will change in such a way that more control about the specific of the solution becomes a requirement, and the language shortcuts will fit less and less, to the point where they become a liability. This is exactly what Go does. Languages like C++ or Rust make it possible to expose and interact with those complex requirements, whereas Go takes it away in the name of “simplification”. Just look at all of the insane hacking tailscale does on Go to make it work for them.
- jstimpfle 3y agoAny example? I honestly don't know tailscale nor have I programmed seriously in Go. I can understand that sometimes you want tools to quickly cut through obstacles, however I've also noticed that applying such tools without extreme care, like on a regular basis, seems to always lead into local maxima and at some point these choices have to be reconsidered. One explanation for this phenomenon that I've found is that language features are typically accessed using special syntax, because otherwise they could be library features. Well, it's hard or typically even impossible to abstract over syntactic uses of such features. For example, it's hard to automate the definition of a class based on more abstract concepts, when such creation has to be done as explicit syntax instead of using a builder-style API that iteratively adds members and methods.
- nmfisher 3y agoEchoing these sentiments - I find Swift very painful to use.
- saagarjha 3y agoDepends on what you think they’re masters of. Developer experience? Sure. Modern programming languages design? Absolutely not.
- Someone 3y agoBut developer experience is a factor that should weigh heavily in evaluating the quality of a programming language. I also fear Swift is going a step too far. For example, IMO Swift's compilation speed isn’t good enough. If that’s a matter of lack of tooling, I won’t blame the language, but is it, or is its slowness unavoidable for a language that is so flexible? If the latter, I would rather have a bit less flexibility and more compilation speed. Similarly, there’s quality of error messages. Swift has gotten better there, but still has some weird ones. Are they unavoidable for the current language?
- dagmx 3y agoWhen discussing compiler speed, Go specifically prioritizes compilation speed over optimization of the resulting code. Swift and Rust both suffer from slower compilation than Go, primarily because LLVM prioritizes optimization over speed. There are of course other reasons like complexity of language, size of compilation units etc… but optimization tends to be the biggest hit in my experience. Hence why Rust is adopting/investigating cranelift as a debug compiler to improve speed.
- Someone 3y ago> There are of course other reasons like complexity of language, size of compilation units etc… but optimization tends to be the biggest hit in my experience. I guess you don’t have much experience with Swift. LLVM code generation may be slower than alternatives, but that’s more or less by a constant factor. Swift’s type inference, on the other hand, can lead to a combinatorial explosion. For example, https://www.hackingwithswift.com/articles/11/how-to-make-swift-compile-faster https://www.hackingwithswift.com/articles/11/how-to-make-swi... claims that let sum = [1, 2, 3].map { String($0) }.flatMap { Int($0) }.reduce(0, +) takes over 11 seconds to compile, while compare this code: let sum = [1, 2, 3].map { (num: Int) -> String in String(num) }.flatMap { (str: String) -> Int? in Int(str) }.reduce(0, +) takes about 75ms, and let numbers = [1, 2, 3] let stringNumbers = numbers.map { String($0) } let intNumbers = stringNumbers.flatMap { Int($0) } let sum = intNumbers.reduce(0, +) compiles in 71ms. Of course, all of these use LLVM, and likely even generate highly similar intermediate code. Also, you’ll see these slowdowns even in debug builds that don’t ask LLVM to optimize code much.
- jb1991 3y agoWhat pain points are you referring to? Beyond the lack of meaningful cross-platform abilities, what "real world" issues do you find painful in Swift?
- bsaul 3y agoindeed that would be number 1 by a VERY high margin. It's pretty ridiculous to start with "world domination" as an objective and end up 10 years later without a portable stdlib (aka foundation). Another issue would be a coherent concurrency system. Today we have a mix of gcd and actor system, declarative task, async await, etc which when put together makes me totally unable to understand what's going on in a real world program, unless you're doing like i do in my team : i specifically ban all modern concurrency apis in favor of the old ones. The same could be said with protocol extension + generics + class + structs. For each problem, there are approximately 4 possible designs with subtle tradeoffs. Swift team advocates for "expressiveness". My personnal experience is that all patterns and technics will ultimately end up showing in the codebase, depending on the mood of the developer. In the end, i've started to do like C++ developers end up doing : write guidelines on which language features are allowed, and which are forbidden. Compare that to go, where there's (at most) one satisfying way to design the problem in the typesystem. As a sideeffect people have to think more about the problem they're trying to solve, and how to simplify it to the maximum. The end result is that go pushes you toward simple and maintainable code. Swift pushes you toward being fancy for no good reasons.
- jb1991 3y ago> protocol extension + generics + class + structs you are referring to basic languauge features... you consider classes and structs pain points? these are the basic building blocks of the language, if you find them painful this is definitely not the language for you.
- bsaul 3y agoprotocol extension adds another axis of design, with all its new gotcha ( pat , overrides, etc) It looks great on paper and do enable beautiful designs in some cases. But after tasting languages like go you realize you can get away with struct & functions in 99% of the cases, and that having less design options is actually a plus. It lets you focus on what really matters : domain modeling.