也就是说,是否可能将其结构化为类似于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程序中使用WIDTH
、PALETTE
等,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中添加该代码。