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

Reply via email to