Notacja infix Scala

12

Czy można wywołać metodę za pomocą notacji infix?

Na przykład w Haskell mógłbym napisać następującą funkcję:

x `isAFactorOf` y = x % y == 0

a następnie użyj go w następujący sposób:

if 2 `isAFactorOf` 10 ...

Co w niektórych przypadkach pozwala na bardzo czytelny kod. Czy coś podobnego do tego jest możliwe w Scali? Szukałem „notacji Scala infix”, ale termin ten wydaje się oznaczać coś innego w Scali.

Carcigenicate
źródło

Odpowiedzi:

15

Począwszy od wersji 2.10, Scala wprowadziła ukryte klasy, aby dokładnie poradzić sobie z tym problemem.

Spowoduje to wykonanie niejawnej konwersji danego typu na opakowaną klasę, która może zawierać własne metody i wartości.

W twoim konkretnym przypadku użyłbyś czegoś takiego:

implicit class RichInt(x: Int) {
  def isAFactorOf(y: Int) = x % y == 0
}

2.isAFactorOf(10)
// or, without dot-syntax
2 isAFactorOf 10

Zauważ, że po skompilowaniu spowoduje to umieszczenie naszej surowej wartości w pliku RichInt(2). Możesz obejść ten problem, deklarując RichInt jako podklasę AnyVal:

implicit class RichInt(val x: Int) extends AnyVal { ... }

Nie spowoduje to boksu, ale jest bardziej restrykcyjne niż typowa klasa domyślna. Może zawierać tylko metody, a nie wartości lub stan.

KChaloux
źródło
2
Prawdopodobnie powinieneś wspomnieć, że niejawne klasy nie mogą być najwyższego poziomu, więc klasa niejawna będzie musiała zostać zdefiniowana lokalnie.
Carcigenicate,
3

Zasadniczo w Scali nie można wywoływać funkcji w sposób niepoprawny, ale można zdefiniować metodę na typie, do którego lewy argument można przekonwertować niejawnie. Na przykład możesz zdefiniować klasę, która ma metodę isAFactorOf (biorąc Int) i wskazać, że Int może być niejawnie przekonwertowany na instancję tej klasy.

Jeśli spojrzysz na tę odpowiedź https://stackoverflow.com/a/3119671 na inne pytanie, zobaczysz składnię w Scali, która działa równorzędnie.

ekw
źródło
Warto podkreślić, że nowe wersje Scala mieć konstrukt wyraźnie na to, którą odpowiedź związana nie adres: implicit class RichInt(i: Int) { def square() = i * i }.
KChaloux,