Power lambdas (suggestions for a better name welcome) #155
Replies: 3 comments 19 replies
-
In #135, @agentgt suggested investigating exising implementations of "more powerful" lambdas, in order to get an overview of existing practice. I replied with this list of implementations I was already aware of:
|
Beta Was this translation helpful? Give feedback.
-
In #153 (comment), I came up with a flavor of "power filter" that could address the masking problem. I think it provides a cleaner alternative to features 1-3. It is less powerful, but still powerful enough to make me want to leave features 1-3 out of the power lambdas specification! |
Beta Was this translation helpful? Give feedback.
-
@jgonggrijp On discovery of other implementations: Another Mustache variant in Java land that has sort-of power lambdas is Trimou: https://github.com/trimou/trimou Trimou went the Handlebars helper route. I'm not sure why Trimou never got that popular. My guess is people in Java land would either just accept the decorating or prebuilding of models (i18n) required in Mustache.java (@spullara) or use actual Handlebars.java. Or probably just marketing and network effect. Several times I have considered experimenting with a Handlebars helpers like extension to JStachio but the only real use case I seem to need it for was i18n. Sort of an open question but I have to wonder how much of power lambda desire / use case is i18n particularly parameters? In the past when we did i18n in my company we used sort of a giant key/value ( In other cases the model would just get all of the i18n resolved apriori. I guess it would be interesting to me and possibly helpful to others if we had a list of fairly concrete use cases power lambdas could solve. Otherwise it appears where we have been using JStachio/JMustache lambdas a filter could have been used instead (well I'm not so sure on the whole fallback stuff but the transform this node to another node is mainly what we are using lambdas for). |
Beta Was this translation helpful? Give feedback.
-
This is a continuation of the discussion in #135. Before that, there was also relevant discussion in #19 and #41, including a comment that hinted at something like power lambdas in #41 (comment).
At the time of writing, (regular) lambdas have the following required capabilities, according to the interpolation and sections specs:
The optional lambdas extension adds one more capability:
Power lambdas would supercharge the capabilities of lambdas, while changing as little about the language as possible. There is no syntactic change and only one semantic change: lambdas that can handle it receive an additional argument, which I refer to as the "magic".
The magic adds one or more of the following features to the existing capabilities of lambdas, in an implementation-defined way. Implementations are free to omit some of them, but encouraged to support as many as they can. However, it is up to debate whether all of the following features should be included in the spec. More on this below.
Edit: I no longer believe features 1-3 are needed, see #155 (comment).
I envision this as an optional extension module, perhaps
~power-lambdas.yml
. It would follow a slightly different format from the existing~lambdas.yml
: each implementation that attempts to pass the specs in that module will need to bring its own lambdas.The first three features mostly cater to a lambda's ability to return a value that gets pushed on the context stack. The other four mostly cater to a lambda's ability to override the template inside a section. There is some interaction between these sets as well. In detail, the features were originally motivated as follows:
{{# someList | enumerate }}
, the equivalent power lambda would be written{{# enumerate.someList }}
.{{ someString | capitalize }}
, one would be able to write{{#capitalize}}someString{{/capitalize}}
. However, passing section content as argument text to lambdas in this way would also open some options that filters do not have, since the lambda is free to interpret the section content in any way that suits the application. Feature 5 could make this use case more efficient.{{>*animal}}
one would write{{#dynPartial}}animal{{/dynPartial}}
(for example). 2 alone would also suffice, but would require recompiling the external template every time. This use case is no longer relevant because dynamic names already made it into the spec in the meanwhile.For the first two motivations, where power lambdas provide a close alternative to filters, I now believe that filters are more appropriate, even though power lambdas would be more powerful. Filters are much easier to implement for a given application: a filter can be any straightforward function in the host language that maps one value to another, while a power lambda requires specific knowledge about the Mustache engine as well as intricate masking and/or argument parsing logic. In addition, I cannot think of a convincing situation where a filter-like use case really requires the additional context awareness or argument parsing that a power lambda could provide.
The next two motivations, which position power lambdas as a solution for the masking problem, are more convincing in my opinion. Syntactic alternatives are discussed in #154, but I feel none of those alternatives is very good, so I currently still have a slight preference for the lambda approach. That said, if a syntactic (or other non-lambda) solution for the masking problem does make it into the spec, this completely removes any justification for feature 3. Update: I think I have now come up with a very good alternative, see #155 (comment). Features 1-3 can all be left out if that alternative is implemented.
Dynamic names are in the spec already. I personally find the remaining motivations very convincing, but since those only involve features 4-7, this makes the inclusion of features 1-3 a bit uncertain as I see it. Of the latter three, 2 is probably the most useful one, but also the most redundant with filters. Still, there might be other good arguments why 1-3 need to be included anyway.
7 is nice to have, but not strictly necessary if 4-6 are also available. Thus, 4-6 seem to be the most "core" features of power lambdas, with 7 being a welcome extra.
An interesting option would be to return a lambda from a filter. That is, a filter might construct and return a closure, bound method or partially applied function with knowledge about a value in the context. That function could then proceed to act as a lambda, with context argument parsing, template overrides and/or pushing a new stack frame. I have discussed this option in #153 in more detail. It could provide a partial alternative to features 1-3, though in many cases, it may not be enough to address the masking problem.
Beta Was this translation helpful? Give feedback.
All reactions