1. 1

    Since I’m more comfortable in Python than JS, when bash gets hairy I tend to switch to Python and use the subprocess module to invoke commands.

    Is there a standard way to invoke shell commands from within “normal” Javascript (e.g. whatever node.js uses)?

    1. 2

      There’s exec and spawn which can be used from JS/node to execute a shell command. Alternatively, you can run JS from the shell with the -e option in node.

    1. 1

      The reason node doesn’t worry about callbacks is because the issue is going away with ES6 generators. This will be available in 0.12 with the –harmony flag; or you can just use the latest 0.11 unstable.

      Promises work only in a limited number of scenarios and gets ugly pretty quickly; a fairly common use case:

      function authenticate() {
          return getUsername()
          .then(function (username) {
              return getUser(username);
          })
          // chained because we will not need the user name in the next event
          .then(function (user) {
              return getPassword()
              // nested because we need both user and password next
              .then(function (password) {
                  if (user.passwordHash !== hash(password)) {
                      throw new Error("Can't authenticate");
                  }
              });
          });
      }
      

      The problem of callbacks in JS cannot be solved in a library. So they’ve has done the right thing; fix it in the language itself.

      1. 3

        What can’t it be solved in a library? This is how it’s solved in Haskell and Scala, for example.

        1. 1

          Haskell has built in support for monads. And works well with async code. Also see computation expressions in F#. Scala seems to be still debating how to best do async. But they have more tools to attack the problem than JS had.

          1. 3

            What does built-in support mean? If it’s the do-notation, then that’s just syntax, which Scala has (not quite as good, but still). I’m not sure if async in Scala is being debated - you either use scala.concurrent.Future or scalaz.concurrent.Task.

            So I don’t see why JavaScript could not solve it as a library - even if it’s not as capable of abstraction, the “built-in support” seems to be just syntax.

            1. 1

              I have rewritten the code in my first comment using generators, which IMO is cleaner than the one with promises. You can convince me with the Scala equivalent of this:

              function authenticate() {
                  username = yield getUsername();
                  user = yield getUser(username);
                  password = yield getPassword();
                  if (user.passwordHash !== hash(password))
                      throw new Error("Can't authenticate!");
              }
              
              1. 1

                The Scala I write avoids exceptions, so it’d be something like this:

                def authenticate: Future[Boolean] = for {
                  username <- getUsername
                  user <- getUser(username)
                  password <- getPassword
                } yield user.passwordHash != hash(password)
                

                But you’re able to throw an exception, if you really want. Also, the type-signature could be inferred.

                1. 1

                  So will getUser() take a string, as it should? I am not able to tell how execution will suspend at: user <- getUser(username)

                  Forgive my inexperience with Scala.

                  1. 2

                    The type of getUser is String => Future[User] or something similar.

                    1. 1

                      Similar to the do notation. I was saying that this needs to be solved in the language. You are relying on language support to turn it into a callback pyramid; actually the other way around.

                      Add: Two ways you could do this. State machines or like you showed above. You need language support for both these things.

                      1. 2

                        Yes, the problem with Callback Hell is not a syntactic one, though.

                        1. 1

                          Lack of support for the expressiveness demonstrated above is not a syntactic difference.

                          clarifying: I was saying that this requires support in the language. Your example and my example demonstrates the same thing.

                          1. 2

                            While I absolutely agree that JavaScript lacks Scala’s expressive power, what was demonstrated above which is missing?

                            Here’s the desugared version:

                            def authenticate =
                              getUsername.flatMap { username =>
                                getUser(username).flatMap { user =>
                                  getPassword.map { password =>
                                    user.passwordHash != hash(password)
                                  }
                                }
                              }
                            

                            JavaScript has lambdas, what else does it need?

                            1. 1

                              This is the callback pyramid that JS users fear; it becomes a problem real quick.

                              Example, which doesn’t work without extracting ‘….’ into another function and passing it into getAmazonMinOrder():

                              if seller == 'amazon'
                                  get minOrder via async getAmazonMinOrder()
                              else
                                  minOrder = 100
                              .... 
                              ....
                              

                              Hope the example is clear enough. I am going to head out for a bit. Will reply once I’m back.

                              1. 2

                                This is one of the reasons why promises/futures are not callback hell:

                                val minOrder: Future[Int] =
                                  if (seller == 'amazon')
                                    getAmazonMinOrder
                                  else
                                    Future { 100 }
                                

                                We’re working with values, not side-effects. It’s possible to abstract and reuse values.

                                1. 2

                                  I gave you a poor example (and left), I should have used the earlier example itself.

                                  What made your Scala example easy to write is the for comprehension. For a JS version of the same thing, the first snippet I posted is how it looks. The limitation of Promises (in JS) is evident in that example; you get only the last value inside the then() function. The callback pyramid is avoided only in the simpler cases.

                                  I think we are mostly on the same page. The difference is that you use a language in which promises aren’t painful to write, which (probably) shaped your opinion.

                                  bct posts a link below, which proposes a solution in JS. The author of that article calls it ‘then hell’.

                    2. 1

                      Execution does not suspend. It’s creating a Future value.

                2. 1

                  I’m not sure if async in Scala is being debated

                  1. 1

                    Neither of those are used or taken past a few experiments.

            2. 1

              This is an interesting proposal for avoiding that situation.

              Basically: Accept promises as function arguments. Then your example becomes:

              function(authenticate) {
                var userNameP = getUsername();
              
                var userP = getUser(userNameP);
              
                $.when(userP, getPassword(userP)).then(function(user, password) {
                   if (user.passwordHash !== hash(password)) {
                      throw new Error("Can't authenticate");
                   }
                });
              }
              

              You probably want the getX functions to accept non-promise arguments too, so some of the complexity is just moved, but I suspect a library can hide most of it.

              1. 2

                getUser() taking a promise instead of a string is not semantic. We are going to have to ask the question for every function we write; whether it needs to take a promise or a value.

                1. 1

                  In the slides I linked he solves with a library that wraps functions so they can accept either a promise or a value.

                  I don’t know if it’s a good idea, but it’s an interesting one.

            1. 2

              Two weeks to launch an app I’ve been working on over the past year. It lets people define “database tables” and build communities around it. Why would anyone use this? Because many apps such as Flickr, Pinterest are communities around various types of information. Essentially a “Forum platform”.

              Screenshots: http://imgur.com/a/agRne

              Code: https://github.com/jeswin/fora/