Ruby Accessing Outer Variables in Nested Function

Ruby accessing outer variables in nested function

As far as I know, defining a named function within a function does not give you access to any local variables.

What you can do instead is use a Proc:

def foo(x)
bar = lambda do
puts x
end
bar.call
42
end

foo(5)

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?

Inner function in Ruby

A Ruby lambda is similar to an anonymous js function:

step1 = lambda {puts "I am a lambda!"}
step1.call "optional args", ...

Some shorthand:

f = -> {puts "Shorthand lambda"}
f.()

More info (including shorthand notation!!) here

Understanding Ruby Nested Functions

It's something called the "scope gate". Basically, when you start a definition of a method/class/module, a new scope is created and all local variables from other scopes can't be accessed. This doesn't apply to instance/global variables, you'll keep access to those.

Since a lambda isn't a method, it doesn't create new scope and reuses existing one instead.

Also,

why line 3 works

x = 123
def b(x)
p x # this "x" is "x the parameter", not "x the local variable from outer scope"
# that's why it works. If you tried to access the local var, it wouldn't work.
def a(u)
p x # like here, see? Doesn't work.
end
a 4
end

b 1

In Ruby, how can inner class access variables/methods defined in outer class?

In Ruby, how can inner class access variables/methods defined in outer class?

Ruby does not have a concept of "inner" or "outer" classes. It sounds like you are coming from a language like BETA, Scala, or Newspeak, but Ruby is not BETA, Scala, or Newspeak. As a general rule, any programming language works exactly how the specification for the programming language says it works, not how the specification for some other programming language says it works. BETA, Scala, and Newspeak have nested classes, but Ruby has not.

In Ruby, you can lexically nest a class definition, but that does not create a nested class. If you nest the definition of a class inside the definition of another class, that does not create any sort of relationship whatsoever between those two classes. None. You cannot "access variables/methods" of one class from the other class because there is no relationship between those two classes you could follow in order to get at those variables/methods.

The only thing a nested class definition does, is namespace the constant defined by the inner class definition to the outer class. That's it. There is no relationship between the two classes, the only relationship is between the constant and the class.

It is just not possible.

The way to create relationships between classes in Ruby is inheritance, not nesting (because there is no nesting). The way to create relationships between objects in Ruby is association, aggregation, or composition, not nesting.

Ruby is flexible enough to implement something that behaves like a "proper" BETA-style inner class. Remember, an inner class is "nested" inside an object instance of the outer class. We can emulate that using an instance variable:

class Outer
attr_reader :Inner

def outer_method
__callee__
end

private

attr_writer :Inner

def initialize
self.Inner = Class.new(self.class) do
def inner_method
[__callee__, outer_method]
end
end
end
end

outer = Outer.new
inner = outer.Inner.new
p inner.inner_method

Please note that I made the inner class inherit from the outer class: that is the way to do behavior sharing in Ruby. You need to have some form of inheritance or association relationship. The nesting does not create a relationship.

how to access a class variable of outer class from inner class in ruby

The only way to access this class variable is via an accessor method

class A
def self.lock
@@lock ||= Monitor.new
end

class B
def method
A.lock.synchronize
puts "xxxxx"
end
end
end
end

How do I set a local variable declared in a nested method to be within the parent method's scope?

Set the result of the proc to old_var so that it’s declared on the same scope where used.

old_var = 
@sandbox.function() do |resp|
resp.var.to_f
end

The same for new_var:

new_var = 
@sandbox.function() do |resp|
resp.var.to_f
end

How do I set a local variable declared in a nested method to be within the parent method's scope?

Answering the question in the title: that is impossible.


If you need to perform some actions before returning a value from a nested block, use break:

value =
@sandbox.function() do |resp|
foo = 42
# do something else
break foo
end

Let inner function use arguments of outer function

1) Define the inner function inside the outer function and the inner function will have access to the outer function's variables. Here inner uses a from outer even though a was not passed to inner.

outer <- function(a, x) {
inner <- function(y) {
a + y
}

inner(2 * x)
}

# test
outer(10, 100)
## [1] 210

2) Alternately, inject inner into outer like this:

inner <- function(y) {
a + y
}

outer <- function(a, x) {
environment(inner) <- environment()
inner(2 * x)
}

# test
outer(10, 100)
## [1] 210


Related Topics



Leave a reply



Submit