Ultimately all these statements are about creating responsive systems.
When we design processes that attempt to corral reality into a neat little box, we set ourselves up for failure. Such systems are brittle. We may feel in control, but it’s an illusion. The real world is not constrained by our imagined boundaries. There are surprises just around the corner.
I have told this story to different audiences. Programmers as a rule are delighted by it and managers, invariably, get more and more annoyed as the story progresses; true mathematicians, however, fail to see the point.
The Lisp model is that programming is a more general kind of interaction with a machine. The act of describing what you want the machine to do is interleaved with the machine actually doing what you have described, observing the results, and then changing the description of what you want the machine to do based on those observations. There is no bright line where a program is finished and becomes an artifact unto itself.
In iOS 8, this code doesn’t just fail, it fails silently. You will get no error or warning, you won’t ever get a location update and you won’t understand why. Your app will never even ask for permission to use location.
I just got bitten by this while updating an app. This post goes through what is needed to fix it.
When they create 4089 libraries for doing asynchronous programming, they’re trying to cope at the library level with a problem that the language foisted onto them.
Each of those function expressions closes over all of its surrounding context. That moves parameters like iceCream and caramel off the callstack and onto the heap. When the outer function returns and the callstack is trashed, it’s cool. That data is still floating around the heap.
The problem is you have to manually reify every damn one of these steps. There’s actually a name for this transformation: continuation-passing style. It was invented by language hackers in the 70s as an intermediate representation to use in the guts of their compilers. It’s a really bizarro way to represent code that happens to make some compiler optimizations easier to do.
No one ever for a second thought that a programmer would write actual code like that. And then Node came along and all of the sudden here we are pretending to be compiler back-ends. Where did we go wrong?
What’s even more difficult to understand is errors. Errors in multi-threaded callback code with shared memory is something that would give me an extremely large headache.
The in-language mixing of synchronous and asynchronous calls makes code hard to reason about. The language-side simplicity of Ruby or Java’s concurrency model is something I have taken for granted.
In my opinion, this is the greatest success “hack” there is. If you live in an environment that nudges you toward the right decision and if you surround yourself with people who make your new behavior seem normal, then you’ll find success is almost an afterthought.
Monads are in danger of becoming a bit of a joke: for every person who raves
about them, there’s another person asking what in the world they are, and
a third person writing a confusing tutorial about them. With their
technical-sounding name and forbidding reputation, monads can seem like
a complex, abstract idea that’s only relevant to mathematicians and Haskell
Forget all that! In this pragmatic article we’ll roll up our sleeves and get
stuck into refactoring some awkward Ruby code, using the good parts of monads to
tackle the problems we encounter along the way. We’ll see how the
straightforward design pattern underlying monads can help us to make our code
simpler, clearer and more reusable by uncovering its hidden structure, and we’ll
end up with a shared understanding of what monads actually are and why people
won’t shut up about them.
The accompanying video is short, snappy, and to the point.