Oggetti Proc e Method

Vedi tutte le pagine e le modifiche recenti o scarica i sorgenti nella pagina


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 do |arg|
      ...codice..
     end

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

 # terzo metodo
 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| puts a,b }
 => #<Proc:0x401f9570@(irb):1>
 >> f=lambda {|a,b| puts a,b }
 => #<Proc:0x401f61b8@(irb):2>
 >> p.call 1,2
 1
 2
 => nil
 >> f.call 1,2
 1
 2
 => nil
 >> p.call 1
 1
 nil
 => nil
 >> f.call 1
 ArgumentError: wrong number of arguments (1 for 2)
         from (irb):2
         from (irb):2:in `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= lambda {|z| print z }
 p(10) # sintassi come in python o scheme
Scriveremo invece
 p= lambda {|z| print z }
 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= lambda {|z| print z }
 p[10] # equivalente a p.call(10)
Un oggetto di tipo metodo invece viene creato cosi’:
 met=method(:nomemetodo)
oppure
 met=oggetto.method(:nomemetodo)
Una volta creati, questi oggeti funzionano praticamente in maniera identica:
 def fun(a)
  a**2
 end
 nil
 oggetto=method :fun # #<Method: Object#fun>
 oggetto.call(10) # 100
 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 “&

Updated on November 26, 2005 13:30 by Ruby Fan (151.37.150.7)