On Tue, Jul 14, 2015 at 10:59 AM, Andreas Rossberg <[email protected]> wrote:
> On 14 July 2015 at 16:48, Mark S. Miller <[email protected]> wrote: > >> On Tue, Jul 14, 2015 at 2:31 AM, Andreas Rossberg <[email protected]> >> 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. > I can see that. I'm torn. > > 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.) > For that part specifically, sure. Gedanken also had full indefinite extent lexical closures. It might have been the first to do so -- Lisp was dynamically scoped at the time and Actors had not yet been invented. I've always been puzzled why Gedanken has not gotten more attention -- especially since it was mainly by John Reynolds. Check it out -- you'll be impressed. > > /Andreas > > > On 14 July 2015 at 01:33, Mark S. Miller <[email protected]> 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 <[email protected]> >>>> 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 >>>>> [email protected] >>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>> >>>>> >>>> >>>> >>>> -- >>>> Cheers, >>>> --MarkM >>>> >>>> _______________________________________________ >>>> es-discuss mailing list >>>> [email protected] >>>> https://mail.mozilla.org/listinfo/es-discuss >>>> >>>> >>> >> >> >> -- >> Cheers, >> --MarkM >> > > -- Cheers, --MarkM
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

