Not a member of Pastebin yet?
                        Sign Up,
                        it unlocks many cool features!                    
                - #Ruby Programming Language
 - #Chapter 6 Methods, Procs, Lambdas, and Closures
 - ##Defining methods
 - * to define method use `def` followed by method name
 - * put method parameters in round brackets ()
 - * Abnormal method termination is when method raises exception
 - * If method terminates normally then last expression evaluated in method body will be method invocation value
 - * `return` keyword is used to **FORCE** return from method and value of the expresion is returned if there is no expression then nil will be returned
 - * common practice is that `return` keyword is omitted
 - * if `return` is used with multiple values then return value is automatically converted to array
 - * to manually return multiple values then you need to create array manually
 - Sample code:
 - ```ruby
 - # Define a method named 'factorial' with a single parameter 'n'
 - def factorial(n)
 - if n < 1 # Test the argument value for validity
 - raise "argument must be > 0"
 - elsif n == 1 1
 - else
 - n * factorial(n-1)
 - end end
 - ```
 - * Defining singleton methods on object can be done with `def` keyword as shown below
 - * Ruby treats `Fixnum`, `Symbol` and `Numeric` objects as immediate values rather than as true referances so defining singleton methods on them is prohibited
 - ```ruby
 - o = "message"
 - def o.printme
 - puts self
 - end
 - o.printme
 - ```
 - * You can undefine method with `undef` keyword followed by method name
 - * You can undefine method that was inherited from superclass if you don't want that class to invoke that method
 - ## Method names
 - * Method names may (but are not required to) end with an equals sign, a question mark, or an exclamation point
 - * You can use equal sign to specify that the method is a setter
 - * Question mark or exclamation point give no logical ability to the method but allow you to keep usefull naming conventions
 - * Methods with question mark are naturally answering question asked by method name
 - * Methods with exclamation mark are the one that you should use with caution like `sort!`, `exit!`
 - * You can define unary and binary operators
 - * Using `alias` keyword for a method name you can create alias name for that method and use this method with that alias even after it was redefined after alias statment
 - * Alias is not the same as overload!!!
 - ## Method parentheses
 - * Parentheses in ruby can be omitted, se example:
 - ```ruby
 - puts("hello world")
 - #is equal to
 - puts "hello world"
 - ```
 - * But some code is ambiguous if you omitt parentheses
 - * The best way to avoid ambiguousness is to use parentheses
 - ## Method arguments
 - * Methods can be define with default parameter value like:
 - ```ruby
 - def prefix(s, len=1)
 - s[0,len]
 - end
 - ```
 - * Methods default value don'd need to be constant, they are evaluated when method is invoked and not at parse time
 - * To define method that will accept arbitrary number of arguments simply put `*` before parameter name
 - * Passing Hash as a method parameter in ruby is allowed with no curly brackets
 - * Methods can have block arguments that can be invoked with `yield` keyword passed as non direct method parameter:
 - ```ruby
 - def sample(x)
 - yield x*x
 - end
 - sample(x) {|x2| puts x2}
 - ```
 - * To have better control over the block, just add another paramter to definition with `&` before parameter name
 - * The value of that parameter will be `Proc` object
 - * To invoke `Proc` object use `call` on block object
 - * It is also possible to pass created `Proc` object as a method parameter created with `Proc.new`, then mentioned `&` is not necessary
 - * Block passed with `&` must be last in the parameter liest because of method unusuall invocation
 - ## Procs and Lambdas
 - * Creating a `Proc` object:
 - ```ruby
 - Proc.new {|x| x+x }
 - proc {|x| -x }
 - lambda {|X| x*x}
 - ```
 - * `lambda` is a global function and since Ruby 1.9 it can be replaced with `->` example:
 - ```ruby
 - m=->(z){z-1}
 - ```
 - * One benefit of `lambda` is that block can be declared with default values like this:
 - ```ruby
 - zoom = ->x,y,factor=2 { [x*factor,y*factor]}
 - ```
 - * `->` can be used to pass inline proc to a method like in example:
 - ```ruby
 - methodName(->{x+1},->x{x-1})
 - ```
 - * Regular block syntax is simpler to use in some situations
 - * `Proc` objects can be invoked with the use of `.()`
 - * `Proc` and `lambda` declare `arity`, it is a number of arguments it expects
 - * If block declares default (optinal) argument then `arity` of that block will be negative number
 - * Block with no arbitrary number of arguments declared with `*` will give `arity` 0 cause no arguments are required
 - * `Proc` define `==` method to detemin euality between objects, but it only returns true if object is a copy, example:
 - ```ruby
 - l = lambda { |x| x*x*x }
 - c = l.dup
 - l == c # => true
 - # but
 - l.object_id == c.object_id # => false, they are not the same objects
 - ```
 - * `Proc` is a block and it behave like a block, `lambda` is more like a method
 - * Calling `Proc` is yielding to a block whereas calling `lambda` is like invoking a method
 - * Ruby gives a method `lambda?` to check if object is `lambda` of a `Proc`
 - * `return` keyword in block will return not only from a block but from a method that yields it
 - * `return` work differently in `lamabda` here it will return only from `lambda` because lambda is more like method itself
 - * It means _LocalJumpError_ is not an issue in Lambdas
 - * `break` keyword will make sense for block used with `&` statment
 - * Breaking lambdas make no sense at all
 - * `next` and `redo` works the same in lambda, proc or block
 - * `retry` cannot be used in procs or lambdas it will cause _LocalJumpError_
 - * `raise` if there is no `rescue` will propagate to the method that invoked the block
 - * lambdas are less flexible regarding handling arguments
 - * procs will handle less or more than required arguments than initialy declared by discarding extra arguments or assigning _nil_ to argument that was not passed to block
 - * lambda will rise _Wrong number of arguments_ error when called with less of to many arguments
 - ## Closures
 - * Procs and lambdas are closures
 - * If you want to return cloasures from methods then be careful about variables scope
 - * `Proc` class defines method named `binding` that returns `Binding` object that can be used with global `eval` method
 - * `Method` object can represent method but remember that calling it through this object is not very efficient
 - * To obtain that object use method named `method` on object like:
 - ```ruby
 - m = 0.method(:succ) # A Method representing the succ method of Fixnum 0
 - ```
 - * Other method that can be used is `public_method` it works the same way but it will ignore private and protected methods
 - * Method objects behave like lambdas so they can be prefixed with `&` and passed to another method as argument
 - * Method objects are not closures so they have no access to local variables outside of their own scope, the only binding retained by `Method` is the value of `self`
 - * Usefull methods declared in `Method` object are:
 - - name - _returns method name as string_
 - - owner - _returns in which method was defined_
 - - receiver - _returns object to which the method is bound_
 - * It is also possible to obtain `UnboundMethod` object using `instance_method`
 - * to use `UnboundMethod` object it needs to be bind again to some object like this:
 - ```ruby
 - plus_2 = unbound_plus.bind(2) # Bind the method to the object 2
 - ```
 - ## Functional Programming
 - * Ruby is not a functional language but can be more or less adopted to functional style
 - * It is possible to automate memoizing with method like:
 - ```ruby
 - 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
 - ```
 
Advertisement
 
                    Add Comment                
                
                        Please, Sign In to add comment