Boolean shortcuts
Doesn't play nice with already existing blocks :
eval("{ !window }") // returns false;
, François
-----Message d'origine---
Curse that eval-uation of a code block! This prevents not only this, but a lot of more possible enhancements/reforms!
Also { !window }.foo
would be problematic since it will be pronounced
code-block before . is reached. :-(
Thanks for pointing out, Herby
p.s. It is really wild. In node.js, eval("{}") returns {}, eval("{;}") returns undefined, eval("{;} 3") returns 3, but eval("{;} {}") returns undefined (why not {}? Or why did not first eval returned undefined?); eval("{;} ({})") returns {}, of course.
-----Pôvodná správa---
I agree that code block is a complex feature that is (almost) never used and that has many quirks.
If ES6 could remove it, I would not be upset at all. If it's here to stay, we should at least have an introductory keyword like "eval { ... }" and allow "var x = eval { ... }".
BTW, I think the reason of your inconsistency is a bug : eval("{}") should return undefined, as in IE9. It seems that node.js has a special case for {}, probably to avoid a common mistake. Or there's a bug in the parser, I don't know.
-----Pôvodná správa---
2012/1/4 Herby Vojčík <herby at mailbox.sk>:
Curse that eval-uation of a code block! This prevents not only this, but a lot of more possible enhancements/reforms!
I don't see the problem. You are proposing a change to the ObjectInitialiser production. Francois's example just demonstrates something we already know -- that there exist strings that will parse as an ObjectInitialiser when you start in the Expression production but parse as a Block when you start in the Program production.
eval('{ !window }') is and would remain a block, and eval('({ !window })') with your proposal would be unambiguously an object initialiser, and is a SyntaxError in ES5.
well, it is true that if {...} is ambiguous, you can always put it in parentheses to enforce parsing it like an expression, but it reduces the convenience of the proposal. If you must think whether you should put it in parentheses or not to prevent runtime error, you rather write { window:false } and reduce the insecurity.
I had in mind some more enhancements of the object literal, but they all would made insecure for that same reason: the code could be mistakenly parsed as code block. Using ({...}) I can in fact always "mark as data", but it is in fact very convenient that such marking is not needed, if it would be, it would make things less useful. If there should be "marking" needed at all, I think it should be there for the (free, stray) code blocks, not for data blocks (as seen in the parallel "No code block without introductory keyword" thread). What do you think of that?
If it would be unambigously (and conveniently) be able to tell code block apart from data block, the data blockk could be made much more powerful (and move even more from imperative to declarative; classes were also a move to that way, but it could go even further).
Like in, for example, the production: { name: aName, age: anAge, if (anAge>60) { retired: true, place: "rural" } else { place: "urban" } }. If
it is ambiguous, { ... } with if inside would be treated as code block, but if it would be known that it is a data block, one could put "data-if" inside without problems.
Herby
-----Pôvodná správa---
2012/1/4 Herby Vojčík <herby at mailbox.sk>:
Hi,
If you must think whether you should put it in parentheses or not to prevent runtime error, you rather write { window:false } and reduce the insecurity.
You already have to.
'boolean' === typeof eval('{ window: false }')
See section 12.4 : es5.github.com/#x12.4 """ 12.4 Expression Statement # Ⓣ Syntax ExpressionStatement : [lookahead ∉ {{, function}] Expression ;
NOTE An ExpressionStatement cannot start with an opening curly brace because that might make it ambiguous with a Block. """
“You already have to.” –> If something is bad, don't change it?
(1) Block expressions are not useful because you can't use them as expressions (=retreive their value) if you don't use “string eval”. (2) Object syntax is restricted because lookahead comes at a cost for parsers.
This is a mess. Beginners hate it. Parsers don't like it. And yet it's still there...
Personnaly, I would like to do something like that (and I remind an earlier proposal from the mailing list) :
// try to create an "x" variable
let x = try { doSomething() } catch (ex) {};
or
// log the value of 1+2+3+...+10
console.log (eval { let i=10, j=0; while(i) { j+=i—; } });
Now, I have to do something like that :
// not as readable
let x; try { x=doSomething() } catch (ex) {}
or
// bad but close in term of input
console.log(eval("let i=10, j=0; while(i) { j+=i--; }"));
// as optimized, but not as readable
{ let i=10; let j=0; while(i) { j+=i--; }; console.log(j); };
The introduction of the “eval” keyword before a block has tons of other advantages :
{}.toString(); // will now compile and return “[object Object]” from anywhere in the code
That means I can do something like :
let props = eval {
let obj = func();
let prop1 = getProp1(obj);
let prop2 = getProp2(obj, prop1);
{
prop1: prop1,
prop2: prop2
}
}
Another proposed syntax, namely
this.function() {} <—> (function() {}).bind(this)
will now be acceptable since
function() {
return this.function(); //ASI
{
doSomething();
}
}
is not allowed in ES6, there’s no syntax conflict. So, we can introduce the [noLineBreak] token after “function” safely.
BTW, I also think we should drop labels for ES6. This will help to simplify syntax, too. With ES6, we should build a new syntax that’s more logical to use.
-----Message d'origine---
as I already posted in the parallel thread, there is that strawman called "do expression" by dherman that does just that.
I feel like crying when I see how powerful data constructs could be if not hampered by "possible to parse as code block" ambiguity.
Herby
-----Pôvodná správa---
On Jan 4, 2012, at 1:57 PM, Herby Vojčík wrote:
Hi,
as I already posted in the parallel thread, there is that strawman called "do expression" by dherman that does just that.
I feel like crying when I see how powerful data constructs could be if not hampered by "possible to parse as code block" ambiguity.
Yes, I have felt like crying too -- I did some work (see esdiscuss/2011-June/015568) on unifying blocks and object literals, inspired by others on this list, but it didn't pan out. It's increasingly future-hostile as we try to extend object literals.
Trying to invert precedence so "{}" as a program source makes an empty object instead of an empty block, IOW favoring expressions over statements, is a breaking change. Not only for eval, but for other variants such as javascript: URLs.
So, I've put unifying blocks and object literals on the back burner. A more nuanced approach that doesn't break compatibility so much would be welcome, but I don't see it.
On Jan 4, 2012, at 2:56 PM, Brendan Eich wrote:
On Jan 4, 2012, at 1:57 PM, Herby Vojčík wrote:
Hi,
as I already posted in the parallel thread, there is that strawman called "do expression" by dherman that does just that.
I feel like crying when I see how powerful data constructs could be if not hampered by "possible to parse as code block" ambiguity.
Yes, I have felt like crying too -- I did some work (see esdiscuss/2011-June/015568)
I should have also linked:
strawman:block_vs_object_literal
Of course,
is much simpler.
Neither addresses the empty-block/object issue by trying to evaluate {} as an object literal where today it's a block statement.
Is breaking current code so much of a problem? If, by default, javascript refers to "ES5" and if we introduce a "use version 6" pragma, breaking old code isn't a problem anymore. Scripting languages on UNIX are doing exactly this [en.wikipedia.org/wiki/Shebang_(Unix)]. The first line indicate the compiler/interpretor to use. That way you will never break the web, but you allow ECMAScript to move forward. We really need this.
That doesn't mean we have to start over a new language but if, to make the language better, we have to make some changes that will have a minor impact on existing code (seriously, who is using code blocks at all?), this should not be a blocking issue. The comitee removed the with functionnality in ES5 strict. That wasn't a problem. People can still use their old code and can opt-in for a new version with stricter rules.
For people wanting to convert old code to ES6, there will be automated tools that can predict reliably if your code continues to work under ES6 and can notice you of problems. If those are rare engouh, most of our code will continue to run.
-----Message d'origine---
thanks for the link. I will look at it. I am just working on something similar, just because it appeared inside my mind and it is really nice (if it was possible). So I probably will finish it and put it online, even if it will be put away (though I'd like not to).
I'm curious about in what scenarios {} as object literal brings is a breaking change.
I devised a "freestanding {...} is always an object literal" rule with "if you want free code block, introduce it in appropriate context" (like a do-expression, for example, even dumb do while (0) is good as a workaround) counsel. I see it breaks old code, but I am looking at it as a feature for the new version, so breaking old code is not a problem and I do not see (yet) any problems when used in context of ES.next only. Is there something beyond free code blocks?
Herby
-----Pôvodná správa---
We are now focused on "new syntax is opt-in" model. No new versions required (allowed but not required). Even with new syntax we do not propose to make existing syntax change meaning(much or at all) in ES.next.
Hello,
sorry that I did not get it from the beginning.
You are right.
I am really concerned about use of boolean shortcuts in the context of
object initializer.
But François's examples scared me.
Especially the impossibility of { !window }.callFunc();
kind of
statements.
But in such case, early error should tell me I am in the wrong way and
people are accepting that this kind of construct need parentheses to
disambiguate (especially for the ({}).foo case).
So I would make the proposal alive again, but the thread got cluttered. :-/
Thanks again for showing me not to panic,
Herby
-----Pôvodná správa---
There was a suggestion for CoffeeScript, which got implemented by Cocosatyr.github.com/cup/#c:{+enumerable, -configurable, +writable},
for {+enumerable, -configurable, +writable}
syntax that does that. It has
the same potential ambiguity, but looks better IMO.
Yeah, it looks. And it needs no special case in used in var.
-----Pôvodná správa---
I have looked at the links and as I understand they are trying to accomplish something slightly different, by adopting code as kind of data, though it is interesting, too (and your are true do-expressions do it elegantly, except for the "explicit zero-arg lambda" thing (I think || is not tragedy)".
I was trying to do something different - not bring code verbatim into data, but powerful code constructs into data - I had posted it in thread "RFC: Empowered data - unification of code block and object literal(and class)". It more a unification of code block and data block to be more similar in appearance as well as expressiveness (while retaining their imperatice/declarative nature).
As for the "empty-block/object issue" I realized it is a non-issue (or, little issue), I was freaked out. :-) This is old known things that {}.f() does not work until one parenthesizes {} and it is the same (anooying, but nothing breakingly new) category of quirk.
Herby
P.S.: Still got no comment on above-mentioned thread. :-(
P.P.S.: And back to boolean shortcuts: would there be a possibility (and demand for them)? I posted my '{ value: "foo", configurable, writable, !enumerable }' and 'var !done, !!soFarSoGood' and someone mentioned there is this kind of proposal in CoffeeScript land which goes more like '{ value: "foo", +configurable, +writable, -enumerable }' and 'var -done, +soFarSoGood'.
-----Pôvodná správa---
(original article in blog.herby.sk/blosxom/Programming/ES-next/boolean-shortcut.html)
Hello, what about shorter way to express booleans?
Booleans are very nice concept, but can get bulky. That is why people may avoid using it, sometimes. Moreover, booleans are often put inside nice "traity" names like isRetired or done which are nice in constructs like if (!retired) {...}. It would be nice if they could be declared using shorter, more natural way (more descriptive) instead of using explicit true and false value assignment (imperative). Booleans have some instrinsic non-imperative, descriptive feel, so I'd like to be able to express it.
In literals. In literals, let it be possible to use not only foo:true and baz:false productions (comma-terminated except the very last one), but also simplified foo and !baz productions. This will allow for example this nice thing:
Object.defineProperty(foo, "id", { value: "Moo", !enumerable, configurable, writable });
By this I have stolen ! character from Allen Wirfs-Brock's use in literal extension ( harmony:concise_object_literal_extensions ), but I believe ! is associated with boolean not and this use would be more fit for it. Literals created this way (if booleans have "traity" names) are shorter and naturally readable, so if this would be accepted for literals only, it would be nice. Though I can envision the use of this in the rest of boolean-value-assignment contexts, like:
In variable declarations. In variable declaration it would be nice if instead of var done = false; it could be simply put that var !done;. I am not proposing this for general assign (it would be awkward), only for initialization in declaration.
This brings a sad assymetry that I can not use similar streamlined var soFarSoGood; instead of var soFarSoGood = true;. false have its shortcut initalization, and true does not? I do have a workaround proposal for this, though it it less nice, but it is an idiom known to all Javascripters with some experience. Let us allow use var !!soFarSoGood; as well. It can then be used as a shortcut true if developer sees it fit for the situation.
The above paragraphs should of course hold for let and const declarations, as well.
In classes. In classes (that is, in their prototypes, which are outlined by class {...} block) the use of booleans is not very common, but for the sake of orthogonality and not creating special cases (it is a curly block, too, same as object literal and code block), let it be used in public declaration akin to var above. This can allow for example creating Smalltalkish isDuckType constructs like this:
class Animal { public !!isAnimal; ... });
class Ape extends Animal { ... });
class Human extends Ape { public !isAnimal; public !!isPerson; ... });
(not that it is a great use-case, but just to show there is some; I would propose it even if I knew of none, not to create differences between {...} constructs.)