Phương pháp danh sách nhiều tham số
Đối với kiểu suy luận
Các phương thức có nhiều phần tham số có thể được sử dụng để hỗ trợ suy luận kiểu cục bộ, bằng cách sử dụng các tham số trong phần đầu tiên để suy ra các đối số kiểu sẽ cung cấp kiểu mong đợi cho một đối số trong phần tiếp theo. foldLeft
trong thư viện chuẩn là ví dụ chính tắc về điều này.
def foldLeft[B](z: B)(op: (B, A) => B): B
List("").foldLeft(0)(_ + _.length)
Nếu điều này được viết như sau:
def foldLeft[B](z: B, op: (B, A) => B): B
Người ta sẽ phải cung cấp các loại rõ ràng hơn:
List("").foldLeft(0, (b: Int, a: String) => a + b.length)
List("").foldLeft[Int](0, _ + _.length)
Đối với API thông thạo
Một cách sử dụng khác cho các phương thức phần nhiều tham số là tạo một API trông giống như một cấu trúc ngôn ngữ. Người gọi có thể sử dụng dấu ngoặc nhọn thay vì dấu ngoặc đơn.
def loop[A](n: Int)(body: => A): Unit = (0 until n) foreach (n => body)
loop(2) {
println("hello!")
}
Ứng dụng của N danh sách đối số vào phương thức có M phần tham số, trong đó N <M, có thể được chuyển đổi thành hàm một cách rõ ràng với a _
hoặc ngầm định, với kiểu mong đợi là FunctionN[..]
. Đây là một tính năng an toàn, hãy xem ghi chú thay đổi cho Scala 2.0, trong Tài liệu tham khảo Scala, để biết thông tin cơ bản.
Chức năng Curry
Các hàm có sẵn (hoặc đơn giản là các hàm trả về các hàm) dễ dàng được áp dụng hơn cho N danh sách đối số.
val f = (a: Int) => (b: Int) => (c: Int) => a + b + c
val g = f(1)(2)
Sự tiện lợi nhỏ này đôi khi rất đáng giá. Lưu ý rằng các hàm không thể là kiểu tham số, vì vậy trong một số trường hợp, một phương thức là bắt buộc.
Ví dụ thứ hai của bạn là kết hợp: phương thức phần một tham số trả về một hàm.
Tính toán nhiều giai đoạn
Các chức năng khác của cà ri hữu ích ở đâu? Đây là một mẫu luôn xuất hiện:
def v(t: Double, k: Double): Double = {
val ft = f(t)
g(ft, k)
}
v(1, 1); v(1, 2);
Làm thế nào chúng ta có thể chia sẻ kết quả f(t)
? Một giải pháp phổ biến là cung cấp một phiên bản vector hóa của v
:
def v(t: Double, ks: Seq[Double]: Seq[Double] = {
val ft = f(t)
ks map {k => g(ft, k)}
}
Xấu xí! Chúng tôi đã vướng mắc các mối quan tâm không liên quan - tính toán g(f(t), k)
và lập bản đồ trên một chuỗi ks
.
val v = { (t: Double) =>
val ft = f(t)
(k: Double) => g(ft, k)
}
val t = 1
val ks = Seq(1, 2)
val vs = ks map (v(t))
Chúng ta cũng có thể sử dụng một phương thức trả về một hàm. Trong trường hợp này, nó dễ đọc hơn một chút:
def v(t:Double): Double => Double = {
val ft = f(t)
(k: Double) => g(ft, k)
}
Nhưng nếu chúng ta cố gắng làm điều tương tự với một phương thức có nhiều phần tham số, chúng ta sẽ gặp khó khăn:
def v(t: Double)(k: Double): Double = {
^
`-- Can't insert computation here!
}