Forum: Ruby return statement

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
116f805694bc0b7543dd359cdac7c205?d=identicon&s=25 Derek Teixeira (derekteixeira)
on 2007-02-19 13:44
i've been getting confused about what exactly the return statement
does...

i really think this book i'm reading "learn to program" is really not
that great of a book to be reading when getting into programming. While
the author covers somethings very much in depth, he barely touches some
things for more than a line, and sometimes not at all, and then you end
up finding it in his code.

Along with that confusion on the return function.. i was code tracing
the code below and i understand it, except for one part, i just don't
see where the code tells the program to print out the numString. I see
it telling the program to in the 'one hundred' section, but not at all
in the teens or single digits?

i read these forums everyday, and i really don't understand that much of
the advanced stuff you guys talk about, but everyday i do begin to
understand more and more little parts, i just hope i'm not being a pain
in the arse. I guess it's just a little hard learning from a book and
having no teacher to learn from.. if you guys are getting annoyed, just
let me know. thank you again in advance.

def englishNumber number
  #  We only want numbers from 0-100.
  if number < 0
    return 'Please enter a number zero or greater.'
  end
  if number > 100
    return 'Please enter a number 100 or lesser.'
  end

  numString = ''  #  This is the string we will return.

  #  "left" is how much of the number we still have left to write out.
  #  "write" is the part we are writing out right now.
  #  write and left... get it?  :)
  left  = number
  write = left/100          #  How many hundreds left to write out?
  left  = left - write*100  #  Subtract off those hundreds.

  if write > 0
    return 'one hundred'
  end

  write = left/10          #  How many tens left to write out?
  left  = left - write*10  #  Subtract off those tens.

  if write > 0
    if write == 1  #  Uh-oh...
      #  Since we can't write "tenty-two" instead of "twelve",
      #  we have to make a special exception for these.
      if    left == 0
        numString = numString + 'ten'
      elsif left == 1
        numString = numString + 'eleven'
      elsif left == 2
        numString = numString + 'twelve'
      elsif left == 3
        numString = numString + 'thirteen'
      elsif left == 4
        numString = numString + 'fourteen'
      elsif left == 5
        numString = numString + 'fifteen'
      elsif left == 6
        numString = numString + 'sixteen'
      elsif left == 7
        numString = numString + 'seventeen'
      elsif left == 8
        numString = numString + 'eighteen'
      elsif left == 9
        numString = numString + 'nineteen'
      end
      #  Since we took care of the digit in the ones place already,
      #  we have nothing left to write.
      left = 0
    elsif write == 2
      numString = numString + 'twenty'
    elsif write == 3
      numString = numString + 'thirty'
    elsif write == 4
      numString = numString + 'forty'
    elsif write == 5
      numString = numString + 'fifty'
    elsif write == 6
      numString = numString + 'sixty'
    elsif write == 7
      numString = numString + 'seventy'
    elsif write == 8
      numString = numString + 'eighty'
    elsif write == 9
      numString = numString + 'ninety'
    end

    if left > 0
      numString = numString + '-'
    end
  end

  write = left  #  How many ones left to write out?
  left  = 0     #  Subtract off those ones.

  if write > 0
    if    write == 1
      numString = numString + 'one'
    elsif write == 2
      numString = numString + 'two'
    elsif write == 3
      numString = numString + 'three'
    elsif write == 4
      numString = numString + 'four'
    elsif write == 5
      numString = numString + 'five'
    elsif write == 6
      numString = numString + 'six'
    elsif write == 7
      numString = numString + 'seven'
    elsif write == 8
      numString = numString + 'eight'
    elsif write == 9
      numString = numString + 'nine'
    end
  end

  if numString == ''
    #  The only way "numString" could be empty is if
    #  "number" is 0.
    return 'zero'
  end

  #  If we got this far, then we had a number somewhere
  #  in between 0 and 100, so we need to return "numString".
  numString
end

puts englishNumber(  0)
puts englishNumber(  9)
puts englishNumber( 10)
puts englishNumber( 11)
puts englishNumber( 17)
puts englishNumber( 32)
puts englishNumber( 88)
puts englishNumber( 99)
puts englishNumber(100)
7223c62b7310e164eb79c740188abbda?d=identicon&s=25 Xavier Noria (Guest)
on 2007-02-19 14:03
(Received via mailing list)
On Feb 19, 2007, at 1:44 PM, Derek Teixeira wrote:

