SlideShare a Scribd company logo
Deepak H B
Full-Stack Developer
Gmail: deepakhb2@gmail.com
Linkedin: http://in.linkedin.com/in/deepakhb
GitHub: https://github.com/deepakhb2
Methods and Functional
Programming
Introduction
• A method is a named block of parameterized code associated with one or
more objects.
• A method invocation specifies the method name and the object on which
the method is invoked.
• The value of the last expression evaluated in the method becomes the
value of the method invocation expression.
• Ruby is purely object oriented language, all the methods are associated
with at least one object.
• Methods are the fundamental part of Ruby’s syntax, but they are not
values that Ruby programs can operate on.
• Methods are not Ruby’s only form of parameterized executable code,
Blocks are also executable chunks of code and may have parameters.
Defining Simple Method
• Methods are defined with the def keyword.
• This is followed by the method name and optional list of parameter names
in parentheses.
• The Ruby code constitutes the method body follows the parameter list
and end of the method is marked with the end keyword.
• Parameter names can be used as variables within the method body and
the values of these named parameters come from the arguments to a
method invocation.
def method_name(n)
#method body
End
• Methods are always invoked on an object.
• Ruby uses “.” to separate the object from the method to be invoked on it.
Method Return Value
• Methods may be terminated normally or abnormally.
Abnormal termination occurs when the method raises an exception.
• The return keyword is used to force a return prior to the end of the
method.
• The expression follows the return keyword is evaluated and returned.
• The nil is returned if there is no expression.
• Ruby methods may return more than one value by using return keyword
explicitly
def return_numbers
return 1,2,3
end
• More than one return values are collected into an array and it becomes
the single return value of the method.
• Methods of this form are typically intended for use with parallel
assignment.
x,y,z = return_numbers
Singleton Methods
• The methods that are defined for single specified object are called
singleton methods.
• Simply follow the def keyword with an object that follows by a period and
the name of the method to be defined.
o = “message”
def o.printme
puts self
end
o.printme # “message”
• Class methods such as Math.sin and File.delete are actually singleton
methods.
• Math is constant that refers to a Module object and File is a constant that
refers to a Class object.
• Ruby implementation typically treat Fixnum and Symbol values as
immediate values rather than as true object reference. For this reason
singleton methods may not be defined on Fixnum and Symbol.
Undefining Methods
• Methods are defined with the def keyword and may be
undefined using undef keyword.
• undef can be used to undefined inherited methods without
affecting the definition of the method in the class form which
it is inherited.
• This is not commonly used statement.
• This should followed by a single identifier that specifies the
method name.
• It cannot be used to undefine a singleton methods.
Method Name
• Method names begin with lower case letters.
• If method name is longer than one word, the usual
convention is to separate the words with underscores
like_this.
• Method names might end with an equal sign, a question
mark, or an exclamation point.
• The equal sign suffix signifies that the method is setter.
• The question mark signifies that method returns a value that
answers question posed by the method invocation.
empty?
Contd..
• Methods whose names are ending with exclamation mark should be used
with caution.
sort!, exit!
• Methods ending with exclamation mark are mutators, which alters the
internal state of an object.
• Ruby’s operators, such as +, * and even the array index [] operator are
implemented with methods that you can define in your own class.
def +(other)
self.concatenate(other)
end
• Ruby can define more than one name for same method.
• The language ahs alias key word to define a new name for existing
method.
alias to_str, to_s #alias new_name existing_name
• This can be used inside the class whose methods needs to be renamed.
Methods and Parentheses
• Ruby allows parentheses to be omitted from most of the method
invocations.
puts “Hello world”
puts(“Hello world”)
• The next example
greeting = “Hello”
size = greeting.length
• Normally length looks like property, field or variable of string
objects. But this is method invocation. Then length method expects
no arguments and is invoked without parentheses.
size = greeting.length()
Contd..
• Parentheses are very commonly omitted when there are zero
or one arguments to the invoked methods.
• Parentheses may also be omitted around the parameter list in
method definitions, though it is hard to argue that this makes
your code clearer or more readable.
• Some code is ambiguous if the parentheses are omitted and
here Ruby requires that you include them.
• The most common case is nested method invocations of the
form f g x,y. In Ruby, invocations of that form mean f(g(x,y))
Method Arguments
• Simple method declarations include a comma-separated list
of names after the method name.
• But there is much more to Ruby’s method arguments:
– How to declare an arguments that has a default value.
– How to declare a method that accepts any number of
arguments.
– How to simulate named method arguments with special
syntax for passing a hash to a method.
Parameter Defaults
• When you define a method, you can specify default values for some or all
of the parameters.
def prefix(s, len=1)
S[0,len]
end
• The above methods defines two parameters, but the second on has a
default value. This can be invoked as below:
prefix(“ruby”, 3) #=> “rub”
prefix(“Ruby”) #=> “R”
• Parameter defaults are evaluated when a method is invoked rather than
when it is parsed. In the following method, the default value [] produces a
new empty array on each invocation.
def append(x, a=[])
a<<x
end
Contd..
• In Ruby 1.8, method parameters with default values must
appear after all ordinary parameters in the parameter list.
• In Ruby 1.9, allows ordinary parameters to appear after the
parameters with defaults. But mixing between these two
parameters are not allowed.
Variable-Length Argument Lists and
Arrays
• The * is put before one of the methods parameter to accept an arbitrary
number of arguments.
def max(first, *rest)
max = first
rest.each{|x| max = x if x > maz}
max
end
• The max method requires at least one argument, but it may accept any
number of additional arguments.
max(1) # first=1, rest=[]
max(1,2)# first=1, rest=[2]
max[1,2,3] #first=1, rest=[2,3]
Contd..
• No more than one argument is prefixed with *.
• This should be the last parameter of a method.
• The max method can also accept single array as argument by using
splat (*) operator on invocation. This will expand the elements of an
array.
data = [3,2,1]
max(*data)
Hashes for Named Arguments
• When a method accepts more than two or three arguments, it will be
difficult for the programmer invoking the method to remember the proper
order.
• The solution for this is to write a method that accepts hash a parameter.
def sequence(args)
n=args[:n] || 0
m=args[:m] || 1
c=args[:c] ||0
end
• This method can be invoked with hash literal as argument
sequence({:n=>3, :m=>5})
• Ruby supports to pass hash without curly braces to the last argument of
the method.
sequence(:n=>3, :m=>5)
• If parenthesis are omitted, then curly braces must be omitted as well.
sequence {:n=>2, :m=>5} # Syntax error
Procs and Lambdas
• Blocks are syntactic structures in Ruby; they are not objects
and cannot be manipulated as object.
• It is possible, however to create an object that represents a
block.
• Depending on how the object is created it is called a proc
or lambda.
• Proc have block-like behavior and lambda’s have method-
like behavior.
• Both Proc and lambdas are instance of class Proc.
Creating Procs
• The Proc object is created by associating a block with a method that is
defined with an ampersand-prefixed block argument.
def makeproc(&p)
p
End
• With a makeproc method like this defined, we can create a Proc object by
adder = makeproc {|x,y| x+y}
• Now the variable adder refers to the Proc object. All proc objects have a
call method that when invoked runs the code contained in the block from
which proc was created.
sum = adder.call(2,2)
Proc.new
• This is the normal new method that most classes support, and it’s the
most obvious way to create a new instance of the Proc class.
• Proc.new expects no arguments and returns the instance of Proc class (not
lambda).
p = Proc.new {|x,y| x+y}
Kernel.lambda
• Another technique for creating Proc objects is with the lambda method.
• The lambda is a method of the kernel module, so it behaves like a global
function.
• The proc object returned from this method is a lambda rather than a proc.
• lambda expects no arguments, but there must be a block associated with
the invocation.
is_positive = lambda {|x| x>0}
Lambda Literals
• The created lambda method below
succ = lambda{|x| x+1}
• Can be converted to literal as follows:
– Replace the method name lambda with the punctuation -
>.
– Move the list of arguments outside of and just before the
curly braces.
– Change the argument list delimiters from || or ().
• With these the lambda literal
succ = ->(x){ x+1 }
Invoking Procs and Lambdas
• Procs and lambdas are objects, not methods and they cannot be invoked in the
same way that methods.
• If p is Proc object, it cannot invoked as method instead it can invoke the method of
p.
• Proc class defines a method named call.
• Invoking this method executes the code in the original block with the arguments
that are passed by call.
f = Proc.new{|x,y|1.0/(1.0/x+1.0/y)}
z = f.call(x,y)
• The Proc class also defines the array access operator to work the same way as call.
z = f[x,y]
• An additional way to invoke a Proc object as an alternative to square brackets, you
can use parenthesis prefixed with a period
z = f.(x,y)
The Arity of a Proc
• The arity of a proc or lambda is the number of arguments it expects.
• Proc object have an arity method that returns the number of arguments
they expect.
lambda{||}.arity # => 0
lambda{|x|}.arity # => 1
lambda{|x,y|}.arity # => 2
• The notion of arity gets confusing, when a Proc accepts an arbitrary
number of arguments in an * prefixed final argument.
• When Proc allows optional arguments, the arity method returns a
negative number of the form –n-1.
lambda{|*args|}.arity # => -1. ~-1 = -(-1)-1 = 0 arguments
required
lambda{|first, *rest|}.arity # => -2. ~-2 = -(-2)-1 = 1 argument
required
Proc Equality
• The Proc class defines an == method to determine whether two Proc
objects are equal.
• It is important to understand, however, that merely having the same
source code is not enough to make two procs or lambdas equal to each
other.
lambda{|x| x*x} == lambda{|x| x*x} #=> false
• The == method only returns true if on Proc is a clone or duplicate of the
other
p = lambda{|x| x*x}
q = p.dup
p == q # => true
p.object_id == q.object_id # => false
Functional Programming
• Ruby is not Functional programming language in the way that
languages like Lisp and Hskell are.
• Any time you use a block with an Enumerable iterators like
map or inject, your programming in a functional style.
mean = a.inject{|x,y| x+y}/a.size
sumOfSquares = a.map{|x| (x-mean)**2}.inject{|x,y| x+y}
Applying a Function to an Enumerable
• The map and inject are two of the most important iterators
defined by Enumerable.
• If we write a programs in a function-centric way, we might
like methods on our functions that allow us to apply those
functions to a specified Enumerable object.
# This module defines methods and operators for functional programming.
module Functional
# Apply this function to each element of the specified Enumerable,
# returning an array of results. This is the reverse of Enumerable.map.
# Use | as an operator alias. Read "|" as "over" or "applied over".
# Example:
# a = [[1,2],[3,4]]
# sum = lambda {|x,y| x+y}
# sums = sum|a # => [3,7]
def apply(enum)
enum.map &self
end
alias | apply
# Use this function to "reduce" an enumerable to a single quantity.
# This is the inverse of Enumerable.inject.
# Use <= as an operator alias.
# Mnemonic: <= looks like a needle for injections
# Example:
# data = [1,2,3,4]
# sum = lambda {|x,y| x+y}
# total = sum<=data # => 10
def reduce(enum)
enum.inject &self
end
alias <= reduce
end
• Notice that we define methods in a module named Functional, and when
we include this module into both the Proc and Method classes.
• Most of the methods that follow also define methods in this Functional
module, so that they work for both Proc and Method.
• With apply and reduce defined as above, we could refactor our statistical
computations as follows:
sum = lambda{|x,y| x+y} #A function to add two numbers
mean = (sum<=a)/a.size #Or sum.reduce(a) or a.inject(&sum)
deviation = lambda{|x| x-mean} #Function to compute difference from mean
square = lambda{|x| x*x} #Function to square a number
standardDeviation = Math.sqrt((sum<=square|(deviation|a))/(a.size-1))
Contd..
# Add these functional programming methods to Proc and
Method classes.
class Proc; include Functional; end
class Method; include Functional; end
Composing Functions
• If we have a functions f and g, we sometimes want to
define a new function h which is f(g()) or f composed with
g.
• We define a method that performs function composition
automatically.
module Functional
# Return a new lambda that computes self[f[args]].
# Use * as an operator alias for compose.
# Examples, using the * alias for this method.
# f = lambda {|x| x*x }
# g = lambda {|x| x+1 }
# (f*g)[2] # => 9
# (g*f)[2] # => 5
# def polar(x,y)
# [Math.hypot(y,x), Math.atan2(y,x)]
# end
# def cartesian(magnitude, angle)
# [magnitude*Math.cos(angle), magnitude*Math.sin(angle)]
# end
# p,c = method :polar, method :cartesian
# (c*p)[3,4] # => [3,4]
def compose(f)
if self.respond_to?(:arity) && self.arity == 1
lambda {|*args| self[f[*args]] }
else
lambda {|*args| self[*f[*args]] }
end
end
Contd..
• The example code in the comment demonstrates the use of
compose with Method objects as well as lambdas.
• We can use this new * function composition operator so slightly
simplify our computation of standard deviation.
standardDeviation = Math.sqrt((sum<=square*deviation|a)/(a.size-1))
• The difference is that we compose square and deviation into a
single function before applying it to the array a.
Partially Applying Functions
• In functional programming, partial application is the process of
taking a function and a partial set of argument values and
producing a new function that is equivalent to the original function
with the specified arguments fixed.
• For example,
$product = lambda {|x, y| x*y} #A function of two arguments
$double = lambda {|x| product(2,x) } #Apply one argument
• Partial application can be simplified with appropriate methods in
our Functional module.
module Functional
# Return a lambda equivalent to this one with one or more initial
# arguments applied. When only a single argument
# is being specified, the >> alias may be simpler to use.
# Example:
# product = lambda {|x,y| x*y}
# doubler = lambda >> 2
def apply_head(*first)
lambda {|*rest| self[*first.concat(rest)]}
end
# Return a lambda equivalent to this one with one or more final arguments
# applied. When only a single argument is being specified,
# the << alias may be simpler.
# Example:
# difference = lambda {|x,y| x-y }
# decrement = difference << 1
def apply_tail(*last)
lambda {|*rest| self[*rest.concat(last)]}
end
# Here are operator alternatives for these methods. The angle brackets
# point to the side on which the argument is shifted in.
alias >> apply_head # g = f >> 2 -- set first arg to 2
alias << apply_tail # g = f << 2 -- set last arg to 2
end
Contd..
• Using these methods and operators, we can define our double
function simply as product >> 2.
• We can use partial application to make our standard deviation
computation somewhat more abstract, by building our deviation
function from more general purpose difference function.
difference = lambda {|x,y| x-y} #Compute difference of two
numbers
deviation = difference << mean #Apply second argument
Memoizing functions
• Memoizing Functions is a functional programming term for caching
the results of a function invocation.
• If a function always returns the same value when passed the same
arguments, if there is reason to believe that the same arguments
will be used repeatedly, and if the computation it performs is
somewhat expensive, then memoization may be a useful
optimization.
• We can automate memorization for Proc and Method objects with
the following method.
module Functional
# Return a new lambda that caches the results of this function and
# only calls the function when new arguments are supplied.
def memoize
cache = {} # An empty cache. The lambda captures this in its closure.
lambda {|*args|
# notice that the hash key is the entire array of arguments!
unless cache.has_key?(args) # If no cached result for these args
cache[args] = self[*args] # Compute and cache the result
end
cache[args] # Return result from cache
}
end
# A (probably unnecessary) unary + operator for memoization
# Mnemonic: the + operator means "improved"
alias +@ memoize # cached_f = +f
end
Contd..
• Here’s how we might use the memoize method or the unary + operator
# A memoized recursive factorial function
factorial = lambda {|x| return 1 if x==0; x*factorial[x-1];}.memoize
#Or, using the unary operator syntax
factorial = +lambda{|x| return 1 if x==0; x*factorial[x-1];}
• Here factorial is a recursive function, It calls the memoized version of
itself, which produces optimal caching.
factorial = lambda {|x| return 1 if x==0; x*factorial[x-1];}
cached_factorial = +factorial # Recursive calls are not cached!

