-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve name resolution documentation #46
Comments
Name resolution should behave identically for sections and inverted sections. The omission of the implicit iterator as a valid name is unintentional; it should always be permitted as a name resolving to the topmost element on the stack. Re-reading the spec, the method / function resolution step occurs before iteration, and methods with an arity of 1 are simply a special case of methods. Since subsequent dotted names would need to be resolved either against the return result or the "method object", and since the latter is a non-portable concept, I vote yes. (Both of these things should be codified and tested by the spec.) |
Thanks a lot for the clarification, @pvande. One more question though. I'm having trouble understanding what is meant by the following part of the spec regarding name resolution in sections. Or else I understand it just fine but don't see the intended use case:
Can you provide an example use case of this part of the spec in action? To provide a starting point, here's a deliberately simple example that we could use to see what issue I'm having. Say you have the following set up (in Python)--
In the example above, in the final step of the rendering process per the spec above, it seems like the section contents
which would yield:
So the upper-case method return value never comes into play (since it's on the top of the context stack as a string value and there is no implicit iterator). If instead, however, we constructed a simple example using an implicit iterator to gain access to the top of the context stack, we would get something like the following, which doesn't seem useful either--
which, using similar reasoning, would yield--
Obviously, either I'm interpreting the spec wrong, or neither of the above is an intended use case. Can you provide your thoughts? Thanks a lot. |
Any thoughts on the question above? Thanks a lot. |
Sorry for the delay. I'm not sure why I didn't see your follow-up questions.
This is a clear issue with the text of the spec. Lambdas (and methods) are intended to have "special" behavior that is not adequately captured by this. Pointing a section at an arity 1 function/method should cause the method to "pre-process" the content of the section, but should (probably?) avoid any direct manipulation of the context stack. So in your example, the transformed contents of the section would be I'll make sure that the text is cleaned up soon. Thanks! |
See issue mustache#46 for related discussion: mustache#46
Okay, great. Thanks for the clarification. I think the crux of the issue here was the phrase "the data is the value returned," because the return value in this case (the pre-processed, unrendered value of the section) does not parallel the use of the word "data" in the previous bullet (i.e. in "If the context is a hash, the data is the value associated with the name."). You also noted this here in the issue #47 discussion. I just uploaded a commit that I think simplifies and clarifies the language in a few ways: 3de4731 First, it explicitly ties the "object method" case back to the language specified in the lambda section, instead of duplicating the lambda language for object methods. It wasn't clear to me before that object methods should be treated the same as lambdas. Second, it removes the phrase "the data is the value returned" that we discussed above. And third, it reduces the amount of special casing in the language. With this change, it is clearer that object methods of arity zero and one should be treated the same as arity zero and one lambdas (respectively), because lambdas can occur as hash values in the previous bullet anyways. Does that seem okay to you? |
@pvande, any reaction to this -- does this seem okay? Thanks. |
@cjerdonek, I disagree with your commit for one main reason: it refers to lambdas, which are an optional portion of the spec. The specification unfortunately requires the reader to assign meanings to several terms, when they should have been defined somewhere within the spec itself. My interpretation of a 'method' is an engine-provided function that is attached to an object in the context stack. (Note that while most, if not all, programming languages pass that object as an implicit parameter to the function, I'm not willing to say that Mustache requires that.) A 'lambda', OTOH, is a user-provided function, etc., and due to uneven support within programming languages, the spec does not require any way to define them. I propose the following:
I still see one problem, that the intermediate form of the rendered data is 'HELLO: {{PERSON}}'. The Mustache spec does not specify that names are case insensitive, so it is implementation dependent if PERSON is recognized or not. Either foo.bar should be re-written to not alter tags, or the context object should be {'foo': foo, 'person': 'Joe', PERSON: 'JOE'}. Perhaps @bobthecow or @groue could comment? |
Lambdas - or any way to let the user inject his own code in the template rendering - are a much needed feature. Without code injection, Mustache is so minimalist it turns into a painful trap as soon as your application starts to leave the trivial zone. So even if the spec does not require implementation of such feature, it's indeed mandatory for any implementation that pretends to be slightly useful. Now, unfortunately, the lambdas described by the spec are quite weak, and do not provide any help for frequently asked features. My own implementation lets, of course, the end-user implement spec-compliant lambda, but not only. You'll see a list of examples on this page, under § Examples. And for a list of much requested feature that I personally consider mandatory to implement, check the GRMustache FAQ. |
@samwyse: You'll see that I don't consider arity being a relevant concept: your modifications still go in a direction I left a long time ago (while keeping users able to implement spec-like lambdas if they need to, of course). |
The name resolution descriptions in the "interpolation," "sections," and "inverted" parts of the documentation are very similar. Indeed, it looks like the descriptions in "sections" and "inverted" are identical. It would help to combine these descriptions into a single section so that it is easier to see how name resolution differs or is the same in these three contexts.
In the meantime, can someone clarify the following?
Should name resolution for sections and inverted sections obey the same rules? Also, is it intentional that a single period cannot be used for sections and inverted sections?
Finally, the spec says for sections, "if the context is an object and the method with the given name has an arity of 1, the method SHOULD be called with a String containing the unprocessed contents of the sections; the data is the value returned." Can someone clarify whether this should be done even for the non-final parts of the name split on periods?
Thanks.
The text was updated successfully, but these errors were encountered: