Why predicates can't be formatters

30 views
Skip to first unread message

Andy Chu

unread,
Jun 18, 2009, 10:12:47 PM6/18/09
to JSON Template
(This is the continuation of an offline conversation, but posting it
here since it includes some generally relevant information.)

Formatters are functions from JSON nodes -> JSON nodes. Strings are
special cases of JSON nodes. In a {value|formatter1|formatter2}
chain, the last thing should be a string.

Predicates are functions from JSON nodes -> booleans. It was pointed
out that if you define *truth* on JSON nodes, which we've already
done, then formatters can serve as predicates.

But it doesn't work, because in the "false" case you may still need
substitutions:

{.section group|plural?}
There are {num} people in group {name}.
{.or}
There is one person in group {name}.
{.end}


So the plural? predicate can't just return "null", since we still need {name}.

Also, predicates and formatters do different things, so we shouldn't
make them the same concept. Formatters are concerned with
substitution of values, and apply only to substitutions. Predicates
are concerned with *whether* to show a section. You can combine the
two on the same section (they are *orthogonal*):

{.section group|plural?}
{@|fancy-formatter-for-plural-groups}
{.or}
There is one person in group {name}. {# No fancy formatter}
{.end}

Or use a totally different file for plurals:

{.section group|plural?}
{@|template-file plural-group.jsont} {# the "include" feature}
{.or}
There is one person in group {name}.
{.end}


Andy

Russ Cox

unread,
Jun 19, 2009, 2:33:00 AM6/19/09
to JSON Template
> Predicates are functions from JSON nodes -> booleans. It was pointed
> out that if you define *truth* on JSON nodes, which we've already
> done, then formatters can serve as predicates.

I admit it; it was me.

> But it doesn't work, because in the "false" case you may still need
> substitutions:

I disagree.

> {.section group|plural?}
>   There are {num} people in group {name}.
> {.or}
>   There is one person in group {name}.
> {.end}

{.section group}
{.section @|plural?}
There are {num} people in group {name}.
{.or}
There is one person in group {name}.
{.end}
{.end}

> {.section group|plural?}
>   {@|fancy-formatter-for-plural-groups}
> {.or}
>   There is one person in group {name}.  {# No fancy formatter}
> {.end}

{.section group|plural?}
{@|fancy-formatter-for-plural-groups}
{.or}
There is one person in group {group.name}. {# No fancy formatter}
{.end}

> Also, predicates and formatters do different things, so we shouldn't
> make them the same concept. Formatters are concerned with
> substitution of values, and apply only to substitutions. Predicates
> are concerned with *whether* to show a section.

This is like saying that calls to an int(*)(void)
and calls to a char(*)(void) do different things, so
we can't refer to them both as function calls.
The | syntax does the same thing in both cases: it takes
the data, pipes it through the function, and uses the
resulting value.

The beauty of JSON Template is that it has four basic
operator: .section, .repeated section, substitute, and pipe.
Allowing pipe in .section and .repeated section would
address the perceived need for predicates by removing
a restriction (no pipes in section expressions); it adds
no new operators.

Adding predicates as a distinct operator grows the
operator set by 25%, adds another restriction
(no predicates in substitute expressions), and makes the
arguments to the | operator context dependent.

Russ

Andy Chu

unread,
Jun 19, 2009, 3:49:14 AM6/19/09
to json-t...@googlegroups.com
Russ, before I respond, check out the next message about an alternate
use of formatters on sections. I think you'll like this, since you
may find it useful specifically for generating technical docs.

This came to me just now, thinking about the problem below, and a
problem another coworker pointed out.

Andy

Andy Chu

unread,
Jun 19, 2009, 11:07:26 PM6/19/09
to json-t...@googlegroups.com
> {.section group}
> {.section @|plural?}
>  There are {num} people in group {name}.
> {.or}
>  There is one person in group {name}.
> {.end}
> {.end}

I don't see the rule that this is implying. If plural? returns
"null", then how does the {.or} section have access to {name}? I
don't see how wrapping it in another section does it. Any rule I can
infer here will have a bunch of special cases and require keeping
track of more state.

>> {.section group|plural?}
>>   {@|fancy-formatter-for-plural-groups}
>> {.or}
>>   There is one person in group {name}.  {# No fancy formatter}
>> {.end}
>
> {.section group|plural?}
>  {@|fancy-formatter-for-plural-groups}
> {.or}
>  There is one person in group {group.name}.  {# No fancy formatter}
> {.end}

Also don't get this -- is the {group.name} vs. {name} a purposeful
disambiguation? I don't see why this is done differently than the
first case.

>
>> Also, predicates and formatters do different things, so we shouldn't
>> make them the same concept.  Formatters are concerned with
>> substitution of values, and apply only to substitutions.  Predicates
>> are concerned with *whether* to show a section.
>
> This is like saying that calls to an int(*)(void)
> and calls to a char(*)(void) do different things, so
> we can't refer to them both as function calls.
> The | syntax does the same thing in both cases: it takes
> the data, pipes it through the function, and uses the
> resulting value.

It's similar but not the same. In one case we substitute the
resulting value into the output. In the other we test the resulting
value for its "truth" and decide *whether* to expand a section into
the output. These are different things.

sections and substitutions are different. And formatters and
predicates are different. Although I agree that there is way to make
formatters apply to both sections AND substitutions -- there is also a
straightforward way for *predicates* to apply to section and
substitutions (coming next mail).

I want to avoid a 2x2 matrix of special cases, and instead have the
concepts be orthogonal. The special case I see here is: "If a
formatter is used in a substitution, its value is used. If it's used
in a section, then the value is tested for truth and that determines
if it's shown."

This morning I came up with a nice consistent model, which I'll write next.

Andy

Russ Cox

unread,
Jun 20, 2009, 1:10:43 AM6/20/09
to json-t...@googlegroups.com
On Fri, Jun 19, 2009 at 8:07 PM, Andy Chu<an...@chubot.org> wrote:
>
>> {.section group}
>> {.section @|plural?}
>>  There are {num} people in group {name}.
>> {.or}
>>  There is one person in group {name}.
>> {.end}
>> {.end}
>
> I don't see the rule that this is implying.  If plural? returns
> "null", then how does the {.or} section have access to {name}?  I
> don't see how wrapping it in another section does it.  Any rule I can
> infer here will have a bunch of special cases and require keeping
> track of more state.

I was assuming here that the new value is pushed on
the name lookup stack only in the true half of the .section.

>>> {.section group|plural?}
>>>   {@|fancy-formatter-for-plural-groups}
>>> {.or}
>>>   There is one person in group {name}.  {# No fancy formatter}
>>> {.end}
>>
>> {.section group|plural?}
>>  {@|fancy-formatter-for-plural-groups}
>> {.or}
>>  There is one person in group {group.name}.  {# No fancy formatter}
>> {.end}
>
> Also don't get this -- is the {group.name} vs. {name} a purposeful
> disambiguation?  I don't see why this is done differently than the
> first case.

There's already a value stack, so if group was a valid name
in the .section line, then even if something did get pushed
onto the value stack during the .or, the lookup could still
find group again, and then use group.name.

Russ

Reply all
Reply to author
Forward
0 new messages