全局变量还是局部变量?

Global vs local variables?

我想知道为什么我的代码在一个实例中有效,但在另一个实例中却无效。跟局部变量和全局变量有关系吗?

这个有效:

def factorial num
  result = 1
  while (num > 1)
    result = result * num
    num -= 1
  end
  puts result
end

这行不通:

result = 1

def factorial num
  while (num > 1)
    result = result.to_i * num
    num -= 1
  end
  puts result
end

方法定义中的所有内容都无法从其他地方看到局部变量。这听起来很奇怪,但有两种解决方法:

    result = 1
    number = 10

    def factorial(num,result_value)
      while (num > 1)
        result_value = result_value.to_i * num
        num -= 1
      end
      puts result_value
    end

    factorial(number, result)

将结果作为参数传递。这是处理方法的好方法,因为它不允许您从方法内部更改结果的值。这可能看起来没什么大不了的,但是 "pure methods" 随着代码大小的增加,这样会变得非常有价值。

这是做同样事情的 "dirty" 或非纯粹的方式:

@result = 1

def factorial(num)
  while (num > 1)
    @result = @result.to_i * num
    num -= 1
  end
  puts @result
end

在变量名前加上 @ 允许其范围扩展到在其范围之外定义的方法。随着代码复杂性的增加,这会成为一个问题。

随机个人意见:尽管 Ruby 不要求您将括号放在方法定义旁边,但您始终应该这样做。它使代码更加明确和易于阅读。随心所欲 ;)

您可以通过在所有 result 前加上一个 $ 符号来进行试验,使其成为全球性的。在实例变量前加上 @ 会产生一个实例变量,这也很有趣。旁注:puts 打印和 returns nil,所以你的方法 returns nil.

result = 1 # line 1

def factorial num
  while (num > 1)
    result = result.to_i * num 
    num -= 1
  end
  puts result
end

在此代码中,factorial 不知道第 1 行中的 result 变量。
当 Ruby 在您的方法中找到 result = result.to_i * num 时,它将首先将 nil 分配给 result。然后Ruby会尝试运行result.to_i * num。因为 result 已经是 nil,所以 result.to_i 等于 0.

这是另一个例子:

def foo
  a = a
  puts "#{a.class}"
end
foo #NilClass

不起作用 版本中,您分配给 1 的 result 变量在 factorial 方法中不可见。

现在 Ruby 中可能出现意外行为,如果您尝试分配一个变量并且在分配的右侧引用同一个变量,如果该变量没有value 然后它被视为 nil 而不是引发错误。所以当你执行

时第一次循环
result = result.to_i * num

它等同于 result = nil.to_i * num 并且 nil.to_i 等于 0 所以这将设置 result 为 0 对于循环的后续迭代,因为你只是乘以结果的值保持为 0。