我正在尝试在对象上实现就地方法,我收到以下错误:
Can't change the value of self (SyntaxError)
尝试时
self = map(&block)
关于以下对象
class Node
include Enumerable
# binary tree representation
attr_accessor :value, :left, :right
def initialize(value=nil, left=nil, right=nil)
@value, @left, @right = value, left, right
end
def map(&block)
res = Array.new
res << yield(value) if value
res << left.map(&block) if left
res << right.map(&block) if right
res.flatten
end
def map!(&block)
self = self.map(&block)
end
def to_a
map { |a| a }
end
end
我也尝试使用Enumerable的一些破坏性方法无济于事
map(&block).collect!
我的方法有什么问题,你会如何实现这样的功能?
更新
为了澄清这个想法是在二叉树上实现map,上面的map方法成功了,我的问题是将该方法转换为就地版本。
irb(main):001:0> require './node.rb'
=> true
irb(main):002:0> root = @root = Node.new(1, Node.new(2, Node.new(3), Node.new(4)),Node.new(5, Node.new(6), Node.new(7)))
=> #<Node:0x78803f58 @value=1, @left=#<Node:0x78abc090 @value=2, @left=#<Node:0x78abc0f0 @value=3, @left=nil, @right=nil>, @right=#<Node:0x78abc0c0 @value=4, @left=nil, @right=nil>>, @right=#<Node:0x78803f88 @value=5, @left=#<Node:0x78abc060 @value=6, @left=nil, @right=nil>, @right=#<Node:0x78abc030 @value=7, @left=nil, @right=nil>>>
irb(main):003:0> root.map { |a| a * 3 }
=> [3, 6, 9, 12, 15, 18, 21]
irb(main):004:0> root
=> #<Node:0x778fb828 @value=1, @left=#<Node:0x778fb9c0 @value=2, @left=#<Node:0x778fba68 @value=3, @left=nil, @right=nil>, @right=#<Node:0x778fb9f0 @value=4, @left=nil, @right=nil>>, @right=#<Node:0x778fb888 @value=5, @left=#<Node:0x778fb930 @value=6, @left=nil, @right=nil>, @right=#<Node:0x778fb8b8 @value=7, @left=nil, @right=nil>>>
irb(main):005:0> root.map! { |a| a * 3 }
=> [3, 6, 9, 12, 15, 18, 21]]
irb(main):006:0> root
=> [3, 6, 9, 12, 15, 18, 21]
答案 0 :(得分:2)
它通常是这样实现的:
class Node
attr_accessor :value, :left, :right
def initialize_copy(source)
super
@value = @value.dup
@left = @left.dup
@right = @right.dup
end
def map(&block)
dup.map!(&block)
end
def map!(&block)
@value.map!(&block) if @value
@left.map!(&block) if @left
@right.map!(&block) if @right
self
end
end
答案 1 :(得分:1)
self
是一个关键字,它不是变量。这就是为什么你不能分配它。
答案 2 :(得分:0)
这样的事情怎么样?
class Foo
attr_accessor :bar
def initialize(bar)
@bar = bar
end
def update!
self.instance_variables.each do |i|
self.instance_variable_set(i, yield(self.instance_variable_get(i)))
end
end
end
答案 3 :(得分:0)
Enumerable module根据您的特定于域的each
方法为您提供了大量方法。没有一种方法具有破坏性。
相反,我会使用Enumerable定义您自己的方法:
class Node
# define each and include, or do it by hand to customize:
Enumerable.instance_methods(false).each do |method|
define_method(method) do |*args|
# apply method to each instance variable
end
end
%w( map reject etc.. ).each do |method|
define_method("#{method}!") do |*args|
results = send(method)
# modify instance vars based on results
end
end
end