Condition system in Ioke


Continuing in the series of “standing on the shoulders of giants”, I will in this post talk a little bit about one feature I always miss in “modern” languages. A condition system. According to Wikipedia, Smalltalk also had one, but I’m only familiar with the Common Lisp and Dylan versions. And that’s where my inspiration is coming from.

So what is a condition system, you might ask? Isn’t that just conditionals? Nope, not really. It’s actually totally different. Conditions are a generalization of errors. This means that errors are a kind of conditions, but you can also do other things with conditions. The main difference is that invoking a condition doesn’t necessarily mean that the stack will be unwinded. Instead, the code handling the condition can choose to do different things depending on the condition. Conditions can have different severity and different default actions. So most real errors would probably end up unwinding the stack if no handler was defined for it. But warnings can also be conditions – and the default warning action might depend on a command line flag. Or maybe you want to have a handler for a specific warning that should be an error in your code. Etc. The possibilities are quite literally endless, and when you can define your own conditions, the power of this mechanism should be apparent. (And if you’re thinking continuations, that’s not exactly it, but almost.)

Common Lisp allow you to disregard some exceptions. You can also restart the code involved that threw an exception, if you think it’s likely to be intermittent. And the handler for this doesn’t need to be lexically close to the place that caused the problem. Instead, the place that raised a condition will give you a couple of options on what to do, commonly called restarts. Restarts are lexical closures that can change the environment that caused the exception, which means it’s possible to fix things quite neatly. Most (all?) Common Lisp implementations have a default exception handler that drops you into the interactive debugger, which is invoked with the lexical closure of the point where the exception happened. You might want to read that last sentence a few times over if it didn’t make sense the first time.

You might ask yourself if this magic is some kind of Lisp trick? That’s a good question, since it seems to mostly be available in Lisp systems, such as Common Lisp and Dylan. (Smalltalk is obviously very Lispy too. =)

There is nothing technical standing in the way for other languages to adopt a condition system. Ruby would do well with it for many things, although I don’t think it would be a great thing to graft it on at this point.

I’m pretty sure I can implement it easily in Ioke, on top of the JVM. The interesting point will be to see how I can make it interact with Java exceptions…

Since I haven’t implemented it yet, I don’t know the exact syntax, but I do have some ideas.

bindHandler(
  noSuchCell: block(c, c asText println),
  incorrectArity: block(c, c asText println),
  # code that might cause the above conditions
)

bindHandler(
  somethingHappened: block(c, invokeRestart(useNewValue, 24))
  loop(
    value = 1
    bindRestart(
      useNewValue: block(val, value = val),
      quit: block(break),

      value println
      signal(somethingHappened)))

These examples show a small subset of what you will be able to do – define handlers for specific conditions, and in these handlers call restarts. I will probably provide some way to collect all handlers for a condition, so Common Lisp style interactive choices can be made. I will try to keep the system a bit easier than the Common Lisp version, but hopefully I’ll be able to retain it’s power.