2011-10-29 67 views
39

Là mới đến Scala (2.9.1), tôi có một List[Event] và muốn sao chép nó vào một Queue[Event], nhưng Cú pháp sau đây mang lại một Queue[List[Event]] thay vì:Param: _ * có nghĩa là gì trong Scala?

val eventQueue = Queue(events) 

Đối với một số lý do, các công việc sau:

val eventQueue = Queue(events : _*) 

Nhưng tôi muốn hiểu nó làm gì và tại sao nó hoạt động? Tôi đã nhìn vào chữ ký của người Queue.apply chức năng:

def apply[A](elems: A*) 

Và tôi hiểu tại sao các nỗ lực đầu tiên không làm việc, nhưng ý nghĩa của điều thứ hai là gì? :_* trong trường hợp này là gì và tại sao chức năng apply chỉ cần chụp Iterable[A]?

Trả lời

40

a: A là loại ghi chú; xem What is the purpose of type ascriptions in Scala?

: _* là một trường hợp đặc biệt của loại ascription cho trình biên dịch xử lý một đối số duy nhất của một loại chuỗi làm chuỗi đối số biến, tức là varargs.

Đó là hoàn toàn hợp lệ để tạo Queue sử dụng Queue.apply rằng có một yếu tố duy nhất mà là một chuỗi hoặc iterable, vì vậy đây là chính xác những gì sẽ xảy ra khi bạn đưa ra một đơn Iterable[A].

+1

Cảm ơn bạn đã chỉ cho tôi nhập kiểu chữ! – Chris

34

Đây là một ký hiệu đặc biệt cho trình biên dịch chuyển mỗi phần tử làm đối số riêng của nó, chứ không phải là tất cả của nó như một đối số duy nhất. Xem here.

Đây là chú thích loại cho biết đối số chuỗi và được đề cập là "ngoại lệ" với quy tắc chung trong phần 4.6.2 của thông số ngôn ngữ, "Tham số lặp lại".

Điều này rất hữu ích khi hàm nhận số lượng đối số thay đổi, ví dụ: một chức năng như def sum(args: Int*), có thể được gọi là sum(1), sum(1,2) v.v. Nếu bạn có danh sách như xs = List(1,2,3), bạn không thể tự mình vượt qua xs, vì đó là List thay vì Int, nhưng bạn có thể chuyển các phần tử của nó sum(xs: _*).

+3

Cũng là một câu trả lời tuyệt vời, nhờ & upvote – Chris

+0

'def sum (xs: _ *) 'ném 'lỗi: không ràng buộc kiểu ký tự đại diện' – 7kemZmani

+0

câu trả lời của bạn là rõ ràng, nhưng điều này thực sự tạo ra nhiều rắc rối cho tôi, thường là trong scala 'xs: int' có nghĩa là xs là int, đi theo đó là cú pháp ở trên trong scala nơi' xs: _ * 'có nghĩa là xs được đúc cho các thành viên riêng lẻ của nó. – Rpant

0

Đối với folks Python:

hành _* Scala là nhiều hay ít tương đương với Python của *-operator.


Ví dụ

Chuyển đổi ví dụ scala từ link cung cấp bởi Luigi Plinge:

def echo(args: String*) = 
    for (arg <- args) println(arg) 

val arr = Array("What's", "up", "doc?") 
echo(arr: _*) 

để Python sẽ trông như thế:

def echo(*args): 
    for arg in args: 
     print "%s" % arg 

arr = ["What's", "up", "doc?"] 
echo(*arr) 

và cả cung cấp cho các followin sản lượng g:

What's
up
doc?


Sự khác biệt: giải nén tham số vị trí

Trong khi * -operator Python cũng có thể đối phó với giải nén các tham số vị trí/thông số cho các chức năng cố định arity:

def multiply (x, y): 
    return x * y 

operands = (2, 4) 
multiply(*operands) 

8

D oing cùng với Scala:

def multiply(x:Int, y:Int) = { 
    x * y; 
} 

val operands = (2, 4) 
multiply (operands : _*) 

sẽ thất bại:

not enough arguments for method multiply: (x: Int, y: Int)Int.
Unspecified value parameter y.

Nhưng chúng ta có thể đạt được cùng với scala:

def multiply(x:Int, y:Int) = { 
    x*y; 
} 

val operands = (2, 4) 
multiply _ tupled operands 

Theo Lorrin Nelson đây là cách hoạt động:

The first part, f _, is the syntax for a partially applied function in which none of the arguments have been specified. This works as a mechanism to get a hold of the function object. tupled returns a new function which of arity-1 that takes a single arity-n tuple.

thêm tác đọc: