On May 19, 11:04 am, Arnaud Delobelle <[EMAIL PROTECTED]> wrote: > Paul McGuire <[EMAIL PROTECTED]> writes: > > [...] > > Could you use it as a decoratore instead? > > integer = Word("0123456789") > > @integer.setParseAction > def parse_integer(tokens): > return int(tokens[0]) > > I could make your grammar clearer, because you don't mix it with > processing code... and no need for lambdas! > > -- > Arnaud
What a sexy little idiom! You could really apply this to any API method that accepts a callable as a single argument, and pyparsing actually has several of these: setParseAction addParseAction setFailAction setDebugActions (Unfortunately, setDebugActions requires 3 callables for its arguments - one to be run when an expression is about to be parsed, one to be run after parsing is complete, and one to be run if the expression fails to be parsed. So setDebugActions can't be used in this decorator manner.) Using these methods as decorators deviates from the typical decorator usage model as I understand it - instead of wrapping the provided function within some enclosing setup/teardown code (like lock/unlock, or open-file/close-file, or begin-transaction/commit-transaction), and then returning the created wrapper function, the decorator usage you propose is one in which the decorator uses the provided function with some side-effect (such as setting a property), but then just returns the original function. By returning the original function, we could stack decorators so that multiple expressions could share the same parse action: @articleTitle.setParseAction @movieTitle.setParseAction @bookTitle.setParseAction def upcase_title(tokens): return " ".join( t.title() for t in tokens ) Here is where I have something of a hitch, with the way pyparsing implements most setXXX methods. setParseAction already returns a value, and the value returned is self. If you have any Smalltalk background, this will seem familiar to you. (Not that I was ever a big-time Smalltalk coder, but this was one language idiom that you learned on Day 0.5 or you were lost forever.) This makes it easy to chain together a constructor and multiple property setters into a single expression: timestamp = Regex(r"\d\d(\/\d\d\){2} \d\d(:\d\d) {2}").setParseAction(convertTimeStamp).leaveWhitespace().setDebug() In the case where we have a single parse action shared by multiple expressions, we have to fall back to: def upcase_title(tokens): return " ".join( t.title() for t in tokens ) articleTitle.setParseAction(upcase_title) movieTitle.setParseAction(upcase_title) bookTitle.setParseAction(upcase_title) But, now that I've looked at this for a while, I may fall back on some other idioms: - just because you *can* do something doesn't mean you *should* do it - explicit is better than implicit Decorator syntax is already a mysterious topic for many newbies, even when used for its normal application. Using a decorator to perform the same function as an explicit "set" call invokes cleverness at the cost of clarity. Using decorators to replace: def methodX(a,b,c): blah methodX = staticmethod(methodX) with @staticmethod def methodX(a,b,c): blah does have some merits, including DRY. But using decorator syntax as an implicit invocation of a set method? It's just taking advantage of the incidental implementation of the decorator syntax. It would be like implementing the logic of a for-loop using a list comprehension - clever, and yes it can be done, but maybe a bit obscure. -- Paul -- http://mail.python.org/mailman/listinfo/python-list