News for hackers. Stuff that matters.
Re:Ask HN: Rust or Swift for system programming? by pcwalton on Monday July 04, 2016 @05:10PM (#12033026)
> Rust & Swift are fairly similar but Swift has a much wider range of possible applications.

Can you elaborate on this? The languages seem very different to me--Swift is garbage collected (reference counting being a form of GC), for example.

Re:Ask HN: Rust or Swift for system programming? by Jerry2 on Monday July 04, 2016 @05:48PM (#12033203)
>Can you elaborate on this? The languages seem very different to me--Swift is garbage collected (reference counting being a form of GC), for example.

ARC is not garbage collection [0]. Swift doesn't have a separate processes managing memory during the runtime. In Swift, compiler analyzes the code during the static compilation pass and inserts release/retain code during the compile time. See this SO answer for more info [1]. And you don't have to use ARC if you don't want to [2].

GC in Java or Go or CLR, for example, is completely different. Obj-C 2.0 was garbage collected but Apple hated it because of GC pauses and they vowed to remove it and never use GC again. [3] Hence, they developed ARC.

[0] https://en.wikipedia.org/wiki/Automatic_Reference_Counting

[1] http://stackoverflow.com/a/7894809

[2] https://developer.apple.com/library/ios/documentation/Swift/...

[3] https://en.wikipedia.org/wiki/Objective-C#Garbage_collection

Re:Ask HN: Rust or Swift for system programming? by pcwalton on Monday July 04, 2016 @08:57PM (#12033820)
Regardless of what Apple's documentation says, reference counting is garbage collection. This is academic consensus since the 1980s and there is no need to change. It is not a semantic quibble, because there are successful GC schemes that combine tracing with reference counting and aren't any less a form of GC for doing that.
Re:Ask HN: Rust or Swift for system programming? by steveklabnik on Monday July 04, 2016 @06:22PM (#12033327)
There's a split between industry and academia here. Reference counting is traditionally considered GC in the literature, but not by working programmers, who usually say "garbage collection" and mean "tracing garbage collection."

Both Swift and Rust muddy this traditional ontology a bit. Swift's ARC has both a compile time and runtime component, and while the Rust language itself doesn't know anything about reference counting, we do provide such types in the standard library.

Re:Ask HN: Rust or Swift for system programming? by Manishearth on Tuesday July 05, 2016 @12:46AM (#12034446)
> Swift doesn't have a separate processes managing memory during the runtime

Plenty of GCs don't have this. You can have cycle collectors and other GCs which run the GC pass on release events (depending on some heuristic) too.

This is a terminology issue, anyway -- in academia reference counting is considered a form of GC. In software often the term is used to mean "tracing GC", or sometimes "any system that can automatically handle retain cycles".

-----

This still doesn't answer why Swift has a wider range of possible applications, though.

I do agree that Swift is or will be better suited for development on iOS, because of good API integration. Rust can program for iOS too, it's just that you will have better support for Swift :)

But aside from that, Rust should be able to apply anywhere Swift does.

Re:Ask HN: Rust or Swift for system programming? by MichaelGG on Monday July 04, 2016 @05:53PM (#12033225)
ARC is a form of GC, but the definition doesn't matter. Why do you say this is a wider range of applications? Swift's ARC no doubt slows it down and makes it unsuitable for some applications, right?
Re:Ask HN: Rust or Swift for system programming? by winstonewert on Monday July 04, 2016 @06:11PM (#12033293)
Is Rust's borrow system also a form of garbage collection?
Re:Ask HN: Rust or Swift for system programming? by pcwalton on Monday July 04, 2016 @08:59PM (#12033832)
No. Automatic memory management dynamically (at runtime) works out which objects are no longer referenced. Swift's reference counting is a form of automatic memory management because keeping the reference counts up to date is a way of dynamically working out which objects are alive and dead. Rust's ownership system does not: it is static, in that objects are unconditionally freed at specific, static program points.
Re:Ask HN: Rust or Swift for system programming? by steveklabnik on Monday July 04, 2016 @06:19PM (#12033318)
It is not, unless you count some library types that add reference counting, but those are rarely used. Ownership and borrowing are calculated at compile time, not runtime.
Re:Ask HN: Rust or Swift for system programming? by winstonewert on Monday July 04, 2016 @07:37PM (#12033576)
Ownership and borrowing may be calculated at compile time, but they still result in code being inserted to do things like deallocate objects at run time. It doesn't seem a useful distinction to call one garbage collection and the other not. Swift and Rust are far more similiar to each other in their memory management scheme then either is to Java or Go or D.
Re:Ask HN: Rust or Swift for system programming? by pcwalton on Monday July 04, 2016 @09:01PM (#12033838)
> but they still result in code being inserted to do things like deallocate objects at run time.

We're not talking about whether the user manually calls free. Even C has automatic memory management (via stack/activation records) by that definition! The difference is whether the memory management is worked out statically, at compile time, or runtime, via tracing and/or reference counting.

Re:Ask HN: Rust or Swift for system programming? by winstonewert on Monday July 04, 2016 @10:36PM (#12034103)
Actually, yes, I think a lot of people would define automatic memory management as not having to manually call free.

C does manage some memory automatically. But it leaves a lot of memory management up to the user, such that any non-trivial C program will manually manage memory. That's different from Rust, Go, Java, or D in that most programs in those languages will not need to do that.

Re:Ask HN: Rust or Swift for system programming? by Manishearth on Tuesday July 05, 2016 @12:37AM (#12034426)
Rust is more similar to C++, not Swift, here.

The distinction is in the programmer model involved. With Swift and GCd languages, you do not know about when the deallocations will happen, because this requires analysis of the whole program and the executions. You program with this in mind. Since GC/ARC is the only way to share, you end up using it often. The compiler can prevent some of this, but not the majority, because there isn't enough annotation helping it.

(There is this difference between Go and Java, too. Go is more explicit about sharing than Java, and needs annotations when you share things (* and &). Java does not. So while Java 8 is getting escape analysis, it can never be as good as what Go does or potentially can do because the compiler just doesn't know enough. Go also generally avoids sharing unless necessary, whereas in Java you will see things shared willy-nilly because the distinction only lies in the optimizer. These annotations aren't as fine grained as Rust -- they're at the same level as Swift, approximately, but I'm trying to give an example of the same annotation-drives-optimization-and-design thing at a different level.)

With Rust and C++, you know just by looking at a function what will be deallocated and where. C++ has API designers implement drop flags anyway (in the form of nulling the internal pointer, or something) for all types with a move constructor. The model of dealing with data changes; you explicitly think about where data comes from and how to share it. The additional annotation of zero-cost borrows (instead of just saying "Share this ... somehow", which is what Go and Swift do) means that zero-cost borrows will always be zero-cost, and not only if the optimizer decides it knows enough to be able to help.

Note that ARC is much much costlier than than pointer-sharing. Not directly because of the increments; but because dynamically allocating for every instance of sharing, and then accessing that allocation whenever you wish to do a read/write or bump the reference count; is horrible for cache performance. This can be assuaged with a tuned allocator, but is less efficient than the usually-to-the-stack borrowed references of Rust.

I will point out that Swift satisfies the academic definition of garbage collection and Rust/C++ do not, but I don't think terminology is as important as understanding what's actually going on.

Rust is "automatic", in a sense, agreed, but automatic memory management is a vague term that can mean anything.

Re:Ask HN: Rust or Swift for system programming? by winstonewert on Tuesday July 05, 2016 @11:17AM (#12036999)
"I will point out that Swift satisfies the academic definition of garbage collection and Rust/C++ do not"

What is this academic definition of garbage collection? I'm familiar with how the different models work. But I'm having trouble with a definition of garbage collection that excludes Rust while containing Swift.

Re:Ask HN: Rust or Swift for system programming? by pcwalton on Tuesday July 05, 2016 @12:38PM (#12037671)
"Down for the Count", for example, surveys the approaches to GC in its introduction: https://users.cecs.anu.edu.au/~steveb/downloads/pdf/rc-ismm-...

Note that reference counting has been considered a form of GC since the 1960s.

Re:Ask HN: Rust or Swift for system programming? by winstonewert on Tuesday July 05, 2016 @12:54PM (#12037794)
The question isn't whether reference counting is garbage collection. In the academic definition: it is. The question is whether Rust's approach which looks a lot like reference counting where most of the time the compiler knows the reference count at compile time, also qualifies as garbage collection.
Re:Ask HN: Rust or Swift for system programming? by Manishearth on Tuesday July 05, 2016 @02:02PM (#12038269)
It isn't, because in other languages with linear/affine types it isn't called as such. Nor is C++s unique_ptr. Or Cyclone, which has region types.

Rust isn't exactly revolutionary in its core memory management ideas, these have been around for a while and have been inside other languages. Cyclone, for example, is basically Rust (memory management wise) but as a safe dialect of C and a different stance on mutation and other things. It is not considered a GCd language. Rust just puts all these ideas together nicely.

The compiler doesn't actually keep track of a reference count, btw. Refcounting and linear types/ownership/borrowing lead to very different programming styles. In Rust's model you actually have to think about ownership and design your program with this in mind that as much as possible you want to use single ownership.

Given that they have very different impacts on programming style, they are pretty different practically speaking. On the other hand in swift you deal with memory management much like in Java, though with a few more choices you can make. Go might be a more apt comparison as far as memory management, though swift is more fine grained than Go as well.

Re:Ask HN: Rust or Swift for system programming? by steveklabnik on Monday July 04, 2016 @07:41PM (#12033585)

  > they still result in code being inserted to do things like deallocate objects at run time.
I mean yeah, functions are called at runtime, just like every function. The key is more like static/dynamic typing: is the decision to call the destructor at all determined at compile time, or at runtime?

(and millstone has been making good points about drop flags on this thread, but that's still only in fairly niche cases, only one bit, and is an implementation detail more than a fundamental aspect of the language. We've had several different variants of drop flags over time, and it's going to change even more in the future, as erickt says.)

  > Swift and Rust are far more similiar...
Agree wholeheartedly.
Re:Ask HN: Rust or Swift for system programming? by winstonewert on Monday July 04, 2016 @08:08PM (#12033684)
"but that's still only in fairly niche cases, only one bit, and is an implementation detail more than a fundamental aspect of the language."

Ok, but isn't the question of whether or not something is done at compile or runtime always an implementation detail? The fact that Rust figures out at compile time whether or not to insert the deallocation functions is super awesome, but it doesn't actually change the semantics of the language relative to if has to check flags or reference counts etc.

This is different, to my mind, from static/dynamic typing because they have very different semantics. Early versions of Java used a VM which was dynamically typed, and PyPy converts python code to machine code that doesn't check types (if I'm lucky). So the distinction really isn't whether or not the decision is made at runtime.

But really, I only objected in this thread because the claim was made that Swing and Rust were very different because Swing had GC and Rust didn't which seemed to be overemphasizing the differences here.

Re:Ask HN: Rust or Swift for system programming? by pcwalton on Monday July 04, 2016 @09:13PM (#12033868)
> Ok, but isn't the question of whether or not something is done at compile or runtime always an implementation detail? The fact that Rust figures out at compile time whether or not to insert the deallocation functions is super awesome, but it doesn't actually change the semantics of the language relative to if has to check flags or reference counts etc.

There is no concept in Swift of a dead object that is in scope. There is in Rust, which is why you see "use of moved value" errors. That is a language difference.

Re:Ask HN: Rust or Swift for system programming? by jjpe on Wednesday July 06, 2016 @06:13AM (#12042158)
"Ok, but isn't the question of whether or not something is done at compile or runtime always an implementation detail?"

No it isn't. It changes the entire semantics of your language. For example Python as it exists today simply can have neither type checking nor GC decisions* done at compile time. The language is not capable of expressing those things adequately. Adding those would require some significant changes to Python the language, its stdlibs, as well as the Python VM.

Conversely, starting to use reference counting in Rust is definitely possible but will jack up your memory-related bug count, a rather undesirable result. The code is also pretty much always more difficult to read, understand and debug. Its only redeeming feature is that some datastructures simply need the flexibility it brings.

* I define a GC decision as deciding what to de/allocate and when to do it, rather than performing the de/allocations themselves. For example, the GC algorithms in Java and Go fall under this definition, as does Swift's ARC mechanism, as well as Rust's ownership based decisions. The former 3 decide at Runtime. Rust usually decides at compile time, the only exceptions I can currently think of being code based on the Rc/Arc/RefCell types, which do reference counting and therefore the de/allocation decisions are deferred until runtime.

Re:Ask HN: Rust or Swift for system programming? by millstone on Monday July 04, 2016 @06:35PM (#12033371)
Borrowing is purely compile time, but ownership has a runtime component, essentially a 1 bit reference count, called the drop flag. This is needed because objects may be conditionally initialized or uninitialized, depending on runtime values.
Re:Ask HN: Rust or Swift for system programming? by erickt on Monday July 04, 2016 @06:45PM (#12033404)
The drop flag is only generated for types that implement the `Drop` trait. Furthermore, there's work [0] that will shift the drop flag out of the value onto the call stack frame, and then even only in situations where the compiler cannot statically prove that that the type will be dropped or not. This should save a lot of memory, and potentially open up a whole host of optimizations.

[0]: https://github.com/rust-lang/rust/issues/34398

Re:Ask HN: Rust or Swift for system programming? by millstone on Monday July 04, 2016 @07:08PM (#12033491)
Yes, that's good. Swift also aggressively elides reference count modifications, and will stack-allocate class types if the lifetime can be proven.
Re:Ask HN: Rust or Swift for system programming? by pcwalton on Monday July 04, 2016 @09:15PM (#12033877)
It is silly to try to equate the drop flags with atomic reference counting on the heap. We could statically eliminate the drop flag entirely if we wanted to, with aggressive tail duplication. (It's not worth it, though, because the drop flag never shows up in profiles, so the code size bloat would be a cure worse than the disease.) Swift can never eliminate the runtime overhead of garbage collection. That's because, at a language level, Rust has static lifetime semantics and Swift has dynamic semantics.
Re:Ask HN: Rust or Swift for system programming? by winstonewert on Monday July 04, 2016 @10:32PM (#12034084)
It is silly to equate drop flags with atomic reference counting on the heap.

It would be sillier to define automatic memory management in terms of conditional releases, (as you seem to have done) and then insist that Rust's conditional releases don't really count. Clearly, it is not really the fact that the releases are conditional that makes the difference.

What is your actual definition of automatic memory management? What, in your view, is the actual semantic difference between a language that has automatic memory management and one that does not?

Re:Ask HN: Rust or Swift for system programming? by Manishearth on Tuesday July 05, 2016 @12:42AM (#12034435)
Swift cannot implement ARC without conditional releases. Rust can. What Rust effectively does is compile an if statement into something a tiny bit more complicated (two if statements, really), in certain conditions. It doesn't need to. The if statement uses function-local information known statically, so it could be compiled in a different way without the drop flag. Basically, the condition already existed, Rust just inserts another one instead of piggybacking on the one inserted by the programmer. ARC needs new conditionals everywhere, and whether or not something will be cleared is often not obvious without looking at the whole program, and even then it could be undecidable.

I can't answer for Patrick, but I don't see the term "automatic memory management" as useful as distinction, I look at it more as a spectrum, and Rust/C++ fall squarely on the "more manual" end of that.

Re:Ask HN: Rust or Swift for system programming? by winstonewert on Tuesday July 05, 2016 @11:35AM (#12037131)
"I can't answer for Patrick, but I don't see the term "automatic memory management" as useful as distinction, I look at it more as a spectrum, and Rust/C++ fall squarely on the "more manual" end of that."

I agree 100%. My objection was to the assertion that Rust and Swift were completely different because Swift was garbage collected and Rust was not. That's just not a helpful way of looking at it, because in many ways Swift's strategy is closer to Rust's then Java's.

Re:Ask HN: Rust or Swift for system programming? by winstonewert on Tuesday July 05, 2016 @03:25PM (#12038868)
Sure there are significant differences between Rust and Swift.

But characterizing that as Swift = GC, Rust = No GC, as I was originally objecting to is a pretty terrible way of describing it.

Re:Ask HN: Rust or Swift for system programming? by Manishearth on Wednesday July 06, 2016 @05:04AM (#12041990)
Right, but the significant difference does lie in the memory management thing. GC/No GC is (a) correct, according to the academic definition, and (b) a decent approximation to the difference.
Re:Ask HN: Rust or Swift for system programming? by Manishearth on Tuesday July 05, 2016 @01:50PM (#12038204)
Right, which is why in my other comment I explained why the memory management strategies make them different, and make that difference important :)

type system wise they are pretty comparable otherwise; As a Rustacean who is used to nice type systems, Swift's type system is a pleasure to work with.

Re:Ask HN: Rust or Swift for system programming? by millstone on Monday July 04, 2016 @10:05PM (#12034004)
Whoa! I simply observed that both Rust and Swift eliminate their respective forms of reference counting when the lifetimes are statically known. The optimization is analogous, even if the nature of the reference counting is very different, as you say.

To be sure, the proper Rust analog of Swift classes is Rc/Arc, not drop flags.

> Swift can never eliminate the runtime overhead of garbage collection. That's because, at a language level, Rust has static lifetime semantics and Swift has dynamic semantics.

Would you agree that Rust can never eliminate the runtime overhead of dynamic dispatch, because trait objects, at a language level, require dynamic dispatch? I would not agree: Rust programmers routinely eliminate it by sticking to the statically-dispatched areas of the language. Likewise, Swift programmers routinely avoid the runtime overhead of reference counting by using structs and not classes.

Re:Ask HN: Rust or Swift for system programming? by Manishearth on Monday July 04, 2016 @11:59PM (#12034322)
> Would you agree that Rust can never eliminate the runtime overhead of dynamic dispatch, because trait objects, at a language level, require dynamic dispatch? I would not agree: Rust programmers routinely eliminate it by sticking to the statically-dispatched areas of the language. Likewise, Swift programmers routinely avoid the runtime overhead of reference counting by using structs and not classes.

Sharing is something that is pretty necessary in programming; you are severely limited in what you can do without sharing. Trait objects are not, and are pretty rare in Rust. I often see people using enums over trait objects, and only sticking to trait objects for creating extensible APIs.

Rust provides a way of sharing that does not involve any extra runtime overhead, which gets used often. Swift does have nice optimizations to value-typeify things, but without a finer-grained distinction between the kind of sharing you want to do to hint the compiler, this will be vastly limited as compared to Rust giving an explicit choice between borrows and Rc.

Re:Ask HN: Rust or Swift for system programming? by millstone on Tuesday July 05, 2016 @01:16AM (#12034519)
When I hear sharing I think of shared ownership, and Rust steers you strongly away from that. See for example the awkwardness of global or thread-local variables in Rust.

If you are referring to borrowing, Swift's answer is not class types, but inout. inout is not as flexible as Rust references, but it does not use reference counting. In most places where a Rust function would return a mutable reference, the analogous Swift function would take a closure that accepts that something as an inout.

Re:Ask HN: Rust or Swift for system programming? by Manishearth on Tuesday July 05, 2016 @03:55AM (#12034985)
Right, I refer to the concept of sharing data without necessarily involving shared ownership.

I am aware of inout, but like you said it's not as flexible. I find myself reaching for class types in Swift a lot more than in Rust.

inout works for sharing that is extremely local, but more complicated sharing in larger codebases is hard.