Ruby Beginner - calling methods within methods

hi all,

i’m having a little trouble trying to call a previously defined variable
within a method. i’ve looked for threads explaining this and can’t seem
to find any, hoping i can get some help.

any input is greatly appreciated.

i’ve tried two ways:

def a_name(name)
puts “#{name}”
end

def random_method
#how would I put the name on the below line as the end of the puts
string?
puts “Example string ending in #{name}”
end

puts “What is your name?”
name = gets.chomp()
puts “Welcome, #{name}.”

random_method

and this way as well:

def a_name(name)
puts “#{name}”
end

def random_method
puts “Example string ending in #{a_name}”
end

puts “What is your name?”
name = gets.chomp()
puts “Welcome, #{name}.”

random_method

again… any help is greatly appreciated.

cheers

class Foo

def initialize
puts “What is your name?”
@name = gets.chomp()
puts “Welcome, #{@name}.”
end
def a_name(name = @name)
puts “#{name}”
end
def random_method(i = @name)
puts “Example string ending in #{i}”
end
end

def random_method
Foo.new.random_method
end

random_method

^^^ the above works

i’m having a little trouble trying to call a previously
defined variable within a method.

Use $ as variable to see the difference.

You will notice that your example will suddenly work.

Ruby honours scoping rules - if you create a variable
in a method, it is local (to that method) and not known
outside the method.

That is why many people like classes - in a class you
can store data in so called instance variables, denoted
by a leading @.

My second example shows that.

In general, just try to store data in proper variables.

Your example should also work if you define your
variable outside a method. Example:

foo = ‘test 1’
puts foo

def ok
foo = ‘hi’
end

ok
puts foo

^^^ the above example does not change the foo variable
because the binding inside method binds less tight
than the variable outside the method. If you change
it to either $ or @ it should work (but everybody
hates $ so you should not use that often).

Edit: Oops sorry, double post … my bad.

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.

thanks so much for the quick and thorough help.

while i didn’t understand all of it, i’m sure as i go along learning,
it’ll make more sense.

here’s the actual code i have, using Marc’s help.

it’s probably something simple i’m doing wrong still.

class Foo

def initialize
puts “What is your name?”
@name = gets.chomp()
puts “Welcome, #{@name}.”
end
def a_name(name = @name)
puts “#{name}”
end
def random_method(i = @name)
puts “#{@name}”
end
end

def random_method
Foo.new.random_method
end

random_method

def start()
puts
puts “Welcome to your story, #{i}.”
end

start()

for what i’m trying (unsuccessfully) to do, is line 6 necessary?

again… thank you so much for the help, much better reception than i’ve
had on other forums and chats.

In that example you have Foo#initialize, Foo#a_name, Foo#random_method,
Main#random_method, and Main#start. I’m not sure of the “main” notation,
but I believe it’s an instance of Object which adds these methods to
itself as a singleton class.

If you define a method outside of a class, at the “base” level, it gets
added into “main”. Try this from the base level to see “main” identify
itself:

p self

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs