Re:Promises and Lisp
by javajosh on Tuesday December 23, 2014 @08:42PM
(#8791161)
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.
Re:Promises and Lisp
by Arnavion on Tuesday December 23, 2014 @09:07PM
(#8791226)
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.
Re:Promises and Lisp
by chaitanya on Tuesday December 23, 2014 @09:00PM
(#8791208)
> 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.
Re:Promises and Lisp
by Arnavion on Tuesday December 23, 2014 @09:15PM
(#8791245)
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.
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.
Re:Promises and Lisp
by debacle on Tuesday December 23, 2014 @05:11PM
(#8790510)
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.
Re:Promises and Lisp
by chaitanya on Tuesday December 23, 2014 @09:03PM
(#8791216)
> 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.
Re:Promises and Lisp
by ScottBurson on Tuesday December 23, 2014 @04:48PM
(#8790414)
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.
Re:Promises and Lisp
by chaitanya on Tuesday December 23, 2014 @10:32PM
(#8791424)
> 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.
Re:Promises and Lisp
by chaitanya on Tuesday December 23, 2014 @10:15PM
(#8791391)
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()).
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.
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.
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
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
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 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?
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.
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.