> i've been getting confused about what exactly the return statement
> does...

Return means "we are done".

Sometimes when you write a method (I don't know the jargon used in
that book, it may be function, or subroutine, or procedure, ...) you
know somewhere in the middle that _if the code reached that point_ we
do not need to do anything else. For instance, see this method that
says where the given number is positive:

   def is_positive?(n)
     if n > 0
       return true
     end
     return false
   end

That method can be written in different ways, but to depict the
meaning of return: if n is greater than 0, you already know the
answer, so in that point you indicate there's no need to execute more
code, you're ready to give the answer: true. If the execution reaches
that point, the following executable line "return false" will be
ignored altogether, execution is halted.

Return in addition accepts a value to be returned (true/false in the
example), which is considered to be the _result_ of that method call
in such case.

> Along with that confusion on the return function.. i was code tracing
> the code below and i understand it, except for one part, i just don't
> see where the code tells the program to print out the numString. I see
> it telling the program to in the 'one hundred' section, but not at all
> in the teens or single digits?

> def englishNumber number

<snip>

> end

The purpose of that method is to compute and return a _string_, not
to actually _print_ that string.

> puts englishNumber(  0)

Now here you have two calls: first a call to englishNumber(  0), and
then a call to puts. They are executed in that order, and the string
returned by the first call is chained into the second call, so puts
is the one that prints the string.

Does that help? Please do no hesitate to send more questions.

-- fxn
430ea1cba106cc65b7687d66e9df4f06?d=identicon&s=25 David Vallner (Guest)
on 2007-02-19 14:22
(Received via mailing list)
Making a wild guess at the signal in the noise.

On Mon, 19 Feb 2007 13:44:46 +0100, Derek Teixeira
<derek.teixeira@gmail.com> wrote:
>
>   #  If we got this far, then we had a number somewhere
>   #  in between 0 and 100, so we need to return "numString".
>   numString ## equivalent to "return numString"
> end
>

In Ruby, a function always returns the value of the last expression in
its
definition by default if it reaches the end.

(I really, really, really hate on relying on this behaviour because it
makes it easy to miss the fact that this is happening instead of just a
"void" method call, or to miss that the method is in fact returning
anything at all, and it really doesn't belong in a beginners' book. Tut.
Oversight maybe?)

David Vallner
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2007-02-19 14:43
(Received via mailing list)
Hi --

On Mon, 19 Feb 2007, David Vallner wrote:

>> [snip self-depreciation - just keep that one out next time ;P]
> In Ruby, a function always returns the value of the last expression in its
> definition by default if it reaches the end.
>
> (I really, really, really hate on relying on this behaviour because it makes
> it easy to miss the fact that this is happening instead of just a "void"
> method call, or to miss that the method is in fact returning anything at all,
> and it really doesn't belong in a beginners' book. Tut. Oversight maybe?)

No; Chris knows what he's doing.  It's pretty fundamental -- I always
make a point of explaining it when I introduce the topic of methods to
beginners.  Otherwise simple things like:

   def of_age?
     age > 17
   end

make no sense.  It's basically just a function that performs a
calculation.


David
116f805694bc0b7543dd359cdac7c205?d=identicon&s=25 Derek Teixeira (derekteixeira)
on 2007-02-19 14:48
> Return means "we are done".
>
> Sometimes when you write a method (I don't know the jargon used in
> that book, it may be function, or subroutine, or procedure, ...) you
> know somewhere in the middle that _if the code reached that point_ we
> do not need to do anything else. For instance, see this method that
> says where the given number is positive:
>
>    def is_positive?(n)
>      if n > 0
>        return true
>      end
>      return false
>    end
>
> That method can be written in different ways, but to depict the
> meaning of return: if n is greater than 0, you already know the
> answer, so in that point you indicate there's no need to execute more
> code, you're ready to give the answer: true. If the execution reaches
> that point, the following executable line "return false" will be
> ignored altogether, execution is halted.
>
> Return in addition accepts a value to be returned (true/false in the
> example), which is considered to be the _result_ of that method call
> in such case.

  So you are saying that it basically saves the confusion of elsif's and
it just makes more sense.. in your example you could have easily written

def is_positive?(n)
 if n > 0
       answer= true
    elsif
    n<0
       answer= false
end

 Right? but that just looks sloppy and could really get confusing if i
had more lines of code.. am i getting it right?

>> def englishNumber number
>
> <snip>
>
>> end
>
> The purpose of that method is to compute and return a _string_, not
> to actually _print_ that string.
>
>> puts englishNumber(  0)
>
> Now here you have two calls: first a call to englishNumber(  0), and
> then a call to puts. They are executed in that order, and the string
> returned by the first call is chained into the second call, so puts
> is the one that prints the string.

   so basically when you define a method you are saying that when i call
this method, i want this done with the thing next to it. So here it is
saying i want you to run all these checks on the number next to
"englishNumber"? then it runs each of those tests .. the if statements
and once one is true to that statement, then it stops there and prints
out the last line before end?
7b4707f974af261f71943e1f2046c9ee?d=identicon&s=25 SonOfLilit (Guest)
on 2007-02-19 14:49
(Received via mailing list)
On 2/19/07, Derek Teixeira <derek.teixeira@gmail.com> wrote:

> I guess it's just a little hard learning from a book and  having no teacher to learn 
from..

Hi Derek,

That is exactly why I started the RubyMentor project last week, which
you can find a thread about in this list titled "adopt-a-newbie".

Please read it, it's exactly for you!
430ea1cba106cc65b7687d66e9df4f06?d=identicon&s=25 David Vallner (Guest)
on 2007-02-19 14:58
(Received via mailing list)
On Mon, 19 Feb 2007 14:43:07 +0100, <dblack@wobblini.net> wrote:

> make no sense.  It's basically just a function that performs a
> calculation.
>

For mathemathical functions with a simple enough control flow, I'm
ambivalent on the topic. However once a method has a premature return
(or
four) somewhere, the inconsistency hurts my sensitivities. Using the
keyword in such a method as a matter of style gives me one less thing to
keep in my head when scanning the code for exit points - either there is
only one and it's completely obvious like in your example, or it's every
line with "return" in it.

David Vallner
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2007-02-19 15:19
(Received via mailing list)
Hi --

On Mon, 19 Feb 2007, David Vallner wrote:

>>   end
> completely obvious like in your example, or it's every line with "return" in
> it.

But if an exit point is midway through a method, it will have to have
a return:

   def m(x)
     return false unless x > 0
     blah
     blah
     return x if x == 1
     blah
     blah
   end

I can't drop the "return"s on those, because the values will just be
thrown away and the method will continue.

The only time you'd see this not literally at the very end of the
method, I think, is if you've got something like an if/else or case
statement:

   def m(x)
     if x > 0
       false
     else
       ...
     end
   end

I agree that if too much happens afterwards -- if you stick a whole
bunhc of lines in that else -- it can be hard to catch the fact that
"false" is a potential exit point.  I'd rather see a hard-coded
conditional return -- sort of in the spirit of "break" -- and then get
on with the method.


David
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2007-02-19 15:20
(Received via mailing list)
Hi --

On Mon, 19 Feb 2007, Derek Teixeira wrote:

>>        return true
>>
>    elsif
>    n<0
>       answer= false
> end
>
> Right? but that just looks sloppy and could really get confusing if i
> had more lines of code.. am i getting it right?

Well, in that particular case, I would just do:

   def is_positive?(n)
     n > 0
   end

You definitely don't need the temporary variable (answer), and in fact
you don't need to code the true/false return values because > will
already give you one or the other.


David
7223c62b7310e164eb79c740188abbda?d=identicon&s=25 Xavier Noria (Guest)
on 2007-02-19 15:22
(Received via mailing list)
On Feb 19, 2007, at 2:48 PM, Derek Teixeira wrote:

>        answer= false
> end
>
>  Right? but that just looks sloppy and could really get confusing if i
> had more lines of code.. am i getting it right?

Right.

Now that you have the idea, there are some details that depend on the
programming language here. I expect that book to abstract them from
the reader so I won't mention them. Just let me add that return is
generally used to end the execution of a method and (normally) give
some result back. That can happen anywhere, it is not required to be
in the middle so to speak. Thus, this is valid:

   def square(n)
     s = n*n
     return s
   end

>    so basically when you define a method you are saying that when i
> call
> this method, i want this done with the thing next to it. So here it is
> saying i want you to run all these checks on the number next to
> "englishNumber"? then it runs each of those tests .. the if statements
> and once one is true to that statement, then it stops there and prints
> out the last line before end?

When you call a method you say: "please, execute the code inside the
method definition with the values I pass and return some result".

