Newsgroup: it.comp.lang
Titolo: [CONFRONTO] Higher order function

>> h(5)
8
</PYTHON>
Ora, le domande che ho sono:
1. Quali linguaggi permettono di utilizzare le higher order functions?
2. Quali vantaggi porta l'utilizzo delle higher order functions?
3. Esempi interessanti?
4. Mi pare di aver letto su "Modern compiler implementation" di
   Andrew W. Appel (ma non l'ho sotto mano e non l'ho ancora studiato),
   che queste funzioni non sono implementabili con uno stack.
   Posso immaginare la questione, ma non mi è del tutto chiara.
   Qualcuno me la spiegherebbe?
Grazie
-- 
Gerolamo
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 3. Esempi interessanti?
L'uso tipico e' nelle "closures".
Eccoti un esempio piuttosto avanzato, se hai dei dubbi, riscrivi:
-------------------------------------------------------------------
The tracing of a single function can be done with a closure 
like this:
::
 
  #<oopp.py>
  def with_tracer(function,namespace='__main__',output=sys.stdout,
indent=[0]):
      """Closure returning traced functions. It is typically invoked
      trough an auxiliary function fixing the parameters of
with_tracer."""
      def _(*args,**kw):
          name=function.__name__
          i=' '*indent[0]; indent[0]+=4 # increases indentation
          output.write("%s[%s] Calling '%s' with arguments\n" % 
                                                   (i,namespace,name))
          output.write("%s %s ...\n" % (i,str(args)+str(kw)))
          res=function(*args,**kw)
          output.write("%s[%s.%s] called with result: %s\n"
                           % (i,namespace,name,str(res)))
          indent[0]-=4 # restores indentation
          return res
      return _ # the traced function
  #</oopp.py>
Here is an example of usage:
  >>> from oopp import with_tracer
  >>> def fact(n): # factorial function
  ...     if n==1: return 1
  ...     else: return n*fact(n-1)
  >>> fact=with_tracer(fact)
  >>> fact(3)
  [__main__] Calling 'fact' with arguments
   (3,){} ...
      [__main__] Calling 'fact' with arguments
       (2,){} ...
          [__main__] Calling 'fact' with arguments
           (1,){} ...
          [__main__.fact] called with result: 1
      [__main__.fact] called with result: 2
  [__main__.fact] called with result: 6
  6
The logic behind ``with_tracer`` should be clear; the only trick is
the
usage of a default list as a way to store a global indentation
parameter.
Since ``indent`` is mutable, the value of ``indent[0]`` changes at any
recursive call of the traced function, resulting in a nested display.

 3. Esempi interessanti?
beh, di sicuro offrono molta piu` flessibilita rispetto alle funzioni "lower
order"; a seconda dei linguaggi che usi quasi non ti accorgi di usare delle
HOF: se ad esempio in caml definisci una funzione con piu` di un argomento
di default ottieni una HOF che permette di effettuare molto facilmente il
currying:
# let sum x y = x+y;;
val sum : int -> int -> int = <fun>
# sum 3 5;;
- : int = 8
# sum 3;;
- : int -> int = <fun>
# let add3 = sum 3;;
val add3 : int -> int = <fun>
# add3 5;;
- : int = 8
Tra gli esempi interessanti direi che se un linguaggio supporta le HOF, e
quindi se funzioni sono first class object, e` molto semplice implementare
il pattern command: se in C++ occorrono diverse classi e righe di codice
per implementarlo, in altri linguaggi e` quasi "gratis"; ad esempio in
python il caso piu` semplice e` immediato da realizzare:
class Document:
    ...
    def save(self):
        ...
mycommand = mydocument.save
# ora posso passare mycommand in giro e richiamarlo quando piu` opportuno
mycommand()
Pero` se abbiamo esigenze un po' piu` specifiche le cose si complicano: ad
esempio se il nostro comando prende dei parametri e noi vogliamo
specificarli al momento della *creazione* (e non nel momento della
chiamata) dobbiamo ricorrere ad una HOF:
class Document:
    ...
    def saveAs(self, filename):
        ...
def commandSaveAs(doc, filename):
    def result():
        doc.saveAs(filename)
    return result
mycommand = commandSaveAs(mydocument, 'prova.doc')
...
mycommand()
In python potevamo anche ottenere lo stesso effetto con una lambda, pero` la
sostanza non cambia.
ciao Anto
-- 
"Computer science is not about computers any more than astronomy
is about telescopes." -- EW Dijkstra