在使用Ruby时,是否有一种方法不使用$作为全局变量,或者将程序结构设置为将全局变量作为一些局部变量放在主方法中



也就是说,是否可能将其结构化为类似于JavaScript中的IIFE,从而使所有这些变量仅在函数范围内可见?

在将一些Go程序转换为Ruby以比较它们的运行速度时,我必须将Ruby中的所有Go全局变量从width转换为$width,以便在任何函数中都可以使用这些全局值。

但是,如果有15或20个这样的变量,那么转换就会变得非常麻烦。在Ruby中,有没有一种方法可以不对全局变量使用$?我试图首先定义一个main方法,并希望它是main:内部的本地方法

def main
  foo = 1
  def another
    p foo
  end
  another()
end
main()

但它不会起作用。在another()内部,它仍然无法识别foo,并且必须将所有foo更改为$foo才能工作。

根据请求,这是Go代码的一些示例:

var palette = []color.Color{color.White, color.Black}
const (
    whiteIndex = 0            
    blackIndex = 1            
    width, height = 800, 400
    viewAngle = math.Pi / 9
)

实际上,对于一些小型Go程序(或C程序)来说,在最上面有一些全局变量,然后是main和下面的一些函数是非常典型的。由于整个程序不是很大,通常不太关心一些全局变量,如颜色、宽度、高度等。

期望一种语言的概念出现在另一种语言中是非常天真的。这里不可能直接翻译。

然而,我认为如果你用原始的go代码创建一个类,你会得到完全相同的结构。看看:

class Program
  # your constants
  WHITE_INDEX = 0
  BLACK_INDEX = 1
  WIDTH = 800
  PALETTE = ['white', 'black'] # or something
  # your mutable data
  attr_accessor :foo
  # constructor and initialization of mutable data 
  # (if it has default values, that is)
  def initialize
    self.foo = 1
  end
  # your other methods/functions
  def another
    p foo
  end
  # or main or whatever you want to call it
  def run
    another
  end
end
# finally, run the damn thing!
Program.new.run

您不必使用全局变量来模拟常量(或者,就这一点而言,用于任何其他目的)。Ruby有常量(它们现在不是真正的常量,但这是你应该使用的)。

我认为一个相关的答案是:很多时候,全局变量实际上只是整个程序的常量。在这种情况下,只需在Ruby程序中使用WIDTHPALETTE等,Ruby就会将任何以大写字母开头的名称视为常量,并允许您在任何函数的全局范围或本地范围中使用它。命名常量的约定都是大写的,用下划线分隔单词,例如TILTING_FACTOR

如果您确实需要使用全局变量,建议仍然使用$foo这样的名称,以表明这是一个全局变量,并且要非常小心。通常,一个好的程序,在Ruby或Go中,不会使用全局变量,或者会尽量不使用全局变量。

根据Sergio的建议,这将是使用类常量的形式:

class Program
  FOO = 1
  VIEWING_ANGLE = Math::PI / 6     # so don't have to calculate again and again
  TILTING_FACTOR = Math.cos(VIEWING_ANGLE)
  COLOR_PALETTE = ['beige', 'darkgrey']
  def some_helper_function
    p "inside of helper function", FOO, VIEWING_ANGLE, TILTING_FACTOR, COLOR_PALETTE
  end
  def run
    p "inside of run", FOO, VIEWING_ANGLE, TILTING_FACTOR, COLOR_PALETTE
    some_helper_function()
  end
end
Program.new.run()

实际上,你可以使用全局常数,任何函数都可以访问它:

FOO = 1
VIEWING_ANGLE = Math::PI / 6     # so don't have to calculate again and again
TILTING_FACTOR = Math.cos(VIEWING_ANGLE)
COLOR_PALETTE = ['beige', 'darkgrey']
def some_helper_function
  p "inside of helper function", FOO, VIEWING_ANGLE, TILTING_FACTOR, COLOR_PALETTE
end
p "in global scope", FOO, VIEWING_ANGLE, TILTING_FACTOR, COLOR_PALETTE
some_helper_function()

还有一些其他方法:

我们实际上可以用函数的方式编写它,因为方法不是第一类值,也不是你可以操作的东西(我们可以用它创建一个method对象,但方法本身不是对象),正如David Flanagan和Matz在《Ruby编程语言》一书中所描述的那样。一个方法总是绑定到一个对象,并且是面向对象的。书中还说:

Method对象和Proc对象之间的一个重要区别是Method对象不是闭包。Ruby的方法是完全自包含的,它们永远不能访问自己范围之外的局部变量。

因此,我认为这意味着lambda(Proc对象的一种类型)是一个闭包,因此可以访问其本地作用域之外的作用域。

这就是功能方式:

foo = 1
some_helper_function = -> {
  p "inside of helper function", foo
}

p "in global scope", foo
some_helper_function.()

如果你不想污染全局空间,确实有一种类似于JavaScript的IIFE的方法:

-> {
    foo = 1
    some_helper_function = -> {
      p "inside of helper function", foo
    }

    p "inside the IIFE", foo
    some_helper_function.()
}.()
# outside of the IIFE, cannot access foo here

在Ruby中使用全局变量,而使用局部变量var或实例变量@var是不好的风格。

Ruby中不需要main()。您可以在所有函数定义之后在main中添加该代码。

最新更新