codegooglecom / json-template

Automatically exported from code.google.com/p/json-template
0 stars 0 forks source link

Repeated section should iterate over dictionaries and have special variables @name and @value #34

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
There are a few use cases for this, like generating code and command line
arguments.

Original issue reported on code.google.com by gtempacc...@yahoo.com on 30 Sep 2009 at 6:04

GoogleCodeExporter commented 9 years ago
Data:

{"dict": {"key1": "value1", "key2": "value2"}}

Template with your proposal:

{.section dict}
<dl>
    {.repeated section @}
    <dt> {$name} </dt><dd> {$value} </dd><!-- what is @ here? -->
    {.end}
</dl>
{.end}

Template with my proposal [1]:

{.section dict}
<dl>
    {.repeated key @}
    <dt> {key} </dt><dd> {@} </dd><!-- @ is same for object and array -->
    {.end}
</dl>
{.end}

With my proposal, you'd also dispense with the $index variable required for 
array
iteration.  Instead, the template designer would choose the name (e.g. 
{.repeated
index list}).  

And for iterating over elements in arrays and members in an object (in JSON 
terms,
they are referred to as objects, not dictionaries) you'd get the same pattern.  
The
cursor assumes the value of the element in an array or the member in an object. 
 The
(optional) name used after the .repeated declaration assumes the index in an 
array
and the name of the member.

This aligns with what people might expect from other languages (for key in 
obj).  It
also dispenses with the extraneous "section" term in ".repeated section".  
Finally,
if you really want to be concise and you don't need a reference to the array 
index or
member name in your template, you could not include a named argument in your
.repeated declaration.

E.g. for an array

<ul>
    {.repeated array}
    <li> {@} </li> <!-- cursor assumes value of element in array -->
    {.end}
</ul>

E.g. for an object

<ul>
    {.repeated object}
    <li> {@} </li> <!-- cursor assumes value of member in object -->
    {.end}
</ul>

All this (my alternate proposal) also allows any names to be used in the data
provided to the template ("$index", "$name", "$value", etc. are all free - and
perfectly valid in JSON).  I don't think it is necessary to reserve terms like 
those.

A number of your responses to similar inquiries are along the lines of "the
application should munge the data to fit my template language."  I think this 
is a
somewhat unnecessary constraint.  The template language could be made simpler 
and
work with data that is less specific to this language alone.  Template 
designers who
don't control all aspects of the application would be happier.  And application
developers who don't care squat about the constraints or limitations of the 
template
language would need to do fewer transforms on the data they pass along.

[1] 
http://groups.google.com/group/json-template/browse_thread/thread/e83c2a0af5396d
a7

Original comment by tim.sch...@gmail.com on 30 Sep 2009 at 4:18

GoogleCodeExporter commented 9 years ago
Right now sections and repeated sections require a name:

{.repeated section foo}
{.section bar}

I don't think we can get rid of "section" in repeated without breaking 
compatibility,
but assuming you can, what's the syntax?

{.repeated <subdict> <name> <value>}  # for objects
{.repeated <subdict> <index>}  # for lists

The <name> <index> <value> can't be first because they're optional.  If I just 
want
to iterate over a list with no index, I want to write:

{.repeated posts}

Not

{.repeated index posts}

And then ignore 'index'.  A lot of your proposal seems to break compatiblity 
unless
I'm missing something.  

Original comment by gtempacc...@yahoo.com on 1 Oct 2009 at 3:22

GoogleCodeExporter commented 9 years ago
Currently you can do this:

{.repeated section foo}

I'm suggesting allowing this:

{.repeated foo}

If one argument, it is the section name, if two, it is the repeat variable 
followed
by the section name:

{.repeated [<repeat_var>] <section_name>}

For objects, the repeat variable would be set to the name of each member in the
object.  For arrays, the repeat variable would be set to the index of each 
element in
an array.

Where things would break:

If someone is currently using referencing a member named "section" in a repeat 
block
in their template.

Data:

{"list": [{"section": "foo"}]}

Template:

{.repeated section list}
    {section}
{.end}

