I mean, that is the only reason. It's a first party language in the Apple ecosystem. If you are working outside that ecosystem, there are better choices.
Outside of targeting Apple devices, the biggest upside would probably be that way more people are using and writing about Swift than those other languages.
The nice thing about Swift is that many broad programming patterns will ultimately be shared between Swift and Rust, and Swift has better support on Apple platforms. That's quite nice if everything you've had available before was Objective C or Objective/C++.
Yeah its so much time to learn all this stuff. Its a good reason they probably will all fade, better stick to js/python/java/C#/C++ like everyone else and wait.
> better stick to js/python/java/C#/C++ like everyone else
I would change Java to Kotlin here, since Kotlin has a 1:1 interop with Java while having goodies like null safety, type inference and functional programming without the academicism of Scala (and its slow compilation time).
If you also account for the smooth learning, Kotlin is probably the safest bet from these 9 mentioned.
A lot of businesses with Java codebases are already messing with it (and not only for Android).
> Since we're talking about the future of programming, can someone sell me on Swift instead of ocaml, SML, or F#?
I don't think the industry is likely to adopt functional languages. What people in the industry seem to want are safer programs with better null handling (e.g. optionals), friendly handling of async programming (e.g. futures/promises/async await), map/filter/reduce, immutable data types, and similar features that make programs safer and easier to write. Yet, the industry does not want to give up the object-oriented paradigm or the ability to do non-functional-programming stuff.
I think the future of programming languages is going to be hybrid languages rather than functional languages, simply because they are easier to adopt. In some cases, existing languages are absorbing those new features, so many companies are benefitting from them without switching languages.
Of the alternatives you mentioned, F# is the closest to being a hybrid language because of its integration with the .NET platform. Similar languages include Scala, JavaScript, Java since Java 8, Swift, Kotlin, etc. Python now has some of this stuff too.
On the other hand, Go is notable for rejecting functional features and it is also growing in popularity.
Excuse me, but what makes you think of OCaml, SML and F# as "future of programming"?
As much as I like OCaml, for example, I don't see it being mass-adopted in the near future, nor its tooling reaching the state of more established languages. All those languages you mentioned are most likely to continue being just niche ones.
The only mostly-functional language I can see being mass-adopted right now is Elixir, and it still has a long way to go.
They would need it to interoperate with their existing stack. They chose Kotlin where they reasonably could have chosen Swift and then worked to extend it to work with their existing stack.
Judging by what I would argue has been a lukewarm reception to Swift for Tensorflow, I think it would a very hard sell to convince people within Google to support Swift as a first-class language in the rest of their ecosystem.
They could for example start by adopting Swift for server-side programming for Google cloud and they seem to be putting no effort
into that, at least public-facing effort.
I'm pretty sure they went with Kotlin before Swift was open sourced, but I agree with you that the likelihood of them doing it is very low.
Swift for Tensorflow hasn't gotten much traction because the overlap between programmers who know swift and machine learning engineers is super tiny. Making the core language differentiable sounds very promising though .
That was the official support from Google. Kotlin had been around for a long time before that. I used to write Android applications using it before Google officially supported it.
Swift for Tensorflow also isn't at 1.0 AFAIK and hasn't been deemed "ready for primetime".
I think it's going to be hard to get data-scientists using anything other than Python any time soon, but I'm hopeful it will take off at some point, since it's really painful to work with scripting languages once you get used to a decent type system.
It's also a super interesting project to follow. The stuff they are doing with automatic differentiation, and the stuff they are talking about with metaprogramming is truly fascinating stuff, with all kinds of applications outside of machine learning. I really hope they manage to get it off the ground.
Yes it’s not at 1.0, but my point when I mention to people actually doing deep learning that Swift is coming and has support for native differentiation and static typing, the response is underwhelming to the point that I wonder if either of those features provide enough pull to get people to ever drop Python for Swift.
Yeah I think it will be a really hard sell since my perception is that programming is python for a lot of data scientists. Also static typing is something you have to use for a bit before you can understand that the little bit of extra formality is actually saving you a lot of trouble in the medium and long term.
Still given the growth of that industry, it's hard to imagine that Python can bear the burden of the increasingly complex work there forever.
> Static typing is useless for exploratory data analysis and data wrangling.
In my experience, doing this kind of task in an weak-typed or duck-typed language is already tedious. Function signatures don't tell me enough detail to know exactly what I'm working with, so I end up spending a lot of time digging through documentation or print debugging. Why not let the compiler, or the function signatures do this work for you?
So instead of using the native tooling provided by Julia, ML.NET, PyTorch, the solution is to somehow either emulate Linux on Windows, or being stuck with Ubuntu as distribution.
I mean containerization is not the same as emulation.
But I would assume a lot of people just want a notebook to do their work in. Does it really matter if it’s running in a container or natively? Most python projects run inside a virtual environment anyway, which is comparable if not more poorly encapsulated.
Also the cloud use-case is expanding. Environment basically doesn’t matter at all in that case.
It is on Windows, because Swift hardly runs there, if at all.
Yes it matters, because many organisations get development stations managed by IT, and there are very strict compliance regulations regarding where data processing takes place.
Swift was open-sourced 18 months before Google announced support for Kotlin.
There was probably several months or more of debate and work within Google by the time of the announcement, but it seems reasonable that during those 18 months they would have also considered and rejected Swift.
It's an interesting value proposition to consider. From one side, Google could have stood to gain by potentially luring the legion of iOS devs onto their platform. At the same time, it's hard to imagine them surrendering any part of their product to a language which is ultimately controlled by Apple at the end of the day (although I suppose they could fork it).
In any case, open source Swift was not ready for prime time at time of release.
Just to clarify Google's choice of Kotlin -- the maker of their IDE invented and did all of the heavy lifting with Kotlin, including building the JVM targeting compiler, and the IDE to develop it in (which is the foundation of Android Studio). Adopting Kotlin was very close to free for Android, and was really just rubber stamping what a lot of developers were doing regardless.
You could use Kotlin for years before Google officially endorsed it...given that Android Studio is made by JetBrains and they made it trivial to use. JetBrains did 100% of the heavy lifting, and Google just conceded eventually.
JetBrains is a plague on mobile development. Their current business model appears to be selling workflows which are totally dependent on their proprietary tooling, and make over-complex monstrosities of mobile applications
I hate to say this, but Swift is to Objective-c, what Scala is to Java....
It was very exiting and promising at first, but it became bogged down due to its sheer run-away complexity and over-academic approach to programming....
To an outsider, or iOS new comer, Swift looks much better than Objective-c, (due to Objective-c weird syntax), but to many insiders, Swift seems like a huge missed opportunity...
The use of Swift, outside Apple's ecosystem is going to be limited.
Rust can be quite usable and productive if you know the right shortcuts. The tradeoff is somewhat lowered performance (and Rust makes sure that you're aware of where you're choosing that tradeoff) but that's just the way it goes. It's not like Swift is any different.
I think Rust is a fine language, but it's undeniable that it involves more tedium than other languages to use.
If there is some tradeoff between safety, performance, and usability, Rust has prioritized safety and performance, where swift has chosen safety and usability. And that's perfectly fine. I am glad that Rust exists for those use-cases where the performance is important, but there are also cases where it's more important to be able to write a lot of code quickly with less friction.
It doesn't devalue Rust to admit that there are places where it is not the optimal choice.
Perhaps you haven't programmed in Java. Or even C++, for that matter (modern "Core C++" programming can be quite tedious at times).
I'd say the jury is still out when it comes to Rust vs. "higher level languages", yes, even Swift. The point of my comment is that the "friction" you're pointing to need not be an inherent property of something like Rust, any more than it is in C++. It remains to be seen if the 'tradeoff' you mention is a binding one.
> Perhaps you haven't programmed in Java. Or even C++, for that matter
I never said Rust was the most tedious language, and I would hope it has learned something from those decades old languages.
I agree that Rust has some usability issues which can be improved upon without sacrificing safety and performance, but I think that trade off will always be there at some level.
For example, Swift’s copy-on-write makes it very easy to reason about value types, but comes at the cost of performance since there will be a lot of copies which aren’t strictly necessary. You can get essentially the same behavior in Rust by cloning everything, but it takes a lot more typing and adds visual noise to your code, because Rust has made the default to be more parsimonious with memory usage.
At some level trade offs have to be made. No one language can be all thing a to all people.
Yeah that is exactly my point. In many cases all the extra work you put into writing Rust code for the additional performance is just that: extra. It doesn’t add any meaningful value to the final product, and it comes at the opportunity cost of that time you could have spent adding or improving features in a more productive language.
Yeah, while Rust is paving the way for affine type systems among mainstream languages, and it already influenced design decisions on other system programming languages, including Swift (memory ownership manifest), it isn't the first on my list for UI or distributed computing applications.
Yeah to me Rust almost feels like the prototype for the next great programming language. There are a lot of great ideas there, but there are also a lot of awkward edges. Like what it accomplishes from a technical perspective is super impressive, but it would be great if somebody could synthesize all of those concepts behind a cleaner front-end which really nails the ergonomics.
A few people have tossed around the idea of “what if Rust but drop the commitment to zero cost abstractions.” That’s probably our principle that causes the most ergonomic hit.
Of course, Rust won’t start taking that path, but if I were to start a new language today, that’s what it would look like.
Interesting. There was a really good talk at the last CPPCon by Chandler Carruth about how there is really no such thing as a zero-cost abstraction. The main point being, while you might be able to optimize against a runtime performance cost for abstractions, the cost will almost always be shifted to compile time, or to the cognitive burden on the developer.
It really makes me think there must be something like the first law of thermodynamics for logical complexity.
Yeah, I haven’t watched the talk, but as you’d expect, Chandler has his head on straight. This is a common misconception: zero cost refers to runtime only. There’s always cost. Some people have started saying “zero overhead” instead to make it more clear, but it takes a while to change entrenched terminology.
Go is a nice language for some use-cases, but a bit too light on abstractions for my needs.
When I tried Kotlin a couple years ago, it seemed to be marginally behind Swift in terms of the power of the type system and some of the cool things you can do in Swift, and I'm not wild about targeting JVM, but I understand that situation has been evolving so maybe I should give it a second look at some point.
Kotlin Native is nice, but its compile times are absolutely horrible. I guess some of this comes from Gradle, which is another mess in itself, but when it takes over half a minute to compile Hello World, there is a problem.
I think the parent cared more about it being driven by a specific company’s interests than Apple’s in particular, because this makes it somewhat difficult to use on other platforms. And I’d argue that Apple’s engineering talent, while good, is not “the best”.
Hard to say if it's the best, but likely the worst attitude of the management on top when it comes to collaboration and general progress (which languages should enable).
I find Swift to be significantly more usable and less academic than Scala, and I like it much more as a result. Sure, it takes a number of cues from Scala, but it takes care to not fall into the same traps.
TIOBE’s methodology and rankings seem very dubious to me. When was the last time you met someone who primarily programs in C? (I was one of those people for 14 years, but that was a while ago).
I’ve never worked at a startup. I know very few people who have been involved in the startup world. I have exclusively used C and C++ in my professional work (with a tiny bit of python for scripting).
Yet I haven’t know anybody who primarily or even occasionally used C in their work for over a decade. I know they exist but the majority of C programmers moved on to C++ a long time ago.
There are areas like kernel and driver development where C is still in widespread use but these jobs represent a tiny fraction of developers.
Any language popularity metric that ranks C as the second most popular language is massively flawed.
The world running on top of C and Linux being popular have nothing to do with this. Have you looked at what TIOBE claims to measure? They very specifically say it’s not about the number of lines of existing code. It’s supposed to be a measure of the popularity of the language.
“The TIOBE Programming Community index is an indicator of the popularity of programming languages. The index is updated once a month. The ratings are based on the number of skilled engineers world-wide, courses and third party vendors. Popular search engines such as Google, Bing, Yahoo!, Wikipedia, Amazon, YouTube and Baidu are used to calculate the ratings. It is important to note that the TIOBE index is not about the best programming language or the language in which most lines of code have been written.”
For a language whose nearly exclusive use case is writing Cocoa applications, it’s odd how Swift ignored most of what had made Obj-C so good for GUI apps. Instead they just doubled down on everything that C++ was and Obj-C actively had tried to avoid.
Objective-C was a good fit for dynamic, object-oriented GUI frameworks like Cocoa because that’s how it itself was structured. SwiftUI and Combine are simply a different way of structuring UI code that fits a lot better with Swift’s strengths.
Can you go into any specifics? Personally I've found Swift to be incredibly easy to read and write, and that it largely delivers in terms of rolling out complexity through progressive disclosure. Most of the complexity is only there if you need it in my experience.
I keep hearing about this concept of "progressive disclosure", but I can't say I've seen it in Swift. Even the simplest functions I want to write, I tug on a little thread of an idea that I have, and pretty soon I'm pulling out this giant tangle that's got 3/4 of the Swift type system dangling off of it.
What you're saying may be technically true. My issue is with the "if you need it" part. Unfortunately, I don't get to choose what I think I need. The compiler does.
For example, every beginning Swift programmer runs into "Protocol can only be used as a generic constraint because it has Self or associatedType requirements" [1]. You start by thinking, I'm going to write a simple little type!, and then 30 seconds later you're digging through the least-documented parts of the Swift manual trying to figure out if there's a simple fix for this. (There isn't.) It's not like Objective-C where you write an -isEqualTo:(id) method and call it a day.
This happens all over the place. Swift lambdas are weirder than Objective-C blocks. Swift errors are weirder than Objective-C exceptions. Swift strings are weirder than Objective-C strings. Ultimately, there is always a reason for the complexity (often: performance), but the upshot is that for any Swift feature I've wanted to use, I always had to learn a lot of extra details before I was able to use it.
I feel there are a lot of other languages which are both easier to read and write, and do a much better job at progressive disclosure.
Interesting. I guess in my opinion, there is a difference between "swift has some pain points" and "swift is inherently over-complex". I have run into the associated types issue (which is improved a bit by the addition of existential by the way) but my reaction was more that this is a particular design pattern to avoid, rather than that the language is null and void.
Given that you've made the comparison to Objective-C, are you sure you're not just running up against the learning curve of a new language? There are cases where Swift is a bit stricter, and therefore it's harder to type code which will compile on the first try, but in many of those cases it's because the strictness is allowing you to avoid entire categories of runtime bugs, which would give a non-specific error in Objective-C given the dynamic nature of the language.
Has Swift improved their text handling? Last time I looked, it took way too many lines of code and temporary variables just to extract a substring range from a string. Their convoluted idea that a string can't be directly sliced with integer indexes–by bytes, let alone by Unicode code points or graphemes–was so frustrating I swore I would never look in Swift's general direction again. It was such a joke just to try to extract x UTF-8 characters starting from position y. I liked the overall feel of the language, but the fact I ran into such a horrible wall trying to perform the most basic of string manipulations was unforgivable.
Swift came out at a time where UTF-8 was already the standard. They talked a lot of talk about grapheme clusters being the most accurate representation, and then failed to deliver a coherent API to back it up. Any chance that has changed?
It's gotten a bit better, but Swift is still probably not the tool you want to use if you need to do a lot of string manipulation. Swift's string implementation has some interesting properties in terms of memory efficiency and performance, but it still requires fairly the verbose use of string indexes when working with strings rather than simple int offsets. There are good reasons for this, but it's not terribly ergonomic to work with.
FWIW it would probably be fairly easy to implement some String extensions which would give you the kind of API it sounds like you are looking for.
I don't think there's any world where Swift is popular outside Apple's ecosystem. It's not anything wrong with the language that's the problem, it's that the primary reason you'd use Swift over similar languages like Rust or Nim is its integration into Apple's ecosystem. It has some unique features outside of that, but not enough to make up for how deep in the wilderness you'd be running Swift on non-Apple platforms. Rust, for example, is probably more complex then Swift — but I'd still choose it over Swift for cross-platform development because the language has a strong cross-platform story.
> I don't think there's any world where Swift is popular outside Apple's ecosystem.
I wouldn't go quite that far. I agree that Swift's cross-platform story is lacking, but as someone who follows the language closely, the story is improving all the time.
I see it as largely a chicken-and-egg problem: i.e. there's not enough activity outside the Apple ecosystem to improve the situation quickly, but I don't think it's impossible for it to get there.
For instance, it's already possible to use Swift in AWS Lambda, and some support for Azure's alternative offering, as well as Google's work on Swift for Tensorflow. All of these cases involve running Swift code in a very controlled environment, like a container, and this is very tenable even in Swift's current state. So even if it might be a bit of a pain to get Swift up and running on whatever exotic linux distro you run on your workstation, there are already starting to be some "easy" use-cases for Swift outside of Apple platforms. As the scope of these one-off use-cases grows, I think it's likely there will be increased demand to improve the cross-platform story in general.
Personally this is appealing to me, because while I agree that Rust is miles ahead in terms of cross-platform support, I find Swift so much more productive and pleasant to work with that I welcome more opportunities to use it.
My greatest gripe with Swift comes not from Swift itself but from its standard library. When most new languages start with their own standard libraries that are usually interfaces towards C APIs or POSIX, Swift's Foundation is half of MacOS and then some.
I recently needed to read some data from a file in Swift, and it took me quite some time to realise there was no fopen equivalent. Read/write files is a function on String? And getting a file handle is an excercise in figuring out proper dir names and user enums? [1]
There are a few other weird things in the language itself like guards which IMO are an entirely unnecessary construct that can be as easily solved with regular ifs. Or Optionals that have no way of working with them except unwrapping them (either with ! or via guards).
SwiftUI, however, is a very interesting approach, and I hope there are more frameworks (especially UI frameworks) like this.
Swift optimizes for lightness at the call site, but even the definition is quite short for the constraints it imposes.
> I recently needed to read some data from a file in Swift, and it took me quite some time to realise there was no fopen equivalent.
You can import Darwin or Glibc to get direct access to fopen. It’s a bit unergonomic to use, though.
> Read/write files is a function on String?
NSString, as a deprecated holdover from Foundation.
> There are a few other weird things in the language itself like guards which IMO are an entirely unnecessary construct that can be as easily solved with regular ifs.
That’s the whole point of syntactic sugar and constructs which make your intent clear.
> Or Optionals that have no way of working with them except unwrapping them (either with ! or via guards).
There’s also the nil-coalescing operator, but the whole point is that you can’t sweep an Optional under the rug.
> but even the definition is quite short for the constraints it imposes.
I'd have to look up how extension method would look in this case in C#, but my hunch is that it would be more lightweight and readable, with the same contstraints.
> You can import Darwin or Glibc to get direct access to fopen. It’s a bit unergonomic to use, though.
FileManager.default, .appendingPath etc. isn't ergonomic either ;)
> NSString, as a deprecated holdover from Foundation.
1. How is it deprecated if that's clearly the way to read/write files?
2. Foundation is the standard lib for Swift, and the way it's designed hurts Swift-the-language immensely, IMO. If that's deprecated, what's not deprecated and how can anyone figure that out?
> There’s also the nil-coalescing operator, but the whole point is that you can’t sweep an Optional under the rug.
There are several languages with Optionals, and they don't let you sweep them under the rug, and they provide better facilities to handle them.
IMO optionals the way they are (and a few other decisions) come precisely from the constraints of Foundation and original goals of Swift: to be a replacement for Obj-C when creating iPhone apps. That's why the NSStrings, and the awkward APIs, and the astonishingly large number of nullable parameters in API calls and nullable results from API calls.
The directory thing is more due to sandboxing than anything else. They don't want someone to be able to write an app that can read anything anywhere on your phone, so it has specific directories that have different levels of access and temporality (i.e. one is a temp folder that gets flushed each time you quit the app, if I remember correctly).
It's not that complicated once you look it up, and like most of this stuff, you can mostly write wrapper classes one time to hide the gnarly bits and call your wrapper class to do what you need to do the way you like to do it.
It's been several years since I've had it read from a file, and I actually thought I would click that twitter link and see something super complicated, but it's actually pretty straight-forward. Not a one-liner like some languages, no, but as soon as you want to open something with options (like the encoding in this one), most other languages start looking more complicated like this as well.
Like python's open looks more like this with options: "open(filename, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)". I've opened many a file in Python scripts, but I'd have to look up buffering, encoding, errors, closefd, and opener right now if I wanted to use them (I haven't really in the past)
And Python has 11 different access modes that I often have to look up to remember what all my options are again: r+,w,wb,w+,wb+,a,ab,a+, and ab+
> They don't want someone to be able to write an app that can read anything anywhere on your phone,
And that's the main problem with Foundation which hurts Swift as a language: it was made for iPhone apps, and hardly anything else. I was trying to make a CLI app on the desktop. I gave up and used something else.
> It's not that complicated once you look it up, and like most of this stuff
Yeah, I tried to look it up. It's extremely complicated, and it doesn't help that the documentation tends to spread all the knowledge across dozens of pages with very terse documentation and next to zero examples.
> I've opened many a file in Python scripts, but I'd have to look up buffering, encoding, errors, closefd, and opener right now if I wanted to use them
My example doesn't have any buffering, or encoding, or anything. It's just reading a file. There's no chance in hell you can deduce those lines from the documnentation, or find out where to put the files to read from, or find out that it's not the file's job to read/write data, but String type's (wat?) etc.
It doesn't help that the only real example of reading and writing files isn't in the docs, but in a StackOverflow answer (most other examples are either outdated, or use calls to Obj-C libs etc.)
It sounds to me like you're just asking for a quick and dirty default that's nice and pithy and short. That's fine, but file i/o tends to get messy and easy to exploit without some safeguards, and doing it "right" tends to be a bit more complicated.
Like part of your complaint above is pathing, and even something as short and pithy as Python (at least in my opinion, that's why I keep going to it to write proof of concepts), in order to do file i/o "right", requires knowing about all sorts of other things.
One thing I forgot to mention in my previous post is paths in Python, which has this whole fun page on it in the Python documentation: https://docs.python.org/3/library/os.path.html. Part of the reason for this in the first place is because pathing is handled differently between Unix and Windows systems, so you're supposed to use this library to navigate (or something completely different, glob, which is another thing to look up and understand) instead of just using a open("c:/blah/blah.txt") so that it can be compatible for either OS.
That's not too much different than having to specify a type of directory for Swift, and has the same types of reasons for why it exists, for safety, but it just doesn't let you do something potentially dumb like open('blah.txt') for something quick and dirty, like Python does, which I admit I do abuse if I'm trying to write something quick and dirty myself.
> One thing I forgot to mention in my previous post is paths in Python, which has this whole fun page on it in the Python documentation: https://docs.python.org/3/library/os.path.html. Part of the reason for this in the first place is because pathing is handled differently between Unix and Windows systems, so you're supposed to use this library to navigate (or something completely different, glob, which is another thing to look up and understand) instead of just using a open("c:/blah/blah.txt") so that it can be compatible for either OS.
There is pathlib nowadays that allows you to navigate in very complex situations using a quite nice OOP API.
Good to know, thanks :) I've only ever used Python for my own tinkering purposes so I haven't been too aware of any new developments.
But I assume the old ways are still valid code, so if you're working with Python code you may encounter any of now 3 different systems of just navigating paths for file i/o, what the parent claims should be dirt simple.
Yes. It is dirt simple, for dirt simple things. It's quite easy and discoverable from documentation for more complex things.
The method in my link (which changed rather drastically between versions):
- is very much iOS and MacOS specific
- requires knowledge of quite a few iOS/MacOS-related things (FileManager.SearchPathDirectory is probably 80% Apple-specific)
- even though it's a "FileManager", it doesn't even let you access/open a file. You have to perform additional operations on the resulting Directory type (.appendingPathComponent)
- even that doesn't give you a means of opening a file, because in order to read a file, you have to invoke a String constructor. In order to write to a file, you need to invoke a method on a String type. Talk about coupling entirely unrelated things
That is an example of objectively bad API design.
And it's clear from API evolution that it's not even Swift APIs. These are very thin wrappers for OS's existing Obj-C APIs. I think it's the first among languages: to provide OS APIs and call them a standard library for a language. I don't think even MS did that when they were creating .NET.
It is still relatively simple because the conversion between Pathlib<->str is literally one method call (from pathlib, just call `str(pathlib_object)`, from string, just call `pathlib.Path(str_object)`.
I know this because I started a project using only strings and `os.path`, however when testing it started to become complicate to mock the correct paths so in tests I use `pathlib` (with conversions back to string when I finish path manipulation) and the code still works.
let fileContents = try? String(contentsOfFile: "file.txt")
That works perfectly fine.
In the context of an iOS or MacOS app, that of course won't work, because apps only have access to certain directories. That is why you typically use the FileManager object to get the path to the directory you'll need.
Swift has come a long way. I remember first trying it and XCode acting like it couldn't figure anything out in Swift, and you could almost never bring up an autocomplete or search for references or jump to definitions or any nice feature in an IDE that worked just fine with Objective-C. I decided to give it another shot years later, and I'm working on a simple game in Swift right now, and it's been a much, much smoother experience.
Although admittedly there's still some bizarre behavior. Like
this morning while iterating over a simple for loop, XCode decided it was just going to stay on the final item in the collection and keep looping until my memory ran out, over and over again, and I couldn't find anyone talking about this online, but eventually decided to do a "Clean Build Folder" and then Build, and that fixed it (but why did it happen in the first place? So odd!).
And it still doesn't always think a class I wrote or renamed is valid when referencing it in another class, but a rebuild or quitting and restarting tends to fix that.
Still, I'm liking it a lot, and having a lot of fun with Swift now. SpriteKit is great for making games, except for the lack of cross-platform capability, but if the game somehow manages to take off, I can write some wrapper classes to have the same behavior as most of the SpriteKit classes I use and port it easily enough.
I guess I should say "My experience in working with Swift has come a long way", because XCode being so crap with it made it a pain in the ass to code in Swift back then, for me, especially considering how rock solid Visual Studio is in comparison.
To be more specific about Swift, though, there used to be a ton of things you had to bridge to Objective-C in order to do back then, and now it seems like there's almost nothing you have to bridge to Objective-C to do unless you want to work with your legacy code (all of their libraries now have Swift support, at least those that I use), and there's now a cool new SwiftUI framework that is very easy to use and very powerful.
I can't really imagine Swift ever breaking out of Apple's walled garden. It's a pretty big garden, but the language concedes so much to Objective-C compatibility, it is hard to see any role for it where Objective-C never got a foothold.
Is this necessarily a bad thing? ObjC did fine as a mostly Apple-centric language. Swift is generally a lot nicer to use than ObjC, even if it wasn't a clean break from backwards compatibility.
One of my projects is pure Swift and I haven’t felt any Objective-C-based pain. Mostly this is because it doesn’t have a UI. When you touch UIKit then the legacy stuff rears its head and you have to deal with selectors and NSObject and such. I think SwiftUI is supposed to be the answer to that. We ought to know whether it works out in a decade or so :). But as long as you’re looking for a general-purpose programming language, Swift is a good choice. The type system is excellent and makes a lot of things easier. I like ARC better than GC, which is the biggest selling point in my opinion.
> the language concedes so much to Objective-C compatibility
Such as?
Personally I've taken to using Swift basically in every use-case where I can, largely because it's so nice to work with. It strikes a very nice balance between productivity (lack of tedium) and strong compile-time guarantees of correctness.
From my perspective, there are a few obstacles preventing Swift from achieving wide adoption:
1. Tooling and support outside Apple platforms has a long way to go. The story is better than it was even a year or two ago, but when compared to Rust, for example, Swift is massively lacking in this area.
2. Swift is still viewed as an iOS-only language. Even though there are now mature libraries for things like writing a webserver, and it's quite possible to write software for Linux using Swift, the developer perception is not there, and thus adoption is slow. This contributes to the lack of tooling and support.
3. Performance needs some improvement. ARC and copy-on-write are great for writing correct code easily, but they lead to some serious and sometimes unpredictable performance cliffs with Swift. There is a lot of low-hanging fruit here, but this needs to be addressed before Swift could ever find a place as a systems programming language for example.
So I would not quite say I'm bullish with respect to Swift's chances of breaking out as a general purpose programming language, but objectively speaking I would say that all the problems preventing Swift reaching that state are solvable problems, and Objective-C compatibility has little to do with it.
Swift doesn't seem to be a bad language, but during my brief adventures with it I encountered a major drawback: differences between versions are so great, that searching the web for examples is problematic and you end up with many fruitless attempts and compiler errors. Apple's documentation isn't nearly as useful and readable as that of the Go team.
This was definitely true in the past, and might still be true now, I'm not sure, but XCode does a good job of catching Swift errors now and can fix several of them for you, and for those that don't, there mostly seems to be useful StackOverflow answers for the error messages online now.
I took a long break from working with Swift and just started diving into it again, and even though there was two major versions since I last messed with it, it was pretty easy to settle into it, and I've only had to look up how to do things on a case by case basis periodically. Maybe that's just my experience, though, and others have a harder time with it.
This is not nearly as much of a problem as it once was. Especially with ABI stability, a lot of the language feels much more "nailed down" and language changes now tend to be additive rather than breaking.
I like a lot about Swift: strong typing, good support for closures, reasonable abstractions. But there's a lot that I dislike too. A lot. In general, I find the language to be far too trendy and fussy. I get the impression the design was guided by the goal of streamlining snippets of code meant to highlight cool features, gaining undesirable complexity as a result. One example: Do we really need $n function parameters? In just about every other language, a function has parameters, period. Those names are used inside the function. Depending on the language they may be used outside the function too. Swift separates those inside and outside views, permitting different names for both. And then allows for no names at all! I don't care. $n parameters seem to come from primitive languages like sh, and should have stayed there.
get/set/didSet introduces ridiculous complications just so we can pretend that a large number of function invocations look like assignment statements. This was a cool idea in C++, briefly, and then we discovered that having arbitrary code hide behind what looks like an ordinary assignment statement was a bad idea.
Extensions also remind me of C++ excesses. It is difficult to look at a piece of code involving a variable some type and be sure that I understand how that type works. The problem is that the code implementing the type is not in one place. There is the type definition, but then there are extensions. Possibly many of them. Defined all over the place.
I really dislike the irregularity surrounding let. In one context in unwraps an Optional. In another context it does not. Why?
I got off the Swift train at the release in which associated types were introduced. I'm sure it solves some actual problem, but it sure wasn't clear at the time. (The project ended -- it's not that I decided to go back to Objective C.)
Reference counting is far too intrusive, and it is easy to get it wrong in subtle ways. I find Java's (!) memory model relatively simple, and that's saying something. I understand why reference counting was chosen over GC. I don't have a good answer, but reference counting is just ugly. I actually think I prefer the C/C++ model of explicitly freeing memory.
I certainly don't disagree that there's too much C++ in Swift (the Swift architects write C++ for a living, not ObjC, so it's hardly surprising) but it's not due to trendiness. Most of the features you mention derive from direct experience with Objective-C. Function arguments, property accessors (get/set/didSet), extensions (categories), etc. Every one of these things solves a real problem in the field.
I don't understand your comment about reference counting being intrusive. Apple's implementation, ARC, used in Swift and modern ObjC, is essentially invisible to you if you're using native objects.
I don't agree that get/set/didSet solve actual problems. Languages without property accessors do just fine, but then they don't overload the getting and setting of variables. I would much rather right thing.setField(123), and have setField do whatever actions need to accompany the assignment; than write thing.field = 123, and then have the actions be hidden. What is so f'ing special about x = thing.field and thing.field = x syntax? Why is it so important to stuff additional semantics into that syntax?
As for reference counting: I'm referring to capture lists, and the "unowned self" hack needed with closures. E.g. https://www.raywenderlich.com/966538-arc-and-memory-manageme.... And it gets more complicated with @escaping. I sure don't view all these subtle interactions of closures and ARC to be invisible. This stuff is subtle. Get it wrong and you have leaks.
>I don't understand your comment about reference counting being intrusive.
It's intrusive because you can never really stop thinking about it if you want to write correct code. Here's an example from a very interesting article by Mark Sands [1]:
How quickly can you tell whether or not this piece of code has a reference cycle?
class ServiceLayer {
// ...
private var task: URLSessionDataTask?
func foo(url: URL) {
task = URLSession.shared.dataTask(with: url) { data, response, error in
let result = // process data
DispatchQueue.main.async { [weak self] in
self?.handleResult(result)
}
}
task?.resume()
}
deinit {
task?.cancel()
}
}
In my view, reference counting does not combine very well with heavy use of closures.
> How quickly can you tell whether or not this piece of code has a reference cycle?
I'm curious. Does it? I would have guessed the "weak self" would have prevented it.
> In my view, reference counting does not combine very well with heavy use of closures.
It's one of the area where one has to be careful for sure! C++ with smart pointers and callbacks exhibits the same problem. And GC based languages make the pattern easier for sure. However I think this is not even the most critical error source in callback based designs. I think threading issues due to callbacks being executed on different threads cause the most trouble.
Therefore I think languages like Javascript and Dart - which only offer a single thread AND GC - are the the easiest to use for callback based designs.
I actually don't mind that feature too much. I do appreciate that it clarifies code with even a few arguments of the same type. Although there are other ways to clarify such situations in other languages. The Swift approach does lead to exceptionally verbose code, but that's obviously subjective.
It's the $n syntax that I think is overkill. Do we really need three different ways to name parameters?
Yeah to each her own I guess, but I don't mind the $n syntax either. It's only relevant in closures, and in my experience it's mostly used in simple, short closures where the identity of the parameter is obvious. So for example if you are doing a simple map:
let incremented = myArray.map { $0 + 1 }
the $n syntax just lets you save a little bit of typing. In my opinion it often makes the intent clearer when reading a line of code, since having to explicitly name the variable here adds noise which isn't really meaningful, especially in the case where you have a chain of map/reduce/filter operations.
I would put it in the same category as Rust's `?` operator, which saves you from typing a bunch of unwraps or match statements everywhere.
Why was refcounting chosen? It seems to me it was only done because the designers were so used to C++ that they don't understand the drawbacks of not having it.
But didn't some version of Objective-C use a GC? My understanding was that the reason it didn't work well was because of issues with the language and not the libraries. So they could still have used a GC for Swift?
So if I understand it correctly, Apple decided to move that complexity to the language itself? I was reading up on the rules for references in Swift, and it looks like a lot of complexity and lots of opportunities for introducing errors leading to leaks.
144 comments
[ 3.1 ms ] story [ 234 ms ] threadSince we're talking about the future of programming, can someone sell me on Swift instead of ocaml, SML, or F#?
I don't see a good reason to pick it outside of targeting Apple devices.
Outside of Apple platforms it is pretty much WIP.
+ scala, go, rust, elixir/erlang
Yeah its so much time to learn all this stuff. Its a good reason they probably will all fade, better stick to js/python/java/C#/C++ like everyone else and wait.
I would change Java to Kotlin here, since Kotlin has a 1:1 interop with Java while having goodies like null safety, type inference and functional programming without the academicism of Scala (and its slow compilation time).
If you also account for the smooth learning, Kotlin is probably the safest bet from these 9 mentioned.
A lot of businesses with Java codebases are already messing with it (and not only for Android).
I don't think the industry is likely to adopt functional languages. What people in the industry seem to want are safer programs with better null handling (e.g. optionals), friendly handling of async programming (e.g. futures/promises/async await), map/filter/reduce, immutable data types, and similar features that make programs safer and easier to write. Yet, the industry does not want to give up the object-oriented paradigm or the ability to do non-functional-programming stuff.
I think the future of programming languages is going to be hybrid languages rather than functional languages, simply because they are easier to adopt. In some cases, existing languages are absorbing those new features, so many companies are benefitting from them without switching languages.
Of the alternatives you mentioned, F# is the closest to being a hybrid language because of its integration with the .NET platform. Similar languages include Scala, JavaScript, Java since Java 8, Swift, Kotlin, etc. Python now has some of this stuff too.
On the other hand, Go is notable for rejecting functional features and it is also growing in popularity.
As much as I like OCaml, for example, I don't see it being mass-adopted in the near future, nor its tooling reaching the state of more established languages. All those languages you mentioned are most likely to continue being just niche ones.
The only mostly-functional language I can see being mass-adopted right now is Elixir, and it still has a long way to go.
They would need it to interoperate with their existing stack. They chose Kotlin where they reasonably could have chosen Swift and then worked to extend it to work with their existing stack.
Judging by what I would argue has been a lukewarm reception to Swift for Tensorflow, I think it would a very hard sell to convince people within Google to support Swift as a first-class language in the rest of their ecosystem.
They could for example start by adopting Swift for server-side programming for Google cloud and they seem to be putting no effort into that, at least public-facing effort.
Swift for Tensorflow hasn't gotten much traction because the overlap between programmers who know swift and machine learning engineers is super tiny. Making the core language differentiable sounds very promising though .
Kotlin was open sourced around 2012 and people were using it in Android apps before Google officially started supporting it in 2016.
Swift open source 2015/12/3: https://developer.apple.com/swift/blog/?id=34
I think it's going to be hard to get data-scientists using anything other than Python any time soon, but I'm hopeful it will take off at some point, since it's really painful to work with scripting languages once you get used to a decent type system.
It's also a super interesting project to follow. The stuff they are doing with automatic differentiation, and the stuff they are talking about with metaprogramming is truly fascinating stuff, with all kinds of applications outside of machine learning. I really hope they manage to get it off the ground.
Still given the growth of that industry, it's hard to imagine that Python can bear the burden of the increasingly complex work there forever.
Once you get to the modelling step all of the data is in typed arrays.
Static types start to shine once the project grows and the new type annotation syntax works great for that.
I've tried doing machine learning in C++, Java, Scala and JavaScript and all of them are a pain compared to python.
Python would be perfect if I could annotate parts of my code and compile them. (Pretty much what's commonly done with cython or numba jit.
In my experience, doing this kind of task in an weak-typed or duck-typed language is already tedious. Function signatures don't tell me enough detail to know exactly what I'm working with, so I end up spending a lot of time digging through documentation or print debugging. Why not let the compiler, or the function signatures do this work for you?
If they want to make an Apple only version of Tensorflow, so be it, but don't expect it to take off on Linux and Windows research labs.
Edit: or on Ubuntu just download the toolchain.
But I would assume a lot of people just want a notebook to do their work in. Does it really matter if it’s running in a container or natively? Most python projects run inside a virtual environment anyway, which is comparable if not more poorly encapsulated.
Also the cloud use-case is expanding. Environment basically doesn’t matter at all in that case.
Yes it matters, because many organisations get development stations managed by IT, and there are very strict compliance regulations regarding where data processing takes place.
There was probably several months or more of debate and work within Google by the time of the announcement, but it seems reasonable that during those 18 months they would have also considered and rejected Swift.
In any case, open source Swift was not ready for prime time at time of release.
May 2017 - https://www.theverge.com/2017/5/17/15654988/google-jet-brain...
You could use Kotlin for years before Google officially endorsed it...given that Android Studio is made by JetBrains and they made it trivial to use. JetBrains did 100% of the heavy lifting, and Google just conceded eventually.
It was very exiting and promising at first, but it became bogged down due to its sheer run-away complexity and over-academic approach to programming....
To an outsider, or iOS new comer, Swift looks much better than Objective-c, (due to Objective-c weird syntax), but to many insiders, Swift seems like a huge missed opportunity...
The use of Swift, outside Apple's ecosystem is going to be limited.
If there is some tradeoff between safety, performance, and usability, Rust has prioritized safety and performance, where swift has chosen safety and usability. And that's perfectly fine. I am glad that Rust exists for those use-cases where the performance is important, but there are also cases where it's more important to be able to write a lot of code quickly with less friction.
It doesn't devalue Rust to admit that there are places where it is not the optimal choice.
Perhaps you haven't programmed in Java. Or even C++, for that matter (modern "Core C++" programming can be quite tedious at times).
I'd say the jury is still out when it comes to Rust vs. "higher level languages", yes, even Swift. The point of my comment is that the "friction" you're pointing to need not be an inherent property of something like Rust, any more than it is in C++. It remains to be seen if the 'tradeoff' you mention is a binding one.
I never said Rust was the most tedious language, and I would hope it has learned something from those decades old languages.
I agree that Rust has some usability issues which can be improved upon without sacrificing safety and performance, but I think that trade off will always be there at some level.
For example, Swift’s copy-on-write makes it very easy to reason about value types, but comes at the cost of performance since there will be a lot of copies which aren’t strictly necessary. You can get essentially the same behavior in Rust by cloning everything, but it takes a lot more typing and adds visual noise to your code, because Rust has made the default to be more parsimonious with memory usage.
At some level trade offs have to be made. No one language can be all thing a to all people.
It all boils down to, does it deliver what the customer of an application written in Swift is asking for?
Of course, Rust won’t start taking that path, but if I were to start a new language today, that’s what it would look like.
It really makes me think there must be something like the first law of thermodynamics for logical complexity.
Kotlin?
When I tried Kotlin a couple years ago, it seemed to be marginally behind Swift in terms of the power of the type system and some of the cool things you can do in Swift, and I'm not wild about targeting JVM, but I understand that situation has been evolving so maybe I should give it a second look at some point.
Apple has the best engineering talent of all tech companies.
Are you trolling or are you that kind of extremist apple fanboy?
I have a Cookbook here:
http://www.h4labs.com/dev/ios/swift_cookbook.html
I’m in the process of putting it on Github.
https://github.com/melling/SwiftCookBook
SwiftUI probably means that millions of apps will eventually move to Swift, making Swift a top 10 language.
https://www.tiobe.com/tiobe-index/
Red Monk seems much closer to reality: https://redmonk.com/sogrady/2019/07/18/language-rankings-6-1...
Yet I haven’t know anybody who primarily or even occasionally used C in their work for over a decade. I know they exist but the majority of C programmers moved on to C++ a long time ago.
There are areas like kernel and driver development where C is still in widespread use but these jobs represent a tiny fraction of developers.
Any language popularity metric that ranks C as the second most popular language is massively flawed.
Linux is pretty popular.
From their site (https://www.tiobe.com/tiobe-index/):
“The TIOBE Programming Community index is an indicator of the popularity of programming languages. The index is updated once a month. The ratings are based on the number of skilled engineers world-wide, courses and third party vendors. Popular search engines such as Google, Bing, Yahoo!, Wikipedia, Amazon, YouTube and Baidu are used to calculate the ratings. It is important to note that the TIOBE index is not about the best programming language or the language in which most lines of code have been written.”
My world runs on top of C++.
C is only relevant on constrained embedded hardware and FOSS UNIX clones.
I am sorry to say, you live in a bubble.
Because I just started playing with SwiftUI/Combine without ever using ObjC/UIKit, I don't know what parts of ObjC shined.
What you're saying may be technically true. My issue is with the "if you need it" part. Unfortunately, I don't get to choose what I think I need. The compiler does.
For example, every beginning Swift programmer runs into "Protocol can only be used as a generic constraint because it has Self or associatedType requirements" [1]. You start by thinking, I'm going to write a simple little type!, and then 30 seconds later you're digging through the least-documented parts of the Swift manual trying to figure out if there's a simple fix for this. (There isn't.) It's not like Objective-C where you write an -isEqualTo:(id) method and call it a day.
This happens all over the place. Swift lambdas are weirder than Objective-C blocks. Swift errors are weirder than Objective-C exceptions. Swift strings are weirder than Objective-C strings. Ultimately, there is always a reason for the complexity (often: performance), but the upshot is that for any Swift feature I've wanted to use, I always had to learn a lot of extra details before I was able to use it.
I feel there are a lot of other languages which are both easier to read and write, and do a much better job at progressive disclosure.
[1]: https://www.youtube.com/watch?v=XWoNjiSPqI8&t=53s
Given that you've made the comparison to Objective-C, are you sure you're not just running up against the learning curve of a new language? There are cases where Swift is a bit stricter, and therefore it's harder to type code which will compile on the first try, but in many of those cases it's because the strictness is allowing you to avoid entire categories of runtime bugs, which would give a non-specific error in Objective-C given the dynamic nature of the language.
Swift came out at a time where UTF-8 was already the standard. They talked a lot of talk about grapheme clusters being the most accurate representation, and then failed to deliver a coherent API to back it up. Any chance that has changed?
FWIW it would probably be fairly easy to implement some String extensions which would give you the kind of API it sounds like you are looking for.
I wouldn't go quite that far. I agree that Swift's cross-platform story is lacking, but as someone who follows the language closely, the story is improving all the time.
I see it as largely a chicken-and-egg problem: i.e. there's not enough activity outside the Apple ecosystem to improve the situation quickly, but I don't think it's impossible for it to get there.
For instance, it's already possible to use Swift in AWS Lambda, and some support for Azure's alternative offering, as well as Google's work on Swift for Tensorflow. All of these cases involve running Swift code in a very controlled environment, like a container, and this is very tenable even in Swift's current state. So even if it might be a bit of a pain to get Swift up and running on whatever exotic linux distro you run on your workstation, there are already starting to be some "easy" use-cases for Swift outside of Apple platforms. As the scope of these one-off use-cases grows, I think it's likely there will be increased demand to improve the cross-platform story in general.
Personally this is appealing to me, because while I agree that Rust is miles ahead in terms of cross-platform support, I find Swift so much more productive and pleasant to work with that I welcome more opportunities to use it.
swift is as pragmatic as kotlin
And a few paragraphs later:
I can't say this is lightweight any longer.My greatest gripe with Swift comes not from Swift itself but from its standard library. When most new languages start with their own standard libraries that are usually interfaces towards C APIs or POSIX, Swift's Foundation is half of MacOS and then some.
I recently needed to read some data from a file in Swift, and it took me quite some time to realise there was no fopen equivalent. Read/write files is a function on String? And getting a file handle is an excercise in figuring out proper dir names and user enums? [1]
There are a few other weird things in the language itself like guards which IMO are an entirely unnecessary construct that can be as easily solved with regular ifs. Or Optionals that have no way of working with them except unwrapping them (either with ! or via guards).
SwiftUI, however, is a very interesting approach, and I hope there are more frameworks (especially UI frameworks) like this.
[1] https://twitter.com/dmitriid/status/1201441652507844608
Swift optimizes for lightness at the call site, but even the definition is quite short for the constraints it imposes.
> I recently needed to read some data from a file in Swift, and it took me quite some time to realise there was no fopen equivalent.
You can import Darwin or Glibc to get direct access to fopen. It’s a bit unergonomic to use, though.
> Read/write files is a function on String?
NSString, as a deprecated holdover from Foundation.
> There are a few other weird things in the language itself like guards which IMO are an entirely unnecessary construct that can be as easily solved with regular ifs.
That’s the whole point of syntactic sugar and constructs which make your intent clear.
> Or Optionals that have no way of working with them except unwrapping them (either with ! or via guards).
There’s also the nil-coalescing operator, but the whole point is that you can’t sweep an Optional under the rug.
I'd have to look up how extension method would look in this case in C#, but my hunch is that it would be more lightweight and readable, with the same contstraints.
> You can import Darwin or Glibc to get direct access to fopen. It’s a bit unergonomic to use, though.
FileManager.default, .appendingPath etc. isn't ergonomic either ;)
> NSString, as a deprecated holdover from Foundation.
1. How is it deprecated if that's clearly the way to read/write files?
2. Foundation is the standard lib for Swift, and the way it's designed hurts Swift-the-language immensely, IMO. If that's deprecated, what's not deprecated and how can anyone figure that out?
> There’s also the nil-coalescing operator, but the whole point is that you can’t sweep an Optional under the rug.
There are several languages with Optionals, and they don't let you sweep them under the rug, and they provide better facilities to handle them.
IMO optionals the way they are (and a few other decisions) come precisely from the constraints of Foundation and original goals of Swift: to be a replacement for Obj-C when creating iPhone apps. That's why the NSStrings, and the awkward APIs, and the astonishingly large number of nullable parameters in API calls and nullable results from API calls.
It's not that complicated once you look it up, and like most of this stuff, you can mostly write wrapper classes one time to hide the gnarly bits and call your wrapper class to do what you need to do the way you like to do it.
It's been several years since I've had it read from a file, and I actually thought I would click that twitter link and see something super complicated, but it's actually pretty straight-forward. Not a one-liner like some languages, no, but as soon as you want to open something with options (like the encoding in this one), most other languages start looking more complicated like this as well.
Like python's open looks more like this with options: "open(filename, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)". I've opened many a file in Python scripts, but I'd have to look up buffering, encoding, errors, closefd, and opener right now if I wanted to use them (I haven't really in the past)
And Python has 11 different access modes that I often have to look up to remember what all my options are again: r+,w,wb,w+,wb+,a,ab,a+, and ab+
And that's the main problem with Foundation which hurts Swift as a language: it was made for iPhone apps, and hardly anything else. I was trying to make a CLI app on the desktop. I gave up and used something else.
> It's not that complicated once you look it up, and like most of this stuff
Yeah, I tried to look it up. It's extremely complicated, and it doesn't help that the documentation tends to spread all the knowledge across dozens of pages with very terse documentation and next to zero examples.
> I've opened many a file in Python scripts, but I'd have to look up buffering, encoding, errors, closefd, and opener right now if I wanted to use them
My example doesn't have any buffering, or encoding, or anything. It's just reading a file. There's no chance in hell you can deduce those lines from the documnentation, or find out where to put the files to read from, or find out that it's not the file's job to read/write data, but String type's (wat?) etc.
It doesn't help that the only real example of reading and writing files isn't in the docs, but in a StackOverflow answer (most other examples are either outdated, or use calls to Obj-C libs etc.)
Like part of your complaint above is pathing, and even something as short and pithy as Python (at least in my opinion, that's why I keep going to it to write proof of concepts), in order to do file i/o "right", requires knowing about all sorts of other things.
One thing I forgot to mention in my previous post is paths in Python, which has this whole fun page on it in the Python documentation: https://docs.python.org/3/library/os.path.html. Part of the reason for this in the first place is because pathing is handled differently between Unix and Windows systems, so you're supposed to use this library to navigate (or something completely different, glob, which is another thing to look up and understand) instead of just using a open("c:/blah/blah.txt") so that it can be compatible for either OS.
That's not too much different than having to specify a type of directory for Swift, and has the same types of reasons for why it exists, for safety, but it just doesn't let you do something potentially dumb like open('blah.txt') for something quick and dirty, like Python does, which I admit I do abuse if I'm trying to write something quick and dirty myself.
EDIT: This link here shows how you can write a helper function to basically turn the file i/o into a 2-liner, and I'm sure there's ways to make this even simpler: https://www.hackingwithswift.com/example-code/strings/how-to...
There is pathlib nowadays that allows you to navigate in very complex situations using a quite nice OOP API.
But I assume the old ways are still valid code, so if you're working with Python code you may encounter any of now 3 different systems of just navigating paths for file i/o, what the parent claims should be dirt simple.
The method in my link (which changed rather drastically between versions):
- is very much iOS and MacOS specific
- requires knowledge of quite a few iOS/MacOS-related things (FileManager.SearchPathDirectory is probably 80% Apple-specific)
- even though it's a "FileManager", it doesn't even let you access/open a file. You have to perform additional operations on the resulting Directory type (.appendingPathComponent)
- even that doesn't give you a means of opening a file, because in order to read a file, you have to invoke a String constructor. In order to write to a file, you need to invoke a method on a String type. Talk about coupling entirely unrelated things
That is an example of objectively bad API design.
And it's clear from API evolution that it's not even Swift APIs. These are very thin wrappers for OS's existing Obj-C APIs. I think it's the first among languages: to provide OS APIs and call them a standard library for a language. I don't think even MS did that when they were creating .NET.
It just did not worked out that way, as WinDev tanked Longhorn efforts and now we have UWP (aka COM) instead of .NET for OS APIs.
Which are anyway easily accessible from .NET given its COM support.
I know this because I started a project using only strings and `os.path`, however when testing it started to become complicate to mock the correct paths so in tests I use `pathlib` (with conversions back to string when I finish path manipulation) and the code still works.
In the context of an iOS or MacOS app, that of course won't work, because apps only have access to certain directories. That is why you typically use the FileManager object to get the path to the directory you'll need.
I would never in my life figure out that
- reading from and writing to a file is not the job of file-related modules, but of a string
- that it would just work like this wothout getting a proper handle to the file (what I assumed what the whole FileManager bruhaha was about)
Compared to what? What this code does can be rather convoluted and/or unsafe in many statically typed languages.
Although admittedly there's still some bizarre behavior. Like this morning while iterating over a simple for loop, XCode decided it was just going to stay on the final item in the collection and keep looping until my memory ran out, over and over again, and I couldn't find anyone talking about this online, but eventually decided to do a "Clean Build Folder" and then Build, and that fixed it (but why did it happen in the first place? So odd!).
And it still doesn't always think a class I wrote or renamed is valid when referencing it in another class, but a rebuild or quitting and restarting tends to fix that.
Still, I'm liking it a lot, and having a lot of fun with Swift now. SpriteKit is great for making games, except for the lack of cross-platform capability, but if the game somehow manages to take off, I can write some wrapper classes to have the same behavior as most of the SpriteKit classes I use and port it easily enough.
To be more specific about Swift, though, there used to be a ton of things you had to bridge to Objective-C in order to do back then, and now it seems like there's almost nothing you have to bridge to Objective-C to do unless you want to work with your legacy code (all of their libraries now have Swift support, at least those that I use), and there's now a cool new SwiftUI framework that is very easy to use and very powerful.
Where am I wrong?
curl -s <https://packagecloud.io/install/repositories/swift-arm/relea... | sudo bash
sudo apt-get install swift5=5.0.2-v0.4
[0] https://lickability.com/blog/swift-on-raspberry-pi/
Such as?
Personally I've taken to using Swift basically in every use-case where I can, largely because it's so nice to work with. It strikes a very nice balance between productivity (lack of tedium) and strong compile-time guarantees of correctness.
From my perspective, there are a few obstacles preventing Swift from achieving wide adoption:
1. Tooling and support outside Apple platforms has a long way to go. The story is better than it was even a year or two ago, but when compared to Rust, for example, Swift is massively lacking in this area.
2. Swift is still viewed as an iOS-only language. Even though there are now mature libraries for things like writing a webserver, and it's quite possible to write software for Linux using Swift, the developer perception is not there, and thus adoption is slow. This contributes to the lack of tooling and support.
3. Performance needs some improvement. ARC and copy-on-write are great for writing correct code easily, but they lead to some serious and sometimes unpredictable performance cliffs with Swift. There is a lot of low-hanging fruit here, but this needs to be addressed before Swift could ever find a place as a systems programming language for example.
So I would not quite say I'm bullish with respect to Swift's chances of breaking out as a general purpose programming language, but objectively speaking I would say that all the problems preventing Swift reaching that state are solvable problems, and Objective-C compatibility has little to do with it.
Objective-C is simply regular C with Smalltalk objects added. If you know Smalltalk and you know C then you're golden.
I took a long break from working with Swift and just started diving into it again, and even though there was two major versions since I last messed with it, it was pretty easy to settle into it, and I've only had to look up how to do things on a case by case basis periodically. Maybe that's just my experience, though, and others have a harder time with it.
get/set/didSet introduces ridiculous complications just so we can pretend that a large number of function invocations look like assignment statements. This was a cool idea in C++, briefly, and then we discovered that having arbitrary code hide behind what looks like an ordinary assignment statement was a bad idea.
Extensions also remind me of C++ excesses. It is difficult to look at a piece of code involving a variable some type and be sure that I understand how that type works. The problem is that the code implementing the type is not in one place. There is the type definition, but then there are extensions. Possibly many of them. Defined all over the place.
I really dislike the irregularity surrounding let. In one context in unwraps an Optional. In another context it does not. Why?
I got off the Swift train at the release in which associated types were introduced. I'm sure it solves some actual problem, but it sure wasn't clear at the time. (The project ended -- it's not that I decided to go back to Objective C.)
Reference counting is far too intrusive, and it is easy to get it wrong in subtle ways. I find Java's (!) memory model relatively simple, and that's saying something. I understand why reference counting was chosen over GC. I don't have a good answer, but reference counting is just ugly. I actually think I prefer the C/C++ model of explicitly freeing memory.
I don't understand your comment about reference counting being intrusive. Apple's implementation, ARC, used in Swift and modern ObjC, is essentially invisible to you if you're using native objects.
As for reference counting: I'm referring to capture lists, and the "unowned self" hack needed with closures. E.g. https://www.raywenderlich.com/966538-arc-and-memory-manageme.... And it gets more complicated with @escaping. I sure don't view all these subtle interactions of closures and ARC to be invisible. This stuff is subtle. Get it wrong and you have leaks.
http://marksands.github.io/2018/05/15/an-exhaustive-look-at-...
I have pasted the most egregious example here: https://news.ycombinator.com/item?id=21919728
It's intrusive because you can never really stop thinking about it if you want to write correct code. Here's an example from a very interesting article by Mark Sands [1]:
How quickly can you tell whether or not this piece of code has a reference cycle?
In my view, reference counting does not combine very well with heavy use of closures.[1] This is an interesting read: http://marksands.github.io/2018/05/15/an-exhaustive-look-at-...
I'm curious. Does it? I would have guessed the "weak self" would have prevented it.
> In my view, reference counting does not combine very well with heavy use of closures.
It's one of the area where one has to be careful for sure! C++ with smart pointers and callbacks exhibits the same problem. And GC based languages make the pattern easier for sure. However I think this is not even the most critical error source in callback based designs. I think threading issues due to callbacks being executed on different threads cause the most trouble.
Therefore I think languages like Javascript and Dart - which only offer a single thread AND GC - are the the easiest to use for callback based designs.
I agree that threading is another big gotcha, arguably a bigger one. Rust has some mitigations against that sort of thing.
The named parameter handling is one of my favorite features of Swift. It makes Swift code self-documenting in a way most languages aren't.
It's the $n syntax that I think is overkill. Do we really need three different ways to name parameters?
I would put it in the same category as Rust's `?` operator, which saves you from typing a bunch of unwraps or match statements everywhere.
However Objective-C ARC is basically the compiler taking care of Cocoa retain/release patterns.
Swift needed to provide a seemless path forward to integrate with Objective-C libraries so reference counting was the easist way forward.
Microsoft has chosen another way to interoperate with COM from .NET, which requires an additional layer.
https://docs.microsoft.com/en-us/dotnet/standard/native-inte...
https://docs.microsoft.com/en-us/dotnet/standard/native-inte...
Although is is quite alright to use, it adds an additional complexity that most likely Apple wasn't willing to make use of.
If you want to hide circular references from developers, then a cycle collector is required on the runtime.
For example this was the approach taken by Mesa/Cedar, or for a more modern reference CPython.
If you look into C++/CX or C++/WinRT, this issue is also surfaced to the programmer.
Rust makes it even more explicit with its reference counting library types.
At the end of the day, it depends on what Swift designers were optimising for.
Which to me looks like the easiest and less performance impact to integrate with the Objective-C runtime and respective libraries.
Swift's approach is still easier than doing the same from Objective-C, its target audience.
https://trends.google.com/trends/explore?date=all&q=%2Fm%2F0...
Imho There’s definitely an issue in the strategy for this language ( or for ios native development since the two are tied).
My guess is cross platform development is eating mobile, and swift has nothing in that area.