In the example above, the method is "square" and it does a different
thing if you call "square(3)" or "square(5)" because you pass a
different number in the call, a "5" in the former, a "3" in the
latter. In each call, the value of the variable "n" is the one in the
call, and so the code is executed for that particular value of "n".
As if the method definition was a template where you substitute "n"
with some actual number in each call.

OK, the _result_ of the computation is returned to who issued the
call and its usage depends on the actual surrounding code. For
example, here

   a = square(3)

you take the result of "square(3)", which is 9, and assign it to "a".
After that line "a" holds the number "9".

You can chain calls, that was the point in your original code:

   b = square(square(3))

The result of "square(3)" becomes the value passed to the outer call
to "square", and so it receives "9". In consequence, "b" will hold "81".

Chained calls do not require chained methods to be equal, you chained
"englishNumber" and "puts" in your code.

-- fxn
7223c62b7310e164eb79c740188abbda?d=identicon&s=25 Xavier Noria (Guest)
on 2007-02-19 15:24
(Received via mailing list)
On Feb 19, 2007, at 3:20 PM, dblack@wobblini.net wrote:

> Well, in that particular case, I would just do:
>
>   def is_positive?(n)
>     n > 0
>   end
>
> You definitely don't need the temporary variable (answer), and in fact
> you don't need to code the true/false return values because > will
> already give you one or the other.

Yes David, as I said in the message that method can be wrriten in
different ways, and its purpose was just to serve as support to
depict what return does.

-- fxn
116f805694bc0b7543dd359cdac7c205?d=identicon&s=25 Derek Teixeira (derekteixeira)
on 2007-02-19 15:44
>    def square(n)
>      s = n*n
>      return s
>    end
>
  so right here we could have gotten rid of the "return" and then below
just write

puts square(3)

and the code will give us 9?
because it returns to us that s value, and we are putting that value?
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2007-02-19 15:55
(Received via mailing list)
Hi --

On Mon, 19 Feb 2007, Derek Teixeira wrote:

>
> and the code will give us 9?
> because it returns to us that s value, and we are putting that value?

Yes.  You could even do:

   def square(n)
     n * n
   end

and square(3) will evaluate to 9 (the value of the last expression in
the method before it ends).  (Aside to Xavier: I know, it's just an
illustration :-)


David
7223c62b7310e164eb79c740188abbda?d=identicon&s=25 Xavier Noria (Guest)
on 2007-02-19 15:57
(Received via mailing list)
On Feb 19, 2007, at 3:44 PM, Derek Teixeira wrote:

> puts square(3)
>
> and the code will give us 9?
> because it returns to us that s value, and we are putting that value?

Exactly.

Now that you have grasped the meaning of return, let me say that not
all languages make it optional at the end, some programming languages
do require an explicit return.

Additionally, in that example the variable "s" is superfluous, you
can just write

   return n*n

but I wanted to have a simple method with two lines of code instead
of one, so that it was visually evident there was a last line of code
in a series of lines.

-- fxn
116f805694bc0b7543dd359cdac7c205?d=identicon&s=25 Derek Teixeira (derekteixeira)
on 2007-02-19 16:02
I UNDERSTAND! (i think =D )

thanks a lot you guys. I really think it's just this book, and it's lack
of depth on certain things ... it sort of leaves a lot to be figured out
by the reader (but when they give you an example as long, and crazy as
that one - for a beginner) it can become over whelming to figure out
what you should be grasping.

from here on out, if i have any questions, like this one, i will be sure
to use the new WIKI thing.
56f2ce19706d05d18b5b66483aa13f98?d=identicon&s=25 Lloyd Zusman (Guest)
on 2007-02-19 16:48
(Received via mailing list)
Derek Teixeira <derek.teixeira@gmail.com> writes:

> and the code will give us 9?
> because it returns to us that s value, and we are putting that value?

You can do the "puts square(3)" and "9" will print out whether the
"return" statement is there or not, because in every function, if there
is no "return", the final value calculated before the "end" is
implicitly passed to the caller as if the "return" were present.

In your "square" function, the final value calculated is the value of
"s = n*n", and therefore, that would be the value that is implicitly
passed to the caller if the "return" were missing.

For example ...

  def square1(n)  # no return statement
    s = n*n
    a = 12345  # this gets implicitly returned
  end

  def square2(n)  # with a return statement
    s = n*n
    a = 12345
    return s   # explicitly returns s
  end

  puts square1(3)
  => 12345

  puts square2(3)
  => 9
This topic is locked and can not be replied to.