
Swift 4.0 Released - runesoerensen
https://swift.org/blog/swift-4-0-released/
======
swivelmaster
"Swift 4 includes a faster, easier to use String implementation that retains
Unicode correctness and adds support for creating, using and managing
substrings."

This alone is grounds for opening and drinking very expensive champagne and/or
wine.

~~~
developer2
>> support for creating, using and managing substrings

Can I finally extract a substring from the middle of a string using integer
offsets, in one line? Something like string.utf8.substr(3, 5)?

Or does it still take an absolutely insane and unacceptable 4 lines of code
with throwaway temp variables to track the start and end indexes? The
inability to do _basic_ string manipulations is a major turnoff, to the point
it makes the entire language look like a bad joke.

~~~
slavapestov
A String in Swift is a sequence of graphemes, unlike most languages which
model strings as sequences of code points or just rawutf8, so there's no way
to do efficient O(1) indexing. This is why the API is a bit more complex than
you'd like.

~~~
developer2
I keep getting this inaccurate answer of "they're just grapheme code points -
you can't do it". That is why my example specifically used the .utf8 view.
It's already possible to do exactly what I'm talking about, but it takes 4
_complex_ lines of code, needing two calls to index() with startIndex/endIndex
references and offsetBy arguments.

The existing solution to this problem already uses integers (the offsetBy
arguments)! I'm not talking about refactoring the String type, or breaking
backwards compatibility. There would be no change in how the underlying String
storage or access works. It's about adding a level of (zero overhead!)
abstraction to simplify a common, _basic_ operation.

Every other language I've ever touched has easy to use substrings. It makes
absolutely no sense that Swift requires assigning throwaway constants to
represent the start and end indexes for a simple substring extraction. There's
this level of superiority regarding the purity and correctness of Swift's
String type that clouds developers' ability to see that there _is no
limitation_ to doing this. It blows my mind that the most modern major
language is this clunky.

------
sinhpham
They implemented what looks like the Rust ownership model: SE-0176 Enforce
Exclusive Access to Memory ([https://github.com/apple/swift-
evolution/blob/master/proposa...](https://github.com/apple/swift-
evolution/blob/master/proposals/0176-enforce-exclusive-access-to-memory.md)),
but I'm having a hard time understanding the proposal, can anyone shed some
light on this?

~~~
Falell
Note: I like to read about Rust but don't work with it seriously, and don't
follow Swift at all. Corrections welcome. That said, these seemed like the key
passages:

"Swift has always considered read/write and write/write races on the same
variable to be undefined behavior. It is the programmer's responsibility to
avoid such races in their code by using appropriate thread-safe programming
techniques."

"The assumptions we want to make about value types depend on having unique
access to the variable holding the value; there's no way to make a similar
assumption about reference types without knowing that we have a unique
reference to the object, which would radically change the programming model of
classes and make them unacceptable for the concurrent patterns described
above."

Sounds like a system in the vein of rust but more limited, with more runtime
checks and no lifetime parameters, falling back to "programmer's
responsibility" when things get hard. The last paragraph makes it sound like
one of the motivations is in enabling specific categories of optimizations, as
opposed to eliminating races at the language level.

One of my biggest questions as a reader is how a language like C handles these
cases that Swift can't handle without these guarantees. Is this a move to get
faster-than-C performance? Does C do these optimizations unsafely? Is there
some other characteristic of Swift that makes this harder than C? Closures get
a lot of focus in the article...

~~~
comex
The other responses to your comment are correct: C generally can't do those
optimizations, unless you manually write `restrict`, and this can hinder
optimization. But to complete the picture -

> Is there some other characteristic of Swift that makes this harder than C?

Yes:

1\. Swift doesn't have pointers.

Instead, you have a lot of copying of value types, and the compiler has to do
its best to elide those copies where it can. For instance, at one point the
document mentions:

> For example, the Array type has an optimization in its subscript operator
> which allows callers to directly access the storage of array elements.

In C, C++, or Rust, you can "directly access the storage" without relying on
any optimizations: just write &array[i] and you get a pointer to it. The
downsides are (a) more complicated semantics and (b) the problem of what
happens if array is deallocated/resized while you have a pointer to it. In C
and C++, this results in memory unsafety; in Rust, the borrow checker
statically rules it out at the cost of somewhat cumbersome restrictions on
code.

