Andreas Rossberg (2015-07-14T15:59:38.000Z)
On 14 July 2015 at 16:48, Mark S. Miller <erights at google.com> wrote:

> On Tue, Jul 14, 2015 at 2:31 AM, Andreas Rossberg <rossberg at google.com>
> wrote:
>
>> I don't see why you need parens at all, see my previous post. But I
>> wouldn't make the do-less forms the base syntax,; rather, only short-hands
>> for the general thing. In particular, because the ability to have an actual
>> block inside an expression is one primary motivation for having
>> do-expressions in the first place.
>>
>
> Ah. Take a look at my full proposal. The bizarre observation is that
> extending the syntax of parens to contain approx a block-body, and
> extending its meaning to creating a block-like scope for evaluating that
> block-body, in addition to returning a value. In that case, we simply don't
> need the "do" expression at all. Don't propose something unnecessarily
> complex just because you expect that something simpler would be too
> controversial. If it actually is too controversial, that's another matter.
>

I would very much dislike introducing a second syntax for blocks, though --
which is essentially what you are suggesting. Especially when curly braces
provide a much better visual clue for the extent of a scope than innocent
plain parens do. It's the natural expectation for a C-like language, too.

In the design of any modern language the whole notion of block of course is
totally obsolete. But JavaScript has its C heritage, and I doubt bolting on
something alien would make it a prettier language.

...Ah, it's 2015, and we still have to come up with ways to overcome the
>> archaic statement/expression distinction from the stone ages. :)
>>
>
> Between Gedanken, Smalltalk, and Actors, almost everything we do in oo
> dynamic language design was already conceived right by the early '70s.
> Retrofitting without breaking things takes much longer than invention ;)
>

Well, statements vs expressions was already found unnecessary before OO, in
the early 60s -- consider Algol 68. (Let alone Lisp, which is late 50s.)

/Andreas


