迭代块中的值

时间:2014-08-12 23:05:00

标签: ruby

我使用块来创建像这样的值

some_block = BlockClass.new {|b|
  b.one   = 1
  b.two   = 2
  b.three = 3
}

以下是BlockClass

class BlockClass
  attr_accessor :one
  attr_accessor :two
  attr_accessor :three
  def initialize
    yield self if block_given?
  end
end

我需要一种迭代some_block的方法,并在不必执行的情况下打印块中的所有值

puts some_block.one
puts some_block.two
puts some_block.three

有没有办法迭代块中的值?

2 个答案:

答案 0 :(得分:1)

首先,块中的b参数为nil,因此您将获得

NoMethodError: undefined method `one=' for nil:NilClass`

要解决此问题,您可以将yield if block_given?更改为yield(self) if block_given?,这会将self作为第一个参数传递给该块。

如果您需要b.one = ..., b.two = ...语法,则应使用OpenStruct

require 'ostruct'
class BlockClass < OpenStruct
  def initialize
    super
    yield(self) if block_given?
  end
end

您可以通过调用Hash来获取内部marshal_dump的转储:

some_block = BlockClass.new {|b|
  b.one   = 1
  b.two   = 2
  b.three = 3
}

some_block.marshal_dump # => {:one=>1, :two=>2, :three=>3}

然后您可以迭代值:

some_block.marshal_dump.each_pair do |k, v|
  puts "the value of #{k} is #{v}"
end

答案 1 :(得分:0)

您的广告代码需要1个参数b,但您的yield语句不能传递任何内容。也许您的意思是yield self if block_given?

此外,如果你想要&#34;迭代&#34;,你需要一个可枚举的东西集合,比如ArrayHash。实际上,onetwothree与您的BlockClass完全无关。

可以遍历BlockClass的所有方法:

(some_block.methods).each do |method_name|
  puts some_block.send(method_name)
end

但这并不像你正在寻找的那样。也许Initialize a Ruby class from an arbitrary hash, but only keys with matching accessors可能有帮助吗?