For this one, you have to think like the computer.
When the parser runs, it goes through the code working out what all the
words and letters are meant to do. Note that it doesn’t do them yet.
When it gets this far through the program:
def random_method
puts “Example string ending in #{name}” #<<<
end
It sees the word “name”, which hasn’t been mentioned before in this
scope. All it can do at this point is assume that “name” is a function
which either: is defined somewhere else, or will be defined dynamically
at runtime.
Then when the parser is done parsing, the interpreter executes the
program*, and at this point:
puts “What is your name?”
name = gets.chomp()
puts “Welcome, #{name}.”
random_method #<<<
…it goes into the “random_method” function, and tries to invoke the
function called “name”, which doesn’t exist. Thus, barf. It doesn’t
matter that in execution order we give “name” a value before we invoke
random_method; the parser had to make an assumption at the time it was
parsing the definition of random_method.
The second attempt is even more convoluted, but hopefully will be able
to work out why it’s making the same mistake, just twice as much.
The main thing is to remember that the parsing phase (which doesn’t
execute any code) steps through the code from top to bottom, left to
right. If you want “random_method” to know that “name” is a variable,
you have to let the parser know by declaring it as a variable first.
E.g.:
name = nil
def random_method
puts “Example string ending in #{name}”
end
Now the parser knows the “name” is a variable, in the same scope as the
random_method function, so random_method is allowed to refer to that
variable. This is called a binding.
HOWEVER as a general rule, it’s not good practice to make functions
depend on their binding/scope to access variables**. That’s why
functions have parameters. Since random_method considers “name” to be
an important piece of information, you should feed “name” straight to
it, as a parameter:
def random_method word
puts “Example string ending in #{word}”
end
puts “What is your name?”
name = gets.chomp
puts “Welcome, #{name}.”
random_method name
Note that in my example, I called the parameter “word”. I did this for
two reasons: to make it clear that it doesn’t have to have the same name
as the “name” variable you’re passing in; and because random_method
seems to be referring to a string, and doesn’t appear to care whether
it’s a name, regular noun, or even a verb, and all variables should be
named appropriately.
You could add the parentheses back in, to make it a bit more C-style, if
that makes you more comfortable:
def random_method(word)
puts “Example string ending in #{word}”
end
puts “What is your name?”
name = gets.chomp()
puts “Welcome, #{name}.”
random_method(name)
- but not really. In C-ruby/MRI it’s more “a bit at a time.” JRuby
might do a full-parse then full-execute.
** until you start defining meaningful data contexts (aka Objects).
Object Oriented design/programming is all around lumping together
contextual data and functions that operate on said data.