2011-06-19 38 views
9

Trong Haskell bạn có thể viết:Việc giải nén tuple có được hỗ trợ trực tiếp trong danh sách tham số trong Scala không?

x :: (Int,Int) -> Int 
x (p,s) = p 

Trong Scala bạn sẽ viết:

def x(a: (Int, Int)) = a._1 

hay:

def x(a: (Int, Int)) = a match { 
    case (p, s) => p 
} 

Tại sao không có một cái gì đó giống như

def x(_: (p: Int, s: Int)) = p 

hoặc

def x(foo: (p @ Int, s @ Int)) = p 

?

+0

Loại đối sánh mẫu đó sẽ không hữu ích nếu bạn chỉ có thể có * một * phương thức xác định. Bạn sẽ cần nhiều định nghĩa như trong Haskell để làm cho nó * thực sự * hữu ích, và điều này sẽ thay đổi cấu trúc của ngôn ngữ một cách đáng kể. – Landei

+0

Để làm rõ nhận xét của @ Landei, Haskell không cho phép nhiều định nghĩa của một hàm. Nó chỉ có đường đẹp cho phù hợp với mô hình. Trong thuật ngữ Scala nó giống như bạn có thể viết "def f [A] (Một số (p: A), alt: A) = p; def f (None, alt: A) = alt" thay vì "def f (x: Tùy chọn [A], alt: A) = x khớp với {case Some (p) => p; case None => alt} ". Thật không may, Scala có quá tải kiểu Java và các kiểu dữ liệu đại số thông qua phân lớp, cả hai đều tạo ra sự mơ hồ. –

+0

@ James Iry: Vâng, tôi biết về mặt kỹ thuật "nhiều định nghĩa" trong Haskell chỉ là các câu lệnh 'case ... of' ẩn. Nhưng từ quan điểm của người dùng, đây chỉ là một chi tiết thực hiện. – Landei

Trả lời

11

Các tính năng mà bạn đang tìm kiếm được gọi là destructuring và, trong đó là hình thức nói chung, sẽ đi xa hơn chỉ tuple giải nén. Tôi thường thấy mình có nhu cầu mà Scala đã có nó vì nó là một phần mở rộng tự nhiên như các mô hình phù hợp với cú pháp:

def first((f: Int, l: Int)) = f 
def displayName(Person(first, last)) = last + ", " + first 

Destructuring (loại) hiện diện trong hình thức định nghĩa biến/giá trị:

val (f, l) = tuple 
val Person(first, last) = person 

Thật không may, có một số typesafetyissues xung quanh các định nghĩa như vậy mà tôi cho rằng không chắc bạn sẽ thấy phá hoại trong danh sách tham số bất kỳ lúc nào.

+0

Cảm ơn tất cả các câu trả lời của bạn. Câu trả lời của Daniel cũng đúng nhưng tôi đã chọn câu trả lời này vì nó chứa các tham chiếu web hữu ích để hiểu thêm một chút chi tiết kỹ thuật. Cảm ơn một lần nữa cho tất cả! – letmaik

+0

tốt đẹp nhất, +1 từ tôi - destructuring yêu cầu một dòng vị ngữ của mã, nhưng vẫn còn dễ dàng hơn để xem xét hơn myTuple._0, v.v. – doug

0

Một cách tiếp cận khác sẽ là tạo danh sách tham số và lưu vào cùng một thứ trong ngôn ngữ.

+0

Tôi nhớ Martin Odersky nói rằng danh sách tham số và bộ dữ liệu có thể được thống nhất trong một phiên bản tương lai của Scala. –

+0

Vâng, anh ta đã đề cập đến nó. Tôi sẽ không giữ hơi thở của tôi mặc dù, có một số vấn đề tương thích khá khó khăn với phương pháp quá tải. –

4

Bạn có thể tạo một hàm nhận được một danh sách đối số tương ứng với các loại của tuple, áp dụng Function.tupled để chức năng đó và sau đó áp dụng các tuple:

scala> def fun(x:Int,y:Int)=x+y 
fun: (x: Int,y: Int)Int 

scala> val tuple = (1,2) 
tuple: (Int, Int) = (1,2) 

scala> Function.tupled(fun _)(tuple) 
res9: Int = 3 

Bằng cách này bạn đạt được một cách giải quyết hợp lệ cho bạn vấn đề

+0

Ok, bạn nói đúng về trường hợp đơn giản mà tôi đưa ra làm ví dụ, nhưng về các thông số phức tạp hơn như: list.foldLeft ((0,0)) ((a: (Int, Int), x: Int) = > ... a._1 ...) Ở đây tôi không thể thay đổi định nghĩa hàm. – letmaik

+0

Bạn có thể sử dụng chức năng currying, áp dụng 'tupled' các tham số của một số phần nhất định của hàm. Tuy nhiên, nó sẽ luôn phức tạp hơn việc sử dụng các biến trung gian như 'val (a, b) = tuple'. Tôi phải nói, tuy nhiên, tôi không ghét tuple._1 hoặc tuple._2 – JaimeJorge

2

Điều đó được gọi là nhiều công văn và nó không được JVM hỗ trợ. Scala có thể viết lại một phương thức để làm cho kết quả rõ ràng không cần thiết, tuy nhiên, nó không phải là một ưu tiên - hoặc, theo như tôi biết, thậm chí đã lên kế hoạch - để làm như vậy.

Điều thú vị là, nó được hỗ trợ cho các hàm, theo nghĩa nào đó, với hạn chế là tất cả các biến thể phải xuất hiện cùng nhau. Ví dụ:

def x: ((Int, Int)) => Int = { 
    case (p, _) => p 
} 
+2

Không phải nhiều công văn. Haskell thậm chí không có công văn động đơn lẻ. –

+0

@ James Tôi tin rằng bạn biết những gì bạn đang nói về, nhưng chắc chắn nó nhìn vào tôi rằng nó chọn định nghĩa được áp dụng dựa trên giá trị thời gian chạy của các tham số, đó là định nghĩa của nhiều công văn. Vậy sự khác biệt là gì? –

+0

Nếu bạn nhìn vào ví dụ của mình một lần nữa không có công văn - anh ta không cố gắng chọn động các phương thức khác nhau. Tất cả những gì anh ta làm là kéo một tuple vào các biến có tên. Anh ta chỉ sử dụng tên "x" theo nhiều cách khác nhau để đưa ra ví dụ về đường Scala có thể có thể đưa vào các đối số phương pháp phá hoại. –

Các vấn đề liên quan