Skip to content

Proposal: extension to catch to only catch certain exceptions #165

@jpco

Description

@jpco

Looking at how catch is used, it's quite common to have something similar to

catch @ e type body {
  if {~ $e error} {
    handle-it
  } {
    throw $e $type $body
  }
} {
  commands
}

(error just being an example for illustration). This pattern shows up in the definitions for whatis and while in initial.es as well as the cdpath.es and status.es canonical extension scripts. It would also be required for an es-based definition of $&batchloop which only handles eof. It also appears in the es paper. (It shows up in my .esrc once or twice as well, and in friedman's intense setup a couple of times, for whatever that's worth).

This pattern can add a fair amount of verbosity that doesn't seem strictly necessary. Many languages' exception-handling systems can specify certain types of exception to catch, and something similar could be nice for es, so that the above becomes:

catch error @ {
  handle-it
} {
  commands
}

I am imagining you could also say catch error signal @ {handle-it} {commands} if you want one of a set of exception types. I would probably prefer to spell it catch (error signal) @ {... but that would just be for better legibility; it wouldn't special syntax.

This can be implemented in es today:

fn-catch = $&noreturn @ args {
	if {~ $#args (0 1)} {
		throw error catch 'usage: catch [exceptions] catcher body'
	}
	let (exceptions = ()) {
		$&catch @ {} {
			forever {
				if {~ $#args 2} {throw break}
				exceptions = $exceptions $args(1)
				args = $args(2 ...)
			}
		}
		$&catch @ e rest {
			if {~ $#exceptions 0 || ~ $e $exceptions} {
				$args(1) $e $rest
			} {
				throw $e $rest
			}
		} {
			$args(2)
		}
	}
}

(forever must be used because while works with exceptions, which seems to lead to infinite recursion.) The whole loop could be removed if we could reverse lists like in #82, but that's an aside. This could also all be moved into the $&catch primitive if we wanted that.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions