Methods
Table of Contents
- Defining a method
- Arguments and Return
- Default valued arguments
- Keyword arguments
- Special method names
- Variable Scope
In this chapter we'll see how to define and use methods of your own. Some aspects of method definition/usage will be covered in later chapters
Defining a method
- the
def
andend
keywords are used to define the beginning and end of method - the method name is given after the
def
keyword - the usual guideline is to indent the body of method with two space characters
- parenthesis are optional, for both defining and calling the method
- the body is optional too - helpful to create placeholder methods
- below example shows a simple method named
greeting
that displays three lines of greeting to the user when called
#!/usr/bin/env ruby
# user defined method
def greeting
puts "-----------------------------"
puts " Hello World "
puts "-----------------------------"
end
# calling method
greeting
Running the above script
$ ./greeting_method.rb
-----------------------------
Hello World
-----------------------------
- let's see another example - this method asks for user input and prints a greeting
- on
irb
, defining a method returns the method name prefixed by:
- that is a symbol(we'll cover that topic later) - by default, result of last expression executed by the method is the return value of that method
- the return value is
nil
in below example as the last executed instruction isputs
whose return value is alwaysnil
- we'll see explicit way of returning values later in the chapter
- the return value is
>> def user_greeting
>> print 'enter name '
>> name = gets.chomp
>> puts "hello #{name}, have a nice day"
>> end
=> :user_greeting
>> user_greeting()
enter name learnbyexample
hello learnbyexample, have a nice day
=> nil
>> user_greeting()
enter name foo
hello foo, have a nice day
=> nil
Further Reading
Arguments and Return
()
are optional - both in method definition and calling- we have seen
puts
calling examples without()
- we have seen
- but for user defined methods, we'll be using
()
- use comma to separate multiple arguments
#!/usr/bin/env ruby
def sum_two_nums(num1, num2)
total = num1 + num2
puts "#{num1} + #{num2} = #{total}"
end
sum_two_nums(2, 3)
sum_two_nums(42, 3.14)
Running the above script
$ ./num_sum.rb
2 + 3 = 5
42 + 3.14 = 45.14
- Use
return
instead of displaying results to save the output in a variable, use it as part of expression etc
>> def num_sq(num)
>> return num ** 2
>> end
=> :num_sq
>> num_sq(3)
=> 9
>> 21 + num_sq(3)
=> 30
Default valued arguments
- method arguments can be given a default value by assigning a value during definition
- we have previously seen examples for
gets
andchomp
methods
- we have previously seen examples for
- arguments with defaults must be grouped together but can be placed at start/end/middle w.r.t normal positional arguments
- default valued arguments are positional - cannot be passed out-of-order while calling
- in the example below, multiple objects are passed to
puts
- newline is added (if not already present) to each object
#!/usr/bin/env ruby
def greeting(msg, style_char='*', fill=5)
gr_len = msg.size + 2*fill
gr_dec = style_char * gr_len
puts gr_dec, msg.center(gr_len), gr_dec
end
# both style_char and fill left out to use their defaults
greeting('hi')
# changing style_char, fill will use the default
greeting('oh', style_char='=')
# changing both the defaults
greeting('42', style_char='%', fill=2)
# cannot change fill alone due to these being positional arguments
greeting('3.14', style_char='*', fill=1)
Running the above script
$ ./styled_greeting.rb
************
hi
************
============
oh
============
%%%%%%
42
%%%%%%
******
3.14
******
- Note that it is optional to use variable assignment while calling a method having default valued arguments
- and the variable name used can be completely different
- See ruby-doc: Default Positional Arguments for more complicated use cases
>> def styled_line(char='*')
>> puts char * 20
>> end
=> :styled_line
>> styled_line
********************
=> nil
>> styled_line(':')
::::::::::::::::::::
=> nil
>> styled_line(c='z')
zzzzzzzzzzzzzzzzzzzz
=> nil
>> c
=> "z"
Keyword arguments
- they are similar to default valued arguments but allows out-of-order passing of arguments while calling
- if there are positional arguments too, they must be defined before keyword arguments
- keyword arguments cannot be passed as positional argument, the keyword has to be always specified
#!/usr/bin/env ruby
def greeting(msg, style_char: '*', fill: 5)
gr_len = msg.size + 2*fill
gr_dec = style_char * gr_len
puts gr_dec, msg.center(gr_len), gr_dec
end
greeting('hi')
greeting('oh', style_char: '=')
greeting('42', fill: 2, style_char: '%')
greeting('3.14', fill: 1)
Running the above script
$ ./keyword_args.rb
************
hi
************
============
oh
============
%%%%%%
42
%%%%%%
******
3.14
******
Special method names
- method names ending with
!
are used to indicate that it modifies the object - Note that this is a guideline and not enforced by Ruby
Example for in-built String method
>> msg = 'hi there'
=> "hi there"
# replaces hi with hello, but doesn't change content of variable
>> msg.sub('hi', 'hello')
=> "hello there"
>> msg
=> "hi there"
# replaces hi with hello, in-place changes content of variable
>> msg.sub!('hi', 'hello')
=> "hello there"
>> msg
=> "hello there"
Example for user defined method
>> def add_hi!(str)
>> str << 'hi'
>> end
=> :add_hi!
>> msg = 'foo'
=> "foo"
>> add_hi!(msg)
=> "foohi"
>> msg
=> "foohi"
- method names ending with
?
are used to indicate it returnstrue/false
# in-built method to check if string has only ascii characters
>> 'foo-123'.ascii_only?
=> true
>> 'hi👍'.ascii_only?
=> false
# a basic palindrome method
>> def palindrome?(str)
>> return str == str.reverse
>> end
=> :palindrome?
>> palindrome?('madam')
=> true
>> palindrome?('bad')
=> false
- the third and final special character for method names is
=
to indicate assignment method- this is usually used for methods defined inside a
class
- See ruby-doc: Assignment Methods for examples
- this is usually used for methods defined inside a
Variable Scope
- the variables we've defined so far are all
local
variables - such variables defined outside of a method are not visible to the method
#!/usr/bin/env ruby
num = 25
def print_num
puts num
end
print_num
Running the above script will result in NameError exception
$ ./variable_scope_1.rb
Traceback (most recent call last):
1: from ./variable_scope_1.rb:9:in `<main>'
./variable_scope_1.rb:6:in `print_num': undefined local variable
or method `num' for main:Object (NameError)
- Similarly, variable defined inside a method is not visible outside its scope
#!/usr/bin/env ruby
def square_of_num(num)
sq_num = num * num
end
square_of_num(5)
puts "sq_num = #{sq_num}"
Running the above script will also result in NameError exception
$ ./variable_scope_2.rb
Traceback (most recent call last):
./variable_scope_2.rb:8:in `<main>': undefined local variable
or method `sq_num' for main:Object (NameError)
Further Reading