QA@IT
«回答へ戻る

tree_printer.call していなかったのを修正

735
     indent -= 2
   end
 end
+
+tree_printer.call tree
 ```
 
 Ruby 1.9.4-p194での実行結果は、以下です。

Nick Sieger さんという方のブログでは ObjectSpace.each_object を使った方法が紹介されていますが、これでどうでしょうか。(僕も昔、調べました!)

exceptions = []
tree = {}

ObjectSpace.each_object(Class) do |cls|
  next unless cls.ancestors.include? Exception
  next if exceptions.include? cls
  next if cls.superclass == SystemCallError
  cls
    .ancestors
    .delete_if {|e| [BasicObject, Object, Kernel].include? e }
    .reverse
    .inject(tree) { |memo, cls| memo[cls] ||= {} }
end

indent = 0
tree_printer = Proc.new do |t|
  t.keys.sort { |c1, c2| c1.name <=> c2.name }.each do |k|
    space = (' ' * indent)
    puts space + k.to_s
    indent += 2
    tree_printer.call t[k]
    indent -= 2
  end
end

tree_printer.call tree

Ruby 1.9.4-p194での実行結果は、以下です。

BasicObject
  Exception
    NoMemoryError
    ScriptError
      LoadError
        Gem::LoadError
      NotImplementedError
      SyntaxError
    SecurityError
    SignalException
      Interrupt
    StandardError
      ArgumentError
      EncodingError
        Encoding::CompatibilityError
        Encoding::ConverterNotFoundError
        Encoding::InvalidByteSequenceError
        Encoding::UndefinedConversionError
      FiberError
      IOError
        EOFError
      IndexError
        KeyError
        StopIteration
      LocalJumpError
      Math::DomainError
      NameError
        NoMethodError
      RangeError
        FloatDomainError
      RegexpError
      RuntimeError
        Gem::Exception
          Gem::CommandLineError
          Gem::DependencyError
          Gem::DependencyRemovalException
          Gem::DocumentError
          Gem::EndOfYAMLException
          Gem::FilePermissionError
          Gem::FormatException
          Gem::GemNotFoundException
          Gem::GemNotInHomeException
          Gem::InstallError
          Gem::InvalidSpecificationException
          Gem::OperationNotSupportedError
          Gem::RemoteError
          Gem::RemoteInstallationCancelled
          Gem::RemoteInstallationSkipped
          Gem::RemoteSourceException
          Gem::VerificationError
      SystemCallError
      ThreadError
      TypeError
      ZeroDivisionError
    SystemExit
      Gem::SystemExitException
    SystemStackError
    fatal
tree = {}

["a","b","c"].inject(tree) do |memo, cls|
  memo[cls] ||= {}
end

tree  # => {"a"=>{"b"=>{"c"=>{}}}}
Nick Sieger さんという方のブログでは ObjectSpace.each_object を使った方法が紹介されていますが、これでどうでしょうか。(僕も昔、[調べました!](http://d.hatena.ne.jp/kitokitoki/20101211/p2))

* [Ruby's Exception Hierarchy](http://blog.nicksieger.com/articles/2006/09/06/rubys-exception-hierarchy)

```ruby
exceptions = []
tree = {}

ObjectSpace.each_object(Class) do |cls|
  next unless cls.ancestors.include? Exception
  next if exceptions.include? cls
  next if cls.superclass == SystemCallError
  cls
    .ancestors
    .delete_if {|e| [BasicObject, Object, Kernel].include? e }
    .reverse
    .inject(tree) { |memo, cls| memo[cls] ||= {} }
end

indent = 0
tree_printer = Proc.new do |t|
  t.keys.sort { |c1, c2| c1.name <=> c2.name }.each do |k|
    space = (' ' * indent)
    puts space + k.to_s
    indent += 2
    tree_printer.call t[k]
    indent -= 2
  end
end

tree_printer.call tree
```

Ruby 1.9.4-p194での実行結果は、以下です。

```
BasicObject
  Exception
    NoMemoryError
    ScriptError
      LoadError
        Gem::LoadError
      NotImplementedError
      SyntaxError
    SecurityError
    SignalException
      Interrupt
    StandardError
      ArgumentError
      EncodingError
        Encoding::CompatibilityError
        Encoding::ConverterNotFoundError
        Encoding::InvalidByteSequenceError
        Encoding::UndefinedConversionError
      FiberError
      IOError
        EOFError
      IndexError
        KeyError
        StopIteration
      LocalJumpError
      Math::DomainError
      NameError
        NoMethodError
      RangeError
        FloatDomainError
      RegexpError
      RuntimeError
        Gem::Exception
          Gem::CommandLineError
          Gem::DependencyError
          Gem::DependencyRemovalException
          Gem::DocumentError
          Gem::EndOfYAMLException
          Gem::FilePermissionError
          Gem::FormatException
          Gem::GemNotFoundException
          Gem::GemNotInHomeException
          Gem::InstallError
          Gem::InvalidSpecificationException
          Gem::OperationNotSupportedError
          Gem::RemoteError
          Gem::RemoteInstallationCancelled
          Gem::RemoteInstallationSkipped
          Gem::RemoteSourceException
          Gem::VerificationError
      SystemCallError
      ThreadError
      TypeError
      ZeroDivisionError
    SystemExit
      Gem::SystemExitException
    SystemStackError
    fatal
```


```ruby
tree = {}

["a","b","c"].inject(tree) do |memo, cls|
  memo[cls] ||= {}
end

tree  # => {"a"=>{"b"=>{"c"=>{}}}}
```

「inject(tree)とやってなぜツリーがハッシュになるのか」というのはたんに上の方で tree = {} しているのを見落としていただけではないでしょうか。

735
 ```
 
 
+```ruby
+tree = {}
+
+["a","b","c"].inject(tree) do |memo, cls|
+  memo[cls] ||= {}
+end
+
+tree  # => {"a"=>{"b"=>{"c"=>{}}}}
+```
+

Nick Sieger さんという方のブログでは ObjectSpace.each_object を使った方法が紹介されていますが、これでどうでしょうか。(僕も昔、調べました!)

exceptions = []
tree = {}

ObjectSpace.each_object(Class) do |cls|
  next unless cls.ancestors.include? Exception
  next if exceptions.include? cls
  next if cls.superclass == SystemCallError
  cls
    .ancestors
    .delete_if {|e| [BasicObject, Object, Kernel].include? e }
    .reverse
    .inject(tree) { |memo, cls| memo[cls] ||= {} }
end

indent = 0
tree_printer = Proc.new do |t|
  t.keys.sort { |c1, c2| c1.name <=> c2.name }.each do |k|
    space = (' ' * indent)
    puts space + k.to_s
    indent += 2
    tree_printer.call t[k]
    indent -= 2
  end
end

Ruby 1.9.4-p194での実行結果は、以下です。

BasicObject
  Exception
    NoMemoryError
    ScriptError
      LoadError
        Gem::LoadError
      NotImplementedError
      SyntaxError
    SecurityError
    SignalException
      Interrupt
    StandardError
      ArgumentError
      EncodingError
        Encoding::CompatibilityError
        Encoding::ConverterNotFoundError
        Encoding::InvalidByteSequenceError
        Encoding::UndefinedConversionError
      FiberError
      IOError
        EOFError
      IndexError
        KeyError
        StopIteration
      LocalJumpError
      Math::DomainError
      NameError
        NoMethodError
      RangeError
        FloatDomainError
      RegexpError
      RuntimeError
        Gem::Exception
          Gem::CommandLineError
          Gem::DependencyError
          Gem::DependencyRemovalException
          Gem::DocumentError
          Gem::EndOfYAMLException
          Gem::FilePermissionError
          Gem::FormatException
          Gem::GemNotFoundException
          Gem::GemNotInHomeException
          Gem::InstallError
          Gem::InvalidSpecificationException
          Gem::OperationNotSupportedError
          Gem::RemoteError
          Gem::RemoteInstallationCancelled
          Gem::RemoteInstallationSkipped
          Gem::RemoteSourceException
          Gem::VerificationError
      SystemCallError
      ThreadError
      TypeError
      ZeroDivisionError
    SystemExit
      Gem::SystemExitException
    SystemStackError
    fatal
tree = {}

["a","b","c"].inject(tree) do |memo, cls|
  memo[cls] ||= {}
end

tree  # => {"a"=>{"b"=>{"c"=>{}}}}
Nick Sieger さんという方のブログでは ObjectSpace.each_object を使った方法が紹介されていますが、これでどうでしょうか。(僕も昔、[調べました!](http://d.hatena.ne.jp/kitokitoki/20101211/p2))

* [Ruby's Exception Hierarchy](http://blog.nicksieger.com/articles/2006/09/06/rubys-exception-hierarchy)

```ruby
exceptions = []
tree = {}

ObjectSpace.each_object(Class) do |cls|
  next unless cls.ancestors.include? Exception
  next if exceptions.include? cls
  next if cls.superclass == SystemCallError
  cls
    .ancestors
    .delete_if {|e| [BasicObject, Object, Kernel].include? e }
    .reverse
    .inject(tree) { |memo, cls| memo[cls] ||= {} }
end

indent = 0
tree_printer = Proc.new do |t|
  t.keys.sort { |c1, c2| c1.name <=> c2.name }.each do |k|
    space = (' ' * indent)
    puts space + k.to_s
    indent += 2
    tree_printer.call t[k]
    indent -= 2
  end
end
```

Ruby 1.9.4-p194での実行結果は、以下です。

```
BasicObject
  Exception
    NoMemoryError
    ScriptError
      LoadError
        Gem::LoadError
      NotImplementedError
      SyntaxError
    SecurityError
    SignalException
      Interrupt
    StandardError
      ArgumentError
      EncodingError
        Encoding::CompatibilityError
        Encoding::ConverterNotFoundError
        Encoding::InvalidByteSequenceError
        Encoding::UndefinedConversionError
      FiberError
      IOError
        EOFError
      IndexError
        KeyError
        StopIteration
      LocalJumpError
      Math::DomainError
      NameError
        NoMethodError
      RangeError
        FloatDomainError
      RegexpError
      RuntimeError
        Gem::Exception
          Gem::CommandLineError
          Gem::DependencyError
          Gem::DependencyRemovalException
          Gem::DocumentError
          Gem::EndOfYAMLException
          Gem::FilePermissionError
          Gem::FormatException
          Gem::GemNotFoundException
          Gem::GemNotInHomeException
          Gem::InstallError
          Gem::InvalidSpecificationException
          Gem::OperationNotSupportedError
          Gem::RemoteError
          Gem::RemoteInstallationCancelled
          Gem::RemoteInstallationSkipped
          Gem::RemoteSourceException
          Gem::VerificationError
      SystemCallError
      ThreadError
      TypeError
      ZeroDivisionError
    SystemExit
      Gem::SystemExitException
    SystemStackError
    fatal
```


```ruby
tree = {}

["a","b","c"].inject(tree) do |memo, cls|
  memo[cls] ||= {}
end

tree  # => {"a"=>{"b"=>{"c"=>{}}}}
```

コメントの指摘を反映。 メソッドチェーンで改行してピリオドから始められるのは Ruby1.9からだった気がします。

735
 ```ruby
 exceptions = []
 tree = {}
+
 ObjectSpace.each_object(Class) do |cls|
   next unless cls.ancestors.include? Exception
   next if exceptions.include? cls
-  next if cls.superclass == SystemCallError # avoid dumping Errno's
-  exceptions << cls
-  cls.ancestors.delete_if {|e| [Object, Kernel].include? e }.reverse.inject(tree) {|memo,cls| memo[cls] ||= {}}
+  next if cls.superclass == SystemCallError
+  cls
+    .ancestors
+    .delete_if {|e| [BasicObject, Object, Kernel].include? e }
+    .reverse
+    .inject(tree) { |memo, cls| memo[cls] ||= {} }
 end
 
 indent = 0
 tree_printer = Proc.new do |t|
-  t.keys.sort { |c1,c2| c1.name <=> c2.name }.each do |k|
-    space = (' ' * indent); space ||= ''
+  t.keys.sort { |c1, c2| c1.name <=> c2.name }.each do |k|
+    space = (' ' * indent)
     puts space + k.to_s
-    indent += 2; tree_printer.call t[k]; indent -= 2
+    indent += 2
+    tree_printer.call t[k]
+    indent -= 2
   end
 end
-tree_printer.call tree
 ```
 
 Ruby 1.9.4-p194での実行結果は、以下です。

Nick Sieger さんという方のブログでは ObjectSpace.each_object を使った方法が紹介されていますが、これでどうでしょうか。(僕も昔、調べました!)

exceptions = []
tree = {}

ObjectSpace.each_object(Class) do |cls|
  next unless cls.ancestors.include? Exception
  next if exceptions.include? cls
  next if cls.superclass == SystemCallError
  cls
    .ancestors
    .delete_if {|e| [BasicObject, Object, Kernel].include? e }
    .reverse
    .inject(tree) { |memo, cls| memo[cls] ||= {} }
end

indent = 0
tree_printer = Proc.new do |t|
  t.keys.sort { |c1, c2| c1.name <=> c2.name }.each do |k|
    space = (' ' * indent)
    puts space + k.to_s
    indent += 2
    tree_printer.call t[k]
    indent -= 2
  end
end

Ruby 1.9.4-p194での実行結果は、以下です。

BasicObject
  Exception
    NoMemoryError
    ScriptError
      LoadError
        Gem::LoadError
      NotImplementedError
      SyntaxError
    SecurityError
    SignalException
      Interrupt
    StandardError
      ArgumentError
      EncodingError
        Encoding::CompatibilityError
        Encoding::ConverterNotFoundError
        Encoding::InvalidByteSequenceError
        Encoding::UndefinedConversionError
      FiberError
      IOError
        EOFError
      IndexError
        KeyError
        StopIteration
      LocalJumpError
      Math::DomainError
      NameError
        NoMethodError
      RangeError
        FloatDomainError
      RegexpError
      RuntimeError
        Gem::Exception
          Gem::CommandLineError
          Gem::DependencyError
          Gem::DependencyRemovalException
          Gem::DocumentError
          Gem::EndOfYAMLException
          Gem::FilePermissionError
          Gem::FormatException
          Gem::GemNotFoundException
          Gem::GemNotInHomeException
          Gem::InstallError
          Gem::InvalidSpecificationException
          Gem::OperationNotSupportedError
          Gem::RemoteError
          Gem::RemoteInstallationCancelled
          Gem::RemoteInstallationSkipped
          Gem::RemoteSourceException
          Gem::VerificationError
      SystemCallError
      ThreadError
      TypeError
      ZeroDivisionError
    SystemExit
      Gem::SystemExitException
    SystemStackError
    fatal
Nick Sieger さんという方のブログでは ObjectSpace.each_object を使った方法が紹介されていますが、これでどうでしょうか。(僕も昔、[調べました!](http://d.hatena.ne.jp/kitokitoki/20101211/p2))

* [Ruby's Exception Hierarchy](http://blog.nicksieger.com/articles/2006/09/06/rubys-exception-hierarchy)

```ruby
exceptions = []
tree = {}

ObjectSpace.each_object(Class) do |cls|
  next unless cls.ancestors.include? Exception
  next if exceptions.include? cls
  next if cls.superclass == SystemCallError
  cls
    .ancestors
    .delete_if {|e| [BasicObject, Object, Kernel].include? e }
    .reverse
    .inject(tree) { |memo, cls| memo[cls] ||= {} }
end

indent = 0
tree_printer = Proc.new do |t|
  t.keys.sort { |c1, c2| c1.name <=> c2.name }.each do |k|
    space = (' ' * indent)
    puts space + k.to_s
    indent += 2
    tree_printer.call t[k]
    indent -= 2
  end
end
```

Ruby 1.9.4-p194での実行結果は、以下です。

```
BasicObject
  Exception
    NoMemoryError
    ScriptError
      LoadError
        Gem::LoadError
      NotImplementedError
      SyntaxError
    SecurityError
    SignalException
      Interrupt
    StandardError
      ArgumentError
      EncodingError
        Encoding::CompatibilityError
        Encoding::ConverterNotFoundError
        Encoding::InvalidByteSequenceError
        Encoding::UndefinedConversionError
      FiberError
      IOError
        EOFError
      IndexError
        KeyError
        StopIteration
      LocalJumpError
      Math::DomainError
      NameError
        NoMethodError
      RangeError
        FloatDomainError
      RegexpError
      RuntimeError
        Gem::Exception
          Gem::CommandLineError
          Gem::DependencyError
          Gem::DependencyRemovalException
          Gem::DocumentError
          Gem::EndOfYAMLException
          Gem::FilePermissionError
          Gem::FormatException
          Gem::GemNotFoundException
          Gem::GemNotInHomeException
          Gem::InstallError
          Gem::InvalidSpecificationException
          Gem::OperationNotSupportedError
          Gem::RemoteError
          Gem::RemoteInstallationCancelled
          Gem::RemoteInstallationSkipped
          Gem::RemoteSourceException
          Gem::VerificationError
      SystemCallError
      ThreadError
      TypeError
      ZeroDivisionError
    SystemExit
      Gem::SystemExitException
    SystemStackError
    fatal
```

実行結果を追加しました

1138
 
 * [Ruby's Exception Hierarchy](http://blog.nicksieger.com/articles/2006/09/06/rubys-exception-hierarchy)
 
-```
+```ruby
 exceptions = []
 tree = {}
 ObjectSpace.each_object(Class) do |cls|
 end
 tree_printer.call tree
 ```
+
+Ruby 1.9.4-p194での実行結果は、以下です。
+
+```
+BasicObject
+  Exception
+    NoMemoryError
+    ScriptError
+      LoadError
+        Gem::LoadError
+      NotImplementedError
+      SyntaxError
+    SecurityError
+    SignalException
+      Interrupt
+    StandardError
+      ArgumentError
+      EncodingError
+        Encoding::CompatibilityError
+        Encoding::ConverterNotFoundError
+        Encoding::InvalidByteSequenceError
+        Encoding::UndefinedConversionError
+      FiberError
+      IOError
+        EOFError
+      IndexError
+        KeyError
+        StopIteration
+      LocalJumpError
+      Math::DomainError
+      NameError
+        NoMethodError
+      RangeError
+        FloatDomainError
+      RegexpError
+      RuntimeError
+        Gem::Exception
+          Gem::CommandLineError
+          Gem::DependencyError
+          Gem::DependencyRemovalException
+          Gem::DocumentError
+          Gem::EndOfYAMLException
+          Gem::FilePermissionError
+          Gem::FormatException
+          Gem::GemNotFoundException
+          Gem::GemNotInHomeException
+          Gem::InstallError
+          Gem::InvalidSpecificationException
+          Gem::OperationNotSupportedError
+          Gem::RemoteError
+          Gem::RemoteInstallationCancelled
+          Gem::RemoteInstallationSkipped
+          Gem::RemoteSourceException
+          Gem::VerificationError
+      SystemCallError
+      ThreadError
+      TypeError
+      ZeroDivisionError
+    SystemExit
+      Gem::SystemExitException
+    SystemStackError
+    fatal
+```
+
 

Nick Sieger さんという方のブログでは ObjectSpace.each_object を使った方法が紹介されていますが、これでどうでしょうか。(僕も昔、調べました!)

exceptions = []
tree = {}
ObjectSpace.each_object(Class) do |cls|
  next unless cls.ancestors.include? Exception
  next if exceptions.include? cls
  next if cls.superclass == SystemCallError # avoid dumping Errno's
  exceptions << cls
  cls.ancestors.delete_if {|e| [Object, Kernel].include? e }.reverse.inject(tree) {|memo,cls| memo[cls] ||= {}}
end

indent = 0
tree_printer = Proc.new do |t|
  t.keys.sort { |c1,c2| c1.name <=> c2.name }.each do |k|
    space = (' ' * indent); space ||= ''
    puts space + k.to_s
    indent += 2; tree_printer.call t[k]; indent -= 2
  end
end
tree_printer.call tree

Ruby 1.9.4-p194での実行結果は、以下です。

BasicObject
  Exception
    NoMemoryError
    ScriptError
      LoadError
        Gem::LoadError
      NotImplementedError
      SyntaxError
    SecurityError
    SignalException
      Interrupt
    StandardError
      ArgumentError
      EncodingError
        Encoding::CompatibilityError
        Encoding::ConverterNotFoundError
        Encoding::InvalidByteSequenceError
        Encoding::UndefinedConversionError
      FiberError
      IOError
        EOFError
      IndexError
        KeyError
        StopIteration
      LocalJumpError
      Math::DomainError
      NameError
        NoMethodError
      RangeError
        FloatDomainError
      RegexpError
      RuntimeError
        Gem::Exception
          Gem::CommandLineError
          Gem::DependencyError
          Gem::DependencyRemovalException
          Gem::DocumentError
          Gem::EndOfYAMLException
          Gem::FilePermissionError
          Gem::FormatException
          Gem::GemNotFoundException
          Gem::GemNotInHomeException
          Gem::InstallError
          Gem::InvalidSpecificationException
          Gem::OperationNotSupportedError
          Gem::RemoteError
          Gem::RemoteInstallationCancelled
          Gem::RemoteInstallationSkipped
          Gem::RemoteSourceException
          Gem::VerificationError
      SystemCallError
      ThreadError
      TypeError
      ZeroDivisionError
    SystemExit
      Gem::SystemExitException
    SystemStackError
    fatal
Nick Sieger さんという方のブログでは ObjectSpace.each_object を使った方法が紹介されていますが、これでどうでしょうか。(僕も昔、[調べました!](http://d.hatena.ne.jp/kitokitoki/20101211/p2))

* [Ruby's Exception Hierarchy](http://blog.nicksieger.com/articles/2006/09/06/rubys-exception-hierarchy)

```ruby
exceptions = []
tree = {}
ObjectSpace.each_object(Class) do |cls|
  next unless cls.ancestors.include? Exception
  next if exceptions.include? cls
  next if cls.superclass == SystemCallError # avoid dumping Errno's
  exceptions << cls
  cls.ancestors.delete_if {|e| [Object, Kernel].include? e }.reverse.inject(tree) {|memo,cls| memo[cls] ||= {}}
end

indent = 0
tree_printer = Proc.new do |t|
  t.keys.sort { |c1,c2| c1.name <=> c2.name }.each do |k|
    space = (' ' * indent); space ||= ''
    puts space + k.to_s
    indent += 2; tree_printer.call t[k]; indent -= 2
  end
end
tree_printer.call tree
```

Ruby 1.9.4-p194での実行結果は、以下です。

```
BasicObject
  Exception
    NoMemoryError
    ScriptError
      LoadError
        Gem::LoadError
      NotImplementedError
      SyntaxError
    SecurityError
    SignalException
      Interrupt
    StandardError
      ArgumentError
      EncodingError
        Encoding::CompatibilityError
        Encoding::ConverterNotFoundError
        Encoding::InvalidByteSequenceError
        Encoding::UndefinedConversionError
      FiberError
      IOError
        EOFError
      IndexError
        KeyError
        StopIteration
      LocalJumpError
      Math::DomainError
      NameError
        NoMethodError
      RangeError
        FloatDomainError
      RegexpError
      RuntimeError
        Gem::Exception
          Gem::CommandLineError
          Gem::DependencyError
          Gem::DependencyRemovalException
          Gem::DocumentError
          Gem::EndOfYAMLException
          Gem::FilePermissionError
          Gem::FormatException
          Gem::GemNotFoundException
          Gem::GemNotInHomeException
          Gem::InstallError
          Gem::InvalidSpecificationException
          Gem::OperationNotSupportedError
          Gem::RemoteError
          Gem::RemoteInstallationCancelled
          Gem::RemoteInstallationSkipped
          Gem::RemoteSourceException
          Gem::VerificationError
      SystemCallError
      ThreadError
      TypeError
      ZeroDivisionError
    SystemExit
      Gem::SystemExitException
    SystemStackError
    fatal
```

回答を投稿

Nick Sieger さんという方のブログでは ObjectSpace.each_object を使った方法が紹介されていますが、これでどうでしょうか。(僕も昔、調べました!)

exceptions = []
tree = {}
ObjectSpace.each_object(Class) do |cls|
  next unless cls.ancestors.include? Exception
  next if exceptions.include? cls
  next if cls.superclass == SystemCallError # avoid dumping Errno's
  exceptions << cls
  cls.ancestors.delete_if {|e| [Object, Kernel].include? e }.reverse.inject(tree) {|memo,cls| memo[cls] ||= {}}
end

indent = 0
tree_printer = Proc.new do |t|
  t.keys.sort { |c1,c2| c1.name <=> c2.name }.each do |k|
    space = (' ' * indent); space ||= ''
    puts space + k.to_s
    indent += 2; tree_printer.call t[k]; indent -= 2
  end
end
tree_printer.call tree
Nick Sieger さんという方のブログでは ObjectSpace.each_object を使った方法が紹介されていますが、これでどうでしょうか。(僕も昔、[調べました!](http://d.hatena.ne.jp/kitokitoki/20101211/p2))

* [Ruby's Exception Hierarchy](http://blog.nicksieger.com/articles/2006/09/06/rubys-exception-hierarchy)

```
exceptions = []
tree = {}
ObjectSpace.each_object(Class) do |cls|
  next unless cls.ancestors.include? Exception
  next if exceptions.include? cls
  next if cls.superclass == SystemCallError # avoid dumping Errno's
  exceptions << cls
  cls.ancestors.delete_if {|e| [Object, Kernel].include? e }.reverse.inject(tree) {|memo,cls| memo[cls] ||= {}}
end

indent = 0
tree_printer = Proc.new do |t|
  t.keys.sort { |c1,c2| c1.name <=> c2.name }.each do |k|
    space = (' ' * indent); space ||= ''
    puts space + k.to_s
    indent += 2; tree_printer.call t[k]; indent -= 2
  end
end
tree_printer.call tree
```