I learned the visitor pattern in pretty ideal circumstances: from a classmate, back in college, when we were writing a compiler together for a class project, and it was just what we needed.
The right conditions for a visitor are when you have a data structure with many different “node” types, and the traversal logic is not simple. In addition, you will be doing many different traversals. You might also be doing transformations on the structure. You might have a library running the traversals/transformations provided by the code that uses the library. There could be correctness or memory management considerations involved that you don’t want the client to have to worry about. You might want to “pipeline” multiple transformations, doing several manipulations in one traversal, in an efficient way. Common traversals might care about only certain types of nodes, like a particular lint rule might just be looking at string literals or references to global variables, but it needs to walk the entire syntax tree of a file of source code.