Hacker News new | past | comments | ask | show | jobs | submit login
Promises and Lisp (lisper.in)
50 points by chaitanya on Dec 23, 2014 | hide | past | favorite | 18 comments



Debugging is a bit of a challenge with promises.

Indeed, and that is why I am personally not really that bullish on promises, at least not how they are currently implemented. When you're debugging you want access to the implicit state-machine that the promise statement constructed, but at least in JS such state is hidden away in the `then()` function.

A good compromise (which I'm currently exploring in JS) is to make the state-machine navigable from the root, giving you the ability to examine it and mutate it explicitly during a debug session.


Libraries like bluebird will give you pretty stack traces that track the sequence of then calls, almost as if it was a single sequential execution. This helps with debugging.

Alternatively you can use the yield-spawn method of getting rid of then() altogether. Then you get code that looks sequential as well, and the browser gives you nice stack traces.

This doesn't help with modifying values during debugging as you mentioned, but it does solve the problem of seeing the "caller" stack frames.


> A good compromise (which I'm currently exploring in JS) is to make the state-machine navigable from the root, giving you the ability to examine it and mutate it explicitly during a debug session.

You might also want to check out the JS library q, which has support for stack traces that span async jumps if a promise errors out https://github.com/kriskowal/q#long-stack-traces


I would not recommend new projects to use Q when Bluebird exists. The latter is better in every way - perf, features and tracking the ES6 Promise API more closely.


Thanks. I had not heard about Bluebird before.


Congratulations, you have almost invented Monads! 8)


I have been told, albeit not part of the core, Haskell is not the first to the party and they most certainly have been monadic CL libs.

http://common-lisp.net/project/cl-monad-macros/monad-macros....

There are some people in the CL community who mention why CL users might not appreciate monads like those in other languages and/or programming styles/disciplines.

(Original) http://marijnhaverbeke.nl/monad.html

(HN Discussion) https://news.ycombinator.com/item?id=7651175


Doesn't async/wait solves the same problem in a more elegant way?


Is this some sort of contorted version of Greenspun's tenth rule?


OP here. I would welcome and feedback or suggestions for the post.


I think you should note in captions that each of your code samples came from Domenic's blog, to be polite. Initially it seems like you sort of lifted the entire first bit of the post.

As far as your Lisp implementation goes, since promises are really just syntactical sugar around continuation passing (not in a bad way), and since both the continuation and the callback are first class, it should be trivial to land on a syntax that is as easy or easier to read than the JavaScript implementation. I think your final implementation hides a bit too much.


> I think you should note in captions that each of your code samples came from Domenic's blog, to be polite.

I actually mention this in a footnote, but I will do what you have suggested to be clearer still.

> it should be trivial to land on a syntax that is as easy or easier to read than the JavaScript implementation. I think your final implementation hides a bit too much.

Can you elaborate how this syntax might look?


Re footnote 4: the Alexandria library has a function 'parse-body' that will be helpful.

Also: I'm not sure it's a good idea to give these macros the same names as the CL builtins. This will require users to do 'shadowing-import' if they want to use them without the package prefix, and then when they want to reference the builtins (in performance-sensitive code, perhaps) they'll have to use an explicit 'cl:'. At the very least, I'd suggest exporting a second set of names also, which are prefixed with "p-" or some such, so people can import them without shadowing.


Package PCL for old people means 'Portable Common LOOPS', the first CLOS implementation... ;-)


> Re footnote 4: the Alexandria library has a function 'parse-body' that will be helpful.

That's nice. I had initially defined LET/LET* using a similar function, but then removed it to keep the macro definitions simpler.

> Also: I'm not sure it's a good idea to give these macros the same names as the CL builtins.

I gave this some thought, and came to the conclusion that using P-LET* is not very different from using PCL:LET*. So the way I envisioned this is that you don't import symbols from the PCL package; just use them with the package prefix. Though not everyone would prefer things this way, so if this was not a toy project I might have done what you suggested.


It would be good to tackle multiple-promises-dependencies that the when()/all() protocols achieve, compared to then().


I avoided it so that the post does not become very long and the main point doesn't get diluted. That said, I do use multiple-promise-depenencies to implement PCL:LET in the accompanying source https://github.com/chaitanyagupta/promises/blob/1.0/pcl.lisp... (ON-PROMISES does the same thing as when()/all()).


think it would also be interesting to compare this approach to other (quasi-) meta-programmatic approach in JS like async.js




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: