2013-03-08 11 views
10

W Scala, dlaczego funkcja curried może być łatwo przekazana bezpośrednio do innych funkcji, ale przy przypisaniu jej do val trzeba również częściowo zastosować ją z _? Na przykład, biorąc pod uwagę dwie funkcje:Dlaczego Scala wymaga częściowego zastosowania funkcji curry podczas przypisywania wartości val?

def curried(a: Int)(b: Int) = a + b 
def test(a: Int, f: Int => Int) = f(a) 

mogę łatwo przejść curried do test z:

test(5, curried(5)) 

i wszystko jest szczęśliwy. Jednak jeśli ja po prostu zadzwonić curried(5) pojawia się błąd:

scala> curried(5) 
<console>:9: error: missing arguments for method curried; 
follow this method with `_' if you want to treat it as a partially applied function 
       curried(5) 

Jeśli zmienię wywołanie zawierać informacje o typie jednak to działa:

val 'curried: Int => Int = curried(5) 

Może ktoś wyjaśnić racjonalnie za niespójność, na pewno Scala kompilator może wnioskować, że funkcja jest Int => Int ze względu na definicję typu w oryginalnej metodzie?

+0

W przypadku 'val', jeśli podasz adnotację typu, nie będziesz potrzebować jawnej częściowej aplikacji' _'. –

Odpowiedz

8

Problem nie polega na wnioskowania o typie, problem polega na wnioskach. Czy popełniłeś błąd, czy też celowo curry funkcja?

Niestety, końcowa składnia podkreślenia jest składnią formalną, a pominięcie jej jest syntaktycznym cukrem.

+0

To ma sens, ale z pewnością fakt, że zdeklarowałem metodę jako funkcję curry, opisał już mój zamiar. Jeśli problem polega na wnioskowania, dlaczego jest on odpowiedni do wprowadzania? –

+0

@MarkDerricutt Nie jestem pewien, co masz na myśli przez "inlining", ale we wszystkich przypadkach pokazałeś, gdzie to działa, że ​​zdeklarowałeś to, czego oczekiwałeś, więc Scala idzie naprzód z curry, ponieważ pasuje do twoich oczekiwań. Jeśli chodzi o pierwsze, Scala nie curry niejawnie, to curry jawnie z końcowym podkreśleniem lub jeśli typy pasują - jeśli pochodzisz z języka z ukrytymi curry, które mogą wydawać się nienaturalne. Funkcja _declaration_ deklaruje jednak wiele list parametrów, co jest przydatne dla innych rzeczy niż curry. –

+0

Przez "inlining" miałem na myśli użycie w pozycji argumentu (myśląc o tym, przypisanie do argumentu ma w pełni kwalifikowaną informację o typie, więc jest w zasadzie takie samo jak mój ostatni przykład). Założono, że Scala jawnie currying, aby pochodzić z wielu list argumentów, w przeciwieństwie do podejścia Haskella, w którym każda deklaracja metody jest domyślnie curried, a każde wywołanie z brakującymi argumentami po prostu zwraca funkcję curried w tej pozycji. Moje zamieszanie bierze się z założenia, że ​​"wiele list parametrów == currying", oczywiście tak nie jest. –

0

Podkreślenie nie zawsze jest potrzebne. Od http://docs.scala-lang.org/cheatsheets/

val zscore = (mean:R, sd:R) => (x:R) => (x-mean)/sd 

currying, oczywiste składni.

def zscore(mean:R, sd:R) = (x:R) => (x-mean)/sd 

Zmiękczanie, oczywiste składni

def zscore(mean:R, sd:R)(x:R) = (x-mean)/sd 

Zmiękczanie składnia cukrowego. ale wtedy:

val normer = zscore(7, 0.4) _ 

potrzeba spływu podkreślenia, aby uzyskać częściowe, tylko dla wersji cukru.

Powiązane problemy