Scala Language
functies
Zoeken…
Opmerkingen
Scala heeft eersteklas functies.
Verschil tussen functies en methoden:
Een functie is geen methode in Scala: functies zijn een waarde en kunnen als zodanig worden toegewezen. Methoden (gemaakt met def
) moeten daarentegen tot een klasse, eigenschap of object behoren.
- Functies worden gecompileerd tot een klasse die een eigenschap (zoals
Function1
) tijdens het compileren uitbreidt, en worden tijdens runtime geconstateerd naar een waarde. Methoden zijn daarentegen lid van hun klasse, eigenschap of object en bestaan daarbuiten niet. - Een methode kan worden geconverteerd naar een functie, maar een functie kan niet worden geconverteerd naar een methode.
- Methoden kunnen typeparameterisatie hebben, functies niet.
- Methoden kunnen standaardparameterwaarden hebben, functies niet.
Anonieme functies
Anonieme functies zijn functies die zijn gedefinieerd maar waaraan geen naam is toegewezen.
Het volgende is een anonieme functie die twee gehele getallen opneemt en de som retourneert.
(x: Int, y: Int) => x + y
De resulterende uitdrukking kan worden toegewezen aan een val
:
val sum = (x: Int, y: Int) => x + y
Anonieme functies worden voornamelijk gebruikt als argumenten voor andere functies. Bijvoorbeeld, de map
-functie op een verzameling verwacht dat een andere functie als argument:
// Returns Seq("FOO", "BAR", "QUX")
Seq("Foo", "Bar", "Qux").map((x: String) => x.toUpperCase)
De typen argumenten van de anonieme functie kunnen worden weggelaten: de typen worden automatisch afgeleid :
Seq("Foo", "Bar", "Qux").map((x) => x.toUpperCase)
Als er slechts één argument is, kunnen de haakjes rond dat argument worden weggelaten:
Seq("Foo", "Bar", "Qux").map(x => x.toUpperCase)
Onderstreept stenografie
Er is een nog kortere syntaxis waarvoor geen namen nodig zijn voor de argumenten. Het bovenstaande fragment kan worden geschreven:
Seq("Foo", "Bar", "Qux").map(_.toUpperCase)
_
vertegenwoordigt de anonieme functieargumenten positioneel. Met een anonieme functie die meerdere parameters heeft, verwijst elk voorkomen van _
naar een ander argument. De twee volgende uitdrukkingen zijn bijvoorbeeld equivalent:
// Returns "FooBarQux" in both cases
Seq("Foo", "Bar", "Qux").reduce((s1, s2) => s1 + s2)
Seq("Foo", "Bar", "Qux").reduce(_ + _)
Wanneer u deze steno gebruikt, kan naar elk argument dat wordt voorgesteld door de positionele _
slechts één keer worden verwezen en in dezelfde volgorde.
Anonieme functies zonder parameters
Om een waarde te creëren voor een anonieme functie waarvoor geen parameters nodig zijn, laat u de parameterlijst leeg:
val sayHello = () => println("hello")
Samenstelling
Met de functiesamenstelling kunnen twee functies werken en worden gezien als een enkele functie. In wiskundige termen uitgedrukt, gegeven een functie f(x)
en een functie g(x)
, de functie h(x) = f(g(x))
.
Wanneer een functie wordt gecompileerd, wordt deze gecompileerd tot een type dat is gerelateerd aan Function1
. Scala biedt twee methoden in de Function1
implementatie met betrekking tot compositie: andThen
en compose
. De compose
methode past als volgt bij de bovenstaande wiskundige definitie:
val f: B => C = ...
val g: A => B = ...
val h: A => C = f compose g
De andThen
(denk h(x) = g(f(x))
) heeft een meer 'DSL-achtig' gevoel:
val f: A => B = ...
val g: B => C = ...
val h: A => C = f andThen g
Er wordt een nieuwe anonieme functie toegewezen die is gesloten voor f
en g
. Deze functie is in beide gevallen gebonden aan de nieuwe functie h
.
def andThen(g: B => C): A => C = new (A => C){
def apply(x: A) = g(self(x))
}
Als f
of g
via een bijwerking werkt, dan roept het aanroepen van h
alle bijwerkingen van f
en g
in de volgorde. Hetzelfde geldt voor eventuele veranderlijke statusveranderingen.
Relatie met gedeeltelijke functies
trait PartialFunction[-A, +B] extends (A => B)
Elke single-argument PartialFunction
is ook een Function1
. Dit is contra-intuïtief in formele wiskundige zin, maar past beter bij objectgeoriënteerd ontwerp. Om deze reden hoeft Function1
geen constante true
isDefinedAt
methode te bieden.
Gebruik de volgende syntaxis om een gedeeltelijke functie (die ook een functie is) te definiëren:
{ case i: Int => i + 1 } // or equivalently { case i: Int ⇒ i + 1 }
Kijk voor meer informatie op PartialFunctions .