2016-04-27 151 views
2

我一直在寻找类似的问题,但无法找到解决这种情况下:PROC设置为默认方法参数

我有这个类:

class BinarySearchTree 

.... 

    find_work_node = Proc.new do |value, node, method| 
    return if node.nil? 
    if value == node.value 
     node = self.send(method node) 
    elsif value < node.value 
     node.left = find_work_node.call(value, node.left, method) 
    elsif 
     node.right = find_work_node.call(value, node.right, method) 
    end 
    node 
    end 

    # Delete a specific value from the tree 
    def delete(value, node = @root, block = find_work_node) 
    block.call(value, node, :delete_node) 
    end 

.... 

end 

当我打电话我delete方法,出现这样的错误:

undefined local variable or method `find_work_node' for #<BinarySearchTree:0x00000001018708> (NameError) 

我怎样才能在delete方法设置为默认参数的PROC find_work_node

回答

4

删除方法是一个实例方法,这样的默认值应该是可以从一个实例方法的范围进行访问的变量。既可以使用一类可变@@var或一个实例变量@var

实施例:

class A 
    @@class_var = Proc.new{|v| puts v} 

    def initialize 
    @instance_var = Proc.new{|v| puts v} 
    end 

    def m1 [email protected]@class_var 
    a.call "foo" 
    end 

    def m2 [email protected]_var 
    a.call "bar" 
    end 

end 
a = A.new 
a.m1 
# foo 
a.m2 
# bar 
+0

由于class_var的值不会改变,所以我推荐使用常量。一般来说,使用更受约束的结构更好,因为它更准确地传达了意图和使用。 –

+0

@KeithBennett我同意,但它确实取决于用例。从问题中不清楚是否存在默认参数的可变性意图。可以认为,由于首先使用了一个变量,并且因为这是一个参数,而参数本身是可变的,所以也可以允许突变默认值。但是我也可以看到论证的另一面。然而,最初的问题是范围,而不是可变性的问题,因此任何解决范围问题的答案都是有效的IMO – Rado

+0

同意。我从来没有打算表示你的回答是不正确的。 –

1

问题是范围。您正在将类find_work_node定义为类体中的局部变量,这样它的作用域就是类体,只能在内部访问,但不能在您定义的任何方法中使用。

注意,只需将其更改为一个实例变量@find_work_node不会工作,因为它仍然是在类级别的实例变量,虽然你不会得到这个错误了,在方法的参数@find_work_node变量无。你需要在类的initialize方法来初始化:

def BinarySearchTree 
    def initialize 
     @find_work_node = ... 
    end 
end 
1

可以使find_work_node一类由全部大写定义它常数,那么这将是实例方法中的访问。注意在output_bar不是一个实例方法访问的IRB会话,但OUTPUT_FOO是:

2.3.0 :001 > output_bar = -> { puts "I am bar." }; def bar; output_bar.(); end; bar 
NameError: undefined local variable or method `output_bar' for main:Object 
    from (irb):1:in `bar' 
    from (irb):1 
    from /Users/kbennett/.rvm/rubies/ruby-2.3.0/bin/irb:11:in `<main>' 
2.3.0 :002 > OUTPUT_FOO = -> { puts "I am foo." }; def foo; OUTPUT_FOO.(); end; foo 
I am foo. 
=> nil 

还要注意,虽然这个例子使用lambda表达式,没关系由变量包含的数据类型是什么。

它也可以定义返回Proc的方法。