Hi
I'd like to propose a change to Clojure's current try-catch syntax.
Currently the syntax is (copied from clojure.org)
(try expr* catch-clause* finally-clause?)
catch-clause -> (catch classname name expr*)
finally-clause -> (finally expr*)
I'd like to propose a change to the catch-clause so that it's possible
to specify different classnames one of which will be caught and its
expr evaluated.
It would be something like
(try ...
(catch SomeException e (println e))
(catch (SomeOtherException OrAnotherException) e
(println "xyz" e))
(finally ...))
In my programming experience I often find that I need to execute the
same code for a few different exceptions but specialized code for some
others and rather than duplicate code (that's why we use lisp right?
no more code duplication!) I thought it would be best that Clojure
support the same.
I saw that it wasn't possible to modify the try syntax from Clojure
itself so I modified the clojure.lang.Compiler file to reflect the
same.
I produced the diff using "svn diff" so patching the same shouldn't be
too hard, I think.
With the new syntax Exceptions can be specified in a List, Vector or a
Set but not a map. The exceptions must be specified explicitly as
they will not be evaluated. So
(try
(foo)
(catch [InterruptedException MalformedURLException] e (dont (do-what-i-say e)))
(catch (ArithmeticException NumberFormatException
NullPointerException) e (do-what-i-mean e))
(catch #{RuntimeException} e)
(catch Exception e (println e)))
are all legal. But
(let [excepts [InterruptedException MalformedURLException]]
(try
(foo)
(catch excepts e (println e))))
will throw an IllegalArgumentException.
Java7 will probably have syntax similar to the above
http://tech.puredanger.com/java7#catch
Cheers
Vijay
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---
Index: src/jvm/clojure/lang/Compiler.java
===================================================================
--- src/jvm/clojure/lang/Compiler.java (revision 1127)
+++ src/jvm/clojure/lang/Compiler.java (working copy)
@@ -1800,34 +1800,54 @@
{
if(Util.equal(op, CATCH))
{
- Class c = HostExpr.maybeClass(RT.second(f), false);
- if(c == null)
- throw new IllegalArgumentException("Unable to resolve classname: " + RT.second(f));
- if(!(RT.third(f) instanceof Symbol))
+ java.util.Collection exceptions = PersistentVector.EMPTY;
+ Object second = RT.second(f);
+
+ if (second instanceof Symbol)
+ {
+ exceptions = ((PersistentVector) exceptions).cons(second);
+ }
+ else if (second instanceof java.util.Collection)
+ {
+ exceptions = (java.util.Collection) second;
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "Expected Exception name or sequence of Exception names, got: " + second.getClass());
+ }
+ if(!(RT.third(f) instanceof Symbol))
throw new IllegalArgumentException(
"Bad binding form, expected symbol, got: " + RT.third(f));
- Symbol sym = (Symbol) RT.third(f);
- if(sym.getNamespace() != null)
- throw new Exception("Can't bind qualified name:" + sym);
+ Symbol sym = (Symbol) RT.third(f);
+ if(sym.getNamespace() != null)
+ throw new Exception("Can't bind qualified name:" + sym);
- IPersistentMap dynamicBindings = RT.map(LOCAL_ENV, LOCAL_ENV.get(),
- NEXT_LOCAL_NUM, NEXT_LOCAL_NUM.get(),
- IN_CATCH_FINALLY, RT.T);
- try
- {
- Var.pushThreadBindings(dynamicBindings);
- LocalBinding lb = registerLocal(sym,
- (Symbol) (RT.second(f) instanceof Symbol ? RT.second(f)
- : null), null);
- Expr handler = (new BodyExpr.Parser()).parse(context, RT.rest(RT.rest(RT.rest(f))));
- catches = catches.cons(new CatchClause(c, lb, handler));
- }
- finally
- {
- Var.popThreadBindings();
- }
- caught = true;
- }
+ for (Object exception : exceptions)
+ {
+ Class c = HostExpr.maybeClass(exception, false);
+ if(c == null)
+ throw new IllegalArgumentException("Unable to resolve classname: " + exception);
+
+ IPersistentMap dynamicBindings = RT.map(LOCAL_ENV, LOCAL_ENV.get(),
+ NEXT_LOCAL_NUM, NEXT_LOCAL_NUM.get(),
+ IN_CATCH_FINALLY, RT.T);
+ try
+ {
+ Var.pushThreadBindings(dynamicBindings);
+ LocalBinding lb = registerLocal(sym,
+ (Symbol) (exception instanceof Symbol ? exception
+ : null), null);
+ Expr handler = (new BodyExpr.Parser()).parse(context, RT.rest(RT.rest(RT.rest(f))));
+ catches = catches.cons(new CatchClause(c, lb, handler));
+ }
+ finally
+ {
+ Var.popThreadBindings();
+ }
+ caught = true;
+ }
+ }
else //finally
{
if(fs.rest() != null)
@@ -2877,7 +2897,7 @@
//fn.thisName = name;
String basename = enclosingMethod != null ?
(enclosingMethod.fn.name + "$")
- : //"clojure.fns." +
+ : //"clojure.fns." +
(munge(currentNS().name.name) + "$");
if(RT.second(form) instanceof Symbol)
name = ((Symbol) RT.second(form)).name;
@@ -2997,7 +3017,7 @@
{
//cv.visitSource(source, null);
String smap = "SMAP\n" +
- ((source.lastIndexOf('.') > 0) ?
+ ((source.lastIndexOf('.') > 0) ?
source.substring(0, source.lastIndexOf('.'))
: simpleName)
+ ".java\n" +
@@ -4037,8 +4057,8 @@
// Symbol meth = Symbol.intern(sname.substring(idx + 1));
// return RT.listStar(DOT, target, meth, form.rest());
// }
- //(StringBuilder. "foo") => (new StringBuilder "foo")
- //else
+ //(StringBuilder. "foo") => (new StringBuilder "foo")
+ //else
if(idx == sname.length() - 1)
return RT.listStar(NEW, Symbol.intern(sname.substring(0, idx)), form.rest());
}
@@ -4473,7 +4493,7 @@
public static Object compile(Reader rdr, String sourcePath, String sourceName) throws Exception{
if(COMPILE_PATH.get() == null)
throw new Exception("*compile-path* not set");
-
+
Object EOF = new Object();
Object ret = null;
LineNumberingPushbackReader pushbackReader =