Hacker News new | ask | show | jobs
by trealira 726 days ago
I have heard this said, mainly because some patterns can be made unnecessary with first-class functions and pattern matching. Closures are emulated with explicit objects, and the visitor pattern is equivalent to pattern matching. Something that's pretty interesting, though, is that it's a transform called defunctionalization. There's an article about it [1] that has been shared before on HN.

One form of defunctionalization is the well-known transformation of a recursive function into one that uses an explicit stack.

The thing is, I don't think defunctionalization (from the equivalent functional form) present in object-oriented languages is strictly worse. Defining things with explicit objects may sometimes be more understandable, and more extensible; for example, the command pattern could be implemented as a closure, but then you can't later add an "undo" method to it later.

Here's an example where defunctionalization makes the code more readable, not less.

Haskell has a difference list [0] data structure; the purpose of it is that you can concatenate two difference lists in constant time, and then turn it into one long normal linked list in O(n) time. This gives much better performance than concatenating lists directly all the time. It's a lot like a rope, except for lists, not strings, and it's immutable.

But the code is somewhat cryptic; it makes use of partial application and stores the tree in terms of partially applied functions. The "Demystifying DList" [0] article I shared shows a defunctionalized form explicitly defined as a tree in concrete data types.

To those interested in it, if you're familiar with the syntax of ML-like languages, I'd recommend the papers [2], [3], and [4].

[0]: http://h2.jaguarpaw.co.uk/posts/demystifying-dlist/

[1]: https://blog.sigplan.org/2019/12/30/defunctionalization-ever...

[2]: "Defunctionalization at work": https://www.cs.purdue.edu/homes/suresh/502-Fall2008/papers/d...

[3]: "Refunctionalization at work": https://www.brics.dk/RS/07/7/BRICS-RS-07-7.pdf

[4]: "Continuation-Passing Style, Defunctionalization, Accumulations, and Associativity": https://www.cs.ox.ac.uk/jeremy.gibbons/publications/continue...

1 comments

There are definitely cases where a structured value is clearer than a function. But at that point you're just modelling your domain and it's not really a "command pattern" at all. The point of the command pattern is that you have an object that really and truly is just a function, you're only representing it as an object because you need to pass it around - but in that case it really is just a workaround for your language lacking first-class functions.

A good language makes it easy to use both functions-as-values and structured-objects-as-callables, and use whichever representation is appropriate to the situation.

That's a fair point; not having first-class functions is a flaw for a high-level programming language, and the command pattern is just making up for a deficiency in the case that it would never need to be anything more than a closure in a language that does have one.