On 14 July 2015 at 01:33, Mark S. Miller <erights at google.com> wrote:
>>
>>> Interesting. Got me thinking. Here's an alternate proposal I'll call "do
>>> expressions without the 'do'."
>>>
>>> At <
>>> https://people.mozilla.org/~jorendorff/es6-draft.html#sec-expression-statement>
>>> we have the syntax of the expression statement. Ignoring sloppy "let"
>>> nonsense, this says that an expression statement cannot begin with "{",
>>> "function", or "class".
>>>
>>> At <
>>> https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-language-statements-and-declarations>
>>> are the legal ES6 statements. Note that most of these begin with a keyword
>>> that cannot possibly be legal at the beginning of an expression. Therefore,
>>> adding all these initial-statement-keywords to the list of things that
>>> cannot begin an expression statement would break nothing. They already
>>> cannot begin an expression statement.
>>>
>>> With the expression statement prohibition in place, now we can allow all
>>> these forms to be expressions. As with "{", "function", or "class", if you
>>> want to state such an expression in expression-statement position, surround
>>> it with parens.
>>>
>>> Because all these new forms will look bizarre and confusing, at least at
>>> first, let's say these always need surrounding parens to be expressions. I
>>> think that would help minimize confusion.
>>>
>>> If we do this, the oddest duck is "{", since it begins an object literal
>>> expression. This proposal gives us no straightforward way to express an
>>> block expression. "function" and "class" are less odd, since their existing
>>> expression forms mean what you almost might expect by this new rule -- even
>>> though they are initial-declaration-keywords rather than
>>> initial-statement-keywords.
>>>
>>> The remaining initial-declaration-keywords are "let" and "const". We
>>> already made "let" insane regarding these issues in sloppy mode, so I'm
>>> going to ignore that. But let's consider "const" and strict "let". These
>>> already cannot appear at the beginning of an expression, so it would not
>>> break anything to add them to the prohibition list for the beginning of
>>> expression statements.
>>>
>>> No current expression can add any binding to the scope in which the
>>> expression appears. Let's examine the consequences of having parens --
>>> rather than containing a "{"-block to create a nested scope with a value
>>> (which would conflict with object literals), instead simply define a
>>> block-like nested scope with a value. This would allow declarations and
>>> statements within the parens, much like the current "do" proposal. It would
>>> even be consistent enough with the existing semantics of paren-surrounded
>>> function and class expressions: Someone who sees these as a function or
>>> class declaration within its own nested scope, whose value was the value
>>> being declared, would rarely be surprised by the subtle difference between
>>> that story and the current semantics.
>>>
>>> Having parens accept a list of declarations and statements rather than
>>> just an expressions seems like a radical change that must break something,
>>> but I can't find a problem. Am I missing something?
>>>
>>> Examples inline:
>>>
>>>
>>>
>>> On Mon, Jul 13, 2015 at 5:47 PM, Isiah Meadows <impinball at gmail.com>
>>> wrote:
>>>
>>>> I was reading a recent thread
>>>> <https://esdiscuss.org/topic/allow-try-catch-blocks-to-return-a-value> where
>>>> do-expressions simplified a common try-catch use case, and I was wondering
>>>> if `do` could be simplified to an expression? It would allow for this to be
>>>> solved very easily, but also add a lot more flexibility in this proposal,
>>>> as well as avoiding some ugly nested braces.
>>>>
>>>> I know it would cause an ambiguity with `do-while` loops, but that
>>>> could be resolved with a single token lookahead of "if the next token is
>>>> the keyword `while`, then the block body is the body of a do-while loop,
>>>> else it is the body of the block statement in a `do` expression".
>>>>
>>>> As for the EBNF, do-expressions could be parsed with a goal symbol of
>>>> either `+While` or `-While`, with do-while statements spec-wise effectively
>>>> being treated as do-expressions without an init part run repetitively, but
>>>> mandated to be statements.
>>>>
>>>> ```js
>>>> // Do expression
>>>> let foo = do {
>>>>   foo(0)
>>>> };
>>>>
>>>
>>> let foo = (foo(0));
>>>
>>> This seems as broken as the original. In both cases, unless I'm missing
>>> something, this is a TDZ violation when the right side evaluates foo.
>>> Mistake?
>>>
>>>
>>>>
>>>> let tried = do try {
>>>>   foo(0)
>>>> } catch (e) {
>>>>   throw e
>>>> };
>>>>
>>>
>>> let tried = (try { foo(0) } catch (e) { throw e });
>>>
>>>
>>>
>>>>
>>>> // Do-while statement
>>>> let i = 0;
>>>> do {
>>>>   foo(i)
>>>> } while (i++ < 10);
>>>>
>>>> // Combined:
>>>> let i = 0;
>>>> let foo9 = do do {
>>>>   foo(i) // can have side effects, foo9 = foo(9)
>>>> } while (i++ < 10);
>>>> ```
>>>>
>>>
>>> let i = 0;
>>> let foo9 = (do { foo(i) } while (i++ < 10));
>>>
>>>
>>>
>>>>
>>>> Another example of where this could come in handy: simplifying
>>>> asynchronous code.
>>>>
>>>> ```js
>>>> function readConfig() {
>>>>   fs.readFileAsync('config.json', 'utf8')
>>>>     .then(JSON.parse)
>>>>     .then(contents => do if (contents.unexpectedProperty) {
>>>>       throw new Error('Bad property') // rejects the promise
>>>>     } else {
>>>>       doSomething(contents)
>>>>     })
>>>>     .catch(err => process.domain.emit('err', error))
>>>> }
>>>>
>>>
>>> ...
>>> .then(contents => (if (contents.unexpectedProperty) {
>>> ...
>>> }))
>>> ...
>>>
>>>
>>>>
>>>> // With only block statement
>>>> function readConfig() {
>>>>   fs.readFileAsync('config.json', 'utf8')
>>>>     .then(JSON.parse)
>>>>     .then(contents => do {
>>>>       if (contents.unexpectedProperty) {
>>>>         throw new Error('Bad property') // rejects the promise
>>>>       } else {
>>>>         doSomething(contents)
>>>>       }
>>>>     })
>>>>     .catch(err => process.domain.emit('err', error))
>>>> }
>>>>
>>>> // Without do-expressions
>>>> function readConfig() {
>>>>   fs.readFileAsync('config.json', 'utf8')
>>>>     .then(JSON.parse)
>>>>     .then(contents => {
>>>>       if (contents.unexpectedProperty) {
>>>>         throw new Error('Bad property') // rejects the promise
>>>>       } else {
>>>>         doSomething(contents)
>>>>       }
>>>>     })
>>>>     .catch(err => process.domain.emit('err', error))
>>>> }
>>>> ```
>>>>
>>>> As you can see, the more general version does simplify things a little.
>>>>
>>>> Also, if-statements look better than long ternaries IMHO, and are less
>>>> repetitive than their counterpart, repeated assignment (us lazy typists...):
>>>>
>>>> ```js
>>>> let foo = do if (someCondition) {
>>>>   value
>>>> } else if (someOtherCondition) {
>>>>   value + 1
>>>> } else if (someEdgeCase) {
>>>>   addressEdgeCase(value)
>>>> } else {
>>>>   value
>>>> }
>>>> ```
>>>>
>>>
>>> let foo = (if (someCondition) {
>>> ...
>>> })
>>>
>>>
>>>
>>>>
>>>> --
>>>> Isiah Meadows
>>>>
>>>> _______________________________________________
>>>> es-discuss mailing list
>>>> es-discuss at mozilla.org
>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>
>>>>
>>>
>>>
>>> --
>>>     Cheers,
>>>     --MarkM
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>>
>>
>
>
> --
>     Cheers,
>     --MarkM
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150714/a25cfc4a/attachment-0001.html>
d at domenic.me (2015-07-25T02:53:51.472Z)
On 14 July 2015 at 16:48, Mark S. Miller <erights at google.com> wrote:

> Ah. Take a look at my full proposal. The bizarre observation is that
> extending the syntax of parens to contain approx a block-body, and
> extending its meaning to creating a block-like scope for evaluating that
> block-body, in addition to returning a value. In that case, we simply don't
> need the "do" expression at all. Don't propose something unnecessarily
> complex just because you expect that something simpler would be too
> controversial. If it actually is too controversial, that's another matter.

I would very much dislike introducing a second syntax for blocks, though --
which is essentially what you are suggesting. Especially when curly braces
provide a much better visual clue for the extent of a scope than innocent
plain parens do. It's the natural expectation for a C-like language, too.

In the design of any modern language the whole notion of block of course is
totally obsolete. But JavaScript has its C heritage, and I doubt bolting on
something alien would make it a prettier language.

> Between Gedanken, Smalltalk, and Actors, almost everything we do in oo
> dynamic language design was already conceived right by the early '70s.
> Retrofitting without breaking things takes much longer than invention ;)

Well, statements vs expressions was already found unnecessary before OO, in
the early 60s -- consider Algol 68. (Let alone Lisp, which is late 50s.)