Jules Jacobs
Posts: 119
Nickname: jules2
Registered: Mar, 2006
|
|
Re: Lexical Scope of Java Inner Classes and Closures
|
Posted: Jun 10, 2007 12:25 PM
|
|
> @Jules, > > Hope you are still listning because I have a question for > you, would the Scheme/Ruby equivalent of this behave as > indicated below: > > > callcc method( continuation ) {
> out.println "Outer";
> callcc method( continuation ) {
> out.println "Inner";
> continuation.call;
> out.println "Not reached"
> }, continuation;
> out.println "Back to outer"
> }, method {
> callcc.return
> };
>
> > In particular, there is a recursive call to callcc and the > continuation exits the inner only, not the whole lot. Is > that what other languages would do?
Well, callcc takes only one parameter.
callcc do |continuation|
print "Outer"
callcc do |continuation|
print "Inner"
continuation.call
print "Not reached"
end
print "Back to outer"
end
This should print Outer, Inner, Back to outer, so the continuation.call jumps to the end of the inner block.
However, your exception-based callcc is far less powerful than a real callcc, because you can only go up the stack using exceptions. You can also jump back to functions that have already returned using callcc.
A continuation contains local variables (like a closure), and the return stack. "return"-stack is a wrong name because the return stack doesn't contain the places to return to, but the places to go next: it's a todo-list. This todo-list is saved in a continuation. When you call it, the current stack is replaced with the stack stored in the continuation. By calling a continuation we can replace the stack with a new stack, possible getting a bigger or completely different stack. With exceptions you can only go up the stack (removing items from it).
A way to think about it:
callcc do |return|
// if we do return.call(...) we jump to
end // <-- here, and we return the value passed to call(...)
// So:
x = callcc do |return|
return.call(3)
end
// x = 3 now
And an infinite loop:
x = callcc do |return|
return
end // x.call(something) goes to the end of this block, and puts something into x
puts "hi"
x.call(x) // go back to the end of the callcc block, putting x back into x again.
// If we just used x.call(), then x would contain nil (null) on the next run, because x.call() is equivalent to x.call(nil).
Callcc() returns multiple times in this example (the return value is assigned to x). x.call() returns from the callcc() again. Yes, it's weird.
But is it clear?
Common Lisps condition system is interesting because it's more powerful than exceptions, and less powerful than continuations. When throwing an exception in CL we don't remove items from the stack yet: we leave them in place. This allows us to return to the point where we threw the exception in the exception handler. We cannot go back to a function that has already returned, however.
|
|