Use of "return"

This is a total newbie question, but I'd like to know how "return" is
specifically used in ruby. From my understanding, it can be avoided in a
lot of cases since ruby returns the last value by default.

However, some of the code in the Rails stuff I'm looking at has "return" and
I was wondering if this "return" is necessary or just the individual
programmer's style (maybe carried over from other languages).

Sorry, I'm vague but I would like to know how "return" is effectively used
in ruby if at all.

Here's a code snippet from the SaltedHash Engine

    def new_security_token(hours = nil)
      write_attribute('security_token', AuthenticatedUser.hashed(
self.salted_password + Time.now.to_i.to_s + rand.to_s))
      write_attribute('token_expiry', Time.at(Time.now.to_i +
token_lifetime(hours)))
      update_without_callbacks
      return self.security_token
    end

or this:

      def authenticate(login, pass)
        u = find(:first, :conditions => ["login = ? AND verified = 1 AND
deleted = 0", login])
        return nil if u.nil?
        find(:first, :conditions => ["login = ? AND salted_password = ? AND
verified = 1", login, AuthenticatedUser.salted_password(u.salt,
AuthenticatedUser.hashed(pass))])
      end

Sorry if my question's off the wall. Still finding my bearings.

Hi --

This is a total newbie question, but I'd like to know how "return" is
specifically used in ruby. From my understanding, it can be avoided in a
lot of cases since ruby returns the last value by default.

However, some of the code in the Rails stuff I'm looking at has "return" and
I was wondering if this "return" is necessary or just the individual
programmer's style (maybe carried over from other languages).

Sorry, I'm vague but I would like to know how "return" is effectively used
in ruby if at all.

Here's a code snippet from the SaltedHash Engine

   def new_security_token(hours = nil)
     write_attribute('security_token', AuthenticatedUser.hashed(
self.salted_password + Time.now.to_i.to_s + rand.to_s))
     write_attribute('token_expiry', Time.at(Time.now.to_i +
token_lifetime(hours)))
     update_without_callbacks
     return self.security_token

Programmer's individual style. You could replace that line with:

   security_token

"self" as receiver would be implied, and since it's the last
expression evaluated, it would be the return value of the method.

   end

or this:

     def authenticate(login, pass)
       u = find(:first, :conditions => ["login = ? AND verified = 1 AND
deleted = 0", login])
       return nil if u.nil?

A return in mid-method needs "return". You could avoid it by
rewriting the end of the method like this:

   if u.nil?
     nil
   else
     other code
   end

But the "return nil if u.nil?" thing both terminates the method and
provides a visual cue that u being nil is a terminal condition. So
it's partly style, but once you decide to do a mid-method return, you
have to use "return".

David

···

On Mon, 9 Jan 2006, SB wrote:

--
David A. Black
dblack@wobblini.net

"Ruby for Rails", from Manning Publications, coming April 2006!

hi,
'return' is used to return a value, and end the method processing.
at the end of a method, 'return' is indeed not needed, and simply that value
will suffice, though i think a return looks nicer :wink:
a good example where a return is needed, is this:

  def method(arg)
    if arg.class==String
      return "invalid argument"
    end
    #rest of processing
  end

this looks a lot nicer than placing your entire method in if/else code.
greetings, Dirk.

dblack@wobblini.net wrote:

Hi --

This is a total newbie question, but I'd like to know how "return" is
specifically used in ruby. From my understanding, it can be avoided in a
lot of cases since ruby returns the last value by default.

However, some of the code in the Rails stuff I'm looking at has "return" and
I was wondering if this "return" is necessary or just the individual
programmer's style (maybe carried over from other languages).

Sorry, I'm vague but I would like to know how "return" is effectively used
in ruby if at all.

Here's a code snippet from the SaltedHash Engine

   def new_security_token(hours = nil)
     write_attribute('security_token', AuthenticatedUser.hashed(
self.salted_password + Time.now.to_i.to_s + rand.to_s))
     write_attribute('token_expiry', Time.at(Time.now.to_i +
token_lifetime(hours)))
     update_without_callbacks
     return self.security_token

Programmer's individual style. You could replace that line with:

  security_token

"self" as receiver would be implied, and since it's the last
expression evaluated, it would be the return value of the method.

   end

or this:

     def authenticate(login, pass)
       u = find(:first, :conditions => ["login = ? AND verified = 1 AND
deleted = 0", login])
       return nil if u.nil?

A return in mid-method needs "return". You could avoid it by
rewriting the end of the method like this:

  if u.nil?
    nil
  else
    other code
  end

But the "return nil if u.nil?" thing both terminates the method and
provides a visual cue that u being nil is a terminal condition. So
it's partly style, but once you decide to do a mid-method return, you
have to use "return".

David

"return" is required if you want to return multiple values like this:

   def foo
     return "a", "b", "c"
   end

Though you can also do this

   def foo
     ["a", "b", "c"]
   end

Personally, I always use "return" if the name of the variable/method is short.

   # Short names
   return result
   return value

   # Long name, no "return" keyword
   Foo::Bar.bur(1, 2, 3)

   # Method call with arguments, no "return" keyword
   foobar(1, 2, 3)
   barfoo 1, 2, 3

Cheers,
Daniel

···

On Mon, 9 Jan 2006, SB wrote:

dblack@wobblini.net wrote:

or this:

     def authenticate(login, pass)
       u = find(:first, :conditions => ["login = ? AND verified = 1
AND deleted = 0", login])
       return nil if u.nil?

A return in mid-method needs "return". You could avoid it by
rewriting the end of the method like this:

   if u.nil?
     nil
   else
     other code
   end

But the "return nil if u.nil?" thing both terminates the method and
provides a visual cue that u being nil is a terminal condition. So
it's partly style, but once you decide to do a mid-method return, you
have to use "return".

In this case a completely different solution is possible:

def authenticate(login, pass)
  u = find(:first, :conditions => ["login = ? AND verified = 1 AND deleted
= 0", login]) and
  find(:first, :conditions => ["login = ? AND salted_password = ? AND
verified = 1",
    login, AuthenticatedUser.salted_password(u.salt,
AuthenticatedUser.hashed(pass))])
end

:slight_smile:

    robert

Dirk Meijer wrote:

hi,
'return' is used to return a value, and end the method processing.
at the end of a method, 'return' is indeed not needed, and simply
that value will suffice, though i think a return looks nicer :wink:
a good example where a return is needed, is this:

  def method(arg)
    if arg.class==String
      return "invalid argument"
    end
    #rest of processing
  end

this looks a lot nicer than placing your entire method in if/else
code. greetings, Dirk.

In this case you wouldn't use return values to flag this error. It's is a
typical case for exceptions.

def mett(arg)
  raise ArgumentError, "#{arg.inspect} is not a String" unless String ===
arg
  # further processing
end

And taking this even further, in the light of Duck Typing (TM) usually no
type checks of this kind are made at all. :slight_smile:

Kind regards

    robert

Seems like every time I check, code with a 'return' runs slower
than code without. Less typing and faster. I say drop the return.

Jim

···

On Jan 9, 2006, at 8:57 AM, dblack@wobblini.net wrote:

     return self.security_token

Programmer's individual style. You could replace that line with:

  security_token

Confirmed:

require 'quickbench'

class Test
  def initialize(test)
    @test = test
  end

  def test
    @test
  end

  def get_test
    return @test
  end
end

t = Test.new("something")
QuickBench.go(3000000, 25) {}

__END__
t.test
t.get_test

Results:

···

On 1/10/06, Jim Freeze <jim@freeze.org> wrote:

Seems like every time I check, code with a 'return' runs slower
than code without. Less typing and faster. I say drop the return.

-------------------------------------------------------------------------

                     QuickBench Session Started |
                         3000000 Iterations |

-------------------------------------------------------------------------
                                  user system total real
1. t.test 2.860000 0.000000 2.860000 ( 2.859000)
2. t.get_test 3.078000 0.000000 3.078000 ( 3.094000)
-------------------------------------------------------------------------

                       Fastest was <1. t.test> |

-------------------------------------------------------------------------

Ryan

Robert Klemme wrote:

Dirk Meijer wrote:

hi,
'return' is used to return a value, and end the method processing.
at the end of a method, 'return' is indeed not needed, and simply
that value will suffice, though i think a return looks nicer :wink:
a good example where a return is needed, is this:

def method(arg)
   if arg.class==String
     return "invalid argument"
   end
   #rest of processing
end

this looks a lot nicer than placing your entire method in if/else
code. greetings, Dirk.
   
In this case you wouldn't use return values to flag this error. It's is a
typical case for exceptions.

def mett(arg)
raise ArgumentError, "#{arg.inspect} is not a String" unless String ===
arg
# further processing
end

And taking this even further, in the light of Duck Typing (TM) usually no
type checks of this kind are made at all. :slight_smile:

Kind regards

   robert

Indeed, arg.to_str would be a more consistent duck typecheck. (Le Groan, what gruesome terminoogy sees the light of day.)

David Vallner

Ryan Leavengood wrote:

···

On 1/10/06, Jim Freeze <jim@freeze.org> wrote:

Seems like every time I check, code with a 'return' runs slower
than code without. Less typing and faster. I say drop the return.
   
Confirmed:

require 'quickbench'

class Test
def initialize(test)
   @test = test
end

def test
   @test
end

def get_test
   return @test
end
end

t = Test.new("something")
QuickBench.go(3000000, 25) {}

__END__
t.test
t.get_test

Results:

-------------------------------------------------------------------------

                     QuickBench Session Started |
                         3000000 Iterations |

-------------------------------------------------------------------------
                                 user system total real
1. t.test 2.860000 0.000000 2.860000 ( 2.859000)
2. t.get_test 3.078000 0.000000 3.078000 ( 3.094000)
-------------------------------------------------------------------------

                       Fastest was <1. t.test> |

-------------------------------------------------------------------------

Ryan

Most weird. Let's hope someone notices and the compiler is modified to plain drop tail-returns. That is, if "return" is a reserved word and thus not viable to being overridden by someone who codes with a dead chicken in his left hand :stuck_out_tongue_winking_eye: (Gotta love it when flexibility bites you back. *daydreams about clean blocks*)