2013-07-09 36 views
6

Tôi hiện đang làm việc trên một dự án với Scala và có vẻ như tôi không hoàn toàn hiểu Scala của hệ thống kiểu: -/Tại sao một số (1) .getOrElse (Một số (1)) không thuộc loại Option [Int]?

Tôi có tình huống sau đây:

def reviews(id: Int) = Action { implicit request => 
    Ok(html.products.reviews(
    reviewlist, 
    reviewlist 
     .find(review => review.id == id) 
     .getOrElse(reviewlist.headOption) 
)) 
} 

Thật không may là trình biên dịch cho biết, ông không thể chuyển đổi sản phẩm để lựa chọn [Review], vì vậy tôi đã thay đổi mã

reviewlist 
    .find(review => review.id == id) 
    .getOrElse(reviewlist.headOption) 

với

id match { 
    case 0 => reviewlist.headOption 
    case id => reviewlist.find(review => review.id == id) 
} 

dường như hoạt động ngay bây giờ, mặc dù nó không chính xác giống như nó, ví dụ, không hiển thị bản ghi đầu tiên nữa nếu id đánh giá không hợp lệ đang được gửi. sau đó nó sẽ giả vờ, rằng chưa có đánh giá nào.

sau đó tôi đã phá vỡ vấn đề xuống một mẫu veeery đơn giản:

val a: Option[Int] = Some(1).getOrElse(Some(1)) 

Vì vậy, có ai có ý tưởng, tại sao biểu hiện ở bên phải không phải là loại Tùy chọn [Int] ?? Cả hai, một số (1) và không thừa kế trực tiếp từ Option và biểu thức này thực sự là một số (1) trong bất kỳ hoặc tôi là sai?

Interestinly đủ

val a: Option[Int] = None.getOrElse(None) 

công trình, nhưng tất cả các kết hợp khác không ...

Trả lời

13

Bạn muốn:

val a: Option[Int] = Some(1).orElse(Some(1)) 

x.getOrElse(y) 

sẽ trở lại 1 nếu x là Some(1) hoặc y (đó là Some(1)) nếu x là None, hoặc nói trong mã:

if (Some(1).isDefined) 1 else Some(1) 
+1

'x.orElse (Một số (y))' luôn ngớ ngẩn cho bất kỳ 'x' và' y' nào. Bạn muốn 'x.getOrElse (y)'. –

+2

@pelotom nó chỉ đơn giản là [không đúng] (http://stackoverflow.com/q/14305308/298389) –

+0

Tôi không nói 'orElse' là ngớ ngẩn, tôi đang nói rằng truyền nó một giá trị được gói gọn trong' Một số là ngớ ngẩn. –

1

An Lựa chọn giá trị có hai đại diện, một giá trị tốt (Some(...)) hoặc một giá trị xấu (None).

Với getOrElse bạn có thể giảm tùy chọn cho loại chứa trong đó. Hãy tưởng tượng nó như là một quá trình giải nén giá trị, loại bỏ nó khỏi container.

Trong quá trình này giải nén, các Option được lột quần áo và chỉ kiểu dữ liệu của nó được trả lại, như vậy trong ví dụ của bạn, bạn thực sự có điều này:

val a int = Some(1).getOrElse(2) // 1 

Và để làm những gì bạn muốn là:

val b Option[Int] = Some(1).orElse(Some(2)) // Some(1) 
6

các loại chữ ký của Option.getOrElse

getOrElse[B >: A](default: ⇒ B): B 

Điều đó có nghĩa là khi bạn gọi getOrElse trên số Option[A], nó sẽ cố gắng trả lại cho bạn một số loại A. Nếu loại mặc định (B) không giống như A, nó sẽ tìm kiếm tổ tiên được chia sẻ gần nhất của AB. Trong trường hợp của bạn, ABOption[Int]Int. Trình biên dịch tốt nhất có thể làm là Any.

+0

đẹp nhất, +1 - trở thành trung tâm của vấn đề nhưng không có chi tiết cụ thể về vấn đề. – doug

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