2\. Swift guarantees memory safety; C and C++ don't.

This goes beyond pointers. For instance, some of the examples in the document
talk about potentially unsafe behavior if a collection is mutated while it's
being iterated over. In Swift, the implementation has to watch out for this
case and behave correctly in spite of it. In C++, if you, say, append to a
std::vector while holding an iterator to it, further use of the iterator is
specified as undefined behavior; the implementation can just assume you won't
do that, and woe to you if you do. (In Rust, see above about the borrow
checker. Iterator invalidation is in fact one of the most common examples Rust
evangelists use to demonstrate that C++ is unsafe, even when using 'modern
C++' style.)

~~~
blub
Those Rust evangelists are only partially correct. It's the STL that's unsafe,
not the language itself.

Iterators could be implemented in C++ in a safer way with some performance
loss, but it doesn't seem to be a priority for anyone except the safercpp guy
that posts here every now and then. STLs can enable iterator validation in a
special debug mode.

~~~
lucian1900
That is incorrect.

The language includes memory unsafe constructs without marking them in any
way, since it must be compatible with C.

~~~
blub
We're discussing iterators here, and the STL iterators implemented as class
templates can't even be compatible with C.

To clarify: safe containers, iterators and algorithms can be designed, but
they don't seem to be a priority of the C++ community. Personally I'm quite
scared of accidentally passing the wrong iterator to some function, but OTOH I
can't recall it ever happening. I don't use the debug STL either, haven't
needed it.

The examples that pcwalton keeps bringing up seem artificial to me. It's true
that you can't have perfect safety in C++, but with some effort and custom
libraries, many errors can be caught at compile or run-time. The advantage of
Rust is that it's safe by default, not necessarily that there's a major safety
difference between quality C++ and quality Rust.

~~~
comex
You’ve probably heard this before, but the security angle is important. “I
haven’t had these problems in my code” really means “I haven’t _triggered_
these problems in my code”… that is, unless you’ve had a security code audit
done. Testing isn’t enough: even well-tested codebases can and do have
vulnerabilities. In practice, they’re usually triggered by input that’s so
nonsensical or insane from a semantic perspective, not only would it never
happen in practice in ‘legitimate’ use, the code author doesn’t even think to
test it. For a simple example, if some binary data has a count field that’s
usually 1 or 2 or 10, what happens if someone passes 0x40000000 or -1? As a
security researcher myself, I think it‘s actually easier to audit code with
_less_ knowledge of how the design is supposed to work, up to a point, because
it leaves my mind more open. Rather than making assumptions about how
different pieces are supposed to fit together, I have to look it up, and as
part of looking it up I might find that the author’s assumptions were subtly
wrong… For this reason, it’s really hard to audit your own code, at least in
my experience. I mean, you can definitely keep reviewing it, building more and
more assurance that it’s correct, but if your codebase is large enough, there
may well be ‘that one thing’ you just never thought of.

I’m not actually sure how frequent iterator invalidation is as a source of
vulnerabilities; I don’t think I’ve ever found one of that type myself.
However, use-after-frees in general (of which iterator invalidation is a
special case) are very common, usually with raw pointers. In theory you can
prevent many use-after-frees by eschewing raw pointers altogether in favor of
shared_ptr, but nobody actually does that – that’s important, because there’s
a big difference between something being theoretically possible in a language
and it being done in practice. (After all, modern C++ recommendations
generally prefer unique_ptr or nothing, not shared_ptr!). And even if you do
that, you can’t make the `this` pointer anything but raw, and same for the
implicit raw pointer behind accesses to captured-by-reference variables in
lambdas.

You can definitely greatly reduce the prevalence of vulnerabilities with both
best practices for memory handling and just general code quality (that helps a
lot). But if you can actually do that well enough - at scale - to get to no
“major safety difference”, well, I haven’t seen the evidence for it, in the
form of large frequently-targeted codebases with ‘zero memory safety bugs’
records. Maybe it’s just that C++’s backwards compatibility encourages people
to build on old codebases rather than start new ones. Maybe. It’s certainly
part of the story. But for now, I’m pretty sure it’s not the whole story.

~~~
blub
C and C++ don't have a culture of safety, they have one of performance.

C++ code could be written significantly safer with a performance loss, e.g:
index checking at run-time, iterator validity checking, exclusive smart ptr
usage with null checking, etc. That, together with code reviews, static &
dynamic analysis should IMO lead to comparable safety. That's what I'd do.

However, there doesn't seem to be a rush in that direction. My guess is that
there won't be a rush to switch to Rust either.

Is the security angle that important that it's handled through education and
better tooling? Or only important enough to do some code audits and pen
testing?

------
valine
The new JSON parser is really slick.
[https://developer.apple.com/documentation/swift/codable](https://developer.apple.com/documentation/swift/codable)

~~~
RubenSandwich
Here is a great article on using it: [https://medium.com/swiftly-
swift/swift-4-decodable-beyond-th...](https://medium.com/swiftly-
swift/swift-4-decodable-beyond-the-basics-990cc48b7375).

~~~
zntfdr
Author of the article here! Thank you for the kind words and thanks for
sharing!

I was wondering why that entry had a huge spike on reads yesterday :D (1500
reads against a daily average of 200).

~~~
RubenSandwich
Glad I could help. Thank you for writing it!

------
jorgemf
> Some source migration will be needed for many projects, although the number
> of source changes are quite modest compared to many previous major changes
> between Swift releases.

It seems like the language still needs some time to be completely mature, or
am I wrong? I haven't used it since 1.0

~~~
blub
I got burned by the migration from 1.0 to 1.something and haven't used it
since. Looks like it was the right choice, breaking changes are a major
failure in language design IMO.

I understand why they do it, but I don't like that they are getting away with
it. Apple seem to be in this endless update cycle where they change stuff
across hardware, operating systems and even programming languages. The
customer doesn't have much choice: they either keep up or get left behind.

~~~
jernfrost
I disagree. Compare macOS today with the initial OS X release and it is
fundamentally the same system both UI wise and code wise. Windows and even
Linux has seen far more dramatic UI shifts in the same period. Same goes with
the code. Windows went from win32 C API to C++ API with MFC and ATL. Then they
promoted COM and Visual Basic development. Only to change gears and make C#
with a completely different API. Then winforms gets depricated. We get
silverlight, WPF and then there has even been more stuff in later years and I
lose track. Compare this to macOS which ever since OSX has used almost
exclusively objective-c and cocoa. Even now with swift you can use cocoa, and
pretty much all apple technologies you allready knew. C# made redundant all
previous win32 and VB skills. The introduction of Java, python, ruby and Go
have not let you use any previous skills or libraries. In this regard Swift is
an amazing accomplishment as you can reuse so much existing skills and code.

~~~
oblio
Can you take code written for the initial Mac OS X release, compile it and run
it on the last version? You can do that for Windows.

~~~
protomyth
They deprecated a lot of UI methods in the 10.4 timeframe so I would bet not.
I’m sure someone has some code, but it is probably very limited.

------
dep_b
Converting two existing projects was pretty painless. Though the larger and
older of the two had a significant amount of automatically generated changes.
Most of them were (Void) in blocks changed to () though. Another nice extra is
mixing 3.2 with 4.0 libraries.

~~~
afro88
The changes to tuples in closures were a little annoying too, with the jump to
4.0. But on a whole it was pretty painless for us too.

------
geodel
With this yearly release cycle and amount of investment Apple is making, I
think Swift 6 or 7 could become general purpose language for client/server
code on non-apple platforms too.

------
ramenmeal
I see some mentions of Server API's on their website. With these libraries in
place, how comparable is swift to golang?

~~~
hasenj
I think it's nicer to program in swift than go.

It's already possible to do so to, by the way.

[http://perfect.org/](http://perfect.org/)

What I think go has over swift is the complete independence from platform. You
can write go code on osx and compile it to a linux binary and it Just Works!

Swift on Linux is not perfect yet, though it can be made to work with some
effort.

~~~
alexashka
Swift has no quality high-level concurrency primitives - until those arrive,
Swift is a complete non-starter as a server language.

Concurrency is at the level of proposals currently, so it'll be another couple
of years until they come up with something, and another couple until good
server libraries/frameworks figure out how to use them properly.

It's a shame really - I imagine this could've been moving along at a faster
rate had Chris Lattner stayed on with Apple and recruited some extra help.

He has written a really nice proposal for concurrency, that'll definitely
influence Swift going forward. [0]

[0]
[https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9...](https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9f782)

~~~
efficax
I agree, for the most part, but then again, C also has no high-level
concurrency primitives, and basically every server ever is written in C.

You can use Grand Central Dispatch, and it works. It's not as wonderful as go
routines and channels, but hey, it works.

~~~
alexashka
I hear you. C has performance because it doesn't have to do any sanity checks
and because 20 years of serious effort has gone towards optimizing everything
possible.

The very motivation behind creating Swift, has been to have performance, and
none of the undefined behaviour (cause of innumerable security breaches and
unintentional complexity in compiler design and everyday programming) [0]

To me, grand-central-dispatch feels one small step above
semaphores/locks/monitors.

There has been a lot of research in distributed computing and concurrency -
I'd like to see libraries, language constructs and runtimes based on research
fresher than before I was born :)

[0] [http://blog.llvm.org/2011/05/what-every-c-programmer-
should-...](http://blog.llvm.org/2011/05/what-every-c-programmer-should-
know.html)

------
mixmastamyk
Ubuntu 16.10 is already out of support, they should update that. Artful is out
in a month or so.

------
dvfjsdhgfv
Note that in spite of supporting Ubuntu only, you can run the 4.0 version in
Debian Stretch without any problems. Just download the package, unpack it and
add the bin/ subdirectory to your $PATH.

Edit: REPL stil doesn't allow importing Glibc by default, you need to specify
the include path manually (e.g. swift -I /opt/swift-4.0-RELEASE-
ubuntu16.10/usr/lib/swift/clang/include/).

------
chhum
There's a good summary of this release here:
[https://www.infoq.com/news/2017/09/swift-4-official-
release](https://www.infoq.com/news/2017/09/swift-4-official-release)

------
amelius
Ignorant question: What other language is Swift like most? And what
improvements does Swift make over that language?

~~~
jernfrost
Kotlin, Rust, Scala and vaguely Go. Swift benefit over Kotlin is that it
easily interfaces with existing objective-c and C code. It also has
deterministic garbage collection through automatic reference counting which is
better for interactive systems and maintaining low memory footprint. Since it
is native code and doesn't have a complicated garbage collector it can be used
like C to create libraries for other programming languages. This is impossible
to do with Go and Kotlin.

Compared to Rust it is considerably easier to learn.

Go is probably easier to learn than Swift but Swift is a lot more expressive.
You could do scientific computations in Swift but that would be cumbersome in
Go since you can't easily define matrix, vector and point types yourself.

------
hasenj
This is great news.

However, I wish the mac release was available as independent binaries without
having to come along with Xcode.

~~~
OberstKrueger
The Command Line Tools include the Swift compiler without needing Xcode
installed. Open up a terminal and type “swift” to enter the REPL or “swiftc”
to compile a Swift File. SPM is included too.

If they’re not already installed, running one of those commands will prompt
you to install them.

~~~
hasenj
If I already have swift-3 and Xcode 8, how do I install only swift-4?

~~~
gre
You can download a toolchain snapshot from here. There's a swift-4.0-branch
download if you scroll a bit.

[https://swift.org/download/#snapshots](https://swift.org/download/#snapshots)

~~~
slavapestov
Keep in mind that binaries built with the toolchain snapshots cannot be
submitted to the App Store. You need an Xcode release for that.

------
msie
Why couldn't they make a PDF version of The Swift Programming Language? I hate
ePub.

~~~
msie
Being voted down is nonsense. 1) I've tried ePub and it just doesn't work as
well as PDF on my iPad mini, which is perfect for reading documents. 2)
Virtually everyone sells their books in both PDF and ePub formats so I don't
see why they can't do the same here.

~~~
mmariani
I've bought an iPad Mini specifically to read ePubs. What do you think is
broken on iBooks?

