They certainly didn’t just make run-of-the mill choices for all language features. Some non-standard design choices they made (for better or for worse):
- Reference counting without any automated cycle-breaking
- Collections are value types (implemented somewhat efficiently by having copy-on-write collections)
- the Character type is closer to what ‘normal’ people think a character is (https://developer.apple.com/documentation/swift/character)
- consequently, string length is closer to what users who don’t know Unicode internals expect it to be.
- Arrays are ‘different’ (‘inherited’ from NSArray. See https://ridiculousfish.com/blog/posts/array.html)
- protocols are a bit like interfaces, but protocol conformance can retroactively be added to classes, even to ones you didn’t write or don’t have the source code of.
Oh nothing. It makes sense for Apple to want a more modern language to replace the now aging Objective C. In turn, that meant Swift was not on my list of languages to try, but instead on my, possibly a language I'll be forced to use one day list, just as Java, C#, JS, and all are, by simply being defacto languages for some platform which depending what you work on, you have no choice over.
But then I started seeing people in the comments claiming things like: "Swift is one of the most interesting languages right now". So I was like... Hum okay, what did I overlook?
Now, I'd be okay with people saying that it improves drastically on C# and Java. If people think Swift is a dramatic improvement because of the sum of its part, like just little details here and there that end up making it much better, and they think that in turn could lead Swift to replace both Java and C# if it gained support on other platforms. That could make it quite interesting as well. So I'd be up to listen to those arguments as well.
I'm sure I'm missing some nuanced downside to this, but this sounds fantastic. I've never fully understood the difference between Unicode code points and code units[0], and would love to think less about this sort of thing in Java (for ex. when using String#toCharArray).
[0] I'm just regurgitating language from the String javadoc, this sentence might not even make sense.
So (not Swift, nor, AFAIK, any other existing language)
for i = 0 to stringlen(s)
print s(i)
would be O(n²), so slow for long strings. It’s rare to have code that accesses the n-th character of a string without accessing all earlier ones, though, and idiomatic code for c in s
print c
can be efficient (not as efficient as iterating over fixed size units, but not dramatic, either)Also, requiring String to know of what code points in Unicode are “combining” means carrying a few tables around in the implementation. That could be problematic when porting Swift to devices with small amounts of memory. It also, I think, ties Swift to a version of Unicode. You cannot predict what code points in future versions will be combining characters (https://en.wikipedia.org/wiki/Combining_character)
I also think there are a few corners where Swift doesn’t reach the goal of “a character is what naive users expect”. Ligatures in Unicode might be problematic. For example. “fl” is a single Unicode code point, but, ideally, would be two characters “f” and “l”.
Most normal people assume Unicode grapheme to be characters. That would be the set of symbols you'd consider a single letter if you were to visually count the number of symbols in the string.
In Unicode though, some code points are non visible, yet are part of the string. So for example, the character at i+1 for some match against a letter might not be the next visible letter. I can see this causing issue either way.
Honestly, I'd say it's best to just learn this, it you'll have some weird bugs one way or another.
Basically, you have code units, those are the smallest chunk of bit that has meaning in Unicode and thus can be sent over a wire, streamed or decoded. In UTF-16 encoding, which is what JVM uses, code units are 16 bit.
The history helps. In the beginning, each character in Unicode was 16bit. So you could represent all Unicode characters with 16bit only. Later, there were even more characters added, and it couldn't fit into 16bit. So UTF-16 where the 16 tells you the code units is 16 bit no longer could represent all characters in one 16 bit unit. Thus code points were invented, those are characters that span two code units 16bit + 16bit. Together they represent the new characters that didn't fit in the single 16bit range.
So nowadays, it actually takes 21 bits to represent all Unicode characters. There's three encodings: UTF-8, UTF-16 and UTF-32. Their number correspond to the bit size of their code units. In UTF-8 we break each character into 8 bit units. In UTF-16 we do so in 16 bit units, and in UTF-32 into 32 bit units.
Ok, now back to measuring length. We can say tell me the number of code units used to represent the string. That's what Java's string.length() does. Or we can say telle the number of bytes needed to represent the string (a byte is 8bit). That's what converting to byteArray and getting the length of the array does. Or you can say tell me the number of code points (Unicode characters) the string contains. In UTF-16 a code point can be 16bit (composed of one unit only), or it can be 32 bit (composed of two units). But not all Unicode characters are visible, so the user might be surprised to get a length that is greater than what it counts visually. So you can also get the number of grapheme in the string, which are "visual characters". In Java you can use BreakIterator to count those. That said, Unicode grapheme don't always make sense to what each speaker of each language would consider a character. That's for example some languages might consider a combo of two letters one character with one pronunciation, etc.
Finally, I'll say there's another interesting length. It's the font width in terms of physical measures like pixel count.
So basically, each measure might be most appropriate depending what your measuring for.
I think the real issue is that we didn't adopt new terminology of Unicode yet. You should try to start referring to things as code units, code points, grapheme and font width/height. And stop using the word character or letter.
And then just make yourself a little library that has string.codeUnitCount(), string.codePointCount(), string.graphemeCount() and string.pixelWidth().
And when you don't care about the difference between these, I'd argue that code unit count is the best default for length, which is why I don't actually disagree with string.length counting code units. Cause I think of string.length from the perspective of looping over the smallest units of the string.
Graphemes are comprised of code points, code points are comprised of code units, and code units are a chunk of binary of variable length depending on the UTF flavor.
UTF-8 uses smaller code units so that strings containing only ASCII (for ex.) are of optimal size (in terms of memory). UTF-32 would mean each "character" takes up 32 bits regardless.
I think the String javadoc could be clearer here. The class overview mentions these concepts but the methods are not as forthcoming.
Thanks!
Arrays still are not guaranteed to be contiguous in memory, though. If you want that, there’s ContiguousArray (https://developer.apple.com/documentation/swift/contiguousar...)
Isn't copy on write data structures mostly discouraged idea these days?
So no, it doesn't really have a whole lot of "innovation or originality" -- but it essentially takes some of the best ideas of modern language design and wraps them into one general-purpose language for application development, and as a result I find it to be a really useful and practical language.
For me Sum Types and pattern matching in particular are an absolutely massive improvement over languages that only have classes/structs. They make statically typed languages feel almost as expressive as dynamic ones.
The weird thing about typescript is that this incredible power and expressively must be backported into the runtime environment. And because of that, the promises that the type system makes are unreliable and also lag way behind the actual language features that are implemented.
I hope these criticisms are read in the proper context: I absolutely love TypeScript, and find it to be a really special unique oddball in the world of language design. I wish it had been ReasonML instead of TypeScript, but TypeScript is incrementally working it’s way there and bringing the whole js community with it, so I can’t complain.
Edit: Prediction: prepare for switch statements to become popular as the typescript community gradually adopts exhaustive pattern-matching types.
A poor example, but this compiles without error and crashes at runtime:
let x: string = "foo"; (x as any) = 1; x.substr(0);
Now, technically, you can do this sort of thing in most, if not all, languages, but this happens organically more often with typescript due to many libraries being written for plain javascript and being looser on their types, or type definitions getting out of sync with the libraries they are written for.
Yes: Swift is now (and has been for a while) the standard language for developing iOS and MacOS apps. That makes it important completely independent of any features it may or may not have.
And up until now, I was thinking I'll try Swift the day I'm forced too, because I'm working to develop an app for Mac or iOS.
But then I started seeing some comments like: "For me, Swift is currently the most interesting language". So I thought I might be overlooking something.
The most innovative feature I can find is null safety, which is alright, but I guess I've had my fun with it with Kotlin already. Someone mentioned good ABI compatibility, that is interesting, and I'll need to read up on that. Others say, it's just a nice mix of modern features in a well maintained package. That's great as well, you could argue C# and Java being older have some less modern aspects lingering. But that's nothing that makes me want to jump in it and try to use it for my next project.
So, if you have to choose between making your app for iOS first, or Android first, then in addition to any consideration of markets which might or might not apply to your business model, you will have a very strong incentive to choose Apple for time to production.
I would love to see more serious competition on that front.
To have adopted any of those other languages requires dramatic changes to a huge amount of platform APIs, along with on-going challenges of divergence. Put another way, any other language would have basically forked the entire platform.
The Swift developers definitely have ambitions beyond being a compatible with Apple's existing SDKs, but that's the fundamental thing Swift does that no other language can do.
It has seamless interop with Objective-C and C, and can be mixed with about any language LLVM/Clang can handle (as long as you have C headers), compiling it all down to a small, self-contained binary.
For now it's mainly useful on Apple platforms, but there's interest and efforts in cross platform from both Apple and the Swift community, so there's a lot of potential for it to be a great language for the main body of application code, with individual bits of functionality written in languages that make the most sense without too many layers of adapters or wrappers.
The interop actually has lots of seams. A huge engineering effort had to be made and has been made to paper over those seams, but they are definitely there.
Calling conventions are gratuitously incompatible, objects have to be converted at API boundaries at significant cost, the meta-systems are incompatible, etc.
Seems like a viable niche to me.
A lot of really good programming languages are “uninteresting” in this way, and that’s probably a good sign, not a bad one.
How long has Swift been available outside of Apple platforms? And I don't mean experimentally available either. They only posted an announcement a few days ago where Swift is deemed ready for early adopters on Windows. That certainly does not sound production quality there.
From looking through the swift official site, it just seems like a new C# or Java with ahead of time compilation.
The only slightly unique bit I can find is that the syntax is a bit more JavaScript inspired.
Am I missing something? Or that's it? It's just the C# of Apple?
For example, Rust has borrow checking for zero cost memory safety.
Go has concurrent sequential processes and its accompanying goroutines.
Haskell is a fully pure language.
Python has cool indent based syntax that looks like pseudocode.
Ruby is objects all the way down and has this unique concept of blocks for passing code around to be yielded.
Clojure has immutable persistent data-structures as default and software transactional memory, while also being a Lisp bringing macros and all to the JVM.
Erlang has actor concurrency.
Etc.
So in a similar vein, what would be Swift's innovation or originality here?