Wziąłem spojrzeć na listę badań wykonanych na scala-lang.org i zauważyłem dziwną pytanie: „ «Czy możesz wymienić wszystkich zastosowań»_ ”. Czy możesz? Jeśli tak, zrób to tutaj. Doceniane są przykłady wyjaśniające.
540
Wziąłem spojrzeć na listę badań wykonanych na scala-lang.org i zauważyłem dziwną pytanie: „ «Czy możesz wymienić wszystkich zastosowań»_ ”. Czy możesz? Jeśli tak, zrób to tutaj. Doceniane są przykłady wyjaśniające.
Odpowiedzi:
Te, o których mogę myśleć, to
Rodzaje egzystencjalne
Wyższe parametry typu
Ignorowane zmienne
Ignorowane parametry
Ignorowane nazwy własnych typów
Wzory symboli wieloznacznych
Wzory symboli wieloznacznych w interpolacjach
Symbol wieloznaczny sekwencji we wzorach
Importowanie symboli wieloznacznych
Ukrywanie importu
Łączenie listów z operatorami
Operatorzy przypisań
Składnia zastępcza
Wartości metod
Konwertowanie parametrów Call-by-Name na funkcje
Domyślny inicjator
Mogą istnieć inne, o których zapomniałem!
Przykład pokazujący, dlaczego
foo(_)
ifoo _
są różne:Ten przykład pochodzi z 0__ :
W pierwszym przypadku
process _
reprezentuje metodę; Scala przyjmuje metodę polimorficzną i próbuje uczynić ją monomorficzną, wypełniając parametr type, ale zdaje sobie sprawę, że nie ma typu, który można by wypełnićA
, który da typ(_ => Unit) => ?
(Existential_
nie jest typem).W drugim przypadku
process(_)
jest lambda; pisząc lambda bez jawnego typu argumentu, Scala wybiera typ z argumentu, który sięforeach
spodziewa, i_ => Unit
jest typem (podczas gdy zwykły_
nie jest), więc można go podstawić i wywnioskować.To może być najtrudniejsza gotcha w Scali, jaką kiedykolwiek spotkałem.
Zauważ, że ten przykład kompiluje się w 2.13. Zignoruj to, jakby zostało przypisane do podkreślenia.
źródło
val x: Any = _
println _
iprintln(_)
są różne. Widać to na przykład w tym, że traktują one typy egzystencjalne i polimorficzne nieco inaczej. Wkrótce podam przykład.Z (mojego wpisu) w FAQ , które z pewnością nie gwarantuję, że są kompletne (dodałem dwa wpisy zaledwie dwa dni temu):
To także część tego pytania .
źródło
var i: Int = _
lub specjalny przypadek dopasowania wzoruval (a, _) = (1, 2)
lub specjalny przypadek odrzuconego valfor (_ <- 1 to 10) doIt()
def f: T; def f_=(t: T)
kombinacja do tworzenia modyfikowalnego elementu F._
nazwy metod oszukują. Ale cóż, ok. Mam tylko nadzieję, że ktoś inny zaktualizuje FAQ ... :-)Doskonałym wyjaśnieniem zastosowania podkreślenia jest magia Scala _ [podkreślenie] .
Przykłady:
W Scali
_
działa podobnie jak*
w Javie podczas importowania pakietów.W Scali getter i setter będą domyślnie zdefiniowane dla wszystkich nieprywatnych zmiennych w obiekcie. Nazwa gettera jest taka sama jak nazwa zmiennej i
_=
jest dodawana do nazwy setera.Stosowanie:
Jeśli spróbujesz przypisać funkcję do nowej zmiennej, funkcja zostanie wywołana, a wynik zostanie przypisany do zmiennej. To zamieszanie występuje z powodu opcjonalnych nawiasów klamrowych do wywołania metody. Powinniśmy użyć _ po nazwie funkcji, aby przypisać ją do innej zmiennej.
źródło
List(1,2,3,4,5).foreach(print(_))
przypadku jest to o wiele bardziej czytelneList(1,2,3,4,5).foreach(print)
, wcale tak naprawdę nie potrzebujesz podkreślenia, ale myślę, że to tylko kwestia styluJest jedno użycie, które widzę, że wszyscy tutaj zapomnieli wymienić ...
Zamiast tego:
Możesz po prostu to zrobić:
źródło
n => n
Oto kilka przykładów
_
użycia:We wszystkich powyższych przykładach jeden znak podkreślenia reprezentuje element na liście (w celu zmniejszenia pierwszy znak podkreślenia reprezentuje akumulator)
źródło
Oprócz zastosowań , o których wspomniał JAiro, podoba mi się ten:
Jeśli ktoś potrzebuje wszystkich właściwości połączenia, może:
Jeśli potrzebujesz tylko hosta i portu, możesz:
źródło
Istnieje konkretny przykład użycia „_”:
może być równy:
Zastosowanie „_” w niektórych scenariuszach spowoduje automatyczną konwersję na „(x $ n) => x $ n”
źródło