2011-12-26 22 views
7

Trong 'Lập trình trong Scala, Second Edition' tại trang 410 bạn có thể tìm lớp Simulation mà có phương pháp sau đây:Liệu có ý nghĩa gì khi sử dụng tính năng khớp mẫu trong Scala với các trường hợp thực sự đơn giản?

private def next() { 
    (agenda: @unchecked) match { 
    case item :: rest => 
     agenda = rest 
     curtime = item.time 
     item.action() 
    } 
} 

tôi tò mò tại sao Odersky thực hiện điều này với mô hình phù hợp chứ không phải chỉ như thế :

private def next() { 
    val item = agenda.head 
    agenda = agenda.tail 
    curtime = item.time 
    item.action() 
} 

Mô hình có khớp với hiệu quả đến mức không quan trọng? Hoặc đó không phải là một ví dụ hoàn hảo?

Trả lời

9

Bình thường, tôi muốn viết nó theo cách bạn đã làm. (Mặc dù mô hình phù hợp là khá hiệu quả, nó không phải là hiệu quả như đầu/đuôi.) Bạn muốn sử dụng mô hình kết hợp nếu

  1. Bạn muốn thực hành mô hình phù hợp với
  2. Bạn muốn có một MatchException thay vì một NoSuchElementException
  3. Bạn sẽ điền vào các trường hợp khác sau.
4

Có một vài lý do:

  1. Một phần của điểm của cuốn sách là để bạn suy nghĩ trong Scala ngữ (chức năng); khớp mẫu là hàm tương đương với chương trình chức năng.

  2. Đối sánh mẫu và cách tiếp cận chức năng là mẫu tự nhiên trong Scala và cho phép những thứ như đồng thời theo cách tự nhiên; tìm hiểu mô hình đó và các chương trình Scala của bạn sẽ sẵn sàng để sử dụng nâng cao hơn.

3

Kết hợp mẫu có nhiều thành ngữ trong Scala và dễ dàng bảo vệ bạn khỏi điều kiện biên.

Trong mã

private def next() { 
    val item = agenda.head 
    agenda = agenda.tail 
    curtime = item.time 
    item.action() 
} 

Cả agenda.headagenda.tail sẽ ném một ngoại lệ NoSuchElementException nếu agenda là một danh sách rỗng, vì vậy để làm cho nó thực sự làm việc bạn cần phải thêm một tấm séc cho điều đó.

Phiên bản khớp mẫu thực sự có một vấn đề tương tự (như đã nêu trong ý kiến ​​th), nhưng tôi thấy việc sửa chữa sạch hơn, như tất cả các bạn phải làm là thêm một mẫu:

private def next() { 
    (agenda: @unchecked) match { 
    case item :: rest => 
     agenda = rest 
     curtime = item.time 
     item.action() 
    case _ => {} 
    } 
} 
+0

mô hình phù hợp với phiên bản sẽ ném MatchException nếu mô hình không phù hợp – gerferra

+0

@gerferra: Tôi đứng sửa chữa. Nhưng phiên bản phù hợp với mẫu ở mọi tốc độ đều có một sửa chữa đơn giản. Tôi sẽ cập nhật câu trả lời. –

+3

Các phiên bản khác cũng có một sửa chữa đơn giản: hoặc bọc trong 'if (! Agenda.isEmpty)', hoặc sử dụng 'agenda.headOption.foreach {item => agenda = agenda.tail; curtime = item.time; item.action()} ' –

0

Tôi đoán trước hết là ngoại lệ không phải lo lắng ở đây, có thể có một số kiểm tra trước khi phương thức "tiếp theo" này được gọi. Trong thực tế, điều này có lẽ là lý do cho chú thích "không được kiểm soát" quá, vì vậy anh ta thực sự có thể không phải đặt thêm case _ =>. Tôi nghĩ rằng lý do là nhiều hơn rằng ông muốn sử dụng "không đúng". Một thay thế ở đây mà không có sự phù hợp với mô hình, nhưng cũng không headtail có thể là một cái gì đó như:

private def next() { 
    val item :: rest = agenda 
    agenda = rest 
    curtime = item.time 
    item.action() 
} 
Các vấn đề liên quan