Sage / streamlinejs

Asynchronous JavaScript for dummies

Home Page:http://bjouhier.wordpress.com/2011/01/09/asynchronous-javascript-the-tale-of-harry/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

default value for _ parameter

bjouhier opened this issue · comments

Submitted by @SGrondin in #182:

Somewhat unrelated, but I'd really love to be able to do (arg1, arg2, _=->) -> in coffeescript, basically putting a default argument for those times when the Node API functions (and 3rd party code) don't pass a callback.

For example, doing this:

http.createServer (req, res, _=->) -> ...

instead of

handler = (req, res, _) -> ...

http.createServer (req, res) ->
    handler req, res, ->

That's amazing!

It's huge in terms of usability and readability.

Not done yet. I just reposted here.

It's a bit tricky because I have to analyze the code which is generated by CoffeeScript.

I prepared a unit test for it and started to investigate but unfortunately it isn't trivial to implement.

The problem is that streamline is putting a wrapper around every function that it transforms and the falsy callback values are intercepted by this wrapper. Then, when the function body is called, the _ == null test is always false because the callback has already been intercepted by the wrapper.

So I'd need to rewrite all the functions that have initializers as follows:

function fn(a, _) {
  if (_ == null) { _ = function() {} }
  // rest of the body
}

becomes:

function fn(a, cb) {
  if (cb == null) { arguments[1] = function() {} }
  return fn__.apply(this, arguments);
  function fn__(a, _) {
    // rest of the body
  }
}

and then I can apply the streamline transform.

This is not impossible but it is a lot more work than I thought. Stay tuned.

Was a bit challenging but it seems to work (only in callbacks mode for now):

fn = (a=1, b, _=(e, r) -> console.log r) -> 
  console.log "hello"
  "world: a=" + a + ", b=" + b

fn()

produces:

hello
world: a=1, b=undefined

That's absolutely perfect. It'll make code that interacts with 3rd party modules A LOT more powerful and readable. I think it'll be worth mentioning this feature in the README. I know I had some head scratching moments looking for a way to go around the "Missing _" error until I realized I had to do the "handler trick". I'm sure I'm not the only one who had that problem. Thank you very much.

I would nevertherless recommend to avoid:

fn = (a, b, _ =->)

and use instead:

fn = (a, b, _ = (e) -> throw e if e)

in public APIs. An alternative would be to pass a global error handler that people can set in your library.

Amending what I just wrote: this feature should not be used for public APIs because it would conflict with promises.

On the other hand it is very handy when registering callbacks written with streamline into non-streamline APIs, and in this case you should probably report errors rather than ignore them silently.

100% agree. Thanks for your wonderful work on Streamline, as always.

Thanks @SGrondin
I implemented generators mode. Fibers mode should follow quickly but I'm taking a break 😄

There was a nasty bug in callbacks mode. Should be ok now.

Note: this feature is not supported in fast modes.