On Thu, Jul 16, 2015 at 8:31 AM, Zibi Braniecki <
zbigniew....@gmail.com> wrote:
> On Wednesday, July 15, 2015 at 5:49:12 PM UTC-7, Staś Małolepszy wrote:
> > That's the point, actually :) By forcing { and } to be always escaped we
> > can make sure that literal { } are either meaningful or are errors. We
> > don't have this luxury with <> now.
>
> Yeah, which in turn may lead to a confusing state between unclosed
> expander vs. unclosed entity. But I'm ok with experimenting with that!
>
I think expander vs. entity are fine, but you made me realize that there's
a problem with unclosed entities vs. opening of hash variants. We need a
better way for the parser to find the beginning of the next entity if the
previous one has not been closed. Back to the drawing board for hashes :)
>
> > It's in the gist:
> >
> > ; index is defined in []
> > ; hashes are defined as series of hash pairs {}
> > ; the default hash pair is marked with {* }
> > ; hash keys are symbols or strings
> >
> > { notifications [(plural n)]
> > {* one "{ n } notification"}
> > {many "{ n } notifications"}
> > {"two words" "{ n } notifications"}}
>
> Ok, then we have the same open-close character for entities, hash values
> and expanders. That's worrying.
>
See above. I need to change this part of the proposal. Thanks for
pointing it out.
>
> > I went for the hash-pair approach instead of key-value-map one to
> emphasize
> > the fact that variants are independent units of translation. They're
> > different facets of the entity and I wanted to make that clearer with a
> > syntax that's similar to the syntax of the whole entity.
>
> I don't think I like it. Once again, the most likely comparison people
> will have is JS Hash Values and I think it's a good one. I prefer
>
> {notifications[plural(n)] {
> *one: "{ n } notifications",
> many: "{ n } notifications",
> other: "{ n } notifications"
> }}
>
I don't think we should mimic JS code too much. There value in using a
different syntax; we have different semantics.
>
> > I like namespacing, but 1) I'm afraid of creating spurious hierarchies
> with
> > one elemnent and 2) it can be achieved by convention, e.g. intl-datetime.
>
> I believe that that's exactly the argument that PHP authors used and that
> led them to an API mess.
>
PHP is a full-on language which was used to build Facebook. Please tell me
you don't want to build the next Facebook in L20n ;)
> I'm much happier with one-element namespace, then flat list of
> namespace-like conventions with strpos, strslice, intl-numberformat and
> cldrPlural.
>
OK, how about the slash character which I used in my previous email when I
mentioned imports? Note this is just part of the name, not a new kind of
expression.
(cldr/plural n)
(intl/format-date datetime)
>
> > Consider this: you can probably write an entire S-expression parser in
> 100
> > lines of code. They're super-easy to implement too, which will make the
> > resolver simpler.
>
> I would prefer us not to design a challenging piece of L20n around how
> easy it is to implement, but how easy it is to learn and use.
>
I think that Lisp is easy to learn because it's so simple. So it's not
only on the merits of the simplicity of implementation that I suggest we
use it.
However, I think much of our discussion here boils down to who likes
S-expressions and who doesn't. We might want other people to weigh in. It
would also make sense (as you suggest later) to see what we could take from
this proposal that we both agree on and see what depends on the fact that I
used Lisp for expressions (like dashes in names). I tried to compile such a
list at the end of this email.
> > We want expressions to support complex logic and in L20n 1.0 we paid
> for them while arguably they aren't used much.
>
> Which is ok. We now introduce them in 3.x slowly and see what we use. I
> believe that the original scope of the expression syntax was designed to
> express plural macros and I think it's a good limit.
>
Why is it OK? L20n.js already is 70kb of JavaSciprt code, 30kb minified.
It's huge. If we want people to use it at all we should be careful about
adding more code to it.
>
> > Only a handful of localizer-engineers will write new expression code.
> So I think there's a benefit of providing complex expressions without
> bundling a complex implementation.
>
> I don't believe we know that. I don't think we got to the point where we
> know how commonly localizers will use expressions and my gut feeling is
> that they will use it more often then we assume.
>
I'd like to share that gut feeling but given how we haven't come up with UI
concepts for L20n in tools like Pootle tells me that it's not going to be
soon that we'll have all localizers writing expressions. I don't want to
optimize our syntax for a rare use-case of writing expressions. I think
the gist of my thinking is to base expressions on something which is proven
to work and easy to learn and implement. Remember v1's compiler and all
the different types of functions it created to be secure? I don't want to
repeat that.
> > A form always looks the same (operand ...args). There are fewer kinds of
> > parsing errors. OTOH, we're able to catch more errors in the runtime:
> e.g.
> > (entity 1) should return "Invalid argument type passed to &entity".
>
> how is it better than entity[1] or entity(1) ?
>
I think it's better suited for our minimal system because it's just one
kind of syntax that we need to support.
(operand ...args)
In the current
http://l20n.github.io/spec/grammar.html you can make a
mistake on every level of the expression syntax. In conditional expr you
can forget the colon. In logic expr you can omit one operand. In call
expr you can mix parens. In computed property and attribute exprs you can
mix brackets. There's just so many permutations of errors and we need to
support all of them.
>
> > Our C-style expressions are very limited: they're always a single
> > expression which makes the ternary if the only way to branch, and that's
> > tedious.
>
> I don't understand your point here.
>
See
https://gist.github.com/stasm/c99010a8ab6d467562ba#file-plural-old-php
for how the complex branching needs to be implemented in one single
expression using three ternary ifs. I think that's a limitation of the
current C-like syntax.
>
> > I think S-expressions give use a bit more flexibility by allowing
> > different interpretations of the arguments passed into form, like in
> (cond
> > ...) which takes an even number of args and pairs them together to
> create a
> > multi-branch if-else.
>
> I don't think that we need more flexibility and definitely I don't think
> that making looser syntax that leave more to the interpretation is going to
> get us less errors.
>
We can move part of the error reporting to runtime which is usually more
informative. We can also run static analysis on parse time (which is easy
with S-expressions because code is data) and possibly detect problems
before runtime.
>
> > I did that! I'm sure I'm not being objective here, but the new syntax
> > looks leaner to me.
>
> I believe that you are not objective here. It's a matter of taste but
> you're introducing a lot of esoteric tokens like &true, mod, or, and (which
> look like variable), while at the same time trying to minimize the number
> of special characters.
>
I think this comes down to teaching users that the opening paren is always
special and calls system functions (unless you call a macro with
(:my-plural ..)). Note that you can't call variables so it's not
ambiguous. If we had a symbol for calling other symbols, the following
would have the same meaning:
(cldr-plural n)
(call &cldr-plural n)
>
> I'm going to even skip the fact that the way we teach people math is by
> teaching them "a + b" not "+ a b", so the former is by design more
> recognizable. I believe that your approach is going to significantly
> increase the entry barrier and basically make the code harder to maintain
> when new people will try to work with pre-existing localizations.
>
Looks like you didn't skip it all ;) I don't think I want people to be
adding often in L20n. What's the use case? Even though I'd like to allow
full expression in placeables, I don't think we should tell localizers to
start doing arithmetic inside of translations. I expect expressions to be
mostly used in macros and I expect macros to be written by tech-savvy
localizers who can easily grasp RPN.
> I also feel like we're going to be less "webby" because all web
> technologies use C-like notation for arthmetic operations and JS-Object
> style notation for Hashes (see CSS, JS, JSON).
>
I think the definition of "webby" isn't very clear and may mean different
things to different people. I agree that RPN is non-standard on the client
side.
Sorry, I means developers here. I just don't think that lack of '-' in ID
> is a problem. CSS doesn't use them, JS doesn't use them. Seems like web
> technologies do just fine without it.
>
CSS very much uses dashes. A lot of dashes everywhere! In ids, class
names, property names, variables, you name it. Which in fact is my
inspiration! I want to be be able to do this:
<p id="hello-word" l10n-id="hello-world"></p>
and not this:
<p id="hello-word" l10n-id="helloWorld"></p>
> > The subtraction operator can only be found as the callee in form, so it's
> > really more like an operand or simply a function call: (- a b).
>
> Well substraction operator may also be found in the middle of the ID in
> your example.
>
In RPN it's not an operator if it's "in the middle". That's the benefit
which I want to reap: make syntax unambiguous.
> Also, I much prefer to have `and` as part of the expression syntax than a
> global call.
>
I know I'm repeating myself, but the whole point of RPN and S-expressions
is to not have operators. Everything is a function call.
> > How about the... hash? :)
> >
> > :entity#one#feminine
>
> I think I prefer $entity:one:feminine over that.
>
I could see this working out quite well, yes. Let me think about it.
> I can imagine going back to your idea of special-casing name `global` or
> `env`. and then env.cldr.plural instead of '@'.
>
Ugh. That's even more hierarchy... :(
> I think that we should discuss pieces of your proposal separately instead
> of building one of top of another to avoid the illusion that it's
> "all-or-nothing" scenario. I like many of your changes, I don't think that
> your expression syntax proposal is a good change. I'd prefer to discuss
> those things without false implications.
>
The consequences of using S-expressions for our use-case are as follows:
- we can use dashes in entity names, like CSS
this-is-a-valid-identifier
- we can use the single colon in references
:brandName
- we can use the question mark in entity and macro names
(:between? 2 1 3)
- every system function is called in the same manner, with (callee arg).
With C-like syntax, there's the confusion between referencing and calling:
@callee vs. @callee(arg).
- the only thing that we need to reserve is the & prefix which denotes
system functions. We can add anything there without the risk of clashing
with the existing syntax. C-like syntax prevents us from ever using &, |,
: etc. OTOH, we still need bool literals with the prefix like in
S-expressions: @true and @false.
- expressions use fewer special characters and are consistent. Compare the
following indexes (I'm already using parts of my proposed changes)
[@cldr/plural(n) user["gender"]]
[(cldr/plural n) (attr user "gender")]
- we're not limited to single-expression bodies. we can pass any number
of args to a function and define custom runtime behaviors. For instance we
could add a `condp` function (condition using a fixed predicate, similar to
a switch)
(condp &= username
"Mary" "she"
"John" "he"
"other")
Sure we could add a @condp global in the current syntax and call it with
any numbers of args, but why would @condp be a function and not @if?
Do we want to say 'no' to all of these advantages? We want to build a
small yet powerful domain language with expressions. Lisp syntax sounds
like a perfect fit to me, tbh.
> > Last but not least, I'd like to keep @ out of the syntax and use it for
> > docstrings like @param.
>
> I'm not sure how special characters in a comment collide with expression
> syntax. In docstrings, the '@id' are only meaningful if they are at the
> beginning of the line preceeded by whitespaces. We won't have any case like
> that with expressions.
>
Wouldn't the following be confusing? @param looks like a global.
/* @param $n Number of hellos */
<hello[@cldr.plural($n)] { ... }>
Thanks again, I'll revisit the design of hashes and will report back here.
-stas