Sorry for being lazy, but can you post an example or two? This is a feature I will definitely try out. One of the unwanted weaknesses of my code on the JS side is the inability to get out of a top level function from inside a lambda.
On Sat, Nov 13, 2010 at 2:11 PM, Vladimir Sedach <[email protected]> wrote: > I just pushed a patch that tries to do the right thing with both > lexical and dynamic-extent BLOCK (including implicit BLOCK forms) and > RETURN-FROM. It's also supposed to provide backwards-compatibility > with the old-style RETURN behavior (although that does issue a > warning). > > The big thing is that right now in most of the interesting cases it > does the control jump, but does not return a value. That will be fixed > in future patches. > > I haven't really tested it, so try it out and let me know what breaks. > > Vladimir > > 2010/8/18 Daniel Gackle <[email protected]>: > > I like your suggestion of emitting TRY/CATCH only in the cases where > > it's necessary, i.e. only when trying to escape out of more than one > > level of function nesting, seems like a good way to go. Then you're > > only paying for the ugliness when you need it. It's in keeping with > > PS's philosophy of staying close to what one would write by hand. > > > > On Wed, Aug 18, 2010 at 6: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 > > > > > > _______________________________________________ > 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
