Archive for July 3, 2015

Friday, July 3, 2015 [Tweets] [Favorites]

Using Siri

My experience with Siri keeps changing. I’m pleased with the recent change where you no longer have to confirm before a reminder is added. Instead, you just tap Remove if Siri got it wrong. There’s still no good way to edit if Siri got it partially right, though. And sometimes Siri is repeatedly so far off that it’s not even enough to jog my memory; I wish I had just stopped to type.

It is maddening how many times I will see that the phone has cell service and dictate my reminder, only to have Siri spin seemingly forever or complain that it doesn’t have an Internet connection. Couldn’t it have told me that sooner? Or recorded what I’d said so that it could be replayed when a connection becomes available? Since Siri requires a connection, it shouldn’t even play the “start talking” prompt unless it knows that it can reach the server.

Arq Supports Amazon Cloud Drive Backup

Stefan Reitshamer:

You can now store your encrypted Arq backups in your own Amazon Cloud Drive account!

Amazon Cloud Drive includes unlimited storage for $59.99/year, so you can back up everything. Amazon provides a web interface to upload and download files, but Arq uses its API to upload directly to the cloud.

Previously: Amazon Cloud Drive.

Twitterrific’s New Facial Detection

Ged Maheux:

By far the coolest of these improvements is the use of Apple’s facial recognition APIs to improve image previews. What does that mean exactly? It means that as Twitterrific displays media thumbnails in the timeline (pictures, videos, etc), the app tries to detect faces and frame the thumbnail so faces are always showing. In short, if Twitterrific sees a face in a tweet, it tries to make sure you see it too!

Should I Use a Swift Struct or a Class?

Drew Crawford:

A lobby that wants you to believe that one weird trick will make your codebase better, replacing the cargo-cult Agile practices with equivalently useless cargo-cult functionalist practices.

[…]

As we’ve established, most types (say, 90%) can implement funcs in a non-mutating way. But to quote another Zawinski law, “Everybody uses a different 10%”. […] Similarly, for every type that is sufficiently large, it conforms to some non-mutating protocol with a mutating implementation. […] Now. How are we going to solve this problem? Well, the mutating inner class.

[…]

It is not wrong to wrap a class in a struct. This is how Swift.Array works under the hood. […] The difference is, A) they have been really clever about hiding the inner class, which involves a lot of code and neat tricks that you can learn more about in the WWDC session (e.g., this is an advanced topic, that you should not sprinkle liberally throughout your codebase where the muggles will see it) and B) there is nothing fundamentally classful about arrays. Arrays are, from a certain point of view, a kind of value. So it makes sense for them to be a value type.

[…]

The moral of this story is that immutable, pure functional programming does not always work even in the literal textbook examples. A mutating implementation of the Sieve is both simpler and faster, and far from helping, functional programming has actually hindered the exercise of writing fast, maintainable code.

[…]

Finally, the official Apple guidance concludes with this dire warning:

In all other cases, define a class, and create instances of that class to be managed and passed by reference. In practice, this means that most custom data constructs should be classes, not structures.

Update (2015-07-05): David Owens II:

The fundamental problem I find with the piece is that it creates a false selection of choices to the problem statement posed while misrepresenting much of the advice about choosing when to use value types. I think it also confuses the purpose of the proposed “inner class device”.

[…]

The entire purpose of the “inner class” is to provide value semantics while maintaining efficiency of implementation. In addition to that, if some of the quoted advice in the article had been followed with regards to struct usage, a different conclusion would have presented itself.

Drew Crawford:

I agree with you that inner mutability “feels” wrong in the CanSend example. But the suggestion that inner mutability should never ever be used is wrong, because of Swift.Array. So we need some rule to distinguish when inner-mutability-with-structs is bad from when it is okay. If the rule was “never do any mutation inside a struct” then we would not have value-typed-arrays to begin with.

(In fact, we didn’t have value-typed-arrays to begin with. I have a serious theory that it was exactly the rigid application of “never have inner mutation” inside Swift that initially led to the silly behavior. Recall that in early betas, the value/reference behavior of arrays used to hinge on whether or not the operation caused a resize--which is exactly those cases in which the array implementation needed to mutate the free block chain.)

David Owens II:

I think it’s safe to say that using inner classes to simply break the mutability contract of a protocol is a poor reason that’s going to lead to all sorts of bad behavior (like the original arrays in Swift).

[…]

I’m saying that I think that line is somewhere near the area of, “I really want to present a value-semantic type, but the performance is going to suck if I do, so let’s create an implementation with a backing inner class”.

Update (2015-07-22): Mike Ash:

The answer is actually really simple: use structs when you need value semantics, and use classes when you need reference semantics. That’s it!

[…]

Thus the fundamental question to ask when deciding which one to use is: does it make sense to copy this type? Is copying an operation you want to make easy, and use often?