Go for Objective-C developers
runtimeintrospection.tumblr.com
runtimeintrospection.tumblr.com
make(chan bool, 1)
what is that 1 for? Why is it not using constructor sytnax shown earlier? (`Chan{bool}` or `BoolChan{1}`?)`go function` is nice, but in ObjC there's `dispatch_async()` and `NSOperationQueue`. Go does some magic with green threads, segmented stacks and whatnot, but the article doesn't elaborate.
And for an Objective-C developer Go's lack of proper interoperability with Cocoa is disappointing:
http://stackoverflow.com/questions/6322194/cocoa-bindings-fo...
BTW:
(CGRect){0, 0, 320, 480}
is valid in ObjC (doesn't apply to classes though).Go's GC has its own caveats that you have to watch out for. It doesn't really save you from having to think about your object graph or architecture design.
Many a time I've seen people shrug off issues as "GC will handle it" in C# projects. Usually accompanied with the sound of many a developer crying whilst trying to work out what has gone wrong in production when 256Gb of RAM across several nodes disappears instantly. Memory ballooning, long GC pauses, reference leaks, swapping, VM over commitment are all waiting to hang you.
For non-gophers, a slice is roughly a bounds-checked Vector.
What you just described is how memory is allocated, but can this cause it to be retained outside a function body?
In Java, you code around it by doing
new String( line.substring( x, y);
String's constructor will copy the characters to a new buffer. I guess go will have something similar. Problem, of course, is that that means copying the objects. That can especially be an issue if the objects are mutable.An alternative in Java is to do
s = s.intern();
But that comes with its own problems. 'intern()' decreases memory usage, but is slow, and library writers cannot know whether it is a good idea to use it or not because they cannot know what is more important to the code calling the library: speed or memory.(1) Oracle is going to change/has changed this after measuring its impact. It turns out that the two extra fields that each string needs to keep track of what part of a buffer contains its characters more or less compensate for the decrease in memory usage that sharing strings brings.
Why? My understanding is that when you interned a string you were given something like a constant token to reference it. This did two things:
1. Equality was trivial. Instead of taking to strings and comparing each character, it could just see if the constants were equal. For strings you know you'll see often this could be great source of speedups. 2. You could end up saving a ton of memory. Let's say that string you're interning is 250 character long. Instead of taking up 250 unicode characters plus overhead, it's now... let's say... 8 bytes. Maybe you saved a few hundred bytes. Now multiply a few hundred bytes by a few fields times 10 million records in memory and that's nothing to sneeze at.
Interning is definitely optimization and not part of normal Java development.
http://www.cocoabuilder.com/archive/xcode/322876-why-arc-ove...
http://daringfireball.net/linked/2011/09/19/the-unfamiliar
http://stackoverflow.com/questions/2484079/how-can-i-avoid-g...
Plus the underlying C part, didn't allow for more than a plain conservative GC.
ARC works by generating the retain/release calls the developers would write anyway with NeXTStep/Cocoa framework.
So while it is a good solution for Objective-C, it isn't because it thrumps GC, but rather due to Apple's failure with a stable GC.
- Lisp OS
- Smalltalk OS
- Mesa/Cedar (a GC enabled systems programming)
However, that's not all of it. The iOS teams wouldn't touch the GC with a 10 foot pole, even had it worked, and with good reason. As the parent poster pointed out, GCs make performance and memory consumption unpredictable, especially on memory-constrained devices.
And yes, phones are memory-constrained, despite the 1/2 - 1GB of memory, because you are also managing some potentially very large assets (retina class images, ...). Especially without virtual memory, where having an unexpected spike in memory consumption can get you killed, having unpredictable memory consumption is a non-starter...and the pain you have to go through on Android to avoid GC problems is significant (for example real-time OCR via the video camera overlaid onto the video stream).
It's interesting that Android appears to be moving away from JIT to AOT with libart, I am very curious as to how that works out. My guess is that at least a subset of developers, those with stringent requirements, would also welcome more predictable memory management solution.
WP7 was full .NET with JIT.
WP8 is WinRT/.NET with AOT compilation.
Both seem to perform much better than Android and on par with iOS.
Although I do conceded that on WP8 there is a mix of reference counting(WinRT) and GC (.NET).
Google was supposed to present more information about ART at FOSDEM, but they canceled the presentation on the last minute. So still no information what they plan there, besides AOSP source code.
Xerox PARC systems already had GC enabled programming languages (Cedar/Lisp/Smalltalk) and they surely were less powerful than today's phones.
Never happen. The HN community is far too mature for that.
It could easily happen if Google wanted it to. Java can call native code (and vice-versa). Other system vendors have changed core implementations before. Apple has pulled it off 2 or 3 times at least.
It wouldn't be easy, but it's certainly possible.
I don't mean to attack the author (I enjoyed the article) but most of Go's "advantages" are also disadvantages when used in an Objective-C/Cocoa environment.
First heading from the article: "Not traditionally object-oriented"
The problem with this is that much of Objective-C is focussed on the AppKit/UIKit view-hierarchy. As the Rust developers noticed when trying to implement the HTML DOM in their Servo project, large hierarchies of similar entities are cumbersome and require repeating yourself often if you don't have access to traditional subclasses. Rust eventually added single inheritance (despite earlier pushing for a purely Go-like compositional interface approach).
Compositional interfaces are a good thing... but so is data and behavioral inheritance. Taking one of these things away makes the language poorer, not richer. Yes, compositional interfaces would be good in Objective-C but a lack of inheritance in Go isn't a perfect world either.
Second heading from the article: "Type inference"
For the mostpart, this is a point in Go's favor. Although the author might not realise that with ARC in Objective-C you can actually just duck type if you want (type as 'id') and the ARC compiler will do type inference behind your back to track memory so you still get all the compile-time checks and other type inference advantages
Third heading from the article: "Garbage collecting"
Ignoring the technical problems with Apple's GC implementation for Objective-C, there were three real reasons why garbage collection sucked badly: (1) it used too much RAM (standard GC drawback), (2) it was slow (because it used too much RAM – it was otherwise efficient), but most critically: (3) it removed deterministic deletion which is critical in Cocoa.
Cocoa relies on its destructors to perform actual work. With GC, you suddenly can't rely on destructors being invoked when you need them. The idea that GC "reduc[es] mental strain" does not apply if instead of transparent lifecycle management with ARC, you suddenly need completely manual "dispose" methods everywhere.
Fourth heading from the article: "Native concurrency"
Apple's approach to native concurrency is that you should use libdispatch. It's slightly more verbose than prefixing a function with "go" but it handles all that go's built-in concurrency handles and actually much more. I think, from its exclusion, that the author is unfamiliar with libdispatch. I've not seen evidence that go has any built in advantages over libdispatch.
Fifth heading from the article: "Packages"
On namespaces: yes, they allow for ways around conflicts. But there is a double edged sword here: names in different namespaces are going to conflict. If you've used a large library like .NET, you'll know what I mean: lots of different classes in different namespaces conflict so that you can't simply say "using XXX" for each namespace and instead you have to reference the whole path. Instead of NSTimer you have to use System.Timers.Timer or System.Threading.Timer – a two letter prefix is now fourteen or seventeen letters.
Also... it is really annoying attempting to follow sample code when the sample code omits all the namespace inclusions. You're trying to learn the API from the code but the code doesn't explain what API it's using forcing you to trial and error hunt around for the correct namespace.
OO: Go is great for building server-side software in a fashion where it responds to events. I think it'd be interesting to explore a framework built like that, the way ReactiveCocoa sits on top of Cocoa.
Type Inference: Like you said, id makes everything dynamic in essence, which loses the value of Objective-C being static type at compile time.
GC: My approach tends to be that the compiler/runtime are smarter than me, so I'd rather depend on it than me.
Concurrency: Definitely have used libdispatch (all the time...), excluding it is merely an oversight. I was more focusing on channels, and the go keyword is necessary to introduce beforehand for the example.
Packages: I believe that if there is no conflict, you can just reference the class name, though I may be thinking of another language. I can see your point for sure though.
Thanks for the feedback, would love to hear more of your thoughts on the matter.
How is reference counting not leaving it up to the runtime?
You lose compile-time type checking with id, so it's not at all like type inference. I'm not sure how ARC is relevant at all, as it changed nothing about how id works. Using id everywhere is pretty similar to using void * everywhere in C.