(This post answers pull request 37[1] on github. I think this is the 
better medium for discussing this)

Hi Jason,

I was/am aware of the lack of consistency in the execution environment 
for parslet's transformation blocks. That's on purpose. Let me explain:

Unlike parsers (< Parslet::Parser), transformations are classes in their 
own right that have state and behaviour. Although the elements of a 
transformation are also called #rule, (which is unfortunate), they act 
very differently. My LISP loving heart wants transformations to be 
stateless, purely functional.

I designed the transformations to be good for one thing: Getting out of 
the horrible Hash/Array/Slice mixture into the realm of your own AST 
classes easily. I think they fulfill that purpose well. Usually, no 
state is associated with that operation.

To you it (going into an AST first, then doing work) may look like an 
added step with no rationale; I can see that and will try to improve 
transformations for people who want to use them to produce results 
directly. However. Your pull request encourages users of parslet to keep 
state in the transformation instance directly, which strikes me as very 
bad OOP - it violates the single responsibility principle.

Having state in the transformation will also make it non-trivial to 
update to new parslet versions - I might use @doc in Parslet::Transform 
in the future, leaving you with broken tests.

But let me propose something that might work for both of us: How about
injecting context during the apply call?

   transform = Parslet::Transform.new do
     rule(...) { doc.insert(...) }         # doc is defined here
     rule(...) { |d| d[:doc].insert(...) } # and also here
   end

   transform.apply(tree, :doc => MyDocument.new)

My hope is to leave the execution context of transformations officially 
undefined, providing for everything needed for nice code without having 
to anchor them. If I find a way to inject local variables without the 
Context hack, I'll eliminate it, opting for definition scope everywhere. 
But I have currently no idea on how to do that. But the above change 
would be trivial.

As an aside: I think implementation discussions and feature requests 
belong to the mailing list - more people watching this. A pull request 
is not a discussion of possibilities, it makes me say 'yes' or 'no', 
hard to strike a note between. Instead of giving you a 'no', I want to 
say 'yes, but how would you like this?'. Github doesn't let me do that 
very well.

How about it?
regards
kaspar

[1] https://github.com/kschiess/parslet/pull/37

Reply via email to