In my Ruby scripts, I often have some top level data structures, that are transformed by a series operations. These transformations are largely independent of each other, but complex enough so that they need local variables to get the work done.

1
2
3
4
5
6
7
8
9
10
11
12
13
my_var = ...

transform1
# update my_var

transform2
# update my_var

transform3
# update my_var

# desired state of my_var
p my_var

In C/Java, I can probably use curly braces, { // transform1 }, to encapsulate all temporary local variables, but Ruby doesn’t support that… Instead, Ruby has something like “self-invoking” function, which defines a new scope for local variables. Additionally, if I am super paranoid wrt mutating the surround scope, I can use def function so that the new scope doesn’t even have access to my top level variables. Technically, I don’t need to wrap def function ... end block in a “self-invoking” function, but the indentation provides a visual aid to discern its boundary. The following snippet shows how the two solutions can be used.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
x = 1

-> {
p x
x += 1
}.[]

p x

1.times do
p x
x += 1
end

p x

-> {
def f
p "calling f"
p defined?(x) # nil
# p x # undefined error
end
f
undef f
}.[]

p defined?(f) # nil

# running results:
# 1
# 2
# 2
# 3
# "calling f"
# nil
# nil

Reference

https://www.sitepoint.com/understanding-scope-in-ruby/