Error Handling

Posts tagged with "Error Handling."
  • 21

    AUG
    2014

    Guard Clauses, Rust Style

    When I'm programming in Ruby, I will often use guard clauses to prevent undesirable scenarios. For example, let's say I'm building a simple Stack:

    class Stack
      def initialize
        @numbers = [ ]
      end
    
      def push(number)
        @numbers.push(number)
      end
    
      def peek
        fail "Stack underflow" if @numbers.empty?
    
        @numbers.last
      end
    end
    
    stack = Stack.new
    
    ARGV.each do |number|
      stack.push(number.to_f)
    end
    
    p stack.peek
    

    If I only want to work with numbers everywhere, I add a line like the call to fail() above. This prevents a nil from being returned from peek(), ruining my expectation that I will have numbers everywhere.

    When I first started playing with Rust, I wanted to write code the same way:

    use std::os;
    
    struct Stack {
        numbers: Vec<f64>
    }
    impl Stack {
        fn new() -> Stack {
            Stack{numbers: vec![]}
        }
    
        fn push(&mut self, number: f64) {
            self.numbers.push(number);
        }
    
        fn peek(&self) -> f64 {
            if self.numbers.is_empty() { fail!("Stack underflow"); }
    
            self.numbers.last()
        }
    }
    
    fn main() {
        let mut stack = Stack::new();
    
        for number in os::args().tail().iter() {
            stack.push(from_str(number.as_slice()).expect("Not a number"));
        }
    
        println!("{}", stack.peek());
    }
    

    Read more…

  • 26

    JUN
    2008

    Summoning Error Classes As Needed

    In the past, I've written a lot of code like this:

    class SomeThing
      class SomeError       < RuntimeError; end
      class AnotherError    < RuntimeError; end
      class YetAnotherError < RuntimeError; end
    
      # some methods that can raise the above errors...
    end
    

    I have a new strategy I've been using for code like this and it has really been working out well. Here is how I do the same thing today:

    class SmarterThing
      def self.const_missing(error_name)  # :nodoc:
        if error_name.to_s =~ /Error\z/
          const_set(error_name, Class.new(RuntimeError))
        else
          super
        end
      end
    
      # error raising methods here...
    end
    

    Let's discuss how this works. The const_missing() method is a hook in Ruby, much like the beloved method_missing(). Note that const_missing() is a class method though, instead of an instance method. When a constant is used and Ruby can't find it, a call to the hook will be triggered.

    In this version, I just check to see if the constant name ends in Error. If it does, I summon an Exception subclass on the fly. Other calls to this hook are forwarded on to Ruby's default error raising implementation via super.

    Read more…