Я работаю через Bruce Tate's Семь языков за семь недель, и пытается выполнить все упражнения. Существует упражнение Tree, в котором пользователь должен изменить только инициализатор, чтобы принять хэш и создать дерево из него. Моя первоначальная попытка была следующая:Почему этот код ruby не генерирует исключение?
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
Почему проверка не требуется? Похоже, я получаю что-то вроде нулевой ссылки (я берусь из фона .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}
Небольшая вещь: вы можете написать '@children = hash.values [0] .map {| k, v | Tree.new (k => v)} '. Ruby позволяет писать хэш без брекетов, когда это аргумент. –
Просто для полноты: в Ruby нет нулевых ссылок. Когда-либо. Любая ссылка всегда будет на действительный объект. –
Ах. Итак, в худшем случае, это был бы NoSuchMerhod на объекте Nil? – tjcertified