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

add a macro to ease the use node.js callbacks? #56

Open
darrencruse opened this Issue Mar 28, 2015 · 0 comments

Comments

Projects
None yet
1 participant
@darrencruse
Contributor

darrencruse commented Mar 28, 2015

Was just playing with a little example of walking file directories asyncronously with node.js and it struck me lispyscript might be well positioned to simplify/hide/eliminate the use of callbacks...

I actually tried it out with a little macro and was delighted with how easy lispyscript made it (i'd been playing with generators recently and this was remarkably simple by comparison!!).

Here's my original function in lispyscript using callbacks:

(var fs (require 'fs'))

(function walk (rootDir)
  (fs.readdir rootDir (function (err files)
    (each files (function (file)
      (do
        (var filePath (str rootDir '/' file))
        (fs.stat filePath (function (err stats)
          (if (stats.isDirectory)
            (do
              (console.log 'directory:' filePath)
              (walk filePath))
            (console.log filePath))))))))))

(walk '.')

Here's the same code with a little "await" macro (which I show further down):

(var fs (require 'fs'))

(function walk (rootDir)
  (await files (fs.readdir rootDir)
    (each files (function (file)
      (var filePath (str rootDir '/' file))
      (await stats (fs.stat filePath)
        (if (stats.isDirectory)
          (do
            (console.log 'directory:' filePath)
              (walk filePath))
          (console.log filePath)))))))

(walk '.')

And here's the little "await" macro:

(macro await (result asynccall rest...)
  (~@asynccall (function (err ~result)
    ~rest...)))

As I mentioned above - I was delighted the above macro was so short and actually worked perfectly on the first try!!

I was trying to think if the same macro could work with both callback taking functions and promise-returning functions without the programmer having to use a different macro.

I couldn't think of any way - please others comment if somebody sees a way.

As it is I could easily see their being an "awaitp" for "await promise" as a sister to the above?

Also I obviously have ignored errors in the above I need to correct that. I thought I would have the macro include code to throw the received "err" parameter if it gets one.

    edit:  I had a feeling I was going to look like an idiot for writing the above...
I know exception handling is broken with async callbacks but I keep having 
selective memory wanting it not to be true...  I guess the "handle the err yourself" 
option below should really should be the only option where node callbacks are used(?)  
But something nicer could/should be done where promises or generators are involved.  
Nice article about such things fwiw:  
    https://strongloop.com/strongblog/comparing-node-js-promises-trycatch-zone-js-angular/

But maybe there should be a way to handle the err parameter yourself if you want to... The ideal syntax to me would look like destructuring assignment:

So this if you want to handle the err yourself:

  (await (err files) (fs.readdir rootDir) 

This if you want it to throw if there's an error:

  (await files (fs.readdir rootDir) 

Would that be doable I wonder?

(still learning the finer points of macros - seems to me the above implies in my macro I need some logic distinguishing what form I've gotten as the first "result" argument to the macro. I don't know how to do that ATM).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment