Skip to content

Try Unless Feedback

Alex Zimin edited this page Jul 11, 2011 · 3 revisions

This page is for user feedback about try/unless syntax, and maybe some other comments. It is kinda old :-)

With the def/unless syntax it's not clear where the unless part will jump out. Maybe something along the lines of:

 try {
   def f = open_file ();
   dont_catch_here {
     use(f); 
   }
 } catch {
   | e => ...
 }

But what to use instead of dont_catch_here?

Pawel: Naah. This is starting to look like CIL code.


How about something like:

 attempt (f = File.OpenText(fileName)) {
   def s = f.ReadToEnd();
   f.Close();
   s + Collect(rest)
 }
 unless (_ is MyException) {
   Collect(rest)
 }

(using the example from the blog)

and a macro to implement it:

 macro AttemptUnless(tryexpr, unlessexpr, ex: parameter, thenexpr)
 syntax("attempt", "(", tryexpr,")", thenexpr, "unless", "(", ex, ")", 
        unlessexpr) {
   match(tryexpr) {
     | <[$(nm: name) = $attempt]> =>
       match(ex) {
         | <[ parameter: $(ex: name): $ty ]> =>
           <[
             def $(nm: name) =
                try { $attempt }
                catch { $(ex: name) is $ty => null}
             if($(nm: name) != null) {
                $thenexpr
             }
             else {
                $unlessexpr
             }
           ]>
         | _ => Message.FatalError("oops")
       }
     | _ => Message.FatalError("d'oh!")
   }
 }

Could almost certainly be made more robust by someone who groks the macro system better than me, and the error messages definitely need improving, but from a quick bit of testing, it seems to basically work. (and rejigging the syntax should be fairly easy, once everyone who matters can decide on which one works best... i was thinking about making it something like attempt {...} unless (...) {...} then {...} , which might work better if the 'then' part is very long (since otherwise the exceptional behaviour gets kind of lost down below everything else (although that's already the case with try... catch, so i'm not sure how much it really matters))) -- MikeRoome


(Mike: thanks for nice feedback and showing us some macro code :) )

My (Kamil's) proposition:

 try (def f = File.OpenText(fileName)) 
 catch {
   | _ is MyException => Collect(rest)
 }
 do {
    def s = f.ReadToEnd();
    f.Close();
    s + Collect(rest)
 }

It has two advantages - no new keywords, there is less confusion about semantics and the question if do is executed after or instad of unless. The disadvantage is that we place catch part before do part (or maybe it is also advantage?).


Well, the different keywords were just because i implemented it as a macro, and the with the current system it wasn't possible to make it use the existing keywords, so i just used the first word i could think of that meant roughly the same thing. As for the catch being before the do, i think that's probably an advantage, overall, at least in the common case (catching a single exception, then doing lots with the object if the allocation succeeded). I think i'd prefer try(...) unless {...} do {...} , though, since at least to me, it expresses the intent better (try this, then unless this happens, do this). Having the exception handling bit be a proper block is definitely a good idea, since it would allow you do filter and do different things on different types of exception, which could be extremely useful in some circumstances. I unfortunately couldn't work out how to do that, though - quoting

 <[ $ex : $type => $handler ]>

just threw errors at me when it hit the => operator (any advice for dealing with the various different syntactic bits in macros would be more than welcome, though :) maybe there should be a wiki page for MacroTips, or something?).

(For futher discussion, especially questions about macros, let us move to the mailing list. Let us keep this page as quick summary for ideas)

Clone this wiki locally