What Are Ruby's Numbered Global Variables

What are Ruby's numbered global variables

They're captures from the most recent pattern match (just as in Perl; Ruby initially lifted a lot of syntax from Perl, although it's largely gotten over it by now :). $1, $2, etc. refer to parenthesized captures within a regex: given /a(.)b(.)c/, $1 will be the character between a and b and $2 the character between b and c. $` and $' mean the strings before and after the string that matched the entire regex (which is itself in $&), respectively.

There is actually some sense to these, if only historically; you can find it in perldoc perlvar, which generally does a good job of documenting the intended mnemonics and history of Perl variables, and mostly still applies to the globals in Ruby. The numbered captures are replacements for the capture backreference regex syntax (\1, \2, etc.); Perl switched from the former to the latter somewhere in the 3.x versions, because using the backreference syntax outside of the regex complicated parsing too much. (By the time Perl 5 rolled around, the parser had been sufficiently rewritten that the syntax was again available, and promptly reused for references/"pointers". Ruby opted for using a name-quote : instead, which is closer to the Lisp and Smalltalk style; since Ruby started out as a Perl-alike with Smalltalk-style OO, this made more sense linguistically.) The same applies to $&, which in historical regex syntax is simply & (but you can't use that outside the replacement part of a substitution, so it became a variable $& instead). $` and $' are both "cutesy": "back-quote" and "forward-quote" from the matched string.

How do you use global variables or constant values in Ruby?

One thing you need to realize is in Ruby everything is an object. Given that, if you don't define your methods within Module or Class, Ruby will put it within the Object class. So, your code will be local to the Object scope.

A typical approach on Object Oriented Programming is encapsulate all logic within a class:

class Point
attr_accessor :x, :y

# If we don't specify coordinates, we start at 0.
def initialize(x = 0, y = 0)
# Notice that `@` indicates instance variables.
@x = x
@y = y
end

# Here we override the `+' operator.
def +(point)
Point.new(self.x + point.x, self.y + point.y)
end

# Here we draw the point.
def draw(offset = nil)
if offset.nil?
new_point = self
else
new_point = self + offset
end
new_point.draw_absolute
end

def draw_absolute
puts "x: #{self.x}, y: #{self.y}"
end
end

first_point = Point.new(100, 200)
second_point = Point.new(3, 4)

second_point.draw(first_point)

Hope this clarifies a bit.

Using a global variable as an argument in a ruby method

You seem to be misunderstanding how a program is read and is executed. In particular, you seem to have a wrong idea about the timing in which a method is called.

When your script is executed, in the top part of the script, the method multiply is defined, not executed, at that point (Method execution is only done when it is called with particular arguments).

Then local variables, not global ones, first_number and second_number are set according to the input from the console.

Then, within the argument of puts, the method multiply is called with the arguments first_number and second_number.

Within the method execution, not definition, of multiply, the given first_number and second_number are assigned to first_num and second_num respectively, which can be accessed only within the method execution.

The calculated value is returned from the method multiply, and is put in the #{} part of the argument of puts. There, the method to_s is applied to the value, and becomes part of what is output.

Global vs local variables?

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. It makes the code a lot more explicit and easier to read. Follow your heart though ;)

Is it good practies to use Global variable in ROR 3.0

Regardless of where global variables are used, they are generally bad.

Why Global Variables Should Be Avoided When Unnecessary

  • Non-locality -- Source code is easiest to understand when the scope of its individual elements are limited. Global variables can be read or modified by any part of the program, making it difficult to remember or reason about every possible use.
  • No Access Control or Constraint Checking -- A global variable can be get or set by any part of the program, and any rules regarding its use can be easily broken or forgotten. (In other words, get/set accessors are generally preferable over direct data access, and this is even more so for global data.) By extension, the lack of access control greatly hinders achieving security in situations where you may wish to run untrusted code (such as working with 3rd party plugins).
  • Implicit coupling -- A program with many global variables often has tight couplings between some of those variables, and couplings between variables and functions. Grouping coupled items into cohesive units usually leads to better programs.
  • Concurrency issues -- if globals can be accessed by multiple threads of execution, synchronization is necessary (and too-often neglected). When dynamically linking modules with globals, the composed system might not be thread-safe even if the two independent modules tested in dozens of different contexts were safe.
  • Namespace pollution -- Global names are available everywhere. You may unknowingly end up using a global when you think you are using a local (by misspelling or forgetting to declare the local) or vice versa. Also, if you ever have to link together modules that have the same global variable names, if you are lucky, you will get linking errors. If you are unlucky, the linker will simply treat all uses of the same name as the same object.
  • Memory allocation issues -- Some environments have memory allocation schemes that make allocation of globals tricky. This is especially true in languages where "constructors" have side-effects other than allocation (because, in that case, you can express unsafe situations where two globals mutually depend on one another). Also, when dynamically linking modules, it can be unclear whether different libraries have their own instances of globals or whether the globals are shared.
  • Testing and Confinement - source that utilizes globals is somewhat more difficult to test because one cannot readily set up a 'clean' environment between runs. More generally, source that utilizes global services of any sort (e.g. reading and writing files or databases) that aren't explicitly provided to that source is difficult to test for the same reason. For communicating systems, the ability to test system invariants may require running more than one 'copy' of a system simultaneously, which is greatly hindered by any use of shared services - including global memory - that are not provided for sharing as part of the test.

In Ruby, is there a way to print out all the Global variables and Constants defined / predefined?

The global_variables method returns an array of all global variable names. To get the names of all the constants defined in a module, send constants to the relevant module. For example, to get all the constants that you can access without specifying a namespace, use Object.constants.

How to dynamically create local and global variables?

You cannot define a local variable with a full stop (.) character in ruby. That is not valid syntax.

(eval):2: unexpected fraction part after numeric literal
string_1.0 = "1.0"

Additionally, you cannot dynamically define local variables. There are various workarounds to sort-of achieve this, however, fundamentally I think you are asking an XY problem.

For example, have you considered using an OpenStruct, or passing this hash as locales when rendering a template, or instead dynamically setting instance variables?

Using global variable iteration with ruby -pe command line

I think that the expression "⎦#{$i+=1}⎡" is computed only once. A block is computed at each replacement.

$i=0
File.open('test.txt') do |f|
f.each_line do |line|
modif = line.gsub(/\d+/) {|num| "#{$i+=1}"}
puts modif
end
end

outputs :

Lorem ipsum dolor 1 sit amet, consectetuer adipiscing elit, sed 2 diam nonummy nibh euismod 3 tincidunt ut laoreet dolore magna 4 aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci 5 tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.

New input :

Lorem ipsum dolor 2 sit amet, consectetuer adipiscing elit, 
sed 7 diam nonummy nibh
euismod 1 tincidunt ut 44

laoreet dolore magna 10 aliquam erat volutpat.
Ut wisi enim 0 ad minim veniam, 4 quis nostrud
exerci 15 tation ullamcorper 66 suscipit 88
lobortis 6 nisl ut aliquip ex 1 ea1 co1mmodo consequat.

output :

Lorem ipsum dolor 1 sit amet, consectetuer adipiscing elit, 
sed 2 diam nonummy nibh
euismod 3 tincidunt ut 4

laoreet dolore magna 5 aliquam erat volutpat.
Ut wisi enim 6 ad minim veniam, 7 quis nostrud
exerci 8 tation ullamcorper 9 suscipit 10
lobortis 11 nisl ut aliquip ex 12 ea13 co14mmodo consequat.


Related Topics



Leave a reply



Submit