|Think about Loose Coupling|
Re^2: Free-Form Delegated Behaviorby John M. Dlugosz (Monsignor)
|on Apr 26, 2011 at 00:56 UTC||Need Help??|
Look at the synopsis for Marpa. It shows a simple grammar that triggers do_add and do_multiply actions, and supplies all the actions in a package called MyActions.
Now suppose I want to derive from this grammar. I add a production that calls do_exponent, which is easy to do: just push it on the list of productions, or call rules again on the existing parser instance to add another rule.
Now how do I add the implementation of do_exponent? I don't want to add it to the MyActions package, although Perl supports injecting it without altering the original source file. That's the problem I ran into with the Alpha API.
Now if the Action methods in MyActions were already acting like true methods, using the first argument as an instance and doing more stuff with it (say, to built a tree representation of the parse), it makes sense that my new do_exponent function would also want to call the (inherited!) helpers to manipulate and prepare the tree nodes.
Knowing the difference between public API functions and private internal guts is a general Perl problem not unique to this. You see a class, you can write code to call anything willy-nilly, since it doesn't have protection. Just don't do that! Call the documented methods for their intended purpose. In this grammar example, the Actions named in the grammar are no different than normal code written to use a class. I code calls to methods I know about, and don't code calls to "other stuff" I found from looking through the source file or the package symbol table.
My suggestions for the Marpa API in particular don't deal with "discovery", and is no different from any other module in that you write code that uses the methods you discover only by reading the documentation.
Extending it to "discovery", like with Catalyst that lets you write methods that will be bound to URLs and called by surfing the web, is more general and not needed by Marpa in particular. But if there was a general module that "did the callback behavior", and it supported tagging the callable actions, that would be just fine.
Hmm, I seem to have strengthened my argument that the Actions in Marpa should be done with an object. When using Marpa, you also code a module/class of some kind yourself, and code calls to that module. It's like any other module usage, only the code that calls the entry points doesn't look like typical Perl code but is highly declarative.