Live data from Hacker News

Grim C++ Tales from the Crypt: The Visitor Pattern (2017)

cppcrypt.tumblr.com

21–30 of 64 posts

Re: Grim C++ Tales from the Crypt: The Visitor Pattern (2017)

#21
post #16

This... I can actually see the point in this. The Visitor pattern is one of those patterns I never really saw the point of, and which mostly struck me as an over-engineered hack about a shortcoming in a language. This example actually makes clear why you'd need to do it this was in C++ at least. Not sure which other languages would need this. It's certainly not pretty. Then again, dispatching twice is not so bad comp…

I've always heard that pattern itself is older than C++, originating from Smalltalk.

Re: Grim C++ Tales from the Crypt: The Visitor Pattern (2017)

#22
post #3

The thing that annoys me most about this pattern is that people always miss the "there needs to be lots of things you want to perform on those thingies". And so we end up with a huge pile of visitor code, and there is one or maybe two actual visitors. When it would have been far easier to read and modify if it was just coded out normally.

Or in this case, since the IThingyInteractor can do exactly the same thing with an IThingy if IThingy has a name() method, you can just implement it with single dispatch.

I don't know if I have ever actually seen a true implementation of this pattern. What I have seen is a pattern someone called a Visitor where a tree is iterated over and the "Visitor" makes virtual function calls on the composite node in a single function body without ever doing something different depending on the type of the node.

Re: Grim C++ Tales from the Crypt: The Visitor Pattern (2017)

#23
The visitor pattern isn't appropriate everywhere, but it's quite good for traversing and manipulating ASTs (abstract syntax trees). An AST typically has many kinds of nodes, but programs that traverse the AST usually only care about some small subset of those nodes. The visitor pattern provides a clean solution: a generic AST traversal library visits all nodes in the tree while allowing the program to customize what happens when visiting specific nodes. I've found the visitor pattern very effective for creating derivative ASTs without knowing about everything that might be in the AST.

Re: Grim C++ Tales from the Crypt: The Visitor Pattern (2017)

#25
It's things like the visitor pattern that led me to implement Clasp - a Common Lisp that interoperates with C++ and uses llvm as the backend (github.com/clasp-developers/clasp.git). Common Lisp has generic functions and multiple dispatch - so it doesn't need the wretched visitor pattern. Try writing a compiler using the visitor pattern - I dare you. :-)

Re: Grim C++ Tales from the Crypt: The Visitor Pattern (2017)

#26
post #10

C++ match expressions would make std::variant a really nice alternative. I assume there is already a proposal out?

Until C++2z rolls out with match support, you can roll your own. Nikolai Wuttke gave a lecture at MeetingCpp 2018 (https://www.youtube.com/watch?v=CELWr9roNno) that presents code that lets you do this:

    // Client visitor code
    match(
      thingy,
      [](const PurpleThingy& ) {std::cout 
Working example: https://coliru.stacked-crooked.com/a/dfed39bc7fcdfb01

Re: Grim C++ Tales from the Crypt: The Visitor Pattern (2017)

#27
post #16

This... I can actually see the point in this. The Visitor pattern is one of those patterns I never really saw the point of, and which mostly struck me as an over-engineered hack about a shortcoming in a language. This example actually makes clear why you'd need to do it this was in C++ at least. Not sure which other languages would need this. It's certainly not pretty. Then again, dispatching twice is not so bad comp…

It's not a "shortcoming" of the language per se. Visitor is a mitigation of the Expression Problem[0] on the Object Oriented spectrum. Object oriented designs need to use Visitor to add functionality to existing data structures, whereas doing such is a natural feature of Functional languages (though FP languages have their own awkward angle in attempting to add new data structures to existing functionality). This is a big motivator for most modern programming languages supporting multiple design paradigms.

[0] https://eli.thegreenplace.net/2016/the-expression-problem-an...

Re: Grim C++ Tales from the Crypt: The Visitor Pattern (2017)

#28

So annoying. I had to click through 20 slides of a cartoon dog acting weaboo to see the code example and I still don't see why the pattern is bad - which was the initial implication of the post. Why do people bury their thesis in horrible garbage like this? Sometimes I wish people were normal.

I probably don't need to read about C++ patterns anymore, so if this was an article I'd probably have skipped. The cartoon dog was pointless but somehow made me read it. It felt like there would be a punchline.

Re: Grim C++ Tales from the Crypt: The Visitor Pattern (2017)

#29
If you ask me, the actual problem is the tree data structure... Maybe post order forms lend themselves better to processing.

The even deeper problem is what ASTs are meant to represent, to which the answer would be "possibly a lot of diverse things". Diversity is never good in a computational context. But I don't see a good way to avoid it in the context of programming languages and ASTs. The reason for the diversity is that programming languages should allow humans to specify what should happen in very few keystrokes.

Re: Grim C++ Tales from the Crypt: The Visitor Pattern (2017)

#30
post #17
post #10

C++ match expressions would make std::variant a really nice alternative. I assume there is already a proposal out?

std::visit mostly allows you to do that already: https://coliru.stacked-crooked.com/a/be5c44281eea8bc4 Then only unfortunate missing piece of the puzzle is that there's no trivial way to create a closure out of this, so it requires a bit more manual work to propagate local state to the visitor.

If you build your visitor out of lambdas, instead of a struct, you can propagate local state to the visitor easily by using lambda captures. There are good examples of this approach at https://en.cppreference.com/w/cpp/utility/variant/visit
Post reply on HN