Những cái tôi có thể nghĩ là
Các loại hiện sinh
def foo(l: List[Option[_]]) = ...
Thông số loại cao hơn
case class A[K[_],T](a: K[T])
Các biến bị bỏ qua
val _ = 5
Bỏ qua các tham số
List(1, 2, 3) foreach { _ => println("Hi") }
Bỏ qua tên của các loại tự
trait MySeq { _: Seq[_] => }
Mẫu ký tự đại diện
Some(5) match { case Some(_) => println("Yes") }
Các mẫu ký tự đại diện trong nội suy
"abc" match { case s"a$_c" => }
Ký tự đại diện trong các mẫu
C(1, 2, 3) match { case C(vs @ _*) => vs.foreach(f(_)) }
Nhập khẩu ký tự đại diện
import java.util._
Ẩn nhập khẩu
import java.util.{ArrayList => _, _}
Tham gia gửi thư cho các nhà khai thác
def bang_!(x: Int) = 5
Toán tử chuyển nhượng
def foo_=(x: Int) { ... }
Cú pháp giữ chỗ
List(1, 2, 3) map (_ + 2)
Giá trị phương thức
List(1, 2, 3) foreach println _
Chuyển đổi các tham số gọi theo tên thành các chức năng
def toFunction(callByName: => Int): () => Int = callByName _
Trình khởi tạo mặc định
var x: String = _ // unloved syntax may be eliminated
Có thể có những người khác tôi đã quên!
Ví dụ cho thấy tại sao foo(_)
và foo _
khác nhau:
Ví dụ này xuất phát từ 0__ :
trait PlaceholderExample {
def process[A](f: A => Unit)
val set: Set[_ => Unit]
set.foreach(process _) // Error
set.foreach(process(_)) // No Error
}
Trong trường hợp đầu tiên, process _
đại diện cho một phương thức; Scala sử dụng phương thức đa hình và cố gắng biến nó thành đơn hình bằng cách điền vào tham số loại, nhưng nhận ra rằng không có loại nào có thể điền vào để A
đưa ra loại (_ => Unit) => ?
(Hiện tại _
không phải là loại).
Trong trường hợp thứ hai, process(_)
là một lambda; khi viết lambda không có loại đối số rõ ràng, Scala sẽ nhập loại từ đối số foreach
mong đợi và _ => Unit
là một loại (trong khi chỉ đơn giản _
là không), vì vậy nó có thể được thay thế và suy ra.
Đây cũng có thể là gotcha khó nhất trong Scala tôi từng gặp.
Lưu ý rằng ví dụ này biên dịch trong 2.13. Bỏ qua nó như nó được gán cho gạch dưới.