Another possibility is to define ? as a unary suffix operator, which means "use my argument to determine whether to show this value". I'll have to think about this a bit.
Andy On Sat, Jun 20, 2009 at 12:56 PM, Andy Chu<[email protected]> wrote: > To be very succinct about it: > > - You're trying to make sections and substitutions the same by > defining common expressions, which include formatters. But sections > and substitutions are not the same. > > - However, the *values* of both sections and substitutions *are* the > same in my model (strings), and thus formatters and predicates can > apply to both. > > thanks, > Andy > > > On Sat, Jun 20, 2009 at 12:48 PM, Andy Chu<[email protected]> wrote: >> OK interesting. I see what you mean more clearly with the single >> definition of expressions. Either a simple name or a >> name|formatter|... chain is an expression, and you just keep the >> existing rule which determines whether to show a section. >> >> But there's a problem as you've defined it: sections can't contain >> .name lookups now. Even if they could, the lookup is "direct", not >> the type that walks the stack. The fundamental problem is that for a >> section, you're looking for context to test for truth and push on the >> stack, while in a substitution, you're looking for a value to put in >> the output. These just can't be made the same. >> >>> An expression has the form name ("|" name)*. >>> To evaluate the expression, the leading name is looked up >>> in the value stack (same as current JSON template) to produce >>> an initial value. Then each .name is applied, replacing the value >>> with the result of looking that name up in value, which must >>> be a JSON map. Then each |name is applied, replacing >>> the value with the result if applying the named filter to the value. >>> The expression a|b|c|d would be written d(c(b(a))) in many >>> programming languages. The special leading name "@" means >>> the top element on the value stack. >> >> As mentioned, we would need 2 types of expressions here. In my >> formulation, there are separate but similar syntaxes for substitutions >> and sections, and then the formatters apply to *values*. You haven't >> defined the value of a section here -- only the value of an >> expression, which may appear inside a section directive. >> >> So it looks like you're punting on the formatters on (expanded value >> of) sections. But I think this is just too useful to pass up. >> >>> A section has the form >>> "{.section" expr "}" true-body ("{.or}" false-body)? "{.end}" >>> In the output, it is replaced by the result of the following procedure. >>> First, expr is evaluated to produce a value v. >>> If v is not false or empty, v is pushed on the value stack, true-body >>> is executed, and v is popped off. Otherwise, false-body is executed >>> if present. >> >> The asymmetry here will lead to awkwardness in practice. Say you have >> {"num": 3}, then the most compact thing to do is: >> >> >> {.section num|plural?) >> There are {...@} people here. >> {.or} >> There is {num} person here. >> {.end} >> >> Of course you can use {num} in the first clause because of the stack >> walk, but this subtlety is confusing. >> >> In my formulation, we retain the original rule that the "num" context >> is pushed on the stack if it's non-empty. The predicate determines >> which one to execute. These decisions would be orthogonal -- in yours >> they're tied together because you discard the original value in favor >> of the filtered one. >> >> Also, the definition for plural? here is: >> >> def Plural(num): >> if num > 1: >> return num >> else: >> return None >> >> I'd rather write: >> >> def Plural(num): >> return num > 1 >> >> >>> A repeated section has the form >>> "{.repeated section" expr "}" body ("{.or}" false-body)? "{.end}" >>> [Yes there's also an alternates-with but it doesn't matter here.] >>> In the output, it is replaced by the result of the following procedure. >>> First, expr is evaluated to produce a value v, which must be an array. >>> For each element of v, that element is pushed on the stack, body is >>> executed, and the element is popped off. If v is empty, false-body >>> is executed if present. >>> >>> As a result of this definition, one style of filters is as "predicates" >>> which return either their input or false. Using them can enable or >>> disable sections appropriately: >>> >>> {.section num|>1} >>> There are {num|english} people in group {name} >>> {.or} >>> {.section num|==1} >>> There is one person in group {name} >>> {.or} >>> There are no people on group {name}. How sad. >>> {.end} >>> {.end} >> >> This brings up something I've been thinking about -- chaining of >> conditions (e.g. elif, elsif). I would rather have a flat structure >> than a nested one. >> >>> It is also possible to use filters to transform the data before iterating >>> over it, for example to select only the public fields from a data structure >>> definition: >>> >>> {.repeated section fields|public?} >>> Field {name} has type {type}. >>> {.end} >> >> Right. In either formulation, I would write that like this, to avoid >> using a loop in the formatter: >> >> {.repeated section fields} >> {section @|public?} {# Repeated sections move the cursor each time} >> Field {name} has type {type}. >> {.end} >> {.end} >> >> public? operates on an element rather than a list of elements. >> >>> Or to order an array in a certain way: >>> >>> {.repeated section people|sort-by-phone-number} >>> {name} {phone-number} >>> {.end} >> >> Unrelated to this discussion -- in either formulation, you can have >> >> {.repeated section people|sort phone-number} >> {name} {phone-number} >> {.end} >> >> {.repeated section people|sort name} >> {name} {phone-number} >> {.end} >> >> Where sort is a single formatter that takes a string argument. This >> works like the template-file ("include" feature) if you haven't seen >> it. >> >> ---- >> >> About overloading | operator -- note that I tried to use ? as an >> operator instead of |. However, this just looks ugly: >> >> {.section ? plural} >> {.end} >> >> {var?plural} >> >> The ? reads better after the predicate name, and it also would look >> too much like a ternary operator, but the position of the predicate >> swapped. >> >> I'm open to suggestions on syntax that distinguishes predicates from >> formatters. Formatters can be chained, so | is appropriate, but >> predicates so far can't, although it's conceivable to have multiple >> predicates. >> >>> Or perhaps to create a potentially large data structure on the fly: >>> >>> {.section x|primes-up-to-10000} >>> {...@} is prime. >>> {.end} >>> Again, the primes are: {x|primes-up-to-10000}. >>> >>> In this implementation, evaluation of expressions has just >>> one behavior: a|b|c|d means take a, pipe it through b, c, and d, >>> and use the result as the value of the expression, no matter >>> what the context. >>> >>> Neither sections nor substitutions have predicates or formatters. >>> Data has filters. Instead of 4 cases, there is 1. >>> Predicates are an idiom, not a built-in concept. >> >> So, as mentioned, you do have 2 cases for expressions. And my >> formulation has 2 as well -- this is because I've introduced the >> concept of "values" of sections and formatters, and defined >> predicates/formatters on values, not a 2x2 matrix. >> >> In the end I think that the practical matter of formatting sections is >> vital. This was asked for by users, and it will fix nastiness I have >> in my doc/makedocs.py stuff. There will be a bunch of silly Python >> code eliminated in favor of simple, declarative templates. >> >> It's very interesting how there can be two consistent but different >> interpretations of the same language. I'm glad that coherent models >> can be made. >> >> thanks, >> Andy >> > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "JSON Template" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/json-template?hl=en -~----------~----~----~----~------~----~------~--~---
