Applicazione parziale
In matematica e informatica si definisce applicazione parziale di una funzione l'applicazione di una funzione a una parte dei suoi argomenti.
A rigore questa operazione dovrebbe essere "proibita", in quanto una funzione per essere definita deve essere applicata a tutti i suoi argomenti. In realtà ci sono diversi linguaggi di programmazione che consentono di farlo, restituendo un risultato utilizzabile, e anche nell'ambito della matematica è possibile dare un senso a un'espressione in cui una funzione sia applicata a una parte dei suoi argomenti.
Approccio intuitivo con degli esempi
[modifica | modifica wikitesto]Prima ancora di fornire la definizione formale, un semplice esempio può mostrare che il significato da dare a un'applicazione parziale è piuttosto intuitivo, al di là delle complicazioni che si pongono quando si voglia formalizzare tale intuizione.
Si supponga di avere una funzione moltiplica che moltiplica due numeri interi, cioè che a ogni coppia di interi fa corrispondere il loro prodotto:
Per definizione, se questa funzione viene applicata a due numeri restituisce un numero. Per esempio . Ma si supponga di avere un'espressione come questa: (dove il punto indica l'assenza di un argomento), o un'espressione come questa: , cioè un'espressione in cui sia presente uno solo dei due argomenti. Quale significato si potrebbe dare a questa espressione?
Se si usa un'espressione come questa in certi linguaggi di programmazione che consentono di farlo, il programma restituisce una funzione. Intuitivamente si capisce che la funzione che viene restituita è una funzione che "aspetta" il secondo argomento, per poter completare l'operazione. Così la funzione che si è scritta come o come prende un argomento e restituisce il prodotto di tale argomento con il numero 2:
Intuitivamente la cosa è talmente banale da sembrare quasi un'inutile complicazione formale, nel senso che sembra non esserci bisogno di introdurre ulteriori definizioni per poter porre:
In realtà però c'è una notevole differenza concettuale, in quanto al primo membro della equazione compare una funzione di due argomenti, cioè moltiplica, applicata a due argomenti, mentre al secondo membro della equazione compare una funzione di un argomento, cioè , applicata ad un argomento. Tornando all'esempio di poco fa, è una funzione, che potremmo definire doppio:
la quale prende come argomento un numero e restituisce il doppio di quel numero.
Inoltre, poiché per m fissato moltiplica(m) è una funzione, allora nel secondo membro della equazione moltiplica deve essere considerata una funzione di un argomento, che per ogni intero m restituisce una funzione da a . Una tale funzione, che prende un "numero" (in senso generico) e restituisce una funzione è detta anche funzionale. Pertanto quando si applica una funzione a una sola parte dei suoi argomenti tale funzione viene implicitamente ridefinita come il funzionale "naturalmente associato" alla funzione stessa. Anzi, più precisamente come uno dei funzionali associabili, poiché per ogni scelta degli argomenti su cui applicare parzialmente la funzione si ha un diverso funzionale associato.
Senza appesantire la notazione definendo un diverso funzionale per ogni possibile combinazione parziale degli argomenti, si può lasciare che sia il contesto a determinarlo, usando una notazione sufficiente a chiarirlo. Così se si scrive moltiplica(2) è chiaro dal contesto che si sta usando moltiplica come un funzionale che associa ad ogni numero una funzione, dopodiché moltiplica(2) è in particolare la funzione doppio, mentre moltiplica(3) sarebbe la funzione triplo eccetera.
Come si diceva sopra, alcuni linguaggi di programmazione implementano questa "sensibilità al contesto", per cui quando una funzione viene applicata a una parte soltanto dei propri argomenti il linguaggio tratta la funzione come funzionale e restituisce una funzione, la quale poi può essere applicata agli argomenti restanti, i quali a loro volta possono essere presi tutti assieme o parzialmente. Altri linguaggi invece richiedono che prima la funzione venga trasformata in un funzionale, e che poi questo funzionale venga applicato a una parte degli argomenti. E siccome in linea di principio ci sono tanti funzionali quante sono le combinazioni possibili degli argomenti, per non appesantire la notazione di solito si compie una scelta "radicale", definendo un operatore che trasforma una funzione in un funzionale che prende gli argomenti "uno alla volta" a cominciare dal primo.
Tale operatore è detto curry, e l'operazione corrispondente è detta currying, in onore di Haskell Curry, che ne studiò a lungo l'implementazione. In tali linguaggi di programmazione di fatto l'applicazione parziale di una funzione ai suoi argomenti torna ad essere "proibita"; se ad esempio si ha una funzione f di tre argomenti, quando non la si voglia applicare subito a tutti e tre gli argomenti, scrivendo f(x,y,z), bisogna prima ridurre la funzione f al funzionale curry(f), e poi applicare tale funzionale al primo argomento, ottenendo il funzionale curry(f)(x), che applicato al secondo argomento dà la funzione curry(f)(x)(y), la quale applicata al terzo argomento restituisce il numero curry(f)(x)(y)(z). Questo operatore è sempre implicito nel lambda calcolo, dove ogni funzione di più argomenti si considera un funzionale e gli argomenti vengono presi appunto "uno alla volta" a cominciare dal primo dando come risultato altri funzionali o (arrivati al penultimo argomento) una funzione.
Definizione formale
[modifica | modifica wikitesto]Dati tre insiemi A, B e C (eventualmente coincidenti) e una funzione
ad essa si possono associare in modo "naturale" due funzionali e definiti in questo modo:
Se aumenta il numero delle variabili la notazione si fa ancora più pesante, e bisogna considerare dei "funzionali a valori funzionali" cioè dei funzionali che applicati ad un loro argomento restituiscono a loro volta un funzionale.
Voci correlate
[modifica | modifica wikitesto]Implementazioni specifiche per ogni linguaggio
[modifica | modifica wikitesto]- ALGOL 68G
- Currying in C (PDF), su asg.unige.ch. URL consultato il 7 dicembre 2010 (archiviato dall'url originale il 25 dicembre 2010).
- Currying in CSharp, Alternative (faster) method
- Currying in Delphi 2009, su blogs.teamb.com. URL consultato il 7 dicembre 2010 (archiviato dall'url originale il 27 novembre 2010).
- Currying in Java [collegamento interrotto], su dis.4chan.org.
- Currying in JavaScript, su flesler.blogspot.com.
- Currying in Lua, su tinylittlelife.org. URL consultato il 7 dicembre 2010 (archiviato dall'url originale il 5 novembre 2010).
- Currying in Perl, su perldesignpatterns.com. URL consultato il 7 dicembre 2010 (archiviato dall'url originale il 28 febbraio 2011).
- Currying in PHP, su zaemis.blogspot.com.
- Partial Application in PowerShell, su nivot.org. URL consultato il 7 dicembre 2010 (archiviato dall'url originale il 14 gennaio 2011).
- Currying in Ruby, su moonbase.rydia.net. URL consultato il 7 dicembre 2010 (archiviato dall'url originale il 12 luglio 2010).
- Currying in Scala, su scala-lang.org.
- Implicit currying in Scheme, su engr.uconn.edu. URL consultato il 19 luglio 2008 (archiviato dall'url originale il 19 luglio 2008).
- Currying in Smalltalk, su blog.3plus4.org. URL consultato il 7 dicembre 2010 (archiviato dall'url originale il 19 luglio 2008).