Note: Testo rimosso dalla rev 1  e Testo aggiunto nella rev2

OggettiProcEMethod

Proc e metodi sono entrambi oggetti in ruby. Le Proc rappresentano, come prima cosa, delle funzioni anonime, cioe’ che possono essere definite senza un nome particolare. Si fa uso di Proc tutte le volte che si passa un blocco in input ad una funzione come ad esempio each.

La creazione di una Proc puo’ avvenire in tre modi:

 # primo metodo                  
 prc=Proc.new                  
 prc=Proc.new do |arg||arg|
      ...codice.....codice..
     end

  1. # secondo metodo prc=proc prc=proc do |arg||arg| ...codice.. ...codice.. end
  1. # terzo metodo prc=lambda do |arg| ...codice.. end prc=lambda do |arg| ...codice.. end

lambda &blk e proc &blk sono effettivamente sinonimi, mentre la creazione di un oggetto Proc con Proc.new ha una differenza sottile. La differenza e’ nel passaggio dei parametri:

p=Proc.new


 >> {|a,b|p=Proc.new {|a,b| puts a,ba,b }
	
 => #
	f=lambda#<Proc:0x401f9570@(irb):1>
 >> {|a,b|f=lambda {|a,b| puts a,ba,b }
	
 => #
	p.call#<Proc:0x401f61b8@(irb):2>
 >> 1,2
	p.call 1
	,2
	
 1
 2
 => nil
	f.call
 >> 1,2
	f.call 1
	,2
	
 1
 2
 => nil
	p.call
 >> p.call 1
	
 1
	
 nil
	
 => nil
	f.call
 >> f.call 1
	ArgumentError:
 ArgumentError: wrong number of arguments (1(1 for 2)
        2)
         from (irb):2
        (irb):2
         from (irb):2:in(irb):2:in `call’
        `call'
         from (irb):6

Cioe’ proc e lambda si comportano come i normali metodi, richiedendo un numero esatto di parametri, mentre l’altra forma e’ piu’ elastica :-).

Per chi si chiedesse cosa cavolo e’ lambda: si tratta del nome che viene dato alle funzioni anonime in altri linguaggi, come ad esempio LISP.

Come potete intuire dall’esempio, un oggetto Proc per essere applicato a dei parametri richiede l’uso del metodo call(). Dunque, non scriveremo p=


 p= lambda {|z|{|z| print z }
 p(10)p(10) # sintassi come in python o scheme

Scriveremo invece
 p=p= lambda {|z|{|z| print z }
 p.call(10)p.call(10) # simile a funcall in Common LISP

La prima sintassi potra’ sembrare piu’ conveniente, ma in ruby e’ impossibile, visto che le parentesi sono opzionali. Come si farebbe a capire se print deve essere usata come funzione o si deve usare il suo valore di ritorno?

Quantomeno, ruby ci permette di “imitare” la sintassi classica, usando delle parentesi quadre:

 p=p= lambda {|z|{|z| print z }
 p[10] # equivalente a p.call(10)

Un oggetto di tipo metodo invece viene creato cosi’:

met=method(:nomemetodo)
 met=method(:nomemetodo)

oppure

met=oggetto.method(:nomemetodo)
 met=oggetto.method(:nomemetodo)

Una volta creati, questi oggeti funzionano praticamente in maniera identica:


 def fun(a)fun(a)
  a**2
 a**2
end

 nil
oggetto=method
 oggetto=method :fun # #
oggetto.call(10)#<Method: Object#fun>
 oggetto.call(10) # 100
oggetto[10]
 oggetto[10] # uguale a call()

Un ultima cosa: le funzioni che accettano in input un blocco si lamenteranno se provate a passargli un oggetto Proc; o Method. Per espandere questi oggetti/funzione in blocchi vi bastera’ mettere davanti al nome della variabile il simbolo “&”&

Created on November 25, 2005 13:39 by il gruppo (256.256.256.256)