[英]Global vs local variables?
I am wondering why my code works in one instance but doesn't in another. 我想知道为什么我的代码只能在一个实例中工作而不能在另一个实例中工作。 Does it have something to do with local and global variables? 它与局部和全局变量有关吗?
This works: 这有效:
def factorial num
result = 1
while (num > 1)
result = result * num
num -= 1
end
puts result
end
This doesn't work: 这不起作用:
result = 1
def factorial num
while (num > 1)
result = result.to_i * num
num -= 1
end
puts result
end
Everything inside of a method definition cannot see local variables from other places. 方法定义中的所有内容都看不到其他地方的局部变量。 That sounds weird, but here's two ways to fix it: 听起来很奇怪,但是有两种解决方法:
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)
That passes result as an argument. 将结果作为参数传递。 That's a great way of handling the method because it doesn't allow you to change the value of result from within the method. 这是处理方法的好方法,因为它不允许您从方法内部更改结果的值。 That might not seem like a big deal but "pure methods" like this become very valuable as the size the code increases. 看起来似乎没什么大不了,但是随着代码的增加,像这样的“纯方法”变得非常有价值。
This is the "dirty" or un-pure way of doing the same thing: 这是做同一件事的“肮脏”或不纯净的方式:
@result = 1
def factorial(num)
while (num > 1)
@result = @result.to_i * num
num -= 1
end
puts @result
end
Putting an @
in front of a variable name allows its scope to expand to methods defined outside of its scope. 在变量名前面放置一个@
,可以将其范围扩展到其范围之外定义的方法。 This becomes a problem as the complexity of your code increases. 随着代码复杂度的增加,这成为一个问题。
Random personal opinion: even though Ruby doesn't require you to put the parentheses next to a method definition, you always should. 个人观点:尽管Ruby不需要您将括号放在方法定义的旁边,但您始终应该这样做。 It makes the code a lot more explicit and easier to read. 它使代码更加明确和易于阅读。 Follow your heart though ;) 虽然跟随你的心;)
You could experiment by prepending all result
s with a $ sign, making it global. 您可以通过在所有result
前加$符号进行实验,使其成为全局变量。 Prepending with a @ results in an instance variable, also interesting. 以@开头会产生一个实例变量,这也很有趣。 Sidenote: puts
prints and returns nil
, so your method returns nil
. 旁注: puts
打印并返回nil
,因此您的方法返回nil
。
result = 1 # line 1
def factorial num
while (num > 1)
result = result.to_i * num
num -= 1
end
puts result
end
In this code, factorial
doesn't know about result
variable from the line 1. 在这段代码中, factorial
不知道第1行的result
变量。
When Ruby find result = result.to_i * num
in your method it will first assign nil
to the result
. 当Ruby在您的方法中找到result = result.to_i * num
时,它将首先为result
分配nil
。 Then Ruby will try to run result.to_i * num
. 然后,Ruby将尝试运行result.to_i * num
。 Since result
is already nil
, result.to_i
is equal 0. 由于result
已经为nil
,所以result.to_i
等于0。
Here is another example: 这是另一个示例:
def foo
a = a
puts "#{a.class}"
end
foo #NilClass
In the Doesn't Work version the result
variable you've assigned to 1 isn't visible inside the factorial
method. 在“不工作”版本中,您分配给1的result
变量在factorial
方法内不可见。
Now there is a possibly unexpected behaviour in Ruby that if you try to assign a variable and you refer to the same variable on the right hand side of the assignment, if that variable doesn't have a value yet then it is treated as nil
rather than raising an error. 现在,在Ruby中可能发生了意外的行为,如果您尝试分配一个变量,并在赋值的右侧引用了相同的变量,则如果该变量没有值,则将其视为nil
而不是而不是引发错误。 So the first time round the loop when you perform 所以当你第一次表演时
result = result.to_i * num
it's equivalent to result = nil.to_i * num
and nil.to_i
is equal to 0 so this then sets up result
to be 0 for subsequent iterations of the loop and as you're just multiplying the value of result stays on 0. 它等效于result = nil.to_i * num
和nil.to_i
等于0,因此在随后的循环迭代中将result
设置为0,因为您乘以result的值保持为0。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.