In Ruby is it possible to create a local variable explicitly
As per the Perl documentation of my,I think you are looking for something like below in Ruby:-
x = 123
p = Proc.new {|;x|
x = 'I do not want change the value of the outer x, I want to create a local x'
}
p.call
# => "I do not want change the value of the outer x, I want to create a local x"
x # => 123
Dynamically set local variables in Ruby
The problem here is that the block inside each_pair has a different scope. Any local variables assigned therein will only be accessible therein. For instance, this:
args = {}
args[:a] = 1
args[:b] = 2
args.each_pair do |k,v|
key = k.to_s
eval('key = v')
eval('puts key')
end
puts a
Produces this:
1
2
undefined local variable or method `a' for main:Object (NameError)
In order to get around this, you could create a local hash, assign keys to this hash, and access them there, like so:
args = {}
args[:a] = 1
args[:b] = 2
localHash = {}
args.each_pair do |k,v|
key = k.to_s
localHash[key] = v
end
puts localHash['a']
puts localHash['b']
Of course, in this example, it's merely copying the original hash with strings for keys. I'm assuming that the actual use-case, though, is more complex.
Local Variables and Methods with Ruby
The variable a
is not defined within the scope of the insert
method.
There are several types of variables in ruby, which can be summarised by the following table:
$ A global variable
@ An instance variable
[a-z] or _ A local variable
[A-Z] A constant
@@ A class variable
In order for your code to work, you could either define a
as a global variable (although this is generally considered bad practice!):
$a = [1,2,3,4,5]
puts "Pick number to insert into array:"
answer = gets.chomp()
def insert(answer)
$a.insert(1, answer)
end
insert(answer)
Or, you could define a
within the scope of the method:
puts "Pick number to insert into array:"
answer = gets.chomp()
def insert(answer)
a = [1,2,3,4,5]
a.insert(1, answer)
end
insert(answer)
Or, you could pass a
into the method as a parameter:
puts "Pick number to insert into array:"
answer = gets.chomp()
def insert(a, answer)
a.insert(1, answer)
end
a = [1,2,3,4,5]
insert(a, answer)
Or, you could define a class and make a
an instance variable of that class - for example, something like:
class HelloWorld
attr_reader :a
def initialize
@a = [1,2,3,4,5]
end
def insert(answer)
@a.insert(1, answer)
end
end
puts "Pick number to insert into array:"
answer = gets.chomp()
my_awesome_object = HelloWorld.new
my_awesome_object.insert(answer)
puts my_awesome_object.a
Local variables and methods with the same name in Ruby?
In ruby you can have local variables and methods with the same name. This has some complications for example with setter methods in classes:
class Test
def active
@active
end
def active=(value)
@active = value
end
def make_active
active = true
end
end
t1 = Test.new
t1.active = true
t1.active #=> true
t2 = Test.new
t2.make_active
t2.active #=> nil
Code for t1 object will return expected result, but code for t2 returns nil, because make_active method is actually creating local variable and not calling active= method. You need to write self.active = true to make this work.
When you write gen_class, ruby tries to access local variable, if it is not defined ruby tries to call method. You can call your method explicit by writing gen_class().
how to use truly local variables in ruby proc/lambda
Sometimes it is the desired behavior:
total = 0
(1..10).each{|x| total += x}
puts total
But sometimes it's accidental and you don't want to mess with an outside variable which happens to have the same name. In that case, follow the list of parameters with a semicolon and a list of the block-local variables:
x = lambda{|v; x| x = 2; v}
p x.call(3) #3
p x #<Proc:0x83f7570@test1.rb:2 (lambda)>
Ruby loop local variables and inmutability
each
loops often mutate the object. Each has to do something.
Because each
doesn't return anything useful - it returns the array itself, It won't mutate the object if it sends every element somewhere, like to be printed on screen.
foo.each do |bar|
# do something with element like
# print it, change it, save it
end
Functional alterantive is map
foo.map { |bar| bar.something }
It returns new array which is original array processed in immutable way. Obviously you have to be careful to use immutable methods. This would not be immutable:
foo.map { |bar| bar.something! }
Here something!
does something destructive to the element of array.
However I have never seen map
used like that. Use each
for something destructive.
listing the local variables in irb
Your code is really complicated and obfuscated. First, let's clean up your code a bit so that we can see more clearly what's going on. You don't need self
, since it is the default receiver anyway. And you don't need send
, because you already know the name of the method you want to call. Also, Kernel#local_variables
uses the current Binding
anyway. Also, typically, such methods which are supposed to by called without an explicit receiver and don't actually make use of self
(e.g. like puts
or require
) are put into Kernel
. So, your code is equivalent to the following:
module Kernel
def list_vars
local_variables.map {|var| "#{var} = " + binding.local_variable_get(var).inspect}
end
end
Now we can immediately see the problem: you are reflecting on the local variables and the Binding
of list_vars
and not the place where it was called from! You need to pass the Binding
into the method and use that instead:
module Kernel
def list_vars(binding)
binding.local_variables.map {|var| "#{var} = " + binding.local_variable_get(var).inspect}
end
end
list_vars(binding)
Or, you could make it an instance method of Binding
:
class Binding
def list_vars
local_variables.map {|var| "#{var} = " + local_variable_get(var).inspect}
end
end
binding.list_vars
Related Topics
Rails Adding Multiple Objects to an Empty Array
How to Specify Formatting Options for To_Yaml in Ruby
"Bad Ecpoint" Ssl Error on Fresh Rvm Ruby 1.9.3 Install on Osx Mountain Lion
How to Install Ruby System-Wide Using Rbenv
How to Deal with a Page Which Fails to Load and Continue Testing in Watir-Webdriver
Ruby Gem Cucumber Ssl Error and Gem Sources
Brew Install Coreutils Failing 10.9.5 Osx
Twitter::Error::Unauthorized in Postscontroller#Create - Invalid or Expired Token
Why Is Autoload Failing to Load Files for Gems
Ruby 1.8: Hash#Sort Not Return Hash But Array (Better Way to Do This)
Confused with Ruby Accessor Methods
How to Dry Up Method with Multiple { 'Not Found' }
Ruby 1.9 Ramaze App Failing with "Illegal Instruction"