Currently produces:

    "foo"

With this proposal this would produce:

    0

I can't think of any other things that would break.  Basically, this proposal 
just
assigns meaning to the second term in the {.repeated section} directive.  
Currently,
it's just an extra word, right?

Original comment by tim.sch...@gmail.com on 1 Oct 2009 at 6:19

GoogleCodeExporter commented 9 years ago
I'm also curious what value the cursor assumes when iterating over elements in 
an
array in your proposal.

It seems to me like the pattern is the same for objects and arrays.  People 
commonly
iterate over members in an object and elements in an array.  In both cases, 
within
the repeat block, you need two references.  For objects, you need a reference 
to the
member name and the member value.  For arrays, you need a reference to the 
element
index and the element value.  Sometimes, you don't need a reference to the 
index for
an array.  And perhaps sometimes someone might not want a reference to the 
member
name in an object (though I wouldn't suggest this is very common).

You've already got the cursor (@).  It makes sense to me that this would become 
the
one thing people always need when iterating: member value for objects and 
element
value for array.  That leaves one variable name that needs to be determined.  
You
suggest reserving names for it in the language ($index and $name).  I'm 
suggesting
letting the template designer pick the name - and taking advantage of the 
second term
you already require in your .repeated directive.

I have no idea how many adopters there already are for json-template.  And I 
don't
mean to neglect the importance of backwards compatibility.  If, however, the 
language
is still young, it would be unfortunate if it became unnecessarily awkward for 
the
sake of preserving backwards compatibility when that might not really be an 
issue
(also, version numbers are cheap).

Original comment by tim.sch...@gmail.com on 1 Oct 2009 at 6:35

GoogleCodeExporter commented 9 years ago
Sorry, and I meant I'm curious what value the cursor assumes when iterating over
members in an object (in your proposal).

Original comment by tim.sch...@gmail.com on 1 Oct 2009 at 6:37

GoogleCodeExporter commented 9 years ago
OK I see the proposal now.  It is clever in repurposing the second word for the
index.  And there is some symmetry in that an array index can be thought of as 
a key.
 That is, an array is a special case of an associative array, where the keys are
contiguous integers.

Main problem: {.repeated index posts}  just reads badly.  It has poor grammar.

{.repeated section posts} doesn't read badly to me.  I don't think of "section" 
as an
"extra" word, any more than "static" is an extra word "static void foo()".  A
repeated section is a variant of a section.

The syntax follows Python's "read the words" style:

'for word in words'

better than

for (word : words)    (java)

[x**2 for x in 1,2,3,4]

better than

[x**2 | x <- [1,2,3,4]]  (haskell)

x = 3 if y > 2 else 5

better than

x = y > 2 ? 3 : 5;

Original comment by gtempacc...@yahoo.com on 2 Oct 2009 at 6:09

GoogleCodeExporter commented 9 years ago
The cursor could either

1) remain unchanged (it will be the top-level object)
2) be undefined
3) be a length 2 array of [$name, $value]

{.repeated section flags}
  {@|unix-flag}
{.end}

unix-flag:  '--%s=%s' % (cursor[0], cursor[1])

Although I suppose it's better to do:

{.repeated section flags}
  --{$name}={$value}
{.end}

Original comment by gtempacc...@yahoo.com on 2 Oct 2009 at 6:11

GoogleCodeExporter commented 9 years ago
Actually, to be consistent with both Python and JavaScript, @ should be the 
key. 
It's redundant with $name.

for var in obj:

for (var in obj) {
}

Original comment by gtempacc...@yahoo.com on 2 Oct 2009 at 6:15

GoogleCodeExporter commented 9 years ago
Right, so at least you notice the redundancy.  No reason to reserve words that 
are
redundant (this just forces more special processing of data structures that may
contain reserved words).

I imagine you'd also admit that there is symmetry among the following:

Python:

    for name in obj:

