You seem very excited about this feature, but I'm afraid I'm having trouble understanding what it's about. :-/
I expected that. ^_^;; I kept trying to find ways to emphasize the motive, but I kept getting swept up in minutia.
Is it a sort of base case upon which all functions' extend layers can be built up? What you've written about it so far reminds me of Ruby's method_missing. Is that a related idea?
I think you're on the right track. The point of my fail parameter is to explicitly describe cases where a function is open to extension. Sometimes a function call has a well-defined return value, and sometimes it has a well-defined error value. If it doesn't end in either of those ways and instead fails--by calling its fail continuation--then it's undefined there, and you're free to replace it with your own function that's well-defined in all the same cases and more.
That was the original idea, anyway. It's a little flawed: If another function ever actually catches a failure and does something with it, then its behavior relies on the callee being undefined in certain cases. Take 'testify for instance; if 'testify checks a 'testify-extensions function first but acts as [fn (x) (iso x _)] on failure, then you can't actually extend 'testify-extensions without changing the behavior of 'testify. In fact, if you replace a function with another function that calls the first one ('extend as we usually know it), then you can no longer extend the first one without impinging upon the new one. But in practice, I think it'll work out well enough.
The alternatives ways to deal with extension I see are a) encoding defined-ness in the return value using a wrapper type, and b) throwing an exception. In a language where almost everything's extensible, to have to unwrap every return value would be madness. As for exceptions, it's hard to tell whether the exception came from the function you called or some function it called. In fact, I was actually trying figure out how to have function calls take ownership of exceptions when I finally realized there needed to be a per-function-call ID, generated on the caller's side; this idea refined a little to become fail parameters.
I know, I digressed a bit again. XD Did it work for you this time?
Also, in my Penknife draft, I'm finding myself much more comfortable using failures rather than exceptions, letting the failures become exceptions when something's called without 'failcall. Failures form a natural tree of blame; this rulebook failed because all these functions failed, and this function failed because this other function failed....
The need to write natural-language error strings diminishes to just the base cases; the rest is pretty-printing and perhaps even a bit of SHRDLU-style "Why did you decide that?" interactive tree-drilling. ^_^
Arc's known for having rotten errors 'cause it shirks the error-checking code; with fail parameters, awesomely comprehensive error reports can be made in almost a single token.