More Related Content

PPTX
6 Object Oriented Programming
PPT
Object-Oriented Programming Using C++
PPTX
Python Data-Types
PDF
Bad Smell In Codes 1
PPTX
PDF
A COMPLETE FILE FOR C++
PDF
String handling(string buffer class)
PPTX
Regular Expressions
6 Object Oriented Programming
Object-Oriented Programming Using C++
Python Data-Types
Bad Smell In Codes 1
A COMPLETE FILE FOR C++
String handling(string buffer class)
Regular Expressions

What's hot (18)

PPT
Core java by a introduction sandesh sharma
PPT
M C6java2
PPTX
Linq and lambda
DOCX
Notes on c++
PPT
M C6java3
PDF
Python Advanced – Building on the foundation
PDF
Datatype
PDF
Object Oriented Programming using C++ Part III
PDF
Oop with c++ notes unit 01 introduction
PPT
9781439035665 ppt ch03
PPTX
11 Unit 1 Chapter 02 Python Fundamentals
PPT
M C6java7
PDF
Python Programming - IV. Program Components (Functions, Classes, Modules, Pac...
PDF
The Ring programming language version 1.5.3 book - Part 187 of 194
PPTX
A New Paradigm for Alignment Extraction
PPTX
Text and Numbers (Data Types)in PHP
PDF
LectureNotes-02-DSA
PDF
RubyMiniGuide-v1.0_0
Core java by a introduction sandesh sharma
M C6java2
Linq and lambda
Notes on c++
M C6java3
Python Advanced – Building on the foundation
Datatype
Object Oriented Programming using C++ Part III
Oop with c++ notes unit 01 introduction
9781439035665 ppt ch03
11 Unit 1 Chapter 02 Python Fundamentals
M C6java7
Python Programming - IV. Program Components (Functions, Classes, Modules, Pac...
The Ring programming language version 1.5.3 book - Part 187 of 194
A New Paradigm for Alignment Extraction
Text and Numbers (Data Types)in PHP
LectureNotes-02-DSA
RubyMiniGuide-v1.0_0
Ad

Similar to 7 Methods and Functional Programming (20)

PDF
Ruby_Basic
PDF
11 ruby methods
PDF
A limited guide to intermediate and advanced Ruby
PDF
RubyMiniGuide-v1.0_0
PDF
Ruby training day1
PPTX
Ruby object model
ODP
Ruby Basics by Rafiq
PPTX
Ruby data types and objects
PDF
Slides chapter3part1 ruby-forjavaprogrammers
PPTX
4 Expressions and Operators
PPT
Rubyforjavaprogrammers 1210167973516759-9
PPT
Rubyforjavaprogrammers 1210167973516759-9
KEY
Learn Ruby 2011 - Session 2
PPTX
Ruby basics ||
PDF
Ruby 2: some new things
PPTX
Metaprogramming in Ruby
PPTX
Ruby Basics
PDF
Ruby — An introduction
KEY
Ruby objects
PPTX
Ruby from zero to hero
Ruby_Basic
11 ruby methods
A limited guide to intermediate and advanced Ruby
RubyMiniGuide-v1.0_0
Ruby training day1
Ruby object model
Ruby Basics by Rafiq
Ruby data types and objects
Slides chapter3part1 ruby-forjavaprogrammers
4 Expressions and Operators
Rubyforjavaprogrammers 1210167973516759-9
Rubyforjavaprogrammers 1210167973516759-9
Learn Ruby 2011 - Session 2
Ruby basics ||
Ruby 2: some new things
Metaprogramming in Ruby
Ruby Basics
Ruby — An introduction
Ruby objects
Ruby from zero to hero
Ad

More from Deepak Hagadur Bheemaraju (8)

PPTX
12 Introduction to Rails
PPTX
PPTX
PPTX
9 Inputs & Outputs
PPTX
8 Exception Handling
PPTX
5 Statements and Control Structures
PPTX
12 Introduction to Rails
9 Inputs & Outputs
8 Exception Handling
5 Statements and Control Structures

Recently uploaded (20)

PDF
Complications of Minimal Access Surgery at WLH
PDF
2.FourierTransform-ShortQuestionswithAnswers.pdf
PPTX
human mycosis Human fungal infections are called human mycosis..pptx
PPTX
Final Presentation General Medicine 03-08-2024.pptx
PDF
Computing-Curriculum for Schools in Ghana
PPTX
Orientation - ARALprogram of Deped to the Parents.pptx
PDF
Weekly quiz Compilation Jan -July 25.pdf
DOC
Soft-furnishing-By-Architect-A.F.M.Mohiuddin-Akhand.doc
PDF
Abdominal Access Techniques with Prof. Dr. R K Mishra
PPTX
Microbial diseases, their pathogenesis and prophylaxis
PDF
Classroom Observation Tools for Teachers
PDF
Chapter 2 Heredity, Prenatal Development, and Birth.pdf
PDF
OBE - B.A.(HON'S) IN INTERIOR ARCHITECTURE -Ar.MOHIUDDIN.pdf
PDF
O5-L3 Freight Transport Ops (International) V1.pdf
PDF
O7-L3 Supply Chain Operations - ICLT Program
PDF
01-Introduction-to-Information-Management.pdf
PDF
Supply Chain Operations Speaking Notes -ICLT Program
PDF
The Lost Whites of Pakistan by Jahanzaib Mughal.pdf
PPTX
GDM (1) (1).pptx small presentation for students
PDF
STATICS OF THE RIGID BODIES Hibbelers.pdf
Complications of Minimal Access Surgery at WLH
2.FourierTransform-ShortQuestionswithAnswers.pdf
human mycosis Human fungal infections are called human mycosis..pptx
Final Presentation General Medicine 03-08-2024.pptx
Computing-Curriculum for Schools in Ghana
Orientation - ARALprogram of Deped to the Parents.pptx
Weekly quiz Compilation Jan -July 25.pdf
Soft-furnishing-By-Architect-A.F.M.Mohiuddin-Akhand.doc
Abdominal Access Techniques with Prof. Dr. R K Mishra
Microbial diseases, their pathogenesis and prophylaxis
Classroom Observation Tools for Teachers
Chapter 2 Heredity, Prenatal Development, and Birth.pdf
OBE - B.A.(HON'S) IN INTERIOR ARCHITECTURE -Ar.MOHIUDDIN.pdf
O5-L3 Freight Transport Ops (International) V1.pdf
O7-L3 Supply Chain Operations - ICLT Program
01-Introduction-to-Information-Management.pdf
Supply Chain Operations Speaking Notes -ICLT Program
The Lost Whites of Pakistan by Jahanzaib Mughal.pdf
GDM (1) (1).pptx small presentation for students
STATICS OF THE RIGID BODIES Hibbelers.pdf

7 Methods and Functional Programming

  • 1. Deepak H B Full-Stack Developer Gmail: [email protected] Linkedin: http://in.linkedin.com/in/deepakhb GitHub: https://github.com/deepakhb2
  • 3. Introduction • A method is a named block of parameterized code associated with one or more objects. • A method invocation specifies the method name and the object on which the method is invoked. • The value of the last expression evaluated in the method becomes the value of the method invocation expression. • Ruby is purely object oriented language, all the methods are associated with at least one object. • Methods are the fundamental part of Ruby’s syntax, but they are not values that Ruby programs can operate on. • Methods are not Ruby’s only form of parameterized executable code, Blocks are also executable chunks of code and may have parameters.
  • 4. Defining Simple Method • Methods are defined with the def keyword. • This is followed by the method name and optional list of parameter names in parentheses. • The Ruby code constitutes the method body follows the parameter list and end of the method is marked with the end keyword. • Parameter names can be used as variables within the method body and the values of these named parameters come from the arguments to a method invocation. def method_name(n) #method body End • Methods are always invoked on an object. • Ruby uses “.” to separate the object from the method to be invoked on it.
  • 5. Method Return Value • Methods may be terminated normally or abnormally. Abnormal termination occurs when the method raises an exception. • The return keyword is used to force a return prior to the end of the method. • The expression follows the return keyword is evaluated and returned. • The nil is returned if there is no expression. • Ruby methods may return more than one value by using return keyword explicitly def return_numbers return 1,2,3 end • More than one return values are collected into an array and it becomes the single return value of the method. • Methods of this form are typically intended for use with parallel assignment. x,y,z = return_numbers
  • 6. Singleton Methods • The methods that are defined for single specified object are called singleton methods. • Simply follow the def keyword with an object that follows by a period and the name of the method to be defined. o = “message” def o.printme puts self end o.printme # “message” • Class methods such as Math.sin and File.delete are actually singleton methods. • Math is constant that refers to a Module object and File is a constant that refers to a Class object. • Ruby implementation typically treat Fixnum and Symbol values as immediate values rather than as true object reference. For this reason singleton methods may not be defined on Fixnum and Symbol.
  • 7. Undefining Methods • Methods are defined with the def keyword and may be undefined using undef keyword. • undef can be used to undefined inherited methods without affecting the definition of the method in the class form which it is inherited. • This is not commonly used statement. • This should followed by a single identifier that specifies the method name. • It cannot be used to undefine a singleton methods.
  • 8. Method Name • Method names begin with lower case letters. • If method name is longer than one word, the usual convention is to separate the words with underscores like_this. • Method names might end with an equal sign, a question mark, or an exclamation point. • The equal sign suffix signifies that the method is setter. • The question mark signifies that method returns a value that answers question posed by the method invocation. empty?
  • 9. Contd.. • Methods whose names are ending with exclamation mark should be used with caution. sort!, exit! • Methods ending with exclamation mark are mutators, which alters the internal state of an object. • Ruby’s operators, such as +, * and even the array index [] operator are implemented with methods that you can define in your own class. def +(other) self.concatenate(other) end • Ruby can define more than one name for same method. • The language ahs alias key word to define a new name for existing method. alias to_str, to_s #alias new_name existing_name • This can be used inside the class whose methods needs to be renamed.
  • 10. Methods and Parentheses • Ruby allows parentheses to be omitted from most of the method invocations. puts “Hello world” puts(“Hello world”) • The next example greeting = “Hello” size = greeting.length • Normally length looks like property, field or variable of string objects. But this is method invocation. Then length method expects no arguments and is invoked without parentheses. size = greeting.length()
  • 11. Contd.. • Parentheses are very commonly omitted when there are zero or one arguments to the invoked methods. • Parentheses may also be omitted around the parameter list in method definitions, though it is hard to argue that this makes your code clearer or more readable. • Some code is ambiguous if the parentheses are omitted and here Ruby requires that you include them. • The most common case is nested method invocations of the form f g x,y. In Ruby, invocations of that form mean f(g(x,y))
  • 12. Method Arguments • Simple method declarations include a comma-separated list of names after the method name. • But there is much more to Ruby’s method arguments: – How to declare an arguments that has a default value. – How to declare a method that accepts any number of arguments. – How to simulate named method arguments with special syntax for passing a hash to a method.
  • 13. Parameter Defaults • When you define a method, you can specify default values for some or all of the parameters. def prefix(s, len=1) S[0,len] end • The above methods defines two parameters, but the second on has a default value. This can be invoked as below: prefix(“ruby”, 3) #=> “rub” prefix(“Ruby”) #=> “R” • Parameter defaults are evaluated when a method is invoked rather than when it is parsed. In the following method, the default value [] produces a new empty array on each invocation. def append(x, a=[]) a<<x end
  • 14. Contd.. • In Ruby 1.8, method parameters with default values must appear after all ordinary parameters in the parameter list. • In Ruby 1.9, allows ordinary parameters to appear after the parameters with defaults. But mixing between these two parameters are not allowed.
  • 15. Variable-Length Argument Lists and Arrays • The * is put before one of the methods parameter to accept an arbitrary number of arguments. def max(first, *rest) max = first rest.each{|x| max = x if x > maz} max end • The max method requires at least one argument, but it may accept any number of additional arguments. max(1) # first=1, rest=[] max(1,2)# first=1, rest=[2] max[1,2,3] #first=1, rest=[2,3]
  • 16. Contd.. • No more than one argument is prefixed with *. • This should be the last parameter of a method. • The max method can also accept single array as argument by using splat (*) operator on invocation. This will expand the elements of an array. data = [3,2,1] max(*data)
  • 17. Hashes for Named Arguments • When a method accepts more than two or three arguments, it will be difficult for the programmer invoking the method to remember the proper order. • The solution for this is to write a method that accepts hash a parameter. def sequence(args) n=args[:n] || 0 m=args[:m] || 1 c=args[:c] ||0 end • This method can be invoked with hash literal as argument sequence({:n=>3, :m=>5}) • Ruby supports to pass hash without curly braces to the last argument of the method. sequence(:n=>3, :m=>5) • If parenthesis are omitted, then curly braces must be omitted as well. sequence {:n=>2, :m=>5} # Syntax error
  • 18. Procs and Lambdas • Blocks are syntactic structures in Ruby; they are not objects and cannot be manipulated as object. • It is possible, however to create an object that represents a block. • Depending on how the object is created it is called a proc or lambda. • Proc have block-like behavior and lambda’s have method- like behavior. • Both Proc and lambdas are instance of class Proc.
  • 19. Creating Procs • The Proc object is created by associating a block with a method that is defined with an ampersand-prefixed block argument. def makeproc(&p) p End • With a makeproc method like this defined, we can create a Proc object by adder = makeproc {|x,y| x+y} • Now the variable adder refers to the Proc object. All proc objects have a call method that when invoked runs the code contained in the block from which proc was created. sum = adder.call(2,2)
  • 20. Proc.new • This is the normal new method that most classes support, and it’s the most obvious way to create a new instance of the Proc class. • Proc.new expects no arguments and returns the instance of Proc class (not lambda). p = Proc.new {|x,y| x+y} Kernel.lambda • Another technique for creating Proc objects is with the lambda method. • The lambda is a method of the kernel module, so it behaves like a global function. • The proc object returned from this method is a lambda rather than a proc. • lambda expects no arguments, but there must be a block associated with the invocation. is_positive = lambda {|x| x>0}
  • 21. Lambda Literals • The created lambda method below succ = lambda{|x| x+1} • Can be converted to literal as follows: – Replace the method name lambda with the punctuation - >. – Move the list of arguments outside of and just before the curly braces. – Change the argument list delimiters from || or (). • With these the lambda literal succ = ->(x){ x+1 }
  • 22. Invoking Procs and Lambdas • Procs and lambdas are objects, not methods and they cannot be invoked in the same way that methods. • If p is Proc object, it cannot invoked as method instead it can invoke the method of p. • Proc class defines a method named call. • Invoking this method executes the code in the original block with the arguments that are passed by call. f = Proc.new{|x,y|1.0/(1.0/x+1.0/y)} z = f.call(x,y) • The Proc class also defines the array access operator to work the same way as call. z = f[x,y] • An additional way to invoke a Proc object as an alternative to square brackets, you can use parenthesis prefixed with a period z = f.(x,y)
  • 23. The Arity of a Proc • The arity of a proc or lambda is the number of arguments it expects. • Proc object have an arity method that returns the number of arguments they expect. lambda{||}.arity # => 0 lambda{|x|}.arity # => 1 lambda{|x,y|}.arity # => 2 • The notion of arity gets confusing, when a Proc accepts an arbitrary number of arguments in an * prefixed final argument. • When Proc allows optional arguments, the arity method returns a negative number of the form –n-1. lambda{|*args|}.arity # => -1. ~-1 = -(-1)-1 = 0 arguments required lambda{|first, *rest|}.arity # => -2. ~-2 = -(-2)-1 = 1 argument required
  • 24. Proc Equality • The Proc class defines an == method to determine whether two Proc objects are equal. • It is important to understand, however, that merely having the same source code is not enough to make two procs or lambdas equal to each other. lambda{|x| x*x} == lambda{|x| x*x} #=> false • The == method only returns true if on Proc is a clone or duplicate of the other p = lambda{|x| x*x} q = p.dup p == q # => true p.object_id == q.object_id # => false
  • 25. Functional Programming • Ruby is not Functional programming language in the way that languages like Lisp and Hskell are. • Any time you use a block with an Enumerable iterators like map or inject, your programming in a functional style. mean = a.inject{|x,y| x+y}/a.size sumOfSquares = a.map{|x| (x-mean)**2}.inject{|x,y| x+y}
  • 26. Applying a Function to an Enumerable • The map and inject are two of the most important iterators defined by Enumerable. • If we write a programs in a function-centric way, we might like methods on our functions that allow us to apply those functions to a specified Enumerable object.
  • 27. # This module defines methods and operators for functional programming. module Functional # Apply this function to each element of the specified Enumerable, # returning an array of results. This is the reverse of Enumerable.map. # Use | as an operator alias. Read "|" as "over" or "applied over". # Example: # a = [[1,2],[3,4]] # sum = lambda {|x,y| x+y} # sums = sum|a # => [3,7] def apply(enum) enum.map &self end alias | apply # Use this function to "reduce" an enumerable to a single quantity. # This is the inverse of Enumerable.inject. # Use <= as an operator alias. # Mnemonic: <= looks like a needle for injections # Example: # data = [1,2,3,4] # sum = lambda {|x,y| x+y} # total = sum<=data # => 10 def reduce(enum) enum.inject &self end alias <= reduce end
  • 28. • Notice that we define methods in a module named Functional, and when we include this module into both the Proc and Method classes. • Most of the methods that follow also define methods in this Functional module, so that they work for both Proc and Method. • With apply and reduce defined as above, we could refactor our statistical computations as follows: sum = lambda{|x,y| x+y} #A function to add two numbers mean = (sum<=a)/a.size #Or sum.reduce(a) or a.inject(&sum) deviation = lambda{|x| x-mean} #Function to compute difference from mean square = lambda{|x| x*x} #Function to square a number standardDeviation = Math.sqrt((sum<=square|(deviation|a))/(a.size-1)) Contd.. # Add these functional programming methods to Proc and Method classes. class Proc; include Functional; end class Method; include Functional; end
  • 29. Composing Functions • If we have a functions f and g, we sometimes want to define a new function h which is f(g()) or f composed with g. • We define a method that performs function composition automatically.
  • 30. module Functional # Return a new lambda that computes self[f[args]]. # Use * as an operator alias for compose. # Examples, using the * alias for this method. # f = lambda {|x| x*x } # g = lambda {|x| x+1 } # (f*g)[2] # => 9 # (g*f)[2] # => 5 # def polar(x,y) # [Math.hypot(y,x), Math.atan2(y,x)] # end # def cartesian(magnitude, angle) # [magnitude*Math.cos(angle), magnitude*Math.sin(angle)] # end # p,c = method :polar, method :cartesian # (c*p)[3,4] # => [3,4] def compose(f) if self.respond_to?(:arity) && self.arity == 1 lambda {|*args| self[f[*args]] } else lambda {|*args| self[*f[*args]] } end end
  • 31. Contd.. • The example code in the comment demonstrates the use of compose with Method objects as well as lambdas. • We can use this new * function composition operator so slightly simplify our computation of standard deviation. standardDeviation = Math.sqrt((sum<=square*deviation|a)/(a.size-1)) • The difference is that we compose square and deviation into a single function before applying it to the array a.
  • 32. Partially Applying Functions • In functional programming, partial application is the process of taking a function and a partial set of argument values and producing a new function that is equivalent to the original function with the specified arguments fixed. • For example, $product = lambda {|x, y| x*y} #A function of two arguments $double = lambda {|x| product(2,x) } #Apply one argument • Partial application can be simplified with appropriate methods in our Functional module.
  • 33. module Functional # Return a lambda equivalent to this one with one or more initial # arguments applied. When only a single argument # is being specified, the >> alias may be simpler to use. # Example: # product = lambda {|x,y| x*y} # doubler = lambda >> 2 def apply_head(*first) lambda {|*rest| self[*first.concat(rest)]} end # Return a lambda equivalent to this one with one or more final arguments # applied. When only a single argument is being specified, # the << alias may be simpler. # Example: # difference = lambda {|x,y| x-y } # decrement = difference << 1 def apply_tail(*last) lambda {|*rest| self[*rest.concat(last)]} end # Here are operator alternatives for these methods. The angle brackets # point to the side on which the argument is shifted in. alias >> apply_head # g = f >> 2 -- set first arg to 2 alias << apply_tail # g = f << 2 -- set last arg to 2 end
  • 34. Contd.. • Using these methods and operators, we can define our double function simply as product >> 2. • We can use partial application to make our standard deviation computation somewhat more abstract, by building our deviation function from more general purpose difference function. difference = lambda {|x,y| x-y} #Compute difference of two numbers deviation = difference << mean #Apply second argument
  • 35. Memoizing functions • Memoizing Functions is a functional programming term for caching the results of a function invocation. • If a function always returns the same value when passed the same arguments, if there is reason to believe that the same arguments will be used repeatedly, and if the computation it performs is somewhat expensive, then memoization may be a useful optimization. • We can automate memorization for Proc and Method objects with the following method.
  • 36. module Functional # Return a new lambda that caches the results of this function and # only calls the function when new arguments are supplied. def memoize cache = {} # An empty cache. The lambda captures this in its closure. lambda {|*args| # notice that the hash key is the entire array of arguments! unless cache.has_key?(args) # If no cached result for these args cache[args] = self[*args] # Compute and cache the result end cache[args] # Return result from cache } end # A (probably unnecessary) unary + operator for memoization # Mnemonic: the + operator means "improved" alias +@ memoize # cached_f = +f end
  • 37. Contd.. • Here’s how we might use the memoize method or the unary + operator # A memoized recursive factorial function factorial = lambda {|x| return 1 if x==0; x*factorial[x-1];}.memoize #Or, using the unary operator syntax factorial = +lambda{|x| return 1 if x==0; x*factorial[x-1];} • Here factorial is a recursive function, It calls the memoized version of itself, which produces optimal caching. factorial = lambda {|x| return 1 if x==0; x*factorial[x-1];} cached_factorial = +factorial # Recursive calls are not cached!