Składnia Scala ma wiele symboli. Ponieważ tego rodzaju nazwy są trudne do znalezienia za pomocą wyszukiwarek, przydatna byłaby ich pełna lista.
Jakie są wszystkie symbole w Scali i co robi każdy z nich?
W szczególności chciałbym wiedzieć ->
, ||=
, ++=
, <=
, _._
, ::
, i :+=
.
Odpowiedzi:
Do celów nauczania dzielę operatorów na cztery kategorie :
Na szczęście zatem większość kategorii jest reprezentowana w pytaniu:
Dokładne znaczenie większości tych metod zależy od klasy, która je definiuje. Na przykład
<=
onInt
oznacza „mniejszy lub równy” . Pierwszy,->
podam jako przykład poniżej.::
jest prawdopodobnie metodą zdefiniowaną naList
(choć może to być obiekt o tej samej nazwie) i:+=
prawdopodobnie jest metodą zdefiniowaną dla różnychBuffer
klas.Zobaczmy ich.
Słowa kluczowe / symbole zastrzeżone
W Scali jest kilka symboli, które są wyjątkowe. Dwa z nich są uważane za właściwe słowa kluczowe, a inne są po prostu „zastrzeżone”. Oni są:
Wszystkie są częścią języka i jako takie można je znaleźć w dowolnym tekście, który prawidłowo opisuje ten język, takim jak sama specyfikacja Scala (PDF).
Ostatni, podkreślenie, zasługuje na specjalny opis, ponieważ jest tak szeroko stosowany i ma tak wiele różnych znaczeń. Oto próbka:
Prawdopodobnie zapomniałem jednak o innym znaczeniu.
Metody importowane automatycznie
Tak więc, jeśli nie znalazłeś szukanego symbolu na powyższej liście, to musi to być metoda lub jej część. Ale często zobaczysz jakiś symbol, a dokumentacja dla klasy nie będzie miała tej metody. Kiedy tak się dzieje, albo patrzysz na kompozycję jednej lub więcej metod z czymś innym, albo metoda została zaimportowana do zakresu lub jest dostępna poprzez zaimportowaną niejawną konwersję.
Są nadal można znaleźć na ScalaDoc : po prostu trzeba wiedzieć gdzie ich szukać. Lub, jeśli to nie wystarczy, spójrz na indeks (obecnie uszkodzony w wersji 2.9.1, ale dostępny w nocy).
Każdy kod Scala ma trzy automatyczne importy:
Pierwsze dwa udostępniają tylko klasy i obiekty singletonowe. Trzeci zawiera wszystkie niejawne konwersje i importowane metody, ponieważ
Predef
jest to sam obiekt.Zaglądając do środka
Predef
szybko pokaż kilka symboli:Każdy inny symbol zostanie udostępniony w drodze domniemanej konwersji . Wystarczy spojrzeć na metody oznaczone
implicit
tym parametrem i otrzymać jako parametr obiekt typu odbierający metodę. Na przykład:W powyższym przypadku
->
jest definiowany w klasieArrowAssoc
za pomocą metody,any2ArrowAssoc
która przenosi obiekt typuA
, gdzieA
jest parametr typu nieograniczony dla tej samej metody.Wspólne metody
Tak więc wiele symboli jest po prostu metodami w klasie. Na przykład jeśli tak
Metodę znajdziesz
++
bezpośrednio w ScalaDoc for List . Istnieje jednak jedna konwencja, o której należy pamiętać podczas wyszukiwania metod. Metody kończące się na dwukropek (:
) wiążą się z prawej zamiast lewej. Innymi słowy, podczas gdy powyższe wywołanie metody jest równoważne z:Gdybym miał,
1 :: List(2, 3)
to byłoby to równoważne z:Musisz więc spojrzeć na typ znaleziony po prawej stronie , szukając metod kończących się dwukropkiem. Zastanów się na przykład:
Pierwsza metoda (
+:
) wiąże się po prawej stronie i znajduje się naList
. Druga metoda (:+
) jest po prostu normalną metodą i wiąże się w lewo - ponownie, dalejList
.Cukry syntaktyczne / skład
Oto kilka cukrów składniowych, które mogą ukryć metodę:
Ostatni jest interesujący, ponieważ dowolną metodę symboliczną można połączyć, aby w ten sposób utworzyć metodę podobną do przypisania.
I oczywiście w kodzie mogą występować różne kombinacje:
źródło
val c = ex(2)
zamiastval ex(c) = 2
?val ex(c) = 2
.Jedną (dobrą, IMO) różnicą między językiem Scala a innymi językami jest to, że pozwala nazwać swoje metody niemal każdą postacią.
To, co wyliczasz, nie jest „interpunkcją”, ale prostymi i prostymi metodami i jako takie ich zachowanie różni się w zależności od obiektu (choć istnieją pewne konwencje).
Na przykład sprawdź dokumentację Scaladoc w polu Lista , a zobaczysz niektóre z metod, o których tu wspomniałeś.
Kilka rzeczy, o których należy pamiętać:
Najczęściej
A operator+equal B
kombinacja przekłada się naA = A operator B
, jak w przykładach||=
lub++=
.Metody kończące się na
:
są odpowiednio asocjacyjne, co oznacza, żeA :: B
tak naprawdę jestB.::(A)
.Większość odpowiedzi znajdziesz w dokumentacji Scali. Zachowanie referencji podwoiłoby wysiłki i szybko się opóźniłoby :)
źródło
Możesz je najpierw pogrupować według niektórych kryteriów. W tym poście wyjaśnię tylko znak podkreślenia i strzałkę w prawo.
_._
zawiera kropkę. Kropka w Scali zawsze oznacza wywołanie metody . Więc po lewej stronie kropki masz odbiornik, a po prawej wiadomość (nazwa metody). Teraz_
jest specjalnym symbolem w Scali. Jest na ten temat kilka postów, na przykład ten wpis na blogu dotyczy wszystkich przypadków użycia. Tutaj jest to anonimowy skrót funkcji , czyli skrót do funkcji, która pobiera jeden argument i wywołuje na nim metodę_
. Teraz_
nie jest poprawną metodą, więc z pewnością widziałeś_._1
lub coś podobnego, to znaczy wywoływanie metody_._1
w argumencie funkcji._1
na_22
są metody krotki tłoczni konkretny element krotki. Przykład:Załóżmy teraz przypadek użycia skrótu do aplikacji funkcji. Biorąc pod uwagę mapę, która mapuje liczby całkowite na ciągi:
Ooooo, już zdarza się dziwne interpunkcja. Łącznik i znaki większe niż, które przypominają prawą strzałkę , są operatorem, który tworzy znak
Tuple2
. Więc nie ma różnicy w wyniku pisania albo,(1, "Eins")
albo1 -> "Eins"
tylko to drugie jest łatwiejsze do odczytania, szczególnie na liście krotek takich jak przykład mapy. To->
nie jest magia, jest, podobnie jak kilka innych operatorów, dostępne, ponieważ masz wszystkie ukryte konwersje w obiekciescala.Predef
w zakresie. Następuje tutaj konwersjaGdzie
ArrowAssoc
jest->
metoda, która tworzyTuple2
. Tak1 -> "Eins"
jest rzeczywiste połączeniePredef.any2ArrowAssoc(1).->("Eins")
. Ok. Wróćmy do pierwotnego pytania ze znakiem podkreślenia:Podkreślenie tutaj skraca następujący równoważny kod:
Zauważ, że
map
metoda Map przekazuje krotkę klucza i wartości do argumentu funkcji. Ponieważ interesują nas tylko wartości (ciągi), wyodrębniamy je za pomocą_2
metody na krotce.źródło
->
metody, ale twoje zdanie „Więc nie ma różnicy w wyniku pisania albo ”(1, "Eins")
albo1 -> "Eins"
pomogło mi zrozumieć składnię i jej użycie.Jako dodatek do genialnych odpowiedzi Daniela i 0__ muszę powiedzieć, że Scala rozumie analogi Unicode dla niektórych symboli, więc zamiast
można pisać
źródło
Jeśli chodzi o
::
inny wpis Stackoverflow, który obejmuje::
sprawę. Krótko mówiąc, służy do konstruowaniaLists
poprzez „ wykorzystanie ” elementu głównego i listy ogona. Jest to zarówno klasa reprezentująca rozpatrywaną listę, która może być używana jako ekstraktor, ale najczęściej jest to metoda na liście. Jak zauważa Pablo Fernandez, ponieważ kończy się dwukropkiem, ma prawy asocjatywny , co oznacza, że odbiorca wywołania metody jest po prawej stronie, a argument po lewej stronie operatora. W ten sposób możesz elegancko wyrazić sumienie, przygotowując nowy element głowy do istniejącej listy:Jest to równoważne z
Zastosowanie jako obiektu wyciągającego jest następujące:
Wygląda to jak operator, ale tak naprawdę jest to po prostu inny (bardziej czytelny) sposób pisania
Możesz przeczytać więcej o ekstraktorach w tym poście .
źródło
<=
jest tak, jakbyś to „przeczytał”: „mniejszy lub równy”. Jest to więc operator matematyczny na liście<
(jest mniejsza niż?),>
(Jest większa niż?),==
(Równa się?),!=
(Nie jest równa?),<=
(Jest mniejsza lub równa?), I>=
(jest większa niż lub równy?).Nie należy tego mylić z czymś w
=>
rodzaju podwójnej prawej strzałki , używanej do oddzielenia listy argumentów od treści funkcji i do oddzielenia warunków testowych w dopasowaniu wzorca (case
bloku) od treści wykonanej w przypadku dopasowania. . Możesz zobaczyć przykład tego w moich dwóch poprzednich odpowiedziach. Po pierwsze, funkcja używa:który jest już skracany, ponieważ typy są pomijane. Byłaby następująca funkcja
i użycie dopasowania wzoru:
źródło
Uważam, że nowoczesne IDE ma kluczowe znaczenie dla zrozumienia dużych projektów Scala. Ponieważ operatory te są również metodami, według intellij po prostu klikam z wciśniętym klawiszem Control lub Control-B w definicjach.
Możesz kliknąć z wciśniętym klawiszem Control w prawo w operatora konsoli (: :) i skończyć na scala javadoc, mówiąc: „Dodaje element na początku tej listy”. W przypadku operatorów zdefiniowanych przez użytkownika staje się to jeszcze bardziej krytyczne, ponieważ można je zdefiniować w trudnych do znalezienia implikacjach ... twoje IDE wie, gdzie zdefiniowano niejawne.
źródło
Właśnie dodając do innych doskonałych odpowiedzi. Scala oferuje dwa często krytykowane operatory symboliczne,
/:
(foldLeft
) i:\
(foldRight
), z których pierwszy jest prawostronny. Zatem następujące trzy stwierdzenia są równoważne:Podobnie jak te trzy:
źródło
Scala dziedziczy większość operatorów arytmetycznych Java . Obejmuje to
|
znak bitowy lub (pojedynczy znak potoku), bitowy i&
bitowy wyłączny lub lub^
logiczny (logiczny) lub||
(dwa znaki potoku) oraz logiczny i&&
. Co ciekawe, możesz używać operatorówboolean
jednoznakowych, więc javowi operatorzy logiczni są całkowicie redundantni:Jak wskazano w innym poście, wywołania kończące się znakiem równości
=
są rozwiązywane (jeśli metoda o takiej nazwie nie istnieje!) Przez zmianę przypisania:Ta „podwójna kontrola” umożliwia łatwą wymianę mutable na niezmienną kolekcję:
źródło
true | { println( "Icke" ); true }
⇒ drukuje!true || { println( "Icke" ); true }
⇒ nie drukuje!