Scala Language
Funzione ordine superiore
Ricerca…
Osservazioni
Scala fa di tutto per trattare i metodi e le funzioni in modo sintatticamente identico. Ma sotto il cofano, sono concetti distinti.
Un metodo è codice eseguibile e non ha alcuna rappresentazione di valore.
Una funzione è un'istanza di oggetto reale di tipo Function1
(o un tipo simile di un'altra arity). Il suo codice è contenuto nel suo metodo di apply
. Effettivamente, agisce semplicemente come un valore che può essere passato in giro.
Per inciso, la capacità di trattare le funzioni come valori è esattamente ciò che si intende per linguaggio che supporta le funzioni di ordine superiore. Le istanze di funzione sono l'approccio di Scala all'implementazione di questa funzione.
Una funzione reale di ordine superiore è una funzione che accetta un valore di funzione come argomento o restituisce un valore di funzione. Ma in Scala, poiché tutte le operazioni sono metodi, è più generale pensare a metodi che ricevono o restituiscono parametri di funzione. Quindi la map
, come definita in Seq
potrebbe essere pensata come una "funzione di ordine superiore" a causa del fatto che il suo parametro è una funzione, ma non è letteralmente una funzione; è un metodo.
Utilizzo dei metodi come valori di funzione
Il compilatore Scala convertirà automaticamente i metodi in valori di funzione allo scopo di passarli in funzioni di ordine superiore.
object MyObject {
def mapMethod(input: Int): String = {
int.toString
}
}
Seq(1, 2, 3).map(MyObject.mapMethod) // Seq("1", "2", "3")
Nell'esempio sopra, MyObject.mapMethod
non è una chiamata di funzione, ma viene invece passata alla map
come valore. Infatti, la map
richiede un valore di funzione passato ad esso, come si può vedere nella sua firma. La firma per la map
di un List[A]
(un elenco di oggetti di tipo A
) è:
def map[B](f: (A) ⇒ B): List[B]
La parte f: (A) => B
indica che il parametro per questa chiamata di metodo è una funzione che accetta un oggetto di tipo A
e restituisce un oggetto di tipo B
A
e B
sono definiti arbitrariamente. Tornando al primo esempio, possiamo vedere che mapMethod
accetta un Int
(che corrisponde ad A
) e restituisce una String
(che corrisponde a B
). Quindi mapMethod
è un valore di funzione valido per passare alla map
. Potremmo riscrivere lo stesso codice come questo:
Seq(1, 2, 3).map(x:Int => int.toString)
Questo inline il valore della funzione, che può aggiungere chiarezza per le funzioni semplici.
Funzioni di ordine elevato (funzione come parametro)
Una funzione di ordine superiore, al contrario di una funzione di primo ordine, può avere una delle tre forme:
Uno o più dei suoi parametri è una funzione e restituisce un valore.
Restituisce una funzione, ma nessuno dei suoi parametri è una funzione.
Entrambi i precedenti: uno o più dei suoi parametri è una funzione e restituisce una funzione.
object HOF { def main(args: Array[String]) { val list = List(("Srini","E"),("Subash","R"),("Ranjith","RK"),("Vicky","s"),("Sudhar","s")) //HOF val fullNameList= list.map(n => getFullName(n._1, n._2)) } def getFullName(firstName: String, lastName: String): String = firstName + "." + lastName }
Qui la funzione mappa assume come parametri un parametro getFullName(n._1,n._2)
. Questo è chiamato HOF (funzione di ordine superiore).
Argomenti valutazione pigra
Scala supporta la valutazione lazy per gli argomenti delle funzioni usando notazione: def func(arg: => String)
. Tale argomento di funzione potrebbe richiedere un oggetto String
regolare o una funzione di ordine superiore con tipo di restituzione String
. Nel secondo caso, l'argomento della funzione verrebbe valutato sull'accesso valore.
Si prega di vedere l'esempio:
def calculateData: String = {
print("Calculating expensive data! ")
"some expensive data"
}
def dumbMediator(preconditions: Boolean, data: String): Option[String] = {
print("Applying mediator")
preconditions match {
case true => Some(data)
case false => None
}
}
def smartMediator(preconditions: Boolean, data: => String): Option[String] = {
print("Applying mediator")
preconditions match {
case true => Some(data)
case false => None
}
}
smartMediator(preconditions = false, calculateData)
dumbMediator(preconditions = false, calculateData)
smartMediator
chiamata smartMediator
restituirà None value e stamperà il messaggio "Applying mediator"
.
dumbMediator
chiamata dumbMediator
restituirebbe Nessun valore e stamperà il messaggio "Calculating expensive data! Applying mediator"
.
La valutazione pigra potrebbe essere estremamente utile quando si desidera ottimizzare un sovraccarico di costosi calcoli di argomenti.