\nfun make_foo() {\n try {\n lambda(){ raise Error; }\n } catch (Error) {\n print("Error caught in make_foo!");\n }\n}\n\nfun main() {\n try\n let foo = make_foo();\n foo();\n catch (Error) {\n print("Error caught in main!");\n }\n}\n
In a conventional exception system, running main() would result in foo() throwing an error that would be caught in main, and the message that main prints would be "Error caught in main!". This is dynamic scoping -- the exception handler chosen is the nearest enclosing handler live on the call stack. I'd like to try a lexically scoped exception system. In this version, the exception thrown in foo() would be caught by the lexically-enclosing exception handler -- that is, the one in make_foo(). So the printed message would be "Error caught in make_foo!"
As it happens, a lexical discipline offers more powerful control flow than a dynamic one (you can write call/cc with it!!), but it is also easier to analyze in a modular way. But this isn't the whole story. To make such a system really useful to the programmer, you still need a type language that can express differing sets of exceptions concisely and precisely, and that's a hard problem: the two needs are at cross-purposes. But the lack of such is what makes Java's checked exceptions mostly useless.