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
-~----------~----~----~----~------~----~------~--~---

Reply via email to