JavaScript:

    for (var name in obj) {

Template:

    {.repeated name obj}

I think most would argue that "for name in obj" is more intuitive than 
"repeated foo
bar," and personally, I don't see how "section" adds any clarity to the syntax. 
Given that you have chosen the word "repeated", I was only trying to propose 
some
logic for iterating over object members that would fit what people expect.

Original comment by tim.sch...@gmail.com on 2 Oct 2009 at 3:39

GoogleCodeExporter commented 9 years ago
Also (apologies for pushing), consider this:

If you allow the template designer to choose variable names when iterating, they
actually don't need to even touch the (somewhat obscure) cursor or remember any
special $words.

Data:

    {
        "obj": {"key1": "value1", "key2": "value2"},
        "list": ["one", "two"]
    }

Template:

    Object members:
    {.repeated key obj}
        {key}: {obj.key}
    {.end}

    Array elements:
    {.repeated index list}
        {index}: {list.index}
    {.end}

Can you really hope to be more readable using @ and $?

Original comment by tim.sch...@gmail.com on 2 Oct 2009 at 3:50

GoogleCodeExporter commented 9 years ago
I don't see what you're getting at in the last example -- you want to iterate 
over
the values in the list typically, not the index.  You seem to be spelling it in 
2
different ways.  The index is always 0..n.

'repeated name obj' is like 'for name in obj', but 'repeated index list' breaks 
down,
because you want to iterate over the items, not the indices.

Either way they don't read very well.  If the intention was to have 'for name in
obj', then we should spell it exactly like that.  The language has no variable
bindings now.  Adding variable bindings for a minor feature isn't worth it.

Here is an alternative:

Lists have {@index} and {@value}.

objects have {@name} and {@value}.

{@} just becomes a shortcut for {@value}.

This lessens the fear for reserved names, because $index is a valid variable 
name in
JavaScript, while @index is not.

At first I thought {@index} looks ugly for some reason, but it's growing on me. 
{$index} looks a little more traditional.  Also @foo means a vector in Perl.  
But we
don't even have a Perl implementation.

Original comment by gtempacc...@yahoo.com on 3 Oct 2009 at 12:53

GoogleCodeExporter commented 9 years ago
Yeah, sorry, that last example was hastily written.

I was thinking bracket notation, not dot notation:

    Object members:
    {.repeated key obj}
        {key}: {obj[key]}
    {.end}

    Array elements:
    {.repeated index list}
        {index}: {list[index]}
    {.end}

But, as that is not supported, it doesn't make sense.

If the cursor is the element value for an array and the member value for an 
object,
this would read:

    Object members:
    {.repeated key obj}
        {key}: {@}
    {.end}

    Array elements:
    {.repeated index list}
        {index}: {@}
    {.end}

(And if you didn't need a reference to the element index or the member name, the
optional middle term could be omitted.)

I agree that what you typically want when iterating over an array is the element
value.  The free "section" term just looked to me like a place to assign the 
index
while you were at it.  And the cursor would assume the element value.  For 
objects,
cursor would assume the member value (as you also suggest).  And I was 
suggesting
that the space currently occupied by "section" (in .repeated section) could be a
place for the member name.

I'll stop being hung up on it now.  I am happy you're considering iterating over
object members now.  I still think you could get away with only reserving "@" 
(or
less) but I won't push it.

PS - In terms of valid identifiers, I wasn't referring to JavaScript or any 
other
language that might be used in an implementation.  I was referring to JSON.  
"@name"
and "$name" are equally valid member names.  And, in JS, the following is 
perfectly
legitimate:

    >>> var o = {"@name": "value"}
    >>> o["@name"]
    "value"

I was thinking about how much care application developers have to put into 
ensuring
that the data they pass to the template doesn't contain member names that are
reserved by the language.  A JDIL (http://jdil.org/) structure will likely have
member names like "@value".  A data structure using JSON referencing will have 
member
names like "$ref".  The more member names you reserve for this language, the 
more
work people have to do to structure their data accordingly.  In my mind, a nice 
JSON
templating language could be used with any valid JSON.

Original comment by tim.sch...@gmail.com on 4 Oct 2009 at 6:29

GoogleCodeExporter commented 9 years ago

Original comment by gtempacc...@yahoo.com on 14 Nov 2009 at 8:49