There are all sorts of optimizations that are much harder to do in a non statically typed language. There are also all types of guaranteed safe automated refactoring you can do with a statically type language. I shutter to think about using a non type safe language with a large code base.
And what few people know, is that Apple already had a platform where all of the “apps” were written with JavaScript + TVML (a proprietary Apple markup language) - the 3rd Gen AppleTV. If I’m not mistaken, you can still write apps for the ATV4 that way.
Plex was ported to the 3rd Gen AppleTV as an unofficial app just by running a server on your computer and redirecting DNS to it.
”One of the best and most annoying things about Objective-C is that it has C in it. This has been hugely important for Objective-C in practice, because if you run into a performance problem with objc_msgSend, you can always rewrite that algorithm in C. That’s really, really, really important for Objective-C being successful in both in the days of NeXT on 16 MHz processors and also today for the low-level code that people are writing.”
This is indeed a great thing about Objective-C: it’s an improved C with a tight set of runtime features that help build interactive applications.
There’s a need for such a language, and I’m sad that so much of the rhetoric from Apple and the Swift community is working on the assumption that Obj-C should be completely replaced by Swift.
Swift is not a compact language like Objective-C. It’s more like C++ in how it tries to incorporate every programming paradigm that can possibly fit. The heavy focus on complex upfront typing is not necessarily the best choice for iterative app development.
Swift is useful in many places, but personally I found Objective-C’s “Smalltalk-flavored C” to hit a sweet spot for my GUI needs where integrating with C and C++ libraries is usually required all over the place.
Those 16MHz processors were two or more orders of magnitude slower than anything anyone's running Objective-C on these days. Is there really a need for C any more?
This is true, but consider that today we are using computers fo to run tasks much more complex than 30 years ago. Rendering a complex HTML page with CSS and Javascript is an herculean and time-consuming task, which is why Firefox and Chrome are written in C++; and don't forget deep learning!
Plus, low-level languages like C are sometimes the only way to go if you are writing for embedded systems with slow CPUs.
Firefox is on a course to remove C++ from safety critical areas and replace those with Rust.
Edit: to be clear this is based on the blog posts I’ve read from Mozilla about the introduction of Rust in different areas of Firefox. I know nothing of firm plans.
'On a course' implies that there's some sort of definite plan and resources delegated to the task. Which isn't true of Firefox and Rust, as far as I know.
While it may not be an explicit goal, everything I’ve read implies that, for example the heading in this wiki on oxidization: https://wiki.mozilla.org/Oxidation
> Moving forward, the goal of Oxidation is to make it easier and more pleasant to use Rust in Firefox, and correspondingly to increase the amount of Rust code in Firefox.
And then there is the Rust page on Mozilla’s site:
> Mozilla also utilizes Rust in many of its core initiatives including Servo and key parts of Firefox.
There is, however, no expectation or any real plan that C++ will be gone from Firefox. There's a huge amount of code, and there's a cost to rewriting it.
You don’t even need higher level tasks like that: take something as seemingly simple as processing text. That used to be 8 byte operations, display was looking up a bitmap and copying it into a buffer, but once programmers accepted that humans use more than ASCII and want nice displays that started to involve context sensitive decoding and display, processing vectors, subpixel rendering, etc. All great improvements but most of them require more CPU/RAM than a 30 year old computer had, too.
I recall discussing the spec of an upcoming phone platform in about 2007 or so. It claimed to be 4x faster than the previous generation and there was much rejoicing. And at the same time the screen went from QVGA to a widescreen that had 5x as many pixels... And the camera from 2MP to 8 or was it 12MP. In practice, from a usability perspective, the new platform was slightly slower than the previous platform :(
When compiling or video encoding I'll take a current processor. For everything else, not so much.
For speed of UI response, loading times, cursor and input latency we're at best no further forward. Quite often we're in an objectively worse situation. With a tiny few exceptions, no one cares about code or data sizes any more and that is reflected in what's delivered.
That's quite apart from the rise of web apps and the slowness that necessarily introduces.
Yeah, but you forgot to copy the other relevant part.
> The fundamental problem was Objective-C was built on top of C. C inherently has pointers. It has uninitialized variables. It has array overflows. It has all these problems that even if you have full control of your compiler and tool stack, you just can’t fix. To fix dangling pointers, you would have to fix lifetime issues, and C doesn’t have a framework to reason about that, and retrofitting that into a compatible way into the system just wouldn’t really work.
If you took away C from Objective-C, you couldn’t use C arrays on the stack, for example. And if you couldn’t do that, there’s entire classes of applications where the performance just wouldn’t be acceptable. We went around, around, around. We said the only way that this can make sense in terms of the cost of the disruption to the community is if we make it a safe programming language: not “safe” as in “you can have no bugs,” but “safe” in terms of memory safety while also providing high performance and moving the programming model forward.
That’s a good reason to create a new language. But all the C code in the world isn’t suddenly going to go away, and so the need for an improved C still remains.
That’s why LLVM is such a great idea - any llvm language can interoperate with any other, within the same binary, with no overhead. Apple isn’t throwing away their C code any time soon either. LLVM provides a smooth upgrade path via mixed language binaries.
I suspect that the move to swift would never have happened without LLVM. And I wouldn’t be surprised if llvm’s cross language compatibility was specifically attractive to Apple because it let them have their cake and eat it too - write a new language but keep legacy C code whenever that’s the best option.
> That’s why LLVM is such a great idea - any llvm language can interoperate with any other, within the same binary, with no overhead.
I don't believe LLVM provides a stable cross language ABI, and AFAIK languages just use regular FFI (via the C ABI) to communicate with one another, regardless of them being implemented on LLVM or not.
> I don't believe LLVM provides a stable cross language ABI, and AFAIK languages just use regular FFI (via the C ABI) to communicate with one another
Provided the compilers generate compatible versions of LLVM IR, then cross-language calls can be done at the IR level. See github.com/Keno/Cxx.jl
IIUC Swift already uses clang to load module maps in order to expose and call Objective-C, and they plan to do something similar with C++ (no link handy but I think there is an issue or enhancement proposal about it).
Yeah, Swift’s C interop goes further than most typical FFIs because it actually calls into Clang internals to read headers, lay out structs and form calls. C and Objective-C types, functions and methods are mapped to Swift definitions, by directly looking at the Clang AST.
Is there really such a thing? I thought the ABI was dependent on the operating system and compiler.
I agree that C is unique in it's ability to generate programs that can be interfaced with from any language. This also seems to apply to older languages like Fortran and Pascal, for some reason. Higher level languages are an ABI nightmare; seriously doubt anyone will ever dynamically link against a C++ library at runtime and call a method on a C++ object from any language that isn't C++.
As the siblings have mentioned, llvm doesn't really do this. What does, though, are the jvm and .net, although those aren't really oriented towards low-level c programming.
Language design graveyard is full of improved C attempts, because the problem is not technical, rather it can only be properly solved through change of generations.
Microsoft, Apple, Google have the luxury to impose moving away from C on their platforms.
On other platforms you have developers that won't touch any kind of Safe C even at gun point.
My guess is that a lot of the C hold-outs will never switch to another language. C represents the siren's call for them: the best performance, requires skilled handling, no seatbelts, stable definition.
A lot of C's endurance is related to programmer psychology, so it would be futile to design a better C.
C++, Rust, Go, Java will continue to drain the pool of C developers until it's only used for maintenance of existing projects.
This is why it's extremely irksome to see people recommend mixing C and e.g. Python for speed, or other such Frankenstein's monsters - it's just prolonging the agony of whoever will maintain that.
C still represents the closest approximation of what is happening on a chip, quasi-atomic operations acting on finite resources like registers, memory, and I/O. Even if you don't know assembly, you can reasonably understand what various chips will do with your C code, especially low level C code that occasionally dips into assembly (e.g., handling interrupts or chip-level atomic operations).
Rust, Go, and Java, with their memory management and cross-platform portability, and general non-determinism may eat away at the edge of C, but can never replace it.
I could see them fully replacing C if features like garbage collection and byte-code interpretation were handled at the chip-level, so languages would not have to necessarily deal with them. Could also see it happening if a chip's out-of-order execution was exposed at the language level. That would not necessarily make C worse, but Java may be more adept at handling it.
1. C is no closer than C++, or Rust (including unsafe) and they're all surprisingly pretty far from the hardware these days... this is visible the most in multi-threading, where high-level C statements are re-ordered by the compiler and even simple C statements like an integer assignment can be split into multiple instructions.
Inlining and register allocation is also quite opaque and perhaps best left to the compiler, unless one uses non-standard code to force specific behaviour.
2. Well put: Go and Java were/are eating at the edge of C. Java took serious bites in the past, nowadays they're not really competing much.
Today, what might have been a small Linux C program could be a Go program, especially if the performance constraints aren't too tight.
Technically speaking, Rust can replace C almost everywhere, it's just that it's a significantly more complex language.
I am fully convinced that if Java and .NET had a proper AOT toolchain from day 1, meaning beyond dynamic linking (NGEN) or commercial offerings from 3rd party JDKs, C's influence on FOSS world would have been much less than it achieved to be.
And we would already have achieved an UNIX like stack closer to what Inferno/Limbo was all about.
Regarding #1, disagree. In C, a function call is just a request to send the instruction pointer to another point in the memory space. In C, code is treated as data, which is how it's treated in hardware.
C++ introduces virtual functions, and when you make a function call, you're no longer going to a single place in memory, you go to where the class's virtual function table tells you to go, effectively jumping to a memory pointer. This is pretty helpful, but it's an incredibly different way to think about code. A function is no longer a set of instructions in memory, it's a logical representation of functionality.
And yes, I know in C, you can set a variable to a function location, and then jump there, but it's painful to do and you have to do it explicitly, so it doesn't really create an abstraction.
I can understand the need to create a new programming langauge, but as the previous poster wrote, they rather recreated all the complexity of C++, instead of a more lean language. Also, Swift seems to suffer from overly static typing in its object oriented approach - which defeats the idea of object oriented programming.
I find that this assertion holds about as much water for Swift as it does for Rust, Swift is not even remotely close to C++'s in terms of complexity, and that's with building in mechanisms for performant memory safety, a concept which C++ literally just shits on to this day and for the foreseeable future.
Swift is a really approachable language, it’s core features are simple and the code is very readable. You can write any app without having to use generics, extensions, protocols, more esoteric enum features, etc, etc.
But once you learn to use the more advanced features, your code just gets easier to write and maintain. I enjoy that I can pickup new language features in Swift one at a time, figuring out where each adds its best value, and occasionally refactoring to take advantage as part of my ongoing efforts to minimize code debt.
Completly different, ARC only works with APIs that follow Cocoa retain/release patterns, which aren't the only APIs that one needs to use, e.g. CoreGraphics.
And unlike JNI they aren't protected by a VM wall.
Nope. I still found many ways to crash my objective C apps while using ARC. Because Swift is memory safe I no longer have to give up days or weeks of my life tracking down obscure bugs caused by overwriting memory I should not have.
Could you please give some concrete examples of how memory corruption has affected you in modern Objective-C? NSArray has range checks, delegates can't dangle anymore because they're weak references now. I think that leaves interaction with C APIs, but don't Swift users have to deal with UnsafeMutablePointer to use them - which isn't memory safe either?
The easiest way to cause memory issues is to access mutable collections from multiple threads. I really wish NSMutableArray and friends were thread safe...
> you couldn’t use C arrays on the stack, for example. And if you couldn’t do that, there’s entire classes of applications where the performance just wouldn’t be acceptable
Would you mind naming a few such classes?
Why would arena allocation, or evrn good generational GC fail to deliver the performance when quick allocation / deallocation of (large) arrays is required?
Generally one feature GCd languages lack is strong support for value types. Cache thrashing due to pointer chasing is an issue, and even if you can allocate large numbers of small objects quickly, the indirection will kill you. In Swift, many small allocations are avoided entirely by storing the value as part of some other object. For example, imagine you want to store an array of points; it’s usually much better if you can have an array of structs of floats where everything is represented as one flat allocation.
Yeah, its one of the few that does. Even then, C# value types are immutable, and there are no value type collections (not a collection of value types, but a collection that is itself a value type). The lack of these two features means it’s not as generally useful as you might like.
An array of value types (including structs) in .NET (not just C#) is laid out contiguously in memory and stored in-place like an array of C/C++ structs would be. The problem of chasing pointers does not exist if you use structs (and don't use non-value types such as strings within those structs). And .NET value types are mutable, of course.
Oberon, Oberon-2, Active Oberon, Component Pascal, Eiffel, Common Lisp, Modula-2+, Modula-3, CLU, C#, D all have strong support for value types.
Java just made a couple of wrong decisions regarding AOT and value types that are now taking years to correct course, while avoid breaking backwards compatibility.
If something like Modula-3 had been granted Java's success story, we wouldn't be talking about how GC languages don't have good support for value types.
I think we have different definitions of value types - in all Common Lisp implementations I’m aware of values have a uniform representation as a (tagged) pointer.
Also I think C# structs do not have mutable fields, but I could be wrong.
Edit: it looks like C# structs are mutable, my mistake.
Which is a problem for developers who simply want to write code without having to reason about whether it’s safe to dereference something, and without having to worry about a simple oversight resulting in the programmatic equivalent of summoning Cthulhu.
The feeling of power is nice for the programmer, but it doesn't influence the technical capabilities of the language, which are deplorable safety-wise.
Did you see the smiley face in my post that’s implied I’m kinda joking.
Also... I’m a little concerned that your post has “we’re all equal” social justice vibe to it... which is silly. C is more powerful than because “safety features” aren’t there.... deplorable... LOL.
You try going a day without using something programmed in C.
Every single day back when I was developing software for ZX Spectrum, Amiga and MS-DOS, before UNIX's influence took over the industry and forced us into dealing with C.
Thankfully there was already C++ for those of us that wouldn't move into such a limited language versus what something like Turbo Pascal 6.0 for MS-DOS was already capable of, feature wise.
Ok... so if I’m getting the idea here... C is more limited, but also dangerous because it gives direct access to memory and pointers making it dangerous.
Man... to listen to hackernews tell it... no one should use C!
I wonder how many comments describing how bad C is are from people on Linux machines?
The problem is not direct access to memory and pointers as such, every systems programming language needs to provide such features.
The problem with C, versus other systems programming languages it that it its pointers, implicit conversions of array into pointers, integer operations, string and array bounds don't have any kind of validation.
On other systems languages disabling such validations is explicit.
C is like JavaScript in the browser, we have to put up with it because UNIX clones won the market of commodity OSes.
C on its own without UNIX, would have failed in the market.
On the desktop world it was already being replaced by C++, Smalltalk, VB, Delphi and 4GL before FOSS based on UNIX and C started to be widespread.
Unfortunately it is impossible to convince people on pure UNIX based OSes to use something else.
Fortunately, Apple, Microsoft, Google, Sony, Nintendo are able to set which programming languages one is allowed to use on their platforms and C is on the way out on their SDKs.
Tone is a tough thing to get right, and I'd say your initial post came off pretty condescending to a lot of people, regardless of whether you meant it or not. It's not even a C thing either, I've seen the same thing where someone declares functional programming as the only "serious programming" and category theory is easy, so everyone else is wasting time with imperative languages. So, it's a bit off-putting.
Oh boy, how I wish I could have at least one day without something programmed in C. I'm so sick of all the vulnerabilities...
No social justice vibe was meant. I was trying to say that we're all bad at dealing with the kind of errors which appear in a typical C or (perhaps to a lesser extent) C++ program.
I know that some people are able to do this more successfully than others because of skill, etc, but it's not just about certain individuals. As a whole, the C community has a really poor track record at security and safety and that has a lot to do with the language itself.
I have used Objective-C since 1997 when I worked with WebObjects back then and I don't miss it for a second. When I have to touch our one codebase with Objective-C I have to groan. It was amazing for its day and I did enjoy it despite its shortcomings. But I can write way more highly functional code faster in Swift than I ever could in Objective-C due to real type safety and other modern features. I also spent years doing regular C and C++ and Java (not at the same time) and all 3 languages seem clunky to me now. Preferring Objective-C over Swift is wishing for the golden oldie days kind of thinking and I'm one with almost 4 decades of programming experience. Swift is still young and growing and sometimes thats a bit challenging to adapt, but its the one language I truly enjoy now.
Objective-C in 1997 and in 2017 are almost two different languages. Between ARC and generics, auto-synthesized ivars, and blocks, there's not much missing from being a modern C#/Java-like language.
I love Objective-C, but calling it (close to) a modern language is a long stretch. The “generics” are a joke, for example. The whole type system is miles from what can be expressed (and guaranteed!) by a modern language. We got an immense amount of fun out of it considering its age, but it’s time to move on.
Totally agree that generics in objective c are very bare. And that's what frustrates me the most. Apple/Lattner could have improved them, but chose not to, by focusing all their energy on Swift.
"Simple" things I want from generics:
1. Carry over generic information from header files to .m files, and not force us to drop all type information by having to use "id".
2. A compiler flag to enforce that the generic type must be specified at usage.
3. Where clauses in generics: Foo <T where T : NSCopying, MyProtocol>>
4. Generics on protocols, ideally with all the other features.
I know some of these are not trivial to implement, but they are mostly new syntax and hence don't have backward compatibility issues (except #2 which is why I asked for a compiler flag).
I don’t understand how you think this should be implemented. Many classes informally conform to protocols or in some cases the conformance can only be checked at runtime with a respondsToSelector: check. So any generics at compile time stricter than what we currently have will just not work or be useful.
The point I'm making is that the compiler can't tell you this, since conventional Objective-C code does generics checking at runtime. There's just not enough information available for this to be reliably diagnosed.
I wan't to ask in all seriousness, or in all ignorance—I don't mind, so please take your pick—why generics are so important. Let's say, in the first case, you have an NSArray in Objective-C. The object in the array is of type id. Now, in the second case, you have an NSArray, but you've declared that it will only hold types of NSString. Why is the second any better?
I ask, because the only way I could see it being better is if you're taking that array—that data structure—and passing it all over the program and using it everywhere. (Note to the literal-minded: this is hyperbole.) If that's what you're doing, that's not Object-Oriented Programming.
If you're instead doing real OOP, you're designing an object that will perform a clearly circumscribed bit of work for you by responding to a set of messages. The NSArray may live inside that object—in other words, the object is composed in part by using an NSArray—but that array is hidden from the rest of the program.
Generics are no big whoop-di-do in that case, because there is no client-programmer that has to worry about them; or, to put it another way, you—the original programmer—only have to worry about that NSArray with respect to the programming of that one object. In that case, the data type the array holds is not a big deal to keep track of.
So, again—seriously—what is so great about generics? The whole point of Objective-C, originally, was that it was late-binding—which, if you ask Alan Kay, was the point of OOP in the first place. If you're worrying about types all over the place, you're doing something wrong, no?
Your array of NSString example has little to do with generics. Instead think of a class that contains an NSArray, and has methods to do specific things to the array items, for example a sort() method. Using generics you can define the array values to match the type given when the class is created. So the same class could contain NSStrings, UImages, UIControls, etc, etc, and sort accordingly.
Alan Kay’s ideas are very interesting and Smalltalk introduced many groundbreaking ideas that still inspire programmers today. But there’s no fundamental law of nature that says dynamic message passing OOP is the “right” way to approach OOP, or even that OOP is the best paradigm for many coding problems developers face today.
Okay, the context of the reply to which I was initially replying to was about how the implementation of generics in Objective-C was "very bare." I'm beginning with this point, because though I agree with your second point about OOP perhaps not being necessarily "the best paradigm for coding problems developers face today," I don't quite see where that point fits in. We're talking about Objective-C, which means we're talking about OOP. If you want to explore some other kind of programming paradigm and insist that generics are needed there, I have no quarrel with you. My point was that I didn't see why generics were needed in OOP.
But that brings us to your first point: namely, what is the "right" way to approach OOP.
When I bring up Alan Kay, I'm bringing up a guy who was there at the start, and who set his stamp on OOP. Granted, "OOP" has been done in different ways. You'll note, however, my use of scare quotes. Allow me to explain.
When OOP had the misfortune to become a managerial buzz, somewhere back in the 1990's, and thus became a "must-have," what happened was a lot of procedural programmers simply took their procedural programming, wrapped in in C++, compiled it with a C++ compiler, nodded to the boss and assured him that they were doing OOP—and went along on their happy way.
Likewise, when college professors—set in their ways, as is their want—were told that they had to start teaching OOP, they largely did the same thing.
The result is that we have lots and lots of people out in the world "doing OOP"—who actually aren't. They're writing procedural programs, with the trappings of classes and sub-classing and what not. But all over in their programs, they are digging into the internals of their classes—and, sometimes, you see them digging in many layers deep.
And they're "doing OOP."
As I understand him, Kay is saying that you send a message to an object, on the understanding that the object will handle the message, the sender not having to worry about the ultimate who or how. If there's another kind of OOP other than that—or other than the travesty I described above—what is it?
But, that's another question, entirely. My original question was: why are generics such a big deal in OOP? I don't believe that's been answered.
For me, the big deal about generics is that they allow the type system to cover a much bigger part of my design. Without generics, any parametrized API will erase your types and then the compiler is blind. With generics the type information is preserved and when I specify a parameter type, somewhere several API layers away a type is suddenly fixed, too. That gives me a warm feeling (and code completion, too). And since expressive static type systems seem to be the right way to go, allowing the type system better insight into your code is a big win.
A fundamental problem with Objective-C generics that cannot be addressed in an additive manner is that generic parameters just desugar to ‘id’; you cannot use Objective-C generics with C types and you still pay the performance and memory use cost of trafficking exclusively in class instances. This of course was the right trade off, since it allowed generics to be layered on top of existing types like NSArray without either changing their implementation or breaking existing client code. However, when designing a new language with generics built in from the start you can make much better design decisions.
It boils down to the self discipline of individual developers. If you’re meticulous in making sure you’ve dotted your I’s and crossed your T’s and haven’t let too many of those insidious cast statements slip in, you can write reasonably safe Obj-C, but during my career as an iOS dev I have yet to encounter an Obj-C codebase that was fully written by such developers. They’ve all been riddled with gratuitous casting, erroneous type assumptions, and other bad practices (that aren’t possible in Swift) to the point that it’s a wonder that they ever functioned as intended.
Personally though, I’ve found that even when I’m keeping a close guard on things when writing Obj-C and am sure to avoid all the obvious pitfalls, bugs slip through in the most unexpected places, so I’m quite happy to have the Swift compiler double checking everything for me.
I’ve never understood this opinion, and always wonder if it’s a professional developer espousing it. Because most of your time as a commercial developer is spent debugging, and Swift makes it far easier to write correct code, and to find bugs when you write incorrect code.
On a positive note, at least you're just writing buggy programs and not killing your patients somewhere or causing industrial accidents.
Unfortunately, as software continues disrupting various industries, it's less and leas certain that even buggy programs written by someone who thinks that safety is overrated will remain harmless.
That’s a real stretch. As someone who previously wrote Obj-C and currently writes Swift full time, whenever I revisit and work on old Obj-C code I constantly have “oh right, Obj-C doesn’t have that” moments and either have to pull in some third-party library that does what I need or settle for a less than satisfactory (and usually dramatically longer) solution.
I do have times when writing Swift where I miss some bit of Obj-C, but those are rare and are becoming fewer as the language develops.
I believe the parent was subjective as well. I am curious as to why you appear to label just this comment. HN is for opinions as well as facts and I deeply value all of them. Particularly the opinions that politely challenge me.
I’m the opposite. When I see Swift I just groan. It’s so much hard and slower to write more highly functional code (not to mention going back to ready it) than Objective-C. Part of that is lots of things about Swift are backwards (variable definition) or overly expressive (var/let/func).
I just cannot enjoy Swift at all. When I go back to Objective-C its just such a joy to write.
I'm surprised that anyone could find Objective-C a better language than Swift. I'm just waiting for iOS to move completely to Swift to start developing on that platform. It's a much better language.
Developer productivity is far less determined by how fast you can write code, than by how many bugs you create, and how hard it is to fix them. The vast majority of time is spent debugging and maintaining code.
And I feel like I can write in Swift nearly as fast as Objective C. Objective C was always so baroque, when I define a method or variable and declare the exact same thing in a header file? Properties syntax?
I actually switched when Swift 1.0 came out (just after writing a twenty thousand line simulation engine in Objective C). It was so lightly baked I was starting to regret my decision for a couple months until version 1.2 released, only then could I ship my app commercially. Since then every release has only gotten better, and the rough edges are entirely gone. The only thing I miss from Objective C is compile time, and now just barely given how much faster the compiles have gotten.
> The vast majority of time is spent debugging and maintaining code.
Not all programming is the same. I've seen a lot more code churn in frontend projects than in the backend, where the actual logic and persistence happens. That makes the speed of (re)writing code relatively more important (at least for the iOS apps I've worked on, YMMV).
But even when I had to clean up legacy code, I spent most of my debugging time on on incorrect threading (typically using UIKit or Core Data from the wrong thread), AutoLayout errors, Apple framework bugs, storyboards/NIBs out of sync with code, performance degradations, or anything else where Swift doesn't help much.
In my experience, Objective-C programmers aren't allergic to safety or brevity. We love ARC! It's just that Swift has taken away too much productivity, mostly through terrible tooling and by dividing the community, for very little gain.
> Objective C was always so baroque, when I define a method or variable and declare the exact same thing in a header file
When I helped out on a Java project, I noticed that my coworkers religiously created interfaces for every single class they wrote. They couldn't really explain it beyond it being a "best practice", but I suspect they enjoyed being able to look at a short file that only contained the interface plus JavaDoc, instead of opening the full implementation every time. They basically re-invented header files :P
I don't think people would mind headers as much if Xcode was a better IDE, and we didn't have to copy declarations around manually.
> They couldn't really explain it beyond it being a "best practice", but I suspect they enjoyed being able to look at a short file that only contained the interface plus JavaDoc, instead of opening the full implementation every time. They basically re-invented header files :P
Then they should have known better.
That makes sense for unit testing, in cases where mock classes would be required.
All Java IDEs have object browsers no need for header files.
Mockability was the official reason until we started using Mockito 2. I hope everyone on the team was aware of the object browser. And yet they felt better with interfaces everywhere. It might have been a simple case of cargo-culting, though.
When people criticize C as a language they are usually referring to the fact that it easily and frequently allows for many classes of bugs that riddle C code. For decades, as an industry we've been apologizing and fixing critical exploits and bugs (ex HeartBleed), that can be traced to the fact that C allows for mistakes. If a bug is allowed, someone will perpetrate it sooner or later. Sacrificing correctness and safety for the speed and complicity of C is not a valid tradeoff for the industry in my opinion.
A major feature of Swift is that it forces you to deal with error conditions and missing values. In practice you do the right thing once and early in your code, and you can write the majority of your code with guarantees that prevent major classes of bugs. Swift is not perfect, still changing, and many complain about being forced to write safe code, but it is absolutely the right move of Apple to make for their platform.
If Swift lets you override dealing with errors (think force unwrapping) then such security is pointless because "someone will perpetrate it sooner or later."
In practice, what we get is an overly pedantic language that gets in the way of the developer.
There is a world between every single string, array and numeric operation being a possible source of memory corruption and being forced to explicitly write unsafe code.
I have been using mostly safe languages since the 80's.
They only get in the way of cowboy programming, which is a very good thing for anyone that praises quality in software development.
C would no longer be around if companies got properly sued for each CVE exploit.
People have written and continue to write secure C code, and insecure code in “safe” languages.
I have written systems in memory safe languages. The languages that provide memory safety also incur GC pauses, which means they’re unsuitable for applications where latency matters at all. (I’ve also noticed that programs written by professionals in memory safe languages tend to have many more serious high-level bugs than those written in C/C++, but I don’t have data to back that up.)
It isn't truly safe like Rust, as Ada can still have dangling pointers laying around, the free function is called "Unchecked_Deallocation", not sure if newer Ada has any mechanisms for better ownership semantics.
And Swift, which uses automatic reference counting instead of GC. This is not a “zero-overhead” design like what Rust aims for; sometimes it has quite a lot of overhead. But it is free from the phenomenon of GC pauses.
> But it is free from the phenomenon of GC pauses.
Not really. RC algorithms can lead to stop the world in cascade deletion of highly nested data structures, and even cause stack overflow due to destructors being called.
Up till Swift 2 that was mostly the case – getting "in the way" – but as it is now I'd say Swift forces you to think about being a better developer, while still letting you be a bad one if you really insist on it.
After working exclusively in it for a while now I can't help but cringe at the practices which I see encouraged in most other languages.
The critical difference is that in swift your have to override safe behavior by using special syntax. This means you can search for it to fix it, you can have compiler/linters enforce certain rules, you can catch it easily in code reviews. No professional team I've worked on would allow forced unwrapped code except in special well documented cases.
The default code you write in swift is safe. You spend less time worrying about its correctness, which means you can focus on solving higher level problem and less time debugging.
When people call swift pedantic, for example, and I take time to ask for the specifics, I mostly get "not familiar to me", or "I'm used to shooting myself in the foot and unwilling to consider alternatives". So my patience has run out.
Lol, I put that code in my last project, a 150,000 line codebase built by lazy contractors, as just one of the tools to clean up the errors from their objective c like approach to software quality.
Interestingly put, "the Objective-C approach to software quality". There's something in the psychology of a large number of C, Objective-C and C++ programmers that makes them overappreciate execution speed and underappreciate memory safety in particular, but also validation and correctness in general.
One of my goals now is to outline safe ways of using C++ for various projects and I'm not too optimistic. In fact I'm unsure what we'll end up with.
I always have a choice if I'm the one writing the code.
But what I want is a way to catch all errors that others may have introduced in code I have no control over. That includes arithmetic overflow as well.
What would you do? If the ordinary array subscript produced an optional value, people would simply fall into the habit of force-unwrapping it, since the hassle of handling the spreading optionals would be too big. And throwing an unchecked exception would lead to empty catch blocks everywhere, just as in Java. And then the execution would continue in God only knows what state. I simply don’t think that the type system can solve the question of trusting your dependencies for you.
What I want to do is to wrap a piece of code running in its own thread in a catch block so I can respond gracefully to any errors without killing the entire process.
What gracefully means depends entirely on the application. Often it means to log the error or display a meaningful error message if it's an interactive app, then maybe do other kinds of cleanup and shut the thread down.
It can also mean to retry later. Array out of bounds errors are quite often just a result of not properly handling an earlier temporary error.
Whether or not errors leave the rest of the application in an inconsistent state depends entirely on the design of the application.
I'm not saying that letting an app crash on buggy code is never the right thing to do. I just want the option to handle it differently where appropriate and possible (it's not always possible anyway).
Speaking of reliable systems, introducing an actor model is a good opportunity and excuse to introduce a mechanism for handling and partially recovering from runtime failures (like failed force-unwrap operations, out-of-bounds array accesses, etc). We explore several options that are possible to implement and make a recommendation that we think will be a good for UI and server applications.
This looks like a more principled approach that we will eventually get in Swift.
This isn’t what Swift means when it says it’s safe. “Safe” doesn’t mean your program doesn’t have bugs or can’t crasg; rather, it will never have to deal with things like memory corruption and related undefined behavior. In fact, Swift considers crashing rather than allowing such errors to propagate to be an explicit design goal.
Right; this is why integer operations trap on overflow by default, instead of silently wrapping, for example. Technically you’ll “crash” more but the crash occurs at the exact location of the problem and not much later in the form of corrupted data.
It’s the difference between a crash pointing exactly at the cause, and spending days or weeks isolating crashes that only occur minutes after the error that caused them, or only on certain devices, or in certain memory configurations, or only on every other Sunday, etc.
> If a bug is allowed, someone will perpetrate it sooner or later. Sacrificing correctness and safety for the speed and complicity of C is not a valid tradeoff for the industry in my opinion.
It depends on what you are building. For an app it is not a big deal to be slower. But you will not write a kernel in Swift as you will lose performance all over the place.
Python/Javascript/Lua are used as scripting languages to create video games. But the 3D engines are written in C or C++.
I have some similar thoughts. I like Objective-C and C and always thought of Objective-C as an improved upon iteration of C. The C/C++ integration is one of my favorite parts.
Also, if Swift is so much better and is supposed to be safer to use why are apps much slower and buggier than I ever remember? My iOS devices went from instant in iPhone 1.0 to pathetic and almost not useable at times on an iPhone 6 Plus, which would still be an awesome phone for my uses (using it as an iPod essentially and the occasional call) except it's slow and buggy. Even answering the phone is no longer instant. I could have sworn I remember when Jobs introduced the iPhone he was bragging how instant everything was. What would he say now and why are apps much less stable if Swift is supposedly that much of a benefit and greater than Objective-C
This is entirely unrelated to Swift. But to address our concern: your iPhone 6 Plus is the slowest iPhone still getting updates today. Sure, it should perform better, and the iOS 12 update later this year will help fix this issue, but Swift has nothing to do with making your phone slow.
I upgraded to the iOS 12 beta a week or so ago on my 6S+. I can say without any doubt that it is so much faster that I feel like I have a new phone in my hand. I honestly never thought an upgrade could make this much difference.
I actually find Swift's C interop pretty extraordinary. Miles better than cgo, JNI, cffi/Cython/ctypes, etc. Parsing C headers, complete with comments and stuff, is super cool, and just about as slick as you can get without bringing in serious C cruft (like having its preprocessor). My biggest disappointment with Swift is that C++ doesn’t get the same treatment.
Yeah I agree it wouldn’t be easy but damn would it be great. And like... given that much of the Swift Core team implemented C++ in clang, they’d be the ones to do it.
I’m assuming they mean that Swift generally is easier to use with dynamic types than Rust.
Rust has dynamic polymorphism like Swift, but Swift you opt-out with final (correct me please if I’m wrong here), whereas in Rust you need to promote to a trait object.
This is a small difference, but means you’re starting with different principles available to you out of the box. Personally I prefer Rust’s opt-in to complexity model, but I can see why people see that as a hinderence, even if it’s technically just as possible to do in Rust.
The memory management is more developer friendly and it doesn't get into the way like it still does in Rust, even with the upcoming NLL improvements, not all productivity use cases are covered, e.g. self referential references to fields in struct methods.
Then there are Swift Playgrounds and REPL for quick prototyping and those still aren't a thing in Rust.
There has definitely been this period of inconvenience where a language-in-progress started taking over all the blogs, became the default language for documentation and code snippets, etc. and even StackOverflow answers. And using Objective-C becomes surprisingly inconvenient with extra barriers to finding help because lots is changing in Cocoa APIs too, etc. during the time that Swift wasn’t fully baked.
To a point perhaps, and at least the official documentation can toggle between them. After the Great Renaming though, things start to look different and reading something like a code snippet is just a lot of mental translation.
"It’s really about taking the best ideas from where we can get them and assembling them together." ~ Chris Lattner
I think this is the root of my dislike of Swift. "Assembling" together the best ideas, which may only be 'best' within a specific context does not suggest the kind of design principles I am looking for in a language.
I was looking for a quote and it seems it was Antoine de Saint Exupéry who said something like "It seems that perfection is attained not when there is nothing more to add, but when there is nothing more to remove."
So I contrast Lattner/Swift with Hickey/Clojure: a small set of coherent design choices that lead to a language that is simple but deep. It's by no means all things to all women and that's a good thing.
I should add I am not trying to make a comparison between Swift & Clojure but between what I see as a fundamental difference in the design principles that lead to those languages and why they might matter.
I guess I am struggling to get across what I mean.
I see Hickey as having a specific, focused, goal about enabling simplicity (given his specific meaning for that word) and yes I totally agree that every designer, including Hickey, does as you say.
What I was trying to get across was that I don’t see the guiding principle that guide the selection of those “best” features to include so much as “there’s this great stuff” that we must include.
Does that make more sense? Or should I put down my shovel?
I get what you're saying, and I get the same feeling from most modern languages. They lack conceptual integrity. It's sort of spreading like a virus, even C++ fell into the same trap lately. Whole system design is difficult, really difficult, tear your hair out difficult. Accumulating features is a Sunday walk in the park in comparison; until the pile tips over, that is.
They didn't include everything, far from it. For example, lambdas were deliberately left out, despite objections from Guy Steele. Parametric polymorphism (generics) was also well known in academia at the time, since the 70's, but Gosling claimed to have not understood it.
I also think it’s interest to listen to Hickeys rationale for why things were not included in Clojure or why things are how they are. I have found his talks on language design to be very clear and rational.
He appears to have specific aims and seems unafraid to make the necessary compromises to achieve them.
Non nullable default types, defer, patterns are great ideas.
Virtual by default,
associated protocols instead of generic protocol,
Exception handling designed based on how objc passes nserror,
Generic instantiation is done at runtime, not by the compiler, so field access and even defining locals involves needless math,
All things with a lot better alternatives at the time swift was designed.
My point is that society is drilling people in the head 24h a day to be gender neutral and then SJWs make the point of using feminine forms to fight sexism with sexism. That's my point. Enjoy your avocado.
There's a phrase "all things to all men", he/she just decided to swap out men with women to achieve more gender equality.
He could've just said all people tho.
(EDIT: to the replies, I'm not saying it has been achieved, just that this was the probable intention, which wasn't obvious to me as a non-native speaker)
Yea, "all things to all people" is really hard to type. Also "he decided?" You have no idea if the OP is a he. You are part of the problem that the OP is fighting poorly.
To me, Swift is an ideal blend of FP/OOP for application programming. A lot like Rust, but higher level. I understand that it's not for everyone, (Objective-C isn't going away), but I really think this is the right design approach modern languages should take.
They could have at least kept the clean messaging syntax of the Objective-C (Smalltalk). The hybrid they chose was just painful. Plus, what is this fascination with the comma. Adding commas has been a pain when trying Swift as I am constantly skipping them.
They could have cleaned up all Objective-C and built a much nicer language, instead we get a improved Java / C++.
most Objective-C code would get rid of the space too
[somePoint moveByX:2.0 y:3.0];
Its just painful to type extra characters that don't do anything and don't help readability. Plus the weird splitting of the moveByX is still odd.
I still am mystified why they didn't just start with:
somePoint.(moveByX: 2.0 y: 3.0)
to keep it inline with Objective-C and start working on giving the method names an overhaul that would benefit everyone including the Objective-C programmers.
The ones in between the arguments. The beauty of sending a message to an object has been replaced with a function call with a horrible syntax. I guess that's what makes Swift a modern language.
This is awesome: watch Lattner reverse the meaning of "working fast" to say that the way to get something working fast is to prevent it from working at all until you chase down all the corner cases. Slow is fast! Refusing to compile is working! Up is down!:
--------------
Swift ... really is designed and optimized for, as a programmer, you can spend the least amount of time to get to a working program as fast as possible.
Getting to a working program includes the time it takes to debug something, to iterate and develop and fight the type system, and all the other things you have to do. But that time you spend having to fight the type system or figure out optionals or things like that pays itself back because your program works more often. You’re actually not spending time chasing own dangling-pointer bugs
Lattner takes "working" software to mean something that can be shipped to production and used in the real world, as opposed to the classic "works on my machine" definition that second rate developers hide behind. It takes a certain maturity and experience shipping to recognize the long term benefit that approach. As the head of Apple developer tools (at the time), his job is not to cater to the hobbyist working on his fun software project, but improve quality of software on his company's platform.
If you remove the value judgments from your comment, you and I are saying the same thing. Many developers say they want to "get something working quickly", where "working" means "executing and performing some simple I/O, etc". Some developers don't value that stage, and prefer to develop until a piece of code is ready for wide-scale production. And that difference in values is just fine.
Lattner used rhetorical slight of hand to assert, in effect, "you 'working quickly' developers need first to adopt my values; only then can you be admitted to the conversation." C.f. Yegge on liberal-vs-conservative developers. [1] Lattner (along with you) is adopting a position towards the conservative end of the spectrum, which is cool. What's not cool is gaslighting the existence of a liberal perspective.
Is there any proof that the liberal perspective is able to produce software of sufficient quality? All the safety-critical development standards take a very conservative approach, especially in respect to development speed.
A program that executes and performs some I/O is a very very low bar to pass. The next step is not being ready for wide-scale production, in fact the IEEE Software Engineering Body of Knowledge aims to define the many steps required for that and it's a lot of them.
Developing by the seat of ones pants is fine for personal projects, but not for publicly used software.
And why should what developers "want" be the main criteria that should be used to choose programming languages? It's certainly important that developers are able to extract some satisfaction from their work, but that doesn't mean we should sacrifice other important goals just for the personal comfort of developers.
There's a tremendous amount of value, in any creative task, in being able to sketch out ideas quickly. The less time you spend seeing if the shape of the thing you're making is broadly okay, the more shapes you will be able to try, and the higher the chance that you'll converge on a good one.
Swift really does not support quickly iterating on a design. It demands that you sit down with your plan fully-formed, ruler and protractor in hand. Due to its strictness, changes ripple very quickly across even a small codebase.
Realized you need another enum case? You can't compile again until you touch all your switches. Protocol would be more expressive with an associated type? Stop what you're doing and write some type eraser boilerplate. Function needs to signal an error condition? Try/do/catch anywhere you call it, right now, before you run again. Need to put another type into that array? Write a new protocol and add some conformances.
Changing a interface as you work in Swift immediately creates a sea of red marks, which hinders the ability to experiment.
You're right that this strictness helps write ~correct~ safe code, and I appreciate that. But it's a tradeoff; there's a real cost in developer productivity/creativity. And I believe that it does not help produce the best design. It takes too long to get to running, which makes it too costly to heavily revise based on what you learn as you build.
EDIT: Actually, I want to go even further, and strike out "correct" in the paragraph above. Swift helps at a certain level of correctness, which is really not much higher than the type system -- it would be better to call this "sound" code, rather than "correct".
The overall point that I'm trying to make is that at the level of application/business logic -- which is the whole point of the program, after all -- Swift does not help with correctness. In fact, it can be detrimental, because, unless/until you understand your use cases well enough to actually lift them into the type system, at that upper level it blocks exploration without adding rigor.
I realized recently that I actually do like static typing, as long as the cost is low. (I really like TypeScript)
Sorry, I don't want to reason about the "shape" of my application state vector before I've written it... but that's what Swift's static type checking forces me to do... Design my app and it's data model at the same time.
> Swift really does not support quickly iterating on a design.
I find the opposite to be the case. You assume that compile errors are a net negative for speed of development and expressivity. Instead I find that the compiler reminds me upfront of all the places I would need to update anyway in due time. In a dynamic language those inconsistencies would be found hours/days later and usually after lengthy debugging. Instead I find myself making large sweeping changes in the design very frequently, because I trust the compiler to warn of any logical inconsistencies.
You have to admit at that this point it boils down to subjective preference. You sound averse to the swift style of doing the right thing up front, and using the compiler to help you stay consistent. I personally tired of the hidden and unacknowledged costs of unsafe language, and compilers that allow your design to degenerate into an unmaintainable ball of mud over time. I'm ok with swift being an acquired taste and a technical advantage of folks who get it.
This has been my experience as well. With Swift I’ve pulled off several large shifts/refactors that I wouldn’t have even considered risking with Obj-C. My Swift code is much further iterated than my Obj-C code.
> Realized you need another enum case? You can't compile again until you touch all your switches. Protocol would be more expressive with an associated type? Stop what you're doing and write some type eraser boilerplate. Function needs to signal an error condition? Try/do/catch anywhere you call it, right now, before you run again. Need to put another type into that array? Write a new protocol and add some conformances.
Changing a interface as you work in Swift immediately creates a sea of red marks, which hinders the ability to experiment.
With the exception of the associated types thing which is a language limitation that would be nice to see resolved eventually, the others can be resolved with a combination of automatic refactoring (add new enum cases, etc) and a compiler mode where type errors compile down to runtime traps without preventing you from running the program. (And faster compilation in general would help as well!) These are both non-trivial to design and implement well, but I think it’s a good future direction for statically typed languages that will give them many of the benefits of dynamic languages during the prototyping phase.
> a compiler mode where type errors compile down to runtime traps without preventing you from running the program
Absolutely, something like this would be perfect. I like being able to leverage the compiler in preventing runtime errors...just not necessarily all at once, right up front. Allowing some strictness to be dialed back in debug builds would be a very nice feature.
There's a high likelyhood that if you have unhandled enums and uncaught exceptions after a refactoring, the code is subtly broken.
In C++ -Wswitch is a valuable tool to find the former, but there is no way to find the latter. This makes writing correct exception handling code much much harder, so having Swift's strict behaviour would be great from my perspective!
It sounds to me that you want to use a few days of exploratory coding to save a few hours of design work. If this type of exploration is needed, then it could be done in another language which supports it and then when the design is in decent shape it can be ported to Swift.
Swift is not detrimental to the correctness of the business logic. It offers you a bedrock at the type sustem level on which to build that.
> There’s a number of things that rolled out over the years, and it was really funny at the time because the Objective-C developers externally and even internally to Apple always accused the compiler and language team of taking Objective-C on this random walk, and they didn’t know how it all fit together, and where’s the strategy, and why are you guys working on this and why aren’t you working on some other syntactic sugar that I want? Of course, we could never tell them, but there was a good reason.
Here it seems like Apple's culture of secrecy just hurt them for no reason. No really, Apple, you can just tell people what your plan is.
I'm playing with rust to solve my use case, but is certainly hard. Is very unlikely you can build a team of mixed developers and use it. Swift is more forgiving, yet you can get great results anyway.
google’s push for kotlin and apple’s push for swift seems like ego-ism and aiming for glory to me.
What new does kotlin or swift offer which python or ruby can not? Why reinvent the damned wheel for syntax sake when they could have worked for their device centric compiler for creating binaries out of python or ruby?
Those languages dont have many of the features that both apple and google were going for when creating these languages, so why would they use them? For example, python isnt statically typed, nor is it typically compiled. Can you do these things? Yes. But it isnt the normal way its done, and is bolted on as an afterthought. This is just a superficial example but it goes much deeper. They have a set of needs and these languages fulfill them. Google didnt even make Kotlin, so why is that ego?
Google didn't write Kotlin. Maybe they're aiming for glory with Go or Dart, but their adoption of Kotlin feels much more like humility than ego-ism to me.
Kotlin and Swift are in a different family of languages from Ruby and Python. The whole family that Kotlin and Swift are in — static languages — offers much better performance and error detection than the family Ruby and Python are in.
Compared to Ruby and Python they doubtless seem a little verbose. Type system features like genetics, which help to make Kotlin and Swift “expressive” in their family of languages, seem pointless from the standpoint of Ruby and Python.
So there are two aspects to this:
* What makes Swift or Kotlin compelling relative to other languages in that family?
* Why use that family instead of languages outside it like Ruby and Python?
People have been promoting dynamic languages as an alternative to static languages for many decades but it doesn’t seem like performance has ever truly caught up enough.
This is true of the examples of dynamic languages you have chosen.
It is not true of LuaJIT, which is as dynamic as languages get. Error detection and correctness, sure; raw performance is not the issue you've made it out to be.
Ruby and Python were fair choices, together they must have 10-50x the mindshare Lua does.
LuaJIT performs well on certain microbenchmarks which are both heavy on numerics while operating on small amounts of data; while it has a cute design it’s no panacea and really rather simplistic.
Lua and JavaScript are both examples of dynamic languages where the performance is really impressive.
Lua (like plain JavaScript) is a more spartan development experience than Ruby or Python. I'm not sure what it is; but languages with rich OO seem to be what get picked up by people who need to build "applications" (windows where people click around in them).
The runtimes of python or ruby are rather complex under the hood. That's like arguing that JS would be as fast as kotlin or swift if Google only invested more time. JS is as fast in a couple benchmarks, but nowhere close overall.
I find myself wondering how many Swift converts actually wrote Objective-C like it was supposed to.
I’ve run into a lot of programmers that worked with ObjC as they would Java or C++, that is, using very small and fine grained objects to divide up the problem.
It’s the standard way in Java. It’s also the opposite of how ObjC is supposed to be, which is ”a few big classes” that uses message passing as glue.
How many former ObjC programmers actually heard of ”Software IC”?
Using ObjC like Java/C++, the language quickly becomes unwieldy and verbose. If you do that, then obviously Swift feels like a huge improvement.
On the other hand, if you essentially write C and let ObjC be your reusability layer, then Swift might feel like you’re back to working inefficiently in Java / C++ with objects all over the place.
The way that I write Objective-C is to use 'id' for everything and have as few classes as possible, mostly I just add methods to the existing classes mainly NSString, NSArray, and NSDictionary.
Objects are interchangeable as long as they can respond to certain messages. For example, any object can be an array as long as it responds to objectAtIndex: and count. There was a whole discussion above about how Objective-C doesn't have generics, but this completely misses the point because Objective-C doesn't even need generics. "Modern" languages are not necessarily an improvement, software generally does not get better over time, it reaches a peak then it declines.
Objective-C is one of the best languages I have ever used, but the vast majority do not understand it, even the ones who say that they used to write Objective-C for X amount of years but now love Swift. The truth is, they never understood the beauty of Objective-C.
I consider Swift to be a language for large teams of average programmers, reading Lattner's response to Swift's criticisms tells me that he is a compiler guy, but that expertise does not carry over at all to programming languages.
I don't really like the direction they were taking Objective-C anyway, so in the end it doesn't matter. I'm against things like dot notation for accessing properties and ARC, I don't use either when I program in Objective-C. Those recent changes end up making the compiler more strict and a pain to deal with.
Interestingly generics seem to drive the addition of type inference in order to avoid having to write too complex types, losing the self documenting nature of the static type, but still not avoiding the problem entirely.
Consider the types of some template generated pointers, or just something like std::unique_ptr<std::vector<std::shared_ptr<Foo>>> (which isn’t a very far-fetched example).
This is ”the generics problem”, where it actually starts having an obscuring effect.
ObjC is immune to the problem since it lacks any need to do do the specialization. Unlike Java where you needed a lot of manually inserted casts without generics, ObjC doesn’t need them at all.
Like you say, dot notation, ARC, stricter resolution of dynamic messages etc were weakening the strong points of the language and would push the programmer towards a Java-like object model - which is very far away from how the language ideally should be used.
246 comments
[ 2.9 ms ] story [ 230 ms ] threadI think it’s time for Apple (and Google) to embrace JavaScript as the app development language.
I don’t think that’s a particularly great choice.
https://blog.meteor.com/an-interesting-kind-of-javascript-me...
Plex was ported to the 3rd Gen AppleTV as an unofficial app just by running a server on your computer and redirecting DNS to it.
https://github.com/iBaa/PlexConnect/wiki/Install-Guide
https://www.raywenderlich.com/372-tvos-tutorial-using-tvml-t...
”One of the best and most annoying things about Objective-C is that it has C in it. This has been hugely important for Objective-C in practice, because if you run into a performance problem with objc_msgSend, you can always rewrite that algorithm in C. That’s really, really, really important for Objective-C being successful in both in the days of NeXT on 16 MHz processors and also today for the low-level code that people are writing.”
This is indeed a great thing about Objective-C: it’s an improved C with a tight set of runtime features that help build interactive applications.
There’s a need for such a language, and I’m sad that so much of the rhetoric from Apple and the Swift community is working on the assumption that Obj-C should be completely replaced by Swift.
Swift is not a compact language like Objective-C. It’s more like C++ in how it tries to incorporate every programming paradigm that can possibly fit. The heavy focus on complex upfront typing is not necessarily the best choice for iterative app development.
Swift is useful in many places, but personally I found Objective-C’s “Smalltalk-flavored C” to hit a sweet spot for my GUI needs where integrating with C and C++ libraries is usually required all over the place.
Plus, low-level languages like C are sometimes the only way to go if you are writing for embedded systems with slow CPUs.
Firefox is on a course to remove C++ from safety critical areas and replace those with Rust.
Edit: to be clear this is based on the blog posts I’ve read from Mozilla about the introduction of Rust in different areas of Firefox. I know nothing of firm plans.
> Moving forward, the goal of Oxidation is to make it easier and more pleasant to use Rust in Firefox, and correspondingly to increase the amount of Rust code in Firefox.
And then there is the Rust page on Mozilla’s site:
> Mozilla also utilizes Rust in many of its core initiatives including Servo and key parts of Firefox.
https://research.mozilla.org/rust/
Where “key parts” is a link to the project quantum announcement: https://medium.com/mozilla-tech/a-quantum-leap-for-the-web-a...
> Initially, Quantum will share a couple of components with Servo, but as the projects evolve we will experiment with adopting even more.
Mikroelektronika has Basic and Pascal compilers, in addition to C, for all those slow CPUs that are market relevant.
https://www.mikroe.com/compilers
And they aren't the only ones still alive.
For speed of UI response, loading times, cursor and input latency we're at best no further forward. Quite often we're in an objectively worse situation. With a tiny few exceptions, no one cares about code or data sizes any more and that is reflected in what's delivered.
That's quite apart from the rise of web apps and the slowness that necessarily introduces.
> The fundamental problem was Objective-C was built on top of C. C inherently has pointers. It has uninitialized variables. It has array overflows. It has all these problems that even if you have full control of your compiler and tool stack, you just can’t fix. To fix dangling pointers, you would have to fix lifetime issues, and C doesn’t have a framework to reason about that, and retrofitting that into a compatible way into the system just wouldn’t really work.
If you took away C from Objective-C, you couldn’t use C arrays on the stack, for example. And if you couldn’t do that, there’s entire classes of applications where the performance just wouldn’t be acceptable. We went around, around, around. We said the only way that this can make sense in terms of the cost of the disruption to the community is if we make it a safe programming language: not “safe” as in “you can have no bugs,” but “safe” in terms of memory safety while also providing high performance and moving the programming model forward.
I suspect that the move to swift would never have happened without LLVM. And I wouldn’t be surprised if llvm’s cross language compatibility was specifically attractive to Apple because it let them have their cake and eat it too - write a new language but keep legacy C code whenever that’s the best option.
I don't believe LLVM provides a stable cross language ABI, and AFAIK languages just use regular FFI (via the C ABI) to communicate with one another, regardless of them being implemented on LLVM or not.
Provided the compilers generate compatible versions of LLVM IR, then cross-language calls can be done at the IR level. See github.com/Keno/Cxx.jl
IIUC Swift already uses clang to load module maps in order to expose and call Objective-C, and they plan to do something similar with C++ (no link handy but I think there is an issue or enhancement proposal about it).
Is there really such a thing? I thought the ABI was dependent on the operating system and compiler.
I agree that C is unique in it's ability to generate programs that can be interfaced with from any language. This also seems to apply to older languages like Fortran and Pascal, for some reason. Higher level languages are an ABI nightmare; seriously doubt anyone will ever dynamically link against a C++ library at runtime and call a method on a C++ object from any language that isn't C++.
2. Prior to LLVM, there were much more complete attempts at this (that were even more successful, actually!)
Microsoft, Apple, Google have the luxury to impose moving away from C on their platforms.
On other platforms you have developers that won't touch any kind of Safe C even at gun point.
A lot of C's endurance is related to programmer psychology, so it would be futile to design a better C.
C++, Rust, Go, Java will continue to drain the pool of C developers until it's only used for maintenance of existing projects.
This is why it's extremely irksome to see people recommend mixing C and e.g. Python for speed, or other such Frankenstein's monsters - it's just prolonging the agony of whoever will maintain that.
Rust, Go, and Java, with their memory management and cross-platform portability, and general non-determinism may eat away at the edge of C, but can never replace it.
I could see them fully replacing C if features like garbage collection and byte-code interpretation were handled at the chip-level, so languages would not have to necessarily deal with them. Could also see it happening if a chip's out-of-order execution was exposed at the language level. That would not necessarily make C worse, but Java may be more adept at handling it.
1. C is no closer than C++, or Rust (including unsafe) and they're all surprisingly pretty far from the hardware these days... this is visible the most in multi-threading, where high-level C statements are re-ordered by the compiler and even simple C statements like an integer assignment can be split into multiple instructions. Inlining and register allocation is also quite opaque and perhaps best left to the compiler, unless one uses non-standard code to force specific behaviour.
2. Well put: Go and Java were/are eating at the edge of C. Java took serious bites in the past, nowadays they're not really competing much. Today, what might have been a small Linux C program could be a Go program, especially if the performance constraints aren't too tight. Technically speaking, Rust can replace C almost everywhere, it's just that it's a significantly more complex language.
I am fully convinced that if Java and .NET had a proper AOT toolchain from day 1, meaning beyond dynamic linking (NGEN) or commercial offerings from 3rd party JDKs, C's influence on FOSS world would have been much less than it achieved to be.
And we would already have achieved an UNIX like stack closer to what Inferno/Limbo was all about.
C++ introduces virtual functions, and when you make a function call, you're no longer going to a single place in memory, you go to where the class's virtual function table tells you to go, effectively jumping to a memory pointer. This is pretty helpful, but it's an incredibly different way to think about code. A function is no longer a set of instructions in memory, it's a logical representation of functionality.
And yes, I know in C, you can set a variable to a function location, and then jump there, but it's painful to do and you have to do it explicitly, so it doesn't really create an abstraction.
I find that this assertion holds about as much water for Swift as it does for Rust, Swift is not even remotely close to C++'s in terms of complexity, and that's with building in mechanisms for performant memory safety, a concept which C++ literally just shits on to this day and for the foreseeable future.
It’s not even close. Swift is (still) minimalist by comparison to C++.
But once you learn to use the more advanced features, your code just gets easier to write and maintain. I enjoy that I can pickup new language features in Swift one at a time, figuring out where each adds its best value, and occasionally refactoring to take advantage as part of my ongoing efforts to minimize code debt.
And unlike JNI they aren't protected by a VM wall.
The Obj-C community (or what's left of it) is trying to make a martyr of an error-prone, cumbersome programming language.
Unfortunately, Swift doesn't fix that AFAIK.
I’ve debugged too much java code where the programmers thought that ”thread-safe” meant ”no need to think about threading issues”.
Would you mind naming a few such classes?
Why would arena allocation, or evrn good generational GC fail to deliver the performance when quick allocation / deallocation of (large) arrays is required?
Java just made a couple of wrong decisions regarding AOT and value types that are now taking years to correct course, while avoid breaking backwards compatibility.
If something like Modula-3 had been granted Java's success story, we wouldn't be talking about how GC languages don't have good support for value types.
Also I think C# structs do not have mutable fields, but I could be wrong.
Edit: it looks like C# structs are mutable, my mistake.
Maybe take some time to check the other ones?
As for value types in Common Lisp, even if one bit is lost for tagging, it doesn't make arrays, structs and primitive values, less of value types.
Still not seeing the problem.
Pointers aren’t magic and aren’t hard.
Pointers, in practice, are hard. Even C-family compilers cannot safely reason about them in many (most) cases.
“As an embedded engineer I can’t agree that C “has problems” because it treats you like a big boy with your big boy pants on. :)”
Edit: Nah, that’s OK. Just downvote and scamper on. Make HN more like Reddit, that’s what this place needs!
C is really good at exploiting those, while at the same time giving programmers a feeling of power.
Isn't that why everyone loves python, solving a complex problem in a handful of easily readable lines of code?
Also... I’m a little concerned that your post has “we’re all equal” social justice vibe to it... which is silly. C is more powerful than because “safety features” aren’t there.... deplorable... LOL.
You try going a day without using something programmed in C.
Thankfully there was already C++ for those of us that wouldn't move into such a limited language versus what something like Turbo Pascal 6.0 for MS-DOS was already capable of, feature wise.
Man... to listen to hackernews tell it... no one should use C!
I wonder how many comments describing how bad C is are from people on Linux machines?
The problem with C, versus other systems programming languages it that it its pointers, implicit conversions of array into pointers, integer operations, string and array bounds don't have any kind of validation.
On other systems languages disabling such validations is explicit.
C is like JavaScript in the browser, we have to put up with it because UNIX clones won the market of commodity OSes.
C on its own without UNIX, would have failed in the market.
On the desktop world it was already being replaced by C++, Smalltalk, VB, Delphi and 4GL before FOSS based on UNIX and C started to be widespread.
Unfortunately it is impossible to convince people on pure UNIX based OSes to use something else.
Fortunately, Apple, Microsoft, Google, Sony, Nintendo are able to set which programming languages one is allowed to use on their platforms and C is on the way out on their SDKs.
No social justice vibe was meant. I was trying to say that we're all bad at dealing with the kind of errors which appear in a typical C or (perhaps to a lesser extent) C++ program.
I know that some people are able to do this more successfully than others because of skill, etc, but it's not just about certain individuals. As a whole, the C community has a really poor track record at security and safety and that has a lot to do with the language itself.
"Simple" things I want from generics:
1. Carry over generic information from header files to .m files, and not force us to drop all type information by having to use "id".
2. A compiler flag to enforce that the generic type must be specified at usage.
3. Where clauses in generics: Foo <T where T : NSCopying, MyProtocol>>
4. Generics on protocols, ideally with all the other features.
I know some of these are not trivial to implement, but they are mostly new syntax and hence don't have backward compatibility issues (except #2 which is why I asked for a compiler flag).
I ask, because the only way I could see it being better is if you're taking that array—that data structure—and passing it all over the program and using it everywhere. (Note to the literal-minded: this is hyperbole.) If that's what you're doing, that's not Object-Oriented Programming.
If you're instead doing real OOP, you're designing an object that will perform a clearly circumscribed bit of work for you by responding to a set of messages. The NSArray may live inside that object—in other words, the object is composed in part by using an NSArray—but that array is hidden from the rest of the program.
Generics are no big whoop-di-do in that case, because there is no client-programmer that has to worry about them; or, to put it another way, you—the original programmer—only have to worry about that NSArray with respect to the programming of that one object. In that case, the data type the array holds is not a big deal to keep track of.
So, again—seriously—what is so great about generics? The whole point of Objective-C, originally, was that it was late-binding—which, if you ask Alan Kay, was the point of OOP in the first place. If you're worrying about types all over the place, you're doing something wrong, no?
But that brings us to your first point: namely, what is the "right" way to approach OOP.
When I bring up Alan Kay, I'm bringing up a guy who was there at the start, and who set his stamp on OOP. Granted, "OOP" has been done in different ways. You'll note, however, my use of scare quotes. Allow me to explain.
When OOP had the misfortune to become a managerial buzz, somewhere back in the 1990's, and thus became a "must-have," what happened was a lot of procedural programmers simply took their procedural programming, wrapped in in C++, compiled it with a C++ compiler, nodded to the boss and assured him that they were doing OOP—and went along on their happy way.
Likewise, when college professors—set in their ways, as is their want—were told that they had to start teaching OOP, they largely did the same thing.
The result is that we have lots and lots of people out in the world "doing OOP"—who actually aren't. They're writing procedural programs, with the trappings of classes and sub-classing and what not. But all over in their programs, they are digging into the internals of their classes—and, sometimes, you see them digging in many layers deep.
And they're "doing OOP."
As I understand him, Kay is saying that you send a message to an object, on the understanding that the object will handle the message, the sender not having to worry about the ultimate who or how. If there's another kind of OOP other than that—or other than the travesty I described above—what is it?
But, that's another question, entirely. My original question was: why are generics such a big deal in OOP? I don't believe that's been answered.
Personally though, I’ve found that even when I’m keeping a close guard on things when writing Obj-C and am sure to avoid all the obvious pitfalls, bugs slip through in the most unexpected places, so I’m quite happy to have the Swift compiler double checking everything for me.
Unfortunately, as software continues disrupting various industries, it's less and leas certain that even buggy programs written by someone who thinks that safety is overrated will remain harmless.
I do have times when writing Swift where I miss some bit of Obj-C, but those are rare and are becoming fewer as the language develops.
I just cannot enjoy Swift at all. When I go back to Objective-C its just such a joy to write.
And I feel like I can write in Swift nearly as fast as Objective C. Objective C was always so baroque, when I define a method or variable and declare the exact same thing in a header file? Properties syntax?
I actually switched when Swift 1.0 came out (just after writing a twenty thousand line simulation engine in Objective C). It was so lightly baked I was starting to regret my decision for a couple months until version 1.2 released, only then could I ship my app commercially. Since then every release has only gotten better, and the rough edges are entirely gone. The only thing I miss from Objective C is compile time, and now just barely given how much faster the compiles have gotten.
Not all programming is the same. I've seen a lot more code churn in frontend projects than in the backend, where the actual logic and persistence happens. That makes the speed of (re)writing code relatively more important (at least for the iOS apps I've worked on, YMMV).
But even when I had to clean up legacy code, I spent most of my debugging time on on incorrect threading (typically using UIKit or Core Data from the wrong thread), AutoLayout errors, Apple framework bugs, storyboards/NIBs out of sync with code, performance degradations, or anything else where Swift doesn't help much.
In my experience, Objective-C programmers aren't allergic to safety or brevity. We love ARC! It's just that Swift has taken away too much productivity, mostly through terrible tooling and by dividing the community, for very little gain.
> Objective C was always so baroque, when I define a method or variable and declare the exact same thing in a header file
When I helped out on a Java project, I noticed that my coworkers religiously created interfaces for every single class they wrote. They couldn't really explain it beyond it being a "best practice", but I suspect they enjoyed being able to look at a short file that only contained the interface plus JavaDoc, instead of opening the full implementation every time. They basically re-invented header files :P
I don't think people would mind headers as much if Xcode was a better IDE, and we didn't have to copy declarations around manually.
Then they should have known better.
That makes sense for unit testing, in cases where mock classes would be required.
All Java IDEs have object browsers no need for header files.
Is this a joke? This sounds like "the language is wrong because it didn't completely ape C"
A major feature of Swift is that it forces you to deal with error conditions and missing values. In practice you do the right thing once and early in your code, and you can write the majority of your code with guarantees that prevent major classes of bugs. Swift is not perfect, still changing, and many complain about being forced to write safe code, but it is absolutely the right move of Apple to make for their platform.
There is a world between every single string, array and numeric operation being a possible source of memory corruption and being forced to explicitly write unsafe code.
I have been using mostly safe languages since the 80's.
They only get in the way of cowboy programming, which is a very good thing for anyone that praises quality in software development.
C would no longer be around if companies got properly sued for each CVE exploit.
I have written systems in memory safe languages. The languages that provide memory safety also incur GC pauses, which means they’re unsuitable for applications where latency matters at all. (I’ve also noticed that programs written by professionals in memory safe languages tend to have many more serious high-level bugs than those written in C/C++, but I don’t have data to back that up.)
https://www.cvedetails.com/vulnerability-list/opmemc-1/memor...
Apparently reviewing code before merging into mainline isn't of much help, but lets keep this myth of secure C code alive.
Σ (Logic errors in safe language) < Σ(Logic errors in C + Memory Corruption in C)
This is incorrect, you can have memory safety without a gc. An example is Ada, and more recently Rust.
Kinda sorta cheating. ;)
Not really. RC algorithms can lead to stop the world in cascade deletion of highly nested data structures, and even cause stack overflow due to destructors being called.
No. It's the inverse. People who are very good with C continue to have vulnerabilities in their code. Why? Because C.
After working exclusively in it for a while now I can't help but cringe at the practices which I see encouraged in most other languages.
The default code you write in swift is safe. You spend less time worrying about its correctness, which means you can focus on solving higher level problem and less time debugging.
When people call swift pedantic, for example, and I take time to ask for the specifics, I mostly get "not familiar to me", or "I'm used to shooting myself in the foot and unwilling to consider alternatives". So my patience has run out.
1. Don’t check for it at runtime and the runtime writes to memory that it shouldn’t like C.
2. Throw an exception and prevent memory corruption.
3. Don’t ever work with indexes and just use iterators.
Is there a fourth way that it can be handled in other languages?
One of my goals now is to outline safe ways of using C++ for various projects and I'm not too optimistic. In fact I'm unsure what we'll end up with.
Those of us that come from Wirth languages always put quality and delivering what the program is expected to do before going crazy with optimizations.
I always got the feel that many in the C communities write code as if they were micro-optimizing every single line, just because.
And those that care about type safe driven programming in C++ usually have background in safer languages.
Perhaps because it's not a huge problem in iOS apps, but for long running multi-threaded applications this is a problem.
But what I want is a way to catch all errors that others may have introduced in code I have no control over. That includes arithmetic overflow as well.
What gracefully means depends entirely on the application. Often it means to log the error or display a meaningful error message if it's an interactive app, then maybe do other kinds of cleanup and shut the thread down.
It can also mean to retry later. Array out of bounds errors are quite often just a result of not properly handling an earlier temporary error.
Whether or not errors leave the rest of the application in an inconsistent state depends entirely on the design of the application.
I'm not saying that letting an app crash on buggy code is never the right thing to do. I just want the option to handle it differently where appropriate and possible (it's not always possible anyway).
https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9...
Speaking of reliable systems, introducing an actor model is a good opportunity and excuse to introduce a mechanism for handling and partially recovering from runtime failures (like failed force-unwrap operations, out-of-bounds array accesses, etc). We explore several options that are possible to implement and make a recommendation that we think will be a good for UI and server applications.
This looks like a more principled approach that we will eventually get in Swift.
https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9...
https://github.com/apple/swift/blob/master/docs/ErrorHandlin...
It depends on what you are building. For an app it is not a big deal to be slower. But you will not write a kernel in Swift as you will lose performance all over the place.
Python/Javascript/Lua are used as scripting languages to create video games. But the 3D engines are written in C or C++.
Each tool has its use.
That used to be the argument against C and C++ in the 80 and 90's regarding 16 bit home computers.
Any serious developer would know that Assembly was the only proper way to write software that required real performance.
Yet a couple of decades later.
> But the 3D engines are written in C or C++.
Also, if Swift is so much better and is supposed to be safer to use why are apps much slower and buggier than I ever remember? My iOS devices went from instant in iPhone 1.0 to pathetic and almost not useable at times on an iPhone 6 Plus, which would still be an awesome phone for my uses (using it as an iPod essentially and the occasional call) except it's slow and buggy. Even answering the phone is no longer instant. I could have sworn I remember when Jobs introduced the iPhone he was bragging how instant everything was. What would he say now and why are apps much less stable if Swift is supposedly that much of a benefit and greater than Objective-C
I think the idea is to make common things easy and uncommon things possible.
What does "higher-level application demands" mean?
Rust has dynamic polymorphism like Swift, but Swift you opt-out with final (correct me please if I’m wrong here), whereas in Rust you need to promote to a trait object.
This is a small difference, but means you’re starting with different principles available to you out of the box. Personally I prefer Rust’s opt-in to complexity model, but I can see why people see that as a hinderence, even if it’s technically just as possible to do in Rust.
Then there are Swift Playgrounds and REPL for quick prototyping and those still aren't a thing in Rust.
I think this is the root of my dislike of Swift. "Assembling" together the best ideas, which may only be 'best' within a specific context does not suggest the kind of design principles I am looking for in a language.
I was looking for a quote and it seems it was Antoine de Saint Exupéry who said something like "It seems that perfection is attained not when there is nothing more to add, but when there is nothing more to remove."
So I contrast Lattner/Swift with Hickey/Clojure: a small set of coherent design choices that lead to a language that is simple but deep. It's by no means all things to all women and that's a good thing.
Surely every language designer including Hickey thinks they are assembling the best set of features for their goals.
I see Hickey as having a specific, focused, goal about enabling simplicity (given his specific meaning for that word) and yes I totally agree that every designer, including Hickey, does as you say.
What I was trying to get across was that I don’t see the guiding principle that guide the selection of those “best” features to include so much as “there’s this great stuff” that we must include.
Does that make more sense? Or should I put down my shovel?
† http://www.win.tue.nl/~evink/education/avp/pdf/feel-of-java....
> "We were after the C++ programmers. We managed to drag a lot of them about halfway to Lisp."
He appears to have specific aims and seems unafraid to make the necessary compromises to achieve them.
I didn’t see a reason to design a new language when Objective-C could be improved (for those that think it needs improved).
Non nullable default types, defer, patterns are great ideas.
Virtual by default, associated protocols instead of generic protocol, Exception handling designed based on how objc passes nserror, Generic instantiation is done at runtime, not by the compiler, so field access and even defining locals involves needless math,
All things with a lot better alternatives at the time swift was designed.
There's a phrase "all things to all men", he/she just decided to swap out men with women to achieve more gender equality.
He could've just said all people tho.
(EDIT: to the replies, I'm not saying it has been achieved, just that this was the probable intention, which wasn't obvious to me as a non-native speaker)
They could have cleaned up all Objective-C and built a much nicer language, instead we get a improved Java / C++.
I still am mystified why they didn't just start with:
to keep it inline with Objective-C and start working on giving the method names an overhaul that would benefit everyone including the Objective-C programmers.--------------
Swift ... really is designed and optimized for, as a programmer, you can spend the least amount of time to get to a working program as fast as possible.
Getting to a working program includes the time it takes to debug something, to iterate and develop and fight the type system, and all the other things you have to do. But that time you spend having to fight the type system or figure out optionals or things like that pays itself back because your program works more often. You’re actually not spending time chasing own dangling-pointer bugs
Lattner used rhetorical slight of hand to assert, in effect, "you 'working quickly' developers need first to adopt my values; only then can you be admitted to the conversation." C.f. Yegge on liberal-vs-conservative developers. [1] Lattner (along with you) is adopting a position towards the conservative end of the spectrum, which is cool. What's not cool is gaslighting the existence of a liberal perspective.
[1] https://plus.google.com/u/0/110981030061712822816/posts/KaSK...
A program that executes and performs some I/O is a very very low bar to pass. The next step is not being ready for wide-scale production, in fact the IEEE Software Engineering Body of Knowledge aims to define the many steps required for that and it's a lot of them. Developing by the seat of ones pants is fine for personal projects, but not for publicly used software.
And why should what developers "want" be the main criteria that should be used to choose programming languages? It's certainly important that developers are able to extract some satisfaction from their work, but that doesn't mean we should sacrifice other important goals just for the personal comfort of developers.
Swift really does not support quickly iterating on a design. It demands that you sit down with your plan fully-formed, ruler and protractor in hand. Due to its strictness, changes ripple very quickly across even a small codebase.
Realized you need another enum case? You can't compile again until you touch all your switches. Protocol would be more expressive with an associated type? Stop what you're doing and write some type eraser boilerplate. Function needs to signal an error condition? Try/do/catch anywhere you call it, right now, before you run again. Need to put another type into that array? Write a new protocol and add some conformances.
Changing a interface as you work in Swift immediately creates a sea of red marks, which hinders the ability to experiment.
You're right that this strictness helps write ~correct~ safe code, and I appreciate that. But it's a tradeoff; there's a real cost in developer productivity/creativity. And I believe that it does not help produce the best design. It takes too long to get to running, which makes it too costly to heavily revise based on what you learn as you build.
EDIT: Actually, I want to go even further, and strike out "correct" in the paragraph above. Swift helps at a certain level of correctness, which is really not much higher than the type system -- it would be better to call this "sound" code, rather than "correct".
The overall point that I'm trying to make is that at the level of application/business logic -- which is the whole point of the program, after all -- Swift does not help with correctness. In fact, it can be detrimental, because, unless/until you understand your use cases well enough to actually lift them into the type system, at that upper level it blocks exploration without adding rigor.
I realized recently that I actually do like static typing, as long as the cost is low. (I really like TypeScript)
Sorry, I don't want to reason about the "shape" of my application state vector before I've written it... but that's what Swift's static type checking forces me to do... Design my app and it's data model at the same time.
Call me a lazy software hippie I guess.
I find the opposite to be the case. You assume that compile errors are a net negative for speed of development and expressivity. Instead I find that the compiler reminds me upfront of all the places I would need to update anyway in due time. In a dynamic language those inconsistencies would be found hours/days later and usually after lengthy debugging. Instead I find myself making large sweeping changes in the design very frequently, because I trust the compiler to warn of any logical inconsistencies.
You have to admit at that this point it boils down to subjective preference. You sound averse to the swift style of doing the right thing up front, and using the compiler to help you stay consistent. I personally tired of the hidden and unacknowledged costs of unsafe language, and compilers that allow your design to degenerate into an unmaintainable ball of mud over time. I'm ok with swift being an acquired taste and a technical advantage of folks who get it.
With the exception of the associated types thing which is a language limitation that would be nice to see resolved eventually, the others can be resolved with a combination of automatic refactoring (add new enum cases, etc) and a compiler mode where type errors compile down to runtime traps without preventing you from running the program. (And faster compilation in general would help as well!) These are both non-trivial to design and implement well, but I think it’s a good future direction for statically typed languages that will give them many of the benefits of dynamic languages during the prototyping phase.
Absolutely, something like this would be perfect. I like being able to leverage the compiler in preventing runtime errors...just not necessarily all at once, right up front. Allowing some strictness to be dialed back in debug builds would be a very nice feature.
In C++ -Wswitch is a valuable tool to find the former, but there is no way to find the latter. This makes writing correct exception handling code much much harder, so having Swift's strict behaviour would be great from my perspective!
It sounds to me that you want to use a few days of exploratory coding to save a few hours of design work. If this type of exploration is needed, then it could be done in another language which supports it and then when the design is in decent shape it can be ported to Swift.
Swift is not detrimental to the correctness of the business logic. It offers you a bedrock at the type sustem level on which to build that.
Also, you really could have phrased this to be a little less inflammatory.
Here it seems like Apple's culture of secrecy just hurt them for no reason. No really, Apple, you can just tell people what your plan is.
https://www.reddit.com/r/swift/comments/8zb9y1/state_of_swif...
I'm playing with rust to solve my use case, but is certainly hard. Is very unlikely you can build a team of mixed developers and use it. Swift is more forgiving, yet you can get great results anyway.
What new does kotlin or swift offer which python or ruby can not? Why reinvent the damned wheel for syntax sake when they could have worked for their device centric compiler for creating binaries out of python or ruby?
Compared to Ruby and Python they doubtless seem a little verbose. Type system features like genetics, which help to make Kotlin and Swift “expressive” in their family of languages, seem pointless from the standpoint of Ruby and Python.
So there are two aspects to this:
* What makes Swift or Kotlin compelling relative to other languages in that family? * Why use that family instead of languages outside it like Ruby and Python?
People have been promoting dynamic languages as an alternative to static languages for many decades but it doesn’t seem like performance has ever truly caught up enough.
It is not true of LuaJIT, which is as dynamic as languages get. Error detection and correctness, sure; raw performance is not the issue you've made it out to be.
Ruby and Python were fair choices, together they must have 10-50x the mindshare Lua does.
Lua (like plain JavaScript) is a more spartan development experience than Ruby or Python. I'm not sure what it is; but languages with rich OO seem to be what get picked up by people who need to build "applications" (windows where people click around in them).
I’ve run into a lot of programmers that worked with ObjC as they would Java or C++, that is, using very small and fine grained objects to divide up the problem.
It’s the standard way in Java. It’s also the opposite of how ObjC is supposed to be, which is ”a few big classes” that uses message passing as glue.
How many former ObjC programmers actually heard of ”Software IC”?
Using ObjC like Java/C++, the language quickly becomes unwieldy and verbose. If you do that, then obviously Swift feels like a huge improvement.
On the other hand, if you essentially write C and let ObjC be your reusability layer, then Swift might feel like you’re back to working inefficiently in Java / C++ with objects all over the place.
The way that I write Objective-C is to use 'id' for everything and have as few classes as possible, mostly I just add methods to the existing classes mainly NSString, NSArray, and NSDictionary.
Objects are interchangeable as long as they can respond to certain messages. For example, any object can be an array as long as it responds to objectAtIndex: and count. There was a whole discussion above about how Objective-C doesn't have generics, but this completely misses the point because Objective-C doesn't even need generics. "Modern" languages are not necessarily an improvement, software generally does not get better over time, it reaches a peak then it declines.
Objective-C is one of the best languages I have ever used, but the vast majority do not understand it, even the ones who say that they used to write Objective-C for X amount of years but now love Swift. The truth is, they never understood the beauty of Objective-C.
I consider Swift to be a language for large teams of average programmers, reading Lattner's response to Swift's criticisms tells me that he is a compiler guy, but that expertise does not carry over at all to programming languages.
I don't really like the direction they were taking Objective-C anyway, so in the end it doesn't matter. I'm against things like dot notation for accessing properties and ARC, I don't use either when I program in Objective-C. Those recent changes end up making the compiler more strict and a pain to deal with.
Consider the types of some template generated pointers, or just something like std::unique_ptr<std::vector<std::shared_ptr<Foo>>> (which isn’t a very far-fetched example).
This is ”the generics problem”, where it actually starts having an obscuring effect.
ObjC is immune to the problem since it lacks any need to do do the specialization. Unlike Java where you needed a lot of manually inserted casts without generics, ObjC doesn’t need them at all.
Like you say, dot notation, ARC, stricter resolution of dynamic messages etc were weakening the strong points of the language and would push the programmer towards a Java-like object model - which is very far away from how the language ideally should be used.