方法的局部变量与另一个方法同名

时间:2013-04-03 14:02:05

标签: ruby

我试图弄清楚Ruby如何处理与self类中的方法具有相同名称的局部变量,并发现了一个我不理解的行为:

class A
  def val
    10
  end

  def test
    val = val
  end
end

p A.new.test

此代码打印nil。为什么?!

4 个答案:

答案 0 :(得分:4)

我认为局部变量一旦声明就会被声明。在ruby中,查找首先查找局部变量,如果它存在则使用它,如果不存在则查找方法。这意味着val = val将第一个val声明为local,然后左手val将其匹配(不确定它我应该检查ruby under microscope以确定)

如果您尝试

class A
  def val
    10
  end

  def test
    back = []
    x = val
    back << x
    val = x + 1
    back << val
    x = val
    back << x
  end
end

p A.new.test

然后一切都很好,打印[10,11,11],这意味着第一个x = val调用方法,第二个调用局部变量,大概是。

答案 1 :(得分:0)

这是nil,因为val是您尝试传递的方法,并且您不会在任何地方调用val并且它会覆盖自己。你基本上陷入了困境。

在每个函数的最后是一个隐式返回,它返回最后一个值,如果它没有值返回Ruby返回nil,但你可能期望一个函数?

这在Python中类似,其中没有返回的函数总是返回None

这可以通过将左手val转换为具有@内涵的实例属性来解决。

我猜你想要用10方法打印val()吗?

def test
    @val = val()
end

puts A.new.test

以下也有效:

def test
    val = self.val() #but this will produce the same as above to no real benefit.
end

关键是您必须调用val方法才能使val变量获取值。

答案 2 :(得分:0)

这应该分为两个问题:

  1. 当你有a = a时,首先评估什么?如果你执行echo 'p a = a' | ruby,则得到nil,而不是未定义的异常,因此首先定义。

  2. 当局部变量与方法具有相同名称时会发生什么?答案:除非您使用self.

  3. ,否则方法将变为不可见

答案 3 :(得分:0)

其他答案解释一切正常我只是想向读者提出official documentation相同的问题。

  

在Ruby中,局部变量名和方法名几乎相同。如果你没有分配给其中一个含糊不清的名字,ruby会假设你想调用一个方法。一旦你分配了名称,ruby就会假设你想引用一个局部变量。

     

当解析器遇到赋值时创建局部变量,而不是在赋值发生时创建:

a = 0 if false # does not assign to a

p local_variables # prints [:a]

p a # prints nil
     

方法和局部变量名称之间的相似性可能会导致代码混淆,例如:

def big_calculation
  42 # pretend this takes a long time
end

big_calculation = big_calculation()
     

现在对big_calculation的任何引用都被视为局部变量并将被缓存。要调用该方法,请使用self.big_calculation。   您可以使用如上所示的空参数括号或使用self.之类的显式接收器强制进行方法调用。如果方法的可见性不公开,则使用显式接收器可能会引发NameError

     

另一个令人困惑的情况是使用修饰符if

p a if a = 0.zero?
     

您不会打印“true”,而是会收到NameError,“未定义的局部变量或方法`a&#39;”。由于ruby首先解析a左侧的if,但尚未看到a的赋值,因此它假设您希望调用方法。然后Ruby看到a的赋值,并假设您引用了一个本地方法。

     

混淆来自表达式的无序执行。首先分配局部变量,然后尝试调用不存在的方法。