使用Ruby将嵌入式块转换为嵌入式数组
考虑到以下几点: 它正在返回:使用Ruby将嵌入式块转换为嵌入式数组,ruby,dsl,Ruby,Dsl,考虑到以下几点: 它正在返回: tree = #<Node:0x007fca1a103268 @name="Simpsons family tree", @children=[#<Node:0x007fca1a103128 @name="gramps", @children=[#<Node:0x007fca1a102fe8 @name="homer+marge", @children=[#<Node:0x007fca1a102ef8 @name="bart", @chil
tree = #<Node:0x007fca1a103268 @name="Simpsons family tree", @children=[#<Node:0x007fca1a103128 @name="gramps", @children=[#<Node:0x007fca1a102fe8 @name="homer+marge", @children=[#<Node:0x007fca1a102ef8 @name="bart", @children=[]>, #<Node:0x007fca1a102e80 @name="lisa", @children=[]>, #<Node:0x007fca1a102e08 @name="maggie", @children=[]>]>]>]>
可能吗?谢谢你的建议
编辑:
实际上,我希望使用基本相同的代码,但是没有任何@children
实例。因此,我想删除@子项
编辑2:
经过一些测试,以下是我的最佳结果:
class Node
def initialize(name=nil)
@name = name
end
def node(name, &block)
child = Node.new(name)
@sub = child.instance_exec(&block) if block
[
name,
@sub
].compact
end
end
def tree(name, &block)
@tree = Node.new(name)
[
name,
@tree.instance_exec(&block)
]
end
t = tree("Simpsons family tree") do
node("gramps") do
node("homer+marge") do
node("bart")
node("lisa")
node("maggie")
end
end
end
puts t.inspect
# => [
# "Simpsons family tree",
# [
# "gramps",
# [
# "homer+marge",
# [
# "maggie"
# ]
# ]
# ]
# ]
但展平节点仍然存在问题。因为只有最后一个是由Ruby返回的。我的格式不完全是您想要的,但这并不是真正重要的部分 如果允许使用子节点集合初始化节点,则可以让
节点
方法在每次调用时返回一个新节点
class Node
def self.new(*args, &block)
instance = super
if block
instance.instance_eval(&block)
else
instance
end
end
def initialize(name, children=[])
@name = name
@children = children
end
attr_reader :children, :name
def node(name, &block)
new_node = Node.new(name)
new_node = new_node.instance_eval(&block) if block
Node.new(self.name, next_children + [new_node])
end
def next_children
children.map{|child| Node.new(child.name, child.next_children) }
end
def inspect
return %{"#{name}"} if children.empty?
%{"#{name}", #{children}}
end
end
t = Node.new("Simpsons family tree") do
node("gramps") do
node("homer+marge") do
node("bart").
node("lisa").
node("maggie")
end
end
end
puts t.inspect
#=> "Simpsons family tree", ["gramps", ["homer+marge", ["bart", "lisa", "maggie"]]]
通过更改初始化和节点
方法的行为,可以在创建节点时累积节点
我还冒昧地删除了您的树
方法,因为它只是初始化节点的包装器,但这可能是恢复格式的地方
我在这篇文章中找到了一些很好地使用instance\u exec
的例子,但是您可以对块使用instance\u exec
或instance\u eval
,因为您没有向它传递任何参数
编辑:我更新了每次返回新值的方法。更改要求将不带块的节点链接在一起,因为每个节点
调用都返回一个新对象。块的返回值是一个新节点
为了获得所需的格式,您需要执行
[t]。检查否,如果您不知道@children
中的数组,则不可能。是的,您是对的@Luiggi。实际上,我想删除这个数组。我的问题不够清楚,我更新了它。您需要将节点的子节点存储在某个位置。为什么不使用@children
?这是实例变量的一个非常合适的用法,因为从语义上讲,这个嵌入数组是一个值,而不是一个对象。它应该是不可变的,由它自己定义。所以,如果我们能通过初始化过程创建这样的数组,它是原子的,对我来说是完美的。
class Node
def initialize(name=nil)
@name = name
end
def node(name, &block)
child = Node.new(name)
@sub = child.instance_exec(&block) if block
[
name,
@sub
].compact
end
end
def tree(name, &block)
@tree = Node.new(name)
[
name,
@tree.instance_exec(&block)
]
end
t = tree("Simpsons family tree") do
node("gramps") do
node("homer+marge") do
node("bart")
node("lisa")
node("maggie")
end
end
end
puts t.inspect
# => [
# "Simpsons family tree",
# [
# "gramps",
# [
# "homer+marge",
# [
# "maggie"
# ]
# ]
# ]
# ]
class Node
def self.new(*args, &block)
instance = super
if block
instance.instance_eval(&block)
else
instance
end
end
def initialize(name, children=[])
@name = name
@children = children
end
attr_reader :children, :name
def node(name, &block)
new_node = Node.new(name)
new_node = new_node.instance_eval(&block) if block
Node.new(self.name, next_children + [new_node])
end
def next_children
children.map{|child| Node.new(child.name, child.next_children) }
end
def inspect
return %{"#{name}"} if children.empty?
%{"#{name}", #{children}}
end
end
t = Node.new("Simpsons family tree") do
node("gramps") do
node("homer+marge") do
node("bart").
node("lisa").
node("maggie")
end
end
end
puts t.inspect
#=> "Simpsons family tree", ["gramps", ["homer+marge", ["bart", "lisa", "maggie"]]]