2013-09-25 13 views
18

Mam trudności ze znalezieniem konkretnych odpowiedzi na to, co wiem, że jest czymś trywialnym. Chciałbym zrozumieć, jak bloki działają w Scali. Pochodzę z tła java/ruby ​​i wydaje się, że scala ma zupełnie inny sposób użycia bloków. Ten kod jest z Play! Framework website. Chciałbym zrozumieć semantycznie, co to jest Action. Czy jest to obiekt lub funkcja, która akceptuje blok, a może nie.Opis bloków Scala

object Application extends Controller { 

    def index = Action { 
    Ok(views.html.index("Your new application is ready.")) 
    } 

} 

Jeśli jest to funkcja, może to cukier syntaktyczny dla następujących elementów (w tym przypadku w jaki sposób scala przechodzić wokół bloków za kulisami):

def index = Action({ 
    Ok(views.html.index("Your new application is ready.")) 
    }) 

czy jest to jakiś scala składnię I” m nieświadomy.

Wszelkie odniesienia do kodu źródłowego Scala pomogą mi zrozumieć, jak działa to za kulisami.

Odpowiedz

21

Lepiej byłoby myśleć o blokach scala jako klasach anonimowych java (np. Takich jak Guava Functions) niż o blokach ruby. Właściwie mówiąc, jeśli dekompilować kod scala widać mniej więcej ten sam kod (taken from Guava examples):

Function<String, Integer> lengthFunction = new Function<String, Integer>() { 
    public Integer apply(String string) { 
    return string.length(); 
    } 
}; 

Różnica polega na tym, że scala zapewnia dużo cukru składni i pozwala na pisanie powyżej kodzie jak:

val lengthFunction = { string: String => string.length } 

chodzi o konkretny przykład działań:

def index = Action({ 
    Ok(views.html.index("Your new application is ready.")) 
    }) 

Tutaj Action prawdopodobnie obiekt z zastosowania metody. Kolejny cukier scala: język pozwala pisać Foo(bar) i oznacza Foo.apply(bar).Następnie you can drop round braces when your call isn't ambiguous, więc tak, w rzeczywistości jest to metoda, która nazywa mnie tak:

def index = Action({ 
    Ok(views.html.index("Your new application is ready.")) 
}) 

i mieć coś takiego jak podpis:

object Action { 
    def apply(block: => Result) = ??? 
} 

Jak już wspomniano przez @yan, to scala sposób powiedzieć hej, jestem funkcją przyjąć inną funkcję, która produkuje Wynik

Odcukrzony inwokacja będzie wyglądać

def index = Action.apply(new AbstractFunction[Result] { 
     def apply() = Ok.apply(views.html.index.apply("...")) 
}) 
8

Jest tu kilka rzeczy. Action to obiekt implementujący metodę apply(), która jest wywoływana, gdy traktujemy obiekt jako funkcję. Jest kilka apply()implementations. Pierwsza implementacja używa parametru nazwy.

Scala obsługuje pojęcie znane jako "parametry nazwy", które są jak normalne parametry, z tym wyjątkiem, że są oceniane tylko wtedy, gdy wykonywany jest kod odwołujący się do nich. Pomagają tworzyć konstrukcje, które wyglądają tak, jakby były częścią języka bez uciekania się do makr. W tym przypadku blok otaczający Ok(..) jest zwykłym blokiem instrukcji, a ostatnia wartość jest używana jako wartość bloku. Podany przykład będzie działał również bez nawiasów klamrowych. Zasadniczo po prostu przekazujesz wynik metody apply Ok na Action 's metodzie apply.

Druga wersja apply() rzeczywiście zajmuje pełną anonimową funkcję, która odwzorowuje zapytanie do wyniku. W takim przypadku możesz przekazać anonimową (lub nazwaną) funkcję.

+0

Dzięki za odpowiedź. Z tego, co zbieram, jest to syntaktyczny cukier dla Action.apply(). Usunięcie cukru, jak wyglądałoby całe oświadczenie? – b1nd

+0

Oświadczenie, jak to masz, jest zasadniczo "Action.apply (Ok.apply (views.html.index (" Twoja nowa aplikacja jest gotowa. ")))'. Jeśli spojrzysz na definicję 'apply()' w podanym adresie URL, zauważysz strzałkę przed typem parametru. Oznacza to po prostu parametr "nazwa-nazwisko", opisany powyżej. (Nie jest też przypadkiem, że składnia dla nazwy jest podobna do anonimowej funkcji bez argumentów) – yan

+0

Link do gry doc jest zepsuty przy okazji. Od czasu do czasu parser SO zawiera łącza zawierające znak dolara. –