令人惊讶的Ruby范围与while循环

时间:2016-10-30 16:10:50

标签: ruby while-loop scope local-variables

(1)

2
1

输出

a = [1, 2]
puts b while b = a.pop

(2)

undefined local variable or method `b'

导致错误

b = nil
a = [1, 2]
puts b while b = a.pop

(3)

2
1

输出

b

发生了什么事?为什么#2中$ ruby --version ruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-linux] 的范围与其他任何范围不同?

public interface IPerson
{
}
public abstract class Person
{
    public string Name { get; set; }
    public string LastName { get; set; }
    public Int16 Age { get; set; }
}
public class Politics : Person, IPerson
{
    public string Party { get; set; }
    public int Experience { get; set; }
}
public class Students : Person, IPerson
{
    public string Major { get; set; }
    public int Year { get; set; }
}
public class Retired: Person, IPerson
{
    public int Pension { get; set; }
    public string Hobby { get; set; }
}
public class PersonLists : IPerson
{
    public List<Retired> AllRetired = new List<Retired>();
    public List<IPerson> AllPeople = new List<IPerson>();
    public Students AStudent = new Students();
    public Politics APolitic = new Politics();
    public Retired ARetired = new Retired();
}
编辑:最初我列出了irb的行为不同。它不是;我在一个“肮脏”的会议中工作。

3 个答案:

答案 0 :(得分:0)

puts语句在最初定义变量'b'之前执行,因此导致错误。

作为一个类似的示例,但使用until语句,请考虑以下代码:

a = [1, 2]
begin
  puts "in the block"
end until b = a.pop

您是否希望在块内定义b?

从技术上讲,唯一的区别是直到真正的返回值停止,而只要a.pop返回真值,while将继续。

两种情况都是b在发生之前,b <范围内 。在作业完成后,例如当循环返回时,b在当前范围内可用。这就是所谓的词法范围,就像ruby一样适用于像这样的局部变量。

我发现this article有助于理解ruby中的范围。

更新1:在我的回答的上一个版本中,我写道,这与 if 无法比较。虽然这仍然是正确的,但它与问题无关,这是一个简单的范围问题。

更新2:添加了一些链接,以获取有关红宝石作用域的更多详细说明。

更新3:删除了第一句,因为它错了。

答案 1 :(得分:0)

变量由词法解析器声明到它们的范围,它是线性的。在while b = a.pop do puts b end中,解析器在使用(b = a.pop)之前会看到赋值(puts b)。在第二个示例puts b while b = a.pop中,当定义仍然未知时会看到使用,这会产生错误。

答案 2 :(得分:-1)

a = [1, 2]
while b = a.pop do puts b end

相同
a = [1, 2]
b = a.pop 
puts b
b = a.pop
puts b 

(2)

a = [1, 2]
puts b while b = a.pop

与此相同

a = [1, 2]
puts b
b = a.pop
puts b
b = a.pop
puts b

当b第一次传入时,它尚未初始化。因此错误信息

(3) b初始化为零。甚至nil是ruby中的一个对象

b = nil
a = [1, 2]
puts b while b = a.pop