本文介绍了为什么Ruby中存在全局变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了有关全局变量的 C2Wiki ,我对此有三个疑问(在这篇文章的底部).主要问题是:如果全局变量如此糟糕,为什么Ruby为什么要使用它们?

I've read C2Wiki on Global Variables, and I have three questions about them (at the bottom of this post). The main question is: If Global Variables are so bad, why does Ruby have them?

此外,我注意到Ruby中有关全局变量的一些有趣行为,这导致它们与常规全局级常量的工作方式不同.

Also, I've noticed some interesting behaviour regarding Global Variables in Ruby, that causes them to work differently to regular global-level constants.

1..引用未定义的全局变量将返回nil.引用未定义的全局常量将返回NameError:

1. Referencing an undefined Global Variable returns nil. Referencing an undefined global constant returns a NameError:

2.2.3 :001 > $THING
 => nil
2.2.3 :002 > THING
NameError: uninitialized constant THING
    from (irb):2
    from /Users/makerslaptop82/.rvm/rubies/ruby-2.2.3/bin/irb:15:in `<main>'

2..irb用定义的$stdoutSTDOUT初始化.您可以重新定义$stdout,这不会影响STDOUT:

2. irb is initialized with both $stdout and STDOUT defined. You can redefine $stdout, and this doesn't affect STDOUT:

2.2.3 :001 > $stdout
 => #<IO:<STDOUT>>
2.2.3 :002 > STDOUT
 => #<IO:<STDOUT>>
2.2.3 :003 > $stdout = IO.new(6)
 => #<IO:fd 6>
2.2.3 :004 > $stdout
 => #<IO:fd 6>
2.2.3 :005 > STDOUT
 => #<IO:<STDOUT>>

我的问题是:

  • 如果全局变量是如此糟糕,为什么Ruby为什么要使用它们?
  • 为什么引用未定义的全局变量返回nil而不是NameError?这个选择是故意的吗?为什么?
  • 在单个程序中拥有两个以相同名称命名的STDOUT版本是否存在危险? (我假设这也适用于其他全局定义的对象)
  • If Global Variables are so bad, why does Ruby have them?
  • Why does referencing undefined Global Variables return nil instead of a NameError? Was this choice deliberate? Why?
  • Is there some danger to having two virtually-identically-named versions of STDOUT in a single program? (I assume there are other globally-defined objects that this applies to as well)

推荐答案

全局变量还不错.他们不是邪恶的.它们非常强大.这就是为什么您不应该使用它们的原因.

Global variables are not bad. They're not evil. They're just incredibly, incredibly powerful. Which is why you shouldn't use them.

全局变量是全局变量-可以在代码中的任何位置访问和修改它们.单个全局变量可能会影响您的所有类,所有函数,加载到项目中的每个库或依赖项的所有类和函数,所有类以及每个将您的项目作为依赖项加载的项目的功能,以及加载那些项目的项目,等等,等等,直到永远.剩下的时间.

Global variables are global- they can be accessed and modified anywhere in the code. A single global variable has the potential to affect all of your classes, all of your functions, all of the classes and functions of every single library or dependency you load into your project, and all of the classes and functions of every single project which loads your project as a dependency, as well as the projects that load those projects, and so and and so forth, for ever and always, for the rest of time.

第二个人开始对使用全局变量感到自在,名称空间变得异常混乱,我们左右冲突,并且编程语言本身的稳定性受到威胁.这就是为什么不建议反复使用全局变量的原因.

The second people start feeling comfortable using global variables, the namespace gets insanely cluttered and we get conflicts left and right and the stability of the programming language itself is threatened. Which is why the use of global variables is emphatically and repeatedly discouraged.

但是全局变量还不错.它们就像标记为仅用于应急车辆"的高速公路车道,或者像标记为紧急情况下要砸碎玻璃"的玻璃后面的那些火斧.

But global variables are not bad. They're like the highway lanes labeled "for emergency vehicles only," or like those fire-axes behind glass labeled "break glass in case of emergency."

在遥远的将来,在某个时候,您很有可能会遇到非常异常的情况,需要使用单个全局变量.但是那天不是今天.而且可能不是明天,也不是现在的一个月,也不是现在的一年.日常生活和日常代码-只是不需要全局变量的强大功能.

It's entirely possible that at some point, in the distant future, you will have an incredibly unusual situation which merits the use of a single global variable. But that day is not today. And it is probably not tomorrow, or a month from now, or a year from now. Daily life, daily code- it just doesn't call for the unbridled power of a global variable.

$stdout是为什么有时全局变量很重要的一个很好的例子. $stdout是ruby中的默认流-如果未指定其他流,则将在其中打印内容.每个库中的每个类和每个函数都可以访问$stdout,因为它的作用就像一个巨大的漏斗,将所有输出推到一个位置.全世界都知道并同意$stdout存在于红宝石中,并且其使用有据可查,因此其功能得到了很好的管理.

$stdout is a great example of why global variables are sometimes important. $stdout is the default stream in ruby- the one where things will print if no other stream is specified. $stdout should be accessible from every class and every function in every library because it acts like a giant funnel, shoveling all output to a single location. The whole world knows and agrees that $stdout exists in ruby, and its uses are well-documented, so its power is well-managed.

这不要与STDOUT混淆,STDOUT是一个常量,代表表示在ruby及其父程序(通常是终端)之间建立流的实际管道. $stdout = STDOUT默认情况下,但$stdout可以更改为任何内容.如果要让程序打印到文件,可以将$stdout更改为文件流.

This isn't to be confused with STDOUT which is a constant representing the actual pipe which sets up a stream between ruby and its parent program (usually a terminal). $stdout = STDOUT by default, but $stdout can be changed to anything. If you want your program to print to a file, you can change $stdout to a file stream.

对于经验丰富的红宝石专家,我认为这个名称选择不会造成混淆.变量被设计为可修改,常量被设计为常量. $ stdout和STDOUT之间的区别在于,可以修改前者以更改程序的标准输出位置,而后者是一个常数,始终指向stdout流.大写字母使世界变得与众不同,并传达了截然不同的含义.

I don't think this name choice is confusing for a seasoned rubyist. A variable is designed to be modified and a constant is designed to be constant. The difference between $stdout and STDOUT is that the former can be modified to change the standard output location of your program, and the latter is a constant, always pointing to the stdout stream. The capitalization makes a world of difference and conveys very different meanings.

关于为什么全局常量未初始化而全局变量为nil的原因,实际上与全局变量无关. Ruby自动将所有变量初始化为nil.您可以使用实例变量(例如@foo@@foo)轻松地看到这一点.在几乎每种情况下,未定义的局部变量都会抛出NameError,因为ruby无法分辨它是变量还是方法.但是在奇怪的情况下,它们也被初始化为nil:

As for why global constants are uninitialized and global variables are nil, that actually has nothing to do with globals. Ruby automatically initializes all variables as nil. You can easily see this with instance variables such as @foo or @@foo. In almost every situation, an undefined local variable will throw a NameError because ruby cannot tell whether it is a variable or a method. But in strange situations, they too are initialized as nil:

puts foo # => NameError: undefined local variable or method 'foo'
foo = 42 if false
puts foo # => nil

puts bar # => NameError
bar = bar
puts bar # => nil

在Ruby中不是,自动初始化常量是明智的设计选择.因为从定义上来说,常量是一个先初始化然后永不更改的东西,所以它将破坏常量的定义,即该常量首先为nil,然后在代码中随后为另一个值.

It was a conscious design choice in Ruby not to automatically initialize constants. Because a constant is, by definition, something which is initialized once and then never changed, it would break the definition for a constant to be nil at first and then a different value later in the code.

我还应该提到,即使在吹捧全局变量的人中也认为全局常量是可以接受的.不同之处在于,常量只能分配一次,如果再次分配常量,通常会引发警告或错误.这样可以保护程序员免受冲突的全局常量可能引起问题的情况的影响.

I should also mention that global constants are considered acceptable, even among people who tout global variables as bad. The difference is that constants can only be assigned once and generally throw a warning or error if they get assigned again. This protects programmers from situations where conflicting global constants might cause problems.

这篇关于为什么Ruby中存在全局变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-13 10:18