Note: Testo rimosso dalla rev 5  e Testo aggiunto nella rev6

Cos’e una funzione lambda o closure? Si tratta, sostanziualmente,sostanzialmente, di una funzione anonima.

Quello che fate quando usate each():

 array.each { |argomenti| codice }

in realta’ e’ equivalente a a:

 def f(argomenti)
  codice
 end
 for i in array
  f(i)
 end

non e’ un caso che in ruby si possa creare una funzione anonima, cioe’ un oggetto Proc scrivendo:

oggetto= lambda {|args| codice}

Le funzioni anonime sono talmente utili che sono state introdotte in molti dei linguaggi moderni: C#, python, ruby sono degli esempi.esempi

C’eIn unarealtà differenzaci sottilesono tradifferenze lesottili, lambdama parliamo di C#/pythoncome e quelle di ruby/lisp (la definizione di vere chiusure lessicali.e’ ambigua,funziona in ogni caso).

In realta’ la differenza e’ molto sottile. ruby. Definiamo lo scope lessicale. In pratica significa che una funzione fa riferimento a delle variabili basandosi su quello che viene definito intorno a se direttamente nel testo, e non al momento dell’esecuzione del codice.

Sembra complicato ma non lo e’, guardate:

 >> def esponenziale(num)
 >>  proc { num=num*num }
 >> end
 => nil
 >> b=esponenziale(2)
 => #<Proc:0x027d61d8@(irb):2>
 >> a=esponenziale(3)
 => #<Proc:0x027d61d8@(irb):2>
 >> a.call
 => 9
 >> b.call
 => 4
 >> a.call
 => 81
 >> a.call
 => 6561
 >> b.call
 => 16 

cosa succede? succede che l’oggetto Proc si chiude sopra alle variabili che si trovano nel suo pezzettino di codice. Non importa se poi noi usiamo altri valori (ad esempio, richiamando esponenziale() con un altro parametro.

Perche’Per questole sistemadifferenze e’vedete diversa da quello di Python e C#? ((pregasi verificare, nn sono esperto di python, faccio riferimento a Paul Graham))


 >>> def esponenziale(n):
 ...  lambda a: n=n*n
 ...
   File "<stdin>", line 2
 SyntaxError: can't assign to lambda

Python ha delle chiusure lessicali nelle quali si ha riferimento all’oggetto, ma non alla variabile stessa. Il comportamento va emulato, chiudendo la variabileClosure in un altro oggettopython


  def esponenziale(n):
   ary=[n]
   def f():
    ary.append(ary.pop()**2)
    return ary[0]
   return f

Ma stiamo divagando :)

Un’altra cosa affascinante che possiamo fare con le chiusure lessicali e’ la condivisione di variabili tra diverse procedure:

 >> def add_sub(default)
 >>   return proc {default+=1},proc {default-=1}
 >> end
 => nil
 >> add,sub=add_sub(10)
 => [#<Proc:0x0275a968@(irb):25>, #<Proc:0x0275a878@(irb):25>]
 >> add
 => #<Proc:0x0275a968@(irb):25>
 >> add.call 
 => 11
 >> sub.call
 => 10
 >> sub.call
 => 9
 >> add.call
 => 10
 >> add.call
 => 11
 >> add.call
 => 12
 >> sub.call
 => 11

Ovviamente, vi starete chiedendo a cosa cavolo vi serve qesta cosa. Beh, capirete l’utilita’, forse, pensando che tra le altre cose, un blocco, cioe’ un oggetto proc, cioe’ una chiusura lessicale, e’ quello che definisce il comportamento di un Thread

 Thread.new { codice }
Created on January 02, 2006 17:11 by Ruby Fan (24.6.173.198)