Hacker News new | ask | show | jobs
by michielderhaeg 644 days ago
This reminds me of when I was still in university. During our compilers course we used the "Modern Compiler Implementation in Java" book. Because I was really into FP at the time, I instead used the "Modern Compiler Implementation in ML" version of this book (which was the original, the Java and C versions were made to make it more accessible). We noticed during the course that my version was missing a whole chapter on visitors, likely because ML's pattern matching made this kind off trivial.

One of the other students made a similar remark, that software design patterns are sometimes failures of the language when they have no concise way of expressing these kinds of concepts.

3 comments

«Design patterns are bug reports against your programming language» (Peter Norvig)

This is pithy, but only applies to some rote design patterns which you have to code every time because the language lacks a good way to factor them out.

Wider-scale patterns often express key approaches enabled by the language, and they can't go onto a one-size-fits-all library or language feature, because you tailor their implementation to your specific needs. They are less like repetitive patterns of a brick wall, and more like themes or motifs that keeps reappering because they are fruitful.

Yes, I wouldn't want all of these https://en.wikipedia.org/wiki/Software_design_pattern to be enabled by the language. I personally like my languages to be simple.

Also, I'm not sure how some of these patterns could be realized as language features. Like, particularly the common UI patterns.

> that software design patterns are sometimes failures of the language when they have no concise way of expressing these kinds of concepts.

This is _the_ most common comment you hear in any language design discussion, and it's so boring. Java doesn't have visitors because it's the best the language could come up with. It has visitors because of a particular dogmatic adherence to OOP principles. A fundamentalist reading that says you're never supposed to have any control flow, only virtual method calls. Visitors come from the same place as Spring and the infamous AbstractSingletonProxyFactoryBean.

Java is perfectly capable of expressing an enum, and you can easily switch on that enum. The limitation that you have to express that enum as a type hierarchy, and therefore encounter the double dispatch problem is entirely OOP brainrot.

> Java is perfectly capable of expressing an enum

I think this is a bit of an exaggeration, unless you're talking about very modern versions of Java (sealed interfaces and better pattern matching). Java has no good way to attach different data types to each enum variant (a la ADTs) except inheritance, and until recently switching over class types was a PITA.

Enums were added in java 5 and I'm pretty sure you could switch on them from day one. From that point you just need a single class (call it TreeNode) that holds a value of that enum (say the node type) and some fields, and you can navigate it and switch over the node type without any sort of visitors.

"But what if I have a leaf node. Wont that have a child pointer, even though it doesn't need it" Sure it will. Who cares. You don't need to make it harder than it has to be. All the new stuff just enables you to get more type safety, it was never necessary.

You're getting downvoted but I don't think you're getting the benefit of understanding the disagreements. The benefit of visitor is for when you need multiple different TreeNode classes with different aspects, either different member variables or different methods/implementations themselves. In that case, the unused child ptrs are the smaller of the class modeling difficulties. For example, if you had a single base TreeNode class with the enum, after switching on the enum you need to explicitly downcast to the type. The dual-dispatch approach bakes this into the visit-accept protocol.

The last time I worked on a complex syntax tree structure, I used the approach you suggested because _editing_ a Visitor suite is a pain in the rear. Only terms that had special payload data (numbers, pointers to metadata objects, etc.) need downcasting.

Indeed there should be no control flow, only computing values of function application :)

Indeed, this is also absolutism, just of a different kind, that proved to be somehow more fruitful in the application programming domain. And, to my mind, it's mostly because functions can be pure and normally return a value, while methods are usually procedures mutating some hidden state.

OTOH in a different domain, system programming, control flow is a good abstraction over the close-by hardware, mutable state is all over the place in the form of hardware registers, and it's more fruitful to think in terms of state machines, not function application.

If a tool forced you to do repetitive irrelevant motions, it's just a wrong tool, you need to find or create a better one.

My experience was some 20-odd years ago, when I was trying to learn design patterns by implementing them in PHP. Specifically, I built the whole array of abstract and concrete factories and all that, until I realised that it can all be replaced by something like:

  $className = "MyClass";
  $classInstance = new $$className();