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