Ruby Can Not Access Variable Outside the Method

Ruby can not access variable outside the method?

The result and template variables inside the generateMethods function are different from the ones declared outside and are local to that function. You could declare them as global variables with $:

$template=<<MTEMP
#methodName#:function(){},
MTEMP
$result="";
def generateMethods(mds)
mds.each do |md|
$result+=$template.gsub(/#methodName#/,md).to_s+"\n";
end
$result;
end
puts generateMethods(['getName','getAge','setName','setAge'])

But what's your purpose with this function? I think there's a cleaner way to do this if you can explain your question more.

Why can't I access a local variable inside a method in Ruby?

The reason ff is inaccessible inside the test method definition is simply that methods (created with the def keyword) create a new scope. Same with defining classes and modules using the class and module keywords respectively.

The role of main (the top-level object) is almost completely irrelevant to the question of scope in this situation.

Note that, if you DO want your test method to have access to locals defined in the definition context, then use the define_method (or in your case, the define_singleton_method method), see here:

ff = "hi"
define_singleton_method("test") { ff }
test #=> "hi"

Unlike the def keyword, the define_method family of methods do not create new scopes but instead close over the current scope, capturing any local variables.

The reason using @ff worked in the next example given by @soup, is not that main is somehow a "special case" it's just that an ivar defined at top-level is an ivar of main and so is accessible to a method invoked on main.

What, however, is the relationship of the test method to main? It is not a method on just main itself - it is actually a private instance method defined on the Object class. This means that the test method would be available (as a private method) to nearly every object in your ruby program. All methods defined at top-level (main) are actually defined as private instance methods on the Object class.

For more information on the Ruby top-level, see this article: http://banisterfiend.wordpress.com/2010/11/23/what-is-the-ruby-top-level/

Can you access Ruby variables with outer scope inside of methods?

This is a duplicate of Ruby accessing outer variables in nested function.

You could make it an instance variable on the containing object by calling it @rotation, but why not just pass string and rotation into the encrypt method?

Ruby struct creation block cannot access variable outside the block

It's because def keyword starts new local variables scope, so default local variable isn't visible inside of it. The workaround is to use define_method, because the block you pass into it is closure:

default = 'test'
A = Struct.new(:a, :b) do
define_method(:initialize) do |*args|
super(*args)
self.b ||= default
end
end
a = A.new
a.b
# => "test"

Why can I refer to a variable outside of an if/unless/case statement that never ran?

It's because of how the Ruby parser works. Variables are defined by the parser, which walks through the code line-by-line, regardless of whether it will actually be executed.

Once the parser sees x =, it defines the local variable x (with value nil) henceforth in the current scope. Since if/unless/case/for/while do not create a new scope, x is defined and available outside the code block. And since the inner block is never evaluated as the conditional is false, x is not assigned to (and is thus nil).

Here's a similar example:

defined?(x) and x = 0
x #=> nil

Note that this is a rather high-level overview of what happens, and isn't necessarily exactly how the parser works.

Unable to access instance variable outside the class in ruby

In order to print an instance variable, you must access it with the context of the instance.

p @obj.stacks

Ruby: Changing the variable outside the method

In your example you always create new binding (context) by calling foo. That is why changes are lost.

It should work if you call the same binding

b = foo
b.local_variable_get(:a) # => 1

eval("a = 2", b)
b.local_variable_get(:a) # => 2

b.local_variable_set(:a, 3)
b.local_variable_get(:a) # => 3

Is there a way to access a local variable defined inside a block outside the block?

binding returns a new instance every time you call it. You have to send eval to the same binding in order to access local variables that you've created earlier:

def create(code, b = binding)
width = code.each_line.map(&:length).max
code.each_line.map do |line|
'%-*s #=> %s' % [width, line.chomp, b.eval(line)]
end
end

puts create <<~'RUBY'
baz, qux = 5, 3
baz
qux
RUBY

Output:

baz, qux = 5, 3    #=> [5, 3]
baz #=> 5
qux #=> 3

Note that in the above example, binding will make the method's local variables available to the block:

create 'local_variables'
#=> ["local_variables #=> [:code, :b, :width]"]

You might want to create a more restricted evaluation context, e.g. (replicating Ruby's main)

def empty_binding
Object.allocate.instance_eval do
class << self
def to_s
'main'
end
alias inspect to_s
end
return binding
end
end

def create(code, b = empty_binding)
# ...
end


Related Topics



Leave a reply



Submit