2017-02-23 12 views
1

私はブルース・テイトのを7週間のうちにで練習しており、すべての演習を行っています。ユーザーがハッシュを受け入れ、そこからツリーを作成するためのイニシャライザのみを変更するというツリー演習があります。私の最初の試みは次のとおりでした:なぜこのルビコードで例外がスローされないのですか?

def initialize(hash={}) 
    if !hash.keys[0].nil? 
    @node_name = hash.keys[0] 
    @children = [] 
    if !(hash.values[0].nil? or hash.values[0] == {}) 
     hash.values[0].each do |k, v| 
     @children.push(Tree.new({k => v}) 
     end 
    end 
    end 
end 

これは機能します。ただし、小切手のないコードも使用できます。

def initialize(hash={}) 
    @node_name = hash.keys[0] 
    @children = [] 
    hash.values[0].each do |k, v| 
    @children.push(Tree.new({k => v}) 
    end 
end 

チェックは不要ですか?それは私がnull参照(私は.Netの背景から来ているので、それはルビーの何か他のものと呼ばれるかもしれない)のようなものを得るだろうと思われる。ここで

は私の完全なコードです:

class Tree 
    attr_accessor :children, :node_name 

    def initialize(hash={}) 
     @node_name = hash.keys[0] 
     @children = [] 
     hash.values[0].each do |k, v| 
     @children.push(Tree.new({k => v}) 
     end 
    end 

    def visit_all(&block) 
    visit &block 
    children.each{|c| c.visit_all &block} 
    end 

    def visit(&block) 
    block.call self 
    end 
end 


ruby_tree = Tree.new({"grampa" => { "dad" => { "son1" => {}, "son2" => {}}, "uncle" => { "nephew1" => {}, "nephew2" => {"youngun1" => {}}}}}) 

puts "Visiting a node" 
ruby_tree.visit {|node| puts node.node_name} 
puts 

puts "visiting entire tree" 
ruby_tree.visit_all {|node| puts node.node_name} 
+0

小さなこと:あなたは '@children = hash.values [0] .map {| k、v | Tree.new(k => v)} 'となります。 Rubyでは引数のときに中括弧なしでハッシュを書くことができます。 –

+0

完全性のために:Rubyにはnull参照はありません。これまで参照は常に有効なオブジェクトになります。 –

+0

Ah。だから、最悪の場合、それはNilオブジェクトのNoSuchMerhodでしょうか? – tjcertified

答えて

2

あなたは、このコードからif条件を削除する場合:

if !(hash.values[0].nil? or hash.values[0] == {}) 
    hash.values[0].each do |v| 
    k = hash.key(v) 
    @children.push(Tree.new({k => v}) 
    end 
end 

あなたは、この場合に例外を取得することができます:

hash = {} 
hash.values  # => [] 
hash.values[0] # => nil 

あなたが条件をチェックせずにeachループを実行すると失敗しますeachnilに定義されていません。

あなたの2番目の条件hash.values[0] == {}はまったくスキップすることができます。

これは、空のハッシュ上のループがループしないようにするためのちょっとした方法です。

hash = { foo: {} } 
hash.values[0]  # => {} 

{}.eachは出力に影響しません。

0

nilのメソッドを呼び出すと例外が発生し、NoMethodErrorが返されます。有効なハッシュを渡したので、小切手は問題ではありません。あなたはruby_treeを作成するときに明示的newに引数としてnilを渡された場合は、さらにNoMethodError

、ライン

hash.values[0].each do |k, v| 

期待どおり動作しませんが表示されます。 hash.valuesを呼び出すと配列が返され、配列のイテレータはブロック(配列の次の位置にある要素)に1つの項目しか与えません。代わりにあなたが使用する必要がありますhash.each do |k, v|