Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nesting do(s) for nested control flow, is this necessary, is there a better way? #47

Closed
hodonsky opened this issue May 25, 2020 · 8 comments

Comments

@hodonsky
Copy link

hodonsky commented May 25, 2020

I'd much rather use an IIFE here, and yes I do understand the performance implications.

Any thoughts on dropping the required nested 'do' and detecting the statements and expressions independently or would that be too much work on the interpreter?

  fn( item ){
    const id = do {
      switch ( item.constructor ) {
        case Array :
          (do {
            if ( item.length >= 1 && item.length < 3 ){
              (do{
                if ( typeof item[ 0 ] === "string" ){
                  item[ 0 ]

vs

  fn( item ){
    const id = () => {
      switch ( item.constructor ) {
        case Array :
          if ( item.length >= 1 && item.length < 3 ){
            if ( typeof item[ 0 ] === "string" ){
              return item[ 0 ]

I'm throwing specific errors here, so please don't tell me to "just combine your second conditional", I'm asking because there could be other situations I can think of where this could get out of control and make reading code very laborious... even requiring a {> ... } I think would be obnoxious here...

I'm also sure there's probably a good reason it requires nesting, but can it not in the future? Because this would be so very nice:

  fn( item ){
    const id = do {
      switch ( item.constructor ) {
        case Array :
          if ( item.length >= 1 && item.length < 3 ){
            if ( typeof item[ 0 ] === "string" ){
              item[ 0 ]
@ljharb
Copy link
Member

ljharb commented May 25, 2020

Since the entire program could be wrapped in a do expression, if we could do that and wanted to, wed just not require the outer do expressions.

Even if we can, i think the explicit marker at every instance is critical for maintainability.

@hodonsky
Copy link
Author

I guess the same could be said about the 'with' keyword... but no one does that, because it's a ridiculous scenario that no one would ever actually implement. You're suggesting because someone can do something stupid with it, we shouldn't add it as a language feature?

@hodonsky
Copy link
Author

hodonsky commented May 25, 2020

Also, I like how babel is handling this right now...

_createClass(Checkout, [{
    key: "fn",
    value: function fn(item) {
      var id = function () {
        switch (item.constructor) {
          case Array:
            return function () {
              if (item.length >= 1 && item.length < 3) {
                return function () {
                  if (typeof item[0] === "string") {
                    return item[0];
                  } else {
                    throw new TypeError("Invalid tuple id, 0 index argument must be a String");
                  }
                }();
              } else {
                throw new TypeError("Invalid tuple size, must be length of 1 or 2, 0 index argument must be String(id)");
              }
            }();

So basically I'm going back to a single IIFE...

@bakkot
Copy link
Collaborator

bakkot commented May 25, 2020

  fn( item ){
    const id = do {
      switch ( item.constructor ) {
        case Array :
          if ( item.length >= 1 && item.length < 3 ){
            if ( typeof item[ 0 ] === "string" ){
              item[ 0 ]

That should work fine in the current proposal. Specifically, if I write it out a bit:

function fn( item ){
  const id = do {
    switch ( item.constructor ) {
      case Array :
        if ( item.length >= 1 && item.length < 3 ){
          if ( typeof item[ 0 ] === "string" ){
            item[ 0 ];
            break;
          }
        }
      default:
        null;
    }
  };
  console.log(id);
}

then fn(x) will log x[0] when x is an Array* of 1 or 2 whose first item is a string, and will otherwise log null.

* modulo some pedantry about item.constructor not quite checking that

Why would you expect to need the nested dos?

@hodonsky
Copy link
Author

hodonsky commented May 25, 2020

@bakkot Well it doesn't transpile correctly in babel at least... but yeah I thought so too.

It's not an expectation, it's what I had to do to that code to get it to work correctly.

@bakkot
Copy link
Collaborator

bakkot commented May 25, 2020

Babel's do expression transform has a bug, then. Not too surprising, since this is a very early stage proposal.

Edit: opened babel/babel#11608. Would you close this issue, since it seems like the specified behavior is the one you want?

@hodonsky
Copy link
Author

@bakkot How helpful... thank you. I thought it might be something like that because they had a switch bug for a while last year I think around June but when I started working with wrapped statements I was like "OH NOOooo is this how it's supposed to be?"

Cool thank you. I will not lose hope in 'do'!

I should report this in babel's plugin then huh?

@bakkot
Copy link
Collaborator

bakkot commented May 25, 2020

I should report this in babel's plugin then huh?

Already done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants