Thanks, Francesco. I'll definitely take a look at those resources. Nathan Davis
On Tuesday, September 22, 2015 at 4:31:07 PM UTC-5, Francesco Bellomi wrote: > > Thanks for taking the time to write such a detailed answer, I really > appreciated it. > > Delimited continuations are useful since they return a value, and thus may > be reused and composed, and used to build complex control mechanisms. > > In my opinion the coolest use of delimited continuations are Effects > > http://math.andrej.com/wp-content/uploads/2012/03/eff.pdf > > a way to separate pure computations and side effects that is more > intuitive and more composable than monads. > > Brandon Bloom has written a (prototype) implementation of effect handlers > for clojure, based on the core.async CPS machinery > > https://github.com/brandonbloom/cleff > > Francesco > > > > > On Tue, Sep 22, 2015 at 10:19 PM, Nathan Davis < > nda...@positronic-solutions.com <javascript:>> wrote: > >> On Tuesday, September 22, 2015 at 6:37:13 AM UTC-5, Francesco Bellomi >> wrote: >>> >>> Hi Nathan, >>> >>> I think it's an awesome project, thanks for sharing this. >>> >>> >> Thanks. I appreciate the feedback. >> >> >>> I see that currently only full continuations are supported. Would it be >>> possible/feasible/easy to support delimited continuations? (ie. with ranges >>> different from the outermost CPS context) >>> >>> >> I haven't done much research into delimited continuations yet, so my >> understanding may be wrong. However, here's my analysis of the current >> situation. >> >> As currently implemented, pulley.cps uses "sort of" full continuations. >> I say "sort of" because continuations are implicitly limited by the >> trampoline. So anytime a new trampoline is introduced (i.e., you call CPS >> code from a non-CPS function), the continuation is limited to that >> trampoline. However, there is currently no way to explicitly delimit the >> continuation. >> >> In light of the above, it seems to me that *reset(f)* could be >> implemented as simply as a non-CPS function that invokes the (presumably >> CPS'd) function *f*. I don't think this would be the ideal >> implementation, but it does seem to suggest it is at least possible. >> >> I'd be interested in hearing from you (and others) what use-cases you see >> for delimited continuations. The overviews of the topic I've seen so far >> seem to neglect this entirely or only address it abstractly. A few >> concrete examples would be a useful "jump-start". >> >> Also, it would be interesting to have a comparison with core.async's CPS >>> machinery: is pulley.cps expected to be more efficient performance-wise? Is >>> it implemented using similar or comparable techniques? >>> >>> >> core.async handles continuations as a state machine. On the other hand, >> pulley.cps implements continuations via closures. The two representations >> are isomorphic, so theoretically anything you can express in one you can >> express in the other. However, state machines (at least as implemented in >> core.async) must be constructed with complete knowledge of all the possible >> states involved. Since *go*-blocks are implemented via macro, and >> macros are limited to local transformations (and analysis), continuations >> (state transitions) within core.async are limited to the same *go*-block. >> >> In contrast, closures can come from different functions or even >> namespaces. So continuations in pulley.cps can cross local boundaries. >> That is, even though pulley.cps transforms code blocks in isolation, >> closures allow these blocks to coordinate and participate in the CPS >> protocol. >> >> This has some practical ramifications. For example, you can't compose >> *go*-blocks the same way you compose regular functions. In fact, you >> can't call a function in a *go*-block and, within that function, suspend >> the *go*-block. You can of course compose core.async processes, but it >> has a distinct look and feel from function composition. >> >> On the other hand, functions transformed by pulley.cps compose just like >> regular functions — because they are functions. In the examples directory, >> there is an implementation of a cooperative multitasking engine. Unlike >> core.async, you can suspend tasks from pretty much any function. There are >> still some limitations, but these are dynamic as opposed to static, and >> have to do with what I said previously about continuations being implicitly >> delimited. >> >> As far as performance goes, I haven't directly compared core.async to >> pulley.cps code yet, but I fully expect core.async to be a hands-down >> winner at this point. core.async is more mature and has had more >> performance tuning than pulley.cps. I have done some limited benchmarking >> against regular clojure code. All I can say is that for compute-intensive >> code with tight loops in CPS code, pulley.cps performs pretty poorly. You >> can expect a CPS version of such code to be 1 to 2 orders of magnitude >> slower than a non-CPS version. >> >> Interestingly, in included benchmark.clj (which benchmarks a few ways of >> computing the factorial function), one of the CPS implementations actually >> out-performed the non-CPS equivalent implemented via *loop* on OpenJDK 7 >> for large n. While for large n there is less time spent in CPS code and >> more time doing the actual multiplication, it is an interesting result >> because it means there was apparently some optimization it was able to >> perform on the CPS code that it wasn't able to do on the *loop* verion. >> On OpenJDK 8, the CPS code is consistently slower in all cases (though, as >> expected, the slow-down decreases as n increases). >> >> >>> thanks, >>> Francesco >>> >>> >>> >>> >>> On Monday, September 21, 2015 at 9:24:20 PM UTC+2, Nathan Davis wrote: >>>> >>>> I'm pleased to annouce the release of verion 0.2.0 of pulley.cps >>>> <https://github.com/positronic-solutions/pulley.cps>. pulley.cps is a >>>> macro-based source-to-source transforming compiler that transforms Clojure >>>> code into Continuation Passing Style (CPS), as well as a supporting >>>> run-time library. >>>> >>>> >>>> The main feature of this release is the addition of exception support — >>>> you can now use try, throw, and catch just like you would in regular >>>> Clojure code. There are various other enhancements as well, mostly to >>>> support the exception code, as documented in the changelog. >>>> >>>> >>>> Nathan Davis >>>> >>>> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clo...@googlegroups.com >> <javascript:> >> Note that posts from new members are moderated - please be patient with >> your first post. >> To unsubscribe from this group, send email to >> clojure+u...@googlegroups.com <javascript:> >> For more options, visit this group at >> http://groups.google.com/group/clojure?hl=en >> --- >> You received this message because you are subscribed to a topic in the >> Google Groups "Clojure" group. >> To unsubscribe from this topic, visit >> https://groups.google.com/d/topic/clojure/ugnV06e0Vlo/unsubscribe. >> To unsubscribe from this group and all its topics, send an email to >> clojure+u...@googlegroups.com <javascript:>. >> For more options, visit https://groups.google.com/d/optout. >> > > > > -- > Francesco Bellomi > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.