Szukaj…


Uwagi

Scala dokłada wszelkich starań, aby traktować metody i funkcje jako identyczne pod względem składniowym. Ale pod maską są to odrębne koncepcje.

Metoda jest kodem wykonywalnym i nie ma reprezentacji wartości.

Funkcja jest faktyczną instancją obiektu typu Function1 (lub podobnego rodzaju innej arity). Jego kod jest zawarty w metodzie apply . Skutecznie działa po prostu jako wartość, którą można przekazać.

Nawiasem mówiąc, zdolność do traktowania funkcji jako wartości jest dokładnie tym, co rozumie się przez język obsługujący funkcje wyższego rzędu. Instancje funkcji są podejściem Scali do implementacji tej funkcji.

Rzeczywista funkcja wyższego rzędu to funkcja, która albo przyjmuje wartość funkcji jako argument, albo zwraca wartość funkcji. Ale w Scali, ponieważ wszystkie operacje są metodami, ogólniej jest myśleć o metodach, które odbierają lub zwracają parametry funkcji. Tak więc map zdefiniowana w Seq może być uważana za „funkcję wyższego rzędu”, ponieważ jej parametr jest funkcją, ale nie jest dosłownie funkcją; to jest metoda.

Wykorzystanie metod jako wartości funkcji

Kompilator Scala automatycznie konwertuje metody na wartości funkcji w celu przekazania ich do funkcji wyższego rzędu.

object MyObject {
  def mapMethod(input: Int): String = {
    int.toString
  }
}

Seq(1, 2, 3).map(MyObject.mapMethod) // Seq("1", "2", "3")

W powyższym przykładzie MyObject.mapMethod nie jest wywołaniem funkcji, ale zamiast tego jest przekazywany do map jako wartość. Rzeczywiście, map wymaga przekazania wartości funkcji, co można zobaczyć w jej sygnaturze. Podpis map List[A] (listy obiektów typu A ) to:

def map[B](f: (A) ⇒ B): List[B]

Część f: (A) => B wskazuje, że parametrem tego wywołania metody jest jakaś funkcja, która pobiera obiekt typu A i zwraca obiekt typu B A i B są arbitralnie zdefiniowane. Wracając do pierwszego przykładu, możemy zobaczyć, że mapMethod przyjmuje Int (co odpowiada A ) i zwraca String (który odpowiada B ). Zatem mapMethod jest prawidłową wartością funkcji, którą należy przekazać do map . Możemy przepisać ten sam kod w ten sposób:

Seq(1, 2, 3).map(x:Int => int.toString)

Podkreśla to wartość funkcji, która może zwiększyć przejrzystość prostych funkcji.

Funkcje wyższego rzędu (funkcja jako parametr)

Funkcja wyższego rzędu, w przeciwieństwie do funkcji pierwszego rzędu, może mieć jedną z trzech postaci:

  • Co najmniej jeden z jego parametrów jest funkcją i zwraca pewną wartość.

  • Zwraca funkcję, ale żaden z jej parametrów nie jest funkcją.

  • Oba powyższe: jeden lub więcej jego parametrów jest funkcją i zwraca funkcję.

    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
        }
    

Tutaj funkcja mapy przyjmuje jako parametr parametr getFullName(n._1,n._2) . Nazywa się to HOF (funkcja wyższego rzędu).

Argumenty leniwe oceny

Scala obsługuje leniwe ocenianie argumentów funkcji za pomocą notacji: def func(arg: => String) . Taki argument funkcji może przyjmować zwykły obiekt String lub funkcję wyższego rzędu z typem zwracanym String . W drugim przypadku argument funkcji byłby oceniany przy dostępie do wartości.

Zobacz przykład:

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 zwróci Brak wartości i wyświetli komunikat "Applying mediator" .

dumbMediator zwróci Brak wartości i wyświetli komunikat "Calculating expensive data! Applying mediator" .

Leniwa ocena może być bardzo przydatna, gdy chcesz zoptymalizować kosztowne obliczenia kosztownych argumentów.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow