Awesome! _Nick_
On Wed, Aug 18, 2010 at 5:14 AM, Red Daly <[email protected]> wrote: > Sorry, I forgot the link. See > > http://github.com/gonzojive/parenscript/commit/d8ebace1bcd60a57470d7a8cf0d4e351b7645e8e > for the commit that adds this. > > My Parenscript branch is now pretty much in sync with the main branch, > with only 2 mostly cosmetic test failures > > Red > > On Wed, Aug 18, 2010 at 5:12 AM, Red Daly <[email protected]> wrote: > > I added RETURN-FROM and BLOCK without too much effort using the > > implicit return functionality and try/catch. In my view this is the > > most reasonable way to implement this in the general case, since > > BLOCK/RETURN-FROM require non-local exit much in the same way that > > lisp's TRY/CATCH do. > > > > The alternative to this approach is to exit from each function in the > > call stack via a Javascript `return' statement. Unfortunately, the > > call stack can contain many functions code over which the Parenscript > > compiler exerts little control, requiring throw as the control > > transfer mechanism. Thus, in the general case of unknown code on the > > call stack, there is no means to exit without a throw. I do not view > > throwing as an ugly solution at all, since try/catch was designed for > > non-local exits of all sorts. > > > > Nonetheless, using try/catch to implement Parenscript features > > deserves some attention. Programs will need to ensure that they do > > not use try/catch in a way that interferes with the Parenscript > > convention. Generally, try/catch blocks should only catch specific > > exceptions and re-throw PS's exceptions. I'm happy to also implement > > a safe TRY/CATCH wrapper that re-throws Parenscript errors and catches > > everything else, too. However, we may want to make an official > > interface change to try/catch if any lisp-style non-local exit code > > becomes part of the language. > > > > I present an example of why try/catch is unavoidable inline below: > > > > On Fri, Apr 9, 2010 at 3:42 PM, Vladimir Sedach <[email protected]> > wrote: > >> Makes sense to me. I'll add this to my todo list (which I'll publish > >> in an email as soon as I'm done my current work on the PS compiler). > >> > >> Vladimir > >> > >> 2010/4/9 Daniel Gackle <[email protected]>: > >>> I just pushed a patch (authored by Scott) to implement JS's LABEL and > BREAK > >>> in PS. (Note that this patch deprecates LABELED-FOR since you can get > the > >>> same effect by combining LABEL and FOR. Was anybody using LABELED-FOR?) > >>> Here's an example: > >>> (label scope > >>> (foo) > >>> (when (bar) > >>> (break scope)) > >>> (blee)) > >>> => > >>> scope: { > >>> foo(); > >>> if (bar()) { > >>> break scope; > >>> }; > >>> blee(); > >>> }; > >>> I was astonished to discover recently that JS has supported this > ability all > >>> along in the form of labeled statements and labeled breaks. I'd always > >>> assumed that to get explicit returns from an arbitrary scope, you'd > have to > >>> resort to the ugly hack of muscling TRY/CATCH to do it, thinking that > this > >>> was the closest JS counterpart. > >>> (See http://news.ycombinator.com/item?id=793092 for a thread in which > >>> several people believe this.) But it appears we were all wrong. > >>> What's not clear yet is how far this can be taken. Can you use it > inside a > >>> nested local function to return immediately from the top-level > function? > >>> That is one thing I've wanted for a long time. > >>> In the ideal case, LABEL/BREAK could be used as a base for implementing > a > >>> proper BLOCK and RETURN-FROM in PS, something which we'd long believed > to be > >>> impossible. One challenge is that in CL, RETURN-FROM can take a value, > which > >>> becomes the value of BLOCK. In other words, BLOCK in CL is an > expression > >>> while LABEL in JS is not. It seems, though, that most of this challenge > has > >>> already been conquered with the development of implicit return in PS. > The > >>> only thing you'd need to add is detecting when BLOCK is being used as > an > >>> expression, declaring a gensymed variable and assigning whatever is > >>> happening inside BLOCK to that variable (much like implicit return > already > >>> does with e.g. CASE), then put the variable in the expression position > that > >>> BLOCK was in. It seems like this ought to work. It would also make > things > >>> like this possible in PS: > >>> (1+ (case foo > >>> (:eleven 11) > >>> (:twelve 12))) > >>> Vladimir (and everybody), is the above clear? What do you think of it? > > > > As stated above, I think try/catch is the way to go. There is no > > other way to exit a stack of functions in the general case otherwise. > > > > For example, I can write a Javascript function that calls its argument > > infinity times and never returns. > > > > function mapForever(fn) { > > while(true) fn(); > > } > > > > Now consider some parenscript: > > > > (block non-local > > (map-forever > > (lambda () > > (return-from non-local "we got out!")))) > > > > To extricate itself from map-forever, there is no alternative but JS's > > throw statement. > > > > Even if we had the ability to alter every function in the system, it > > would be necessary to inspect nearly every function call's return > > values to properly unwind the stack to the appropriate BLOCK. > > > > Having said all that, there are cases when try/catch is not necessary > > for BLOCK/RETURN-FROM, as you have described. BLOCK should emit code > > according to the contexts in which RETURN-FROM appears. If there is a > > RETURN-FROM inside the same function, BLOCK can use a label for a > > local exit. If RETURN-FROM appears inside a lambda, try/catch is > > necessary (except in cases where you want to optimize this away by > > inspecting how that lambda gets passed around). If there are no > > return-froms, just emit a PROGN. > > > > My solution does not do the local optimization, but it does refrain > > from putting try/catches around code with no return-froms. > > > > > > > > Red > > > >>> Daniel > >>> _______________________________________________ > >>> parenscript-devel mailing list > >>> [email protected] > >>> http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel > >>> > >>> > >> > >> _______________________________________________ > >> parenscript-devel mailing list > >> [email protected] > >> http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel > >> > > > > _______________________________________________ > parenscript-devel mailing list > [email protected] > http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel >
_______________________________________________ parenscript-devel mailing list [email protected] http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
