Reputation: 150956
That is, possibly structuring it so that it is like an IIFE in JavaScript so that all those variables are visible only within a function scope?
When converting some Go programs into Ruby to compare their running speed, I had to convert all the Go global variables from width
to $width
in Ruby, so that inside any function, these global values can be used.
But if there are 15 or 20 of these variables, then it becomes very troublesome to convert. In Ruby, is there a way to not use $
for global variables? I tried to define a main
method first, and hoping it is local inside of main
:
def main
foo = 1
def another
p foo
end
another()
end
main()
but it won't work. Inside of another()
, it still won't recognize foo
and all the foo
have to be changed to $foo
for it to work.
As per request, this is some sample of the Go code:
var palette = []color.Color{color.White, color.Black}
const (
whiteIndex = 0
blackIndex = 1
width, height = 800, 400
viewAngle = math.Pi / 9
)
it actually is quite typical for some small Go program (or C program), to have some global variables at the very top, and then the main
and some functions down below. Since the whole program is not very big, there usually is not so much concern for some global variables such as the color, width, height, etc.
Upvotes: 0
Views: 656
Reputation: 150956
I think a relevant answer is this: a lot of times, the globals are really just constants for the whole program. In that case, just use WIDTH
, PALETTE
, etc in your Ruby program, and Ruby treats any name that begins with a capital letter as constants, and will let you use that in the global scope or local scope inside of any function. The convention to name constants are all caps, with underscore separating the words, such as TILTING_FACTOR
.
If you do really need to use a global variable, the recommendation is still to use a name such as $foo
, to signal that this is a global and be very careful. Typically, a good program, in Ruby or Go, will not use global variables or will try not to use it as much as possible.
Based on Sergio's suggestion, this will be the form, with the use of Class constants:
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()
and actually, you can use global constants and any function can access it:
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()
And some more ways:
We actually can write it in a functional way, because a method is not a first class value, and is not something you can operate on (we can create a Method object out of it, but a method itself is not an object), as described in the book The Ruby Programming Language by David Flanagan and Matz. A method is always tied to an object, and is intended for OOP. The book also said:
One important difference between Method objects and Proc objects is that Method objects are not closures. Ruby's methods are intended to be completely self-contained and they never have access to local variables outside of their own scope.
So I think that implies that lambda, which is one type of Proc objects, is a closure and therefore have access to the scope outside of its own local scope.
This is how in a functional way:
foo = 1
some_helper_function = -> {
p "inside of helper function", foo
}
p "in global scope", foo
some_helper_function.()
and if you don't want to contaminate the global space, there really is a way similar to JavaScript's 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
Upvotes: 1
Reputation: 230286
It is quite naive to expect concepts of one language to be present in another. Direct translation is not possible here.
However, I think that you'll get quite the same structure if you make a class out of original go code. Check it out:
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
You don't have to use global variables for emulating constants (or, for that matter, for any other purpose). Ruby has constants (they're not really constants at the moment, but this is what you're supposed to use).
Upvotes: 2
Reputation: 33732
It's bad style to use global variables in Ruby, use local variables var
or instance variables @var
instead.
main()
is not needed in Ruby. You can just add that code inside main after all the function definitions.
Upvotes: 0