# Looking for simple Ruby scoping docs

**URL:** <https://www.ruby-forum.com/t/looking-for-simple-ruby-scoping-docs/260632>\
**Category:** Development\
**Created:** [December 17, 2020, 7:47am UTC](https://www.ruby-forum.com/t/looking-for-simple-ruby-scoping-docs/260632 "2020-12-17T07:47:03Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![G4143](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/a88e57/32.png) [@G4143](https://www.ruby-forum.com/u/G4143)\
**Post date:** [December 17, 2020, 7:47am UTC](https://www.ruby-forum.com/t/looking-for-simple-ruby-scoping-docs/260632/1 "2020-12-17T07:47:03Z")

</div>

I always liked Ruby but one simple thing kept me from really digging into Ruby… Scoping.

I’m missing something fundamental about Ruby’s scoping. I know the code below has a scoping problem because I get an error.

```ruby
#! /usr/bin/env ruby
#encoding: utf-8

arr = [1, 2, 3,]

def displayArr
  arr.each{|e| puts e}
end

displayArr

```

But I fail to see why this fixes the problem

```ruby
#! /usr/bin/env ruby
#encoding: utf-8

arr = [1, 2, 3,]

def displayArr(a)
  a.each{|e| puts e}
end

displayArr(arr)

```

Is there any docs which cover Ruby scoping? Something that explains why its done this way.

Note: I prefer to read something that explains why its done this way over something that demonstrates the scoping rules.

---

<div class="post-metadata">

**Author:** ![pcl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ecae2f/32.png) [@pcl](https://www.ruby-forum.com/u/pcl)\
**Post date:** [December 17, 2020, 12:46pm UTC](https://www.ruby-forum.com/t/looking-for-simple-ruby-scoping-docs/260632/2 "2020-12-17T12:46:35Z")

</div>

Ruby starts a new scope whenever you start a new Class, Module or Method definition (these are called “scope gates”). That is why in your first case ‘arr’ is not visible within ‘displayArr’. In the second case you are passing a reference to the value so it works.

I read about this in the book _Metaprogramming Ruby_ by Paolo Perrotta, which discusses how to “flatten the scope”.

If writing a simple script, you could use a global variable:

```auto
$arr = [1, 2, 3,]

def displayArr
  $arr.each{|e| puts e}
end

displayArr

```

although I much prefer the second solution, passing in a value to a method.

> **[Understanding Variable Scope & Binding Objects in Ruby](https://www.rubyguides.com/2019/03/ruby-scope-binding/)**
>
> Scope is an important concept to understand for all Ruby developers. Why? Because it's the source of many error messages & confusion. What is scope? Scope refers to what variables are available at any given point in time. Different kind

---

<div class="post-metadata">

**Author:** ![G4143](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/a88e57/32.png) [@G4143](https://www.ruby-forum.com/u/G4143)\
**Post date:** [December 18, 2020, 3:33am UTC](https://www.ruby-forum.com/t/looking-for-simple-ruby-scoping-docs/260632/3 "2020-12-18T03:33:00Z")

</div>

I think what bothers me the most(in my posted example) is that I expected the scopes to nest in my posted example. I expected arr to be available in displayArr.

---

<div class="post-metadata">

**Author:** ![SouravGoswami](https://www.ruby-forum.com/user_avatar/www.ruby-forum.com/souravgoswami/32/2543_2.png) [@SouravGoswami](https://www.ruby-forum.com/u/SouravGoswami)\
**Post date:** [December 18, 2020, 5:49pm UTC](https://www.ruby-forum.com/t/looking-for-simple-ruby-scoping-docs/260632/4 "2020-12-18T17:49:38Z")

</div>

To make arr available to displayArr:

```auto
#! /usr/bin/env ruby
#encoding: utf-8

arr = [1, 2, 3,]

define_method(:displayArr) do
	arr.each{|e| puts e}
end

displayArr

```

But this also defines the method under Kernel if defined like this.

This define\_method() or define\_singleton\_method(), etc, are very helpful because they work as block, but `def` don’t. So if you need to access variables outside the scope, either use instance variables, global variables, or use `define_method()`

---

<div class="post-metadata">

**Author:** ![G4143](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/a88e57/32.png) [@G4143](https://www.ruby-forum.com/u/G4143)\
**Post date:** [December 19, 2020, 3:38am UTC](https://www.ruby-forum.com/t/looking-for-simple-ruby-scoping-docs/260632/5 "2020-12-19T03:38:27Z")

</div>

Can someone explain why its done this way or at least show me another language that does it this way?

---

<div class="post-metadata">

**Author:** ![SouravGoswami](https://www.ruby-forum.com/user_avatar/www.ruby-forum.com/souravgoswami/32/2543_2.png) [@SouravGoswami](https://www.ruby-forum.com/u/SouravGoswami)\
**Post date:** [December 19, 2020, 7:34am UTC](https://www.ruby-forum.com/t/looking-for-simple-ruby-scoping-docs/260632/6 "2020-12-19T07:34:52Z")

</div>

[Crystal](https://crystal-lang.org/) also does it that way 🤣🤣

And as said above by me and pcl, you have options, you can use global variable or instance variable to do that. It’s _not_ like you can’t absolutely do that.

If you think that’s confusing try JS:

 ![image](https://www.ruby-forum.com/uploads/default/original/2X/b/be639cfb1229b57ed11b49c2bddcf00eeaa3fde1.png)

* * *

Or maybe try perl:

```auto
$ perl -e "print 'a' x 5"
aaaaa

$ perl -e "print 'b' x 5"
bbbbb

$ perl -e "print 5 x 5"
55555

```

Which language use `x` to multiply string?

* * *

Everything is language specific, and you shouldn’t compare one to another.

JS also has let, var, const, let is more like defining local variable like Ruby, but it pollutes nested scopes. Ruby doesn’t do that. What other language use let and var to define variables? It’s just so confusing, Most of the times JS programs will work without those. People use `;` in JS, even though it has Automatic Semicolon Insertion. No other ASI language ask you to use `;`, in fact it’s a bad practice in Ruby or Python or in most shells.

So, if another language doesn’t have block concept like Ruby, doesn’t mean Ruby has to eliminate that. It’s been there like this forever. If you think Ruby’s syntax is confusing, try using JS for your console apps!

---

<div class="post-metadata">

**Author:** ![G4143](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/a88e57/32.png) [@G4143](https://www.ruby-forum.com/u/G4143)\
**Post date:** [December 19, 2020, 11:20am UTC](https://www.ruby-forum.com/t/looking-for-simple-ruby-scoping-docs/260632/7 "2020-12-19T11:20:27Z")

</div>

I think you mistook me. This isn’t a complaint about Ruby. If anything, its a complaint about me and understanding local variables in Ruby.

I just find it remarkable that I can’t understand why locals behave this way in Ruby. There must be a reason it was designed this way. They must have been designed this way for a reason and I can’t figure out what that reason is.

I’m odd this way. If I can’t understand why something behaves the way it does… I can’t understand it and use it with confidence.

---

<div class="post-metadata">

**Author:** ![pcl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ecae2f/32.png) [@pcl](https://www.ruby-forum.com/u/pcl)\
**Post date:** [December 19, 2020, 2:49pm UTC](https://www.ruby-forum.com/t/looking-for-simple-ruby-scoping-docs/260632/8 "2020-12-19T14:49:48Z")

</div>

> There must be a reason it was designed this way. They must have been designed this way for a reason

Actually, I think the other way. _Why_ should local variables be visible from within a method? A method definition is a “clean room” - I should be able to write a method definition and use that method anywhere without worrying about the context of local variables. Even in small scripts, I wouldn’t intermingle variable and method definitions in the way you did - it just seems unnatural to me. e.g. in Java, there is no option to declare local variables and methods in the mixed way that Ruby allows.

Allowing local variables to be visible inside methods opens up several complications:

- e.g. say you gave me a method definition, and I called it. Should I have to worry about _my_ local variable names to be able to use your method? e.g. if your method uses internally the variable _i_, then suddenly I cannot use the variable _i_ because you did? How would I know that?

- Or perhaps methods only “see” the local variables where they are defined, not where they are called? So I have to be careful where I copy-paste that method?

There’s a separate concept, the “closure”, which is a function which includes its local environment (local variables) at the point where it is defined. Closures are defined “on the fly”, when you need them in specific cases. You can see an example of a closure with do-end blocks, e.g.:

```auto
sum = 0
[1,2,3,4].each do |number|
  sum += number
end
puts sum

```

The do-end closure includes the local environment so it can use sum. The do-end defines a (nameless) function that gets passed to tne `each` method as an argument.

As @SouravGoswami has said, different languages offer different ways of doing things and different ways of thinking about problems. Which language are you most familiar with? I suspect that language has left you thinking of programs in “one way”.

To my way of thinking, Ruby’s method definitions are perfectly natural. You get a “clean room” within the method definition, but if you really, really want to work with the local environment within your method, you have closures and the scope-flattening `define_method` etc techniques.

---

<div class="post-metadata">

**Author:** ![pcl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ecae2f/32.png) [@pcl](https://www.ruby-forum.com/u/pcl)\
**Post date:** [December 19, 2020, 3:39pm UTC](https://www.ruby-forum.com/t/looking-for-simple-ruby-scoping-docs/260632/9 "2020-12-19T15:39:50Z")

</div>

> [@G4143](#):
>
> at least show me another language that does it this way?

Rust works this way. You can nest a function inside another function, but it cannot see the local variables, e.g.

```auto
fn main() {
    let x = 3;

    fn inner() {
        println!("X is {}", x)
    }

    inner();
}

```

gives error:

```auto
error[E0434]: can't capture dynamic environment in a fn item
 --> fns.rs:8:29
  |
8 | println!("X is {}", x)
  | ^
  |
  = help: use the `|| { ... }` closure form instead

error: aborting due to previous error

```

Note it recommends using a ‘closure’ if we want to see the local scope.

In Go, you can only use a ‘nameless’ function definition, i.e. a closure, within another function:

```auto
package main

import "fmt"

func main() {
  x := 3

  inner := func() { fmt.Printf("X is %d\n", x) }

  inner()
}

```

C supports shadowing of local variables, and it allows you to use a local variable in a local function definition:

```auto
#include<stdio.h>

int main(int argc, char* argv) {
  int x = 3;

  int inner() {
    printf("X is %d\n", x);
  }

  inner();
}

```
