2011-10-17 11 views
8

Tôi đang mã hóa trong SML để phân công và tôi đã thực hiện một số vấn đề về thực hành và tôi cảm thấy như tôi đang thiếu điều gì đó - tôi cảm thấy mình đang sử dụng quá nhiều câu hỏi case. Dưới đây là những gì tôi đang thực hiện và báo cáo sự cố cho những gì tôi đang gặp sự cố với .:Bản sao kê mẫu và Khớp mẫu

  1. Viết một hàm all_except_option, lấy một chuỗi và một danh sách chuỗi. Trả về NONE nếu chuỗi không có trong danh sách, ngược lại trả về SOME lst trong đó lst giống như danh sách đối số ngoại trừ chuỗi không nằm trong nó.

    fun all_except_option(str : string, lst : string list) = 
        case lst of 
        [] => NONE 
        | x::xs => case same_string(x, str) of 
           true => SOME xs 
          | false => case all_except_option(str, xs) of 
              NONE => NONE 
             | SOME y=> SOME (x::y) 
    
  2. Viết một hàm get_substitutions1, trong đó có một danh sách danh sách chuỗi (một danh sách các danh sách các chuỗi, các thay) và một chuỗi s và trả về một danh sách chuỗi. Kết quả có tất cả các chuỗi nằm trong một số danh sách trong các thay thế cũng có s, nhưng chính nó không nên ở trong kết quả.

    fun get_substitutions1(lst : string list list, s : string) = 
        case lst of 
        [] => [] 
        | x::xs => case all_except_option(s, x) of 
           NONE => get_substitutions1(xs, s) 
           | SOME y => y @ get_substitutions1(xs, s) 
    

- same_string là một chức năng cung cấp, fun same_string(s1 : string, s2 : string) = s1 = s2

+10

Đây là một phần của nhiệm vụ cho tuần 2 trong khóa học Ngôn ngữ lập trình Coursera.Vì đó là vi phạm để đăng các giải pháp trực tuyến, tôi yêu cầu câu hỏi này được diễn đạt lại để thay đổi tên hàm để chúng không khớp chính xác với bài tập. – arnab

Trả lời

9

Trước hết tôi sẽ bắt đầu sử dụng mô hình kết hợp trong định nghĩa hàm thay vì có một "top-level" tuyên bố như vậy. Về cơ bản, nó sẽ hạ xuống thành sau khi khử đường. Ngoài ra tôi sẽ thoát khỏi các chú thích kiểu tường minh, trừ trường hợp nghiêm cần thiết:

fun all_except_option (str, []) = NONE 
    | all_except_option (str, x :: xs) = 
    case same_string(x, str) of 
     true => SOME xs 
    | false => case all_except_option(str, xs) of 
       NONE => NONE 
       | SOME y => SOME (x::y) 

fun get_substitutions1 ([], s) = [] 
    | get_substitutions1 (x :: xs, s) = 
    case all_except_option(s, x) of 
     NONE => get_substitutions1(xs, s) 
    | SOME y => y @ get_substitutions1(xs, s) 

Nếu tốc độ không phải là quan trọng, sau đó bạn có thể hợp nhất hai trường hợp trong hàm đầu tiên:

fun all_except_option (str, []) = NONE 
    | all_except_option (str, x :: xs) = 
    case (same_string(x, str), all_except_option(str, xs)) of 
     (true, _)  => SOME xs 
    | (false, NONE) => NONE 
    | (false, SOME y) => SOME (x::y) 

Nhưng kể từ bạn đang sử dụng phụ thêm (@), trong hàm thứ hai, và vì nó không phải là đệ quy đuôi , tôi không tin rằng đó là mối quan tâm chính của bạn. Hãy nhớ rằng nối thêm là tiềm năng "ác" và bạn hầu như luôn luôn sử dụng nối (và sau đó đảo ngược kết quả của bạn khi trả lại) và đuôi đệ quy khi có thể (nó luôn luôn là).

Nếu bạn thực sự thích các chú thích loại rõ ràng, sau đó bạn có thể làm điều đó như thế này:

val rec all_except_option : string * string list -> string list option = 
fn (str, []) => NONE 
    | (str, x :: xs) => 
    case (same_string(x, str), all_except_option(str, xs)) of 
     (true, _)  => SOME xs 
    | (false, NONE) => NONE 
    | (false, SOME y) => SOME (x::y) 


val rec get_substitutions1 : string list list * string -> string list = 
fn ([], s) => [] 
    | (x :: xs, s) => 
    case all_except_option(s, x) of 
     NONE => get_substitutions1(xs, s) 
    | SOME y => y @ get_substitutions1(xs, s) 

Nhưng đó chỉ là cách ưa thích của tôi, nếu tôi thực sự có thêm chú thích loại.

Nhân tiện, tại sao bạn có chức năng same_string? Bạn chỉ có thể thực hiện so sánh trực tiếp. Sử dụng một hàm auxilary chỉ là khủng khiếp, trừ khi bạn có kế hoạch trao đổi nó với một số logic đặc biệt tại một số điểm. Tuy nhiên tên chức năng của bạn không sugest đó.

+0

Khi tôi thử khối mã trên cùng, tôi nhận được các lỗi biên dịch nói 'Lỗi: toán tử không phải là một hàm' - Có vẻ như trường hợp all_except_options (s, x) phần không thể tách khỏi get_substitutions1 (x :: xs, s) khối. Làm thế nào tôi có thể nói sml rằng KHÔNG và MỘT SỐ là trường hợp cho những gì được trả về bởi all_except_options và không phải trường hợp cho get_substitutions? – Sekm

+2

Bạn có thể nói rằng "từ khóa thú vị chia nhỏ hai chức năng". Nó hoạt động trong SML/NJ 110.72, do đó, hoặc là bạn đang sử dụng một trình thông dịch khác hoặc bạn đã làm điều gì sai. Bạn có thể đặt biểu thức lồng nhau bên trong dấu ngoặc đơn. Tuy nhiên, thông báo lỗi bạn đang nhận được, có vẻ như nó không liên quan gì đến các trường hợp? –

+0

@ Jesper.Reenberg Tôi biết đây là một chủ đề cũ, nhưng tôi đang cố gắng để tìm ra những gì trong 'MỘT SỐ y' trong' all_except_option'. Nếu bạn chuyển đổi nó để trả về SOME (x :: "wtf" :: y), bạn có thể thấy rằng chạy trên tất cả các phần tử trước khi khớp chuỗi, nhưng không phải trên bất kỳ phần tử nào sau khi chuỗi được khớp. Nếu y giữ phần còn lại của danh sách, tại sao tôi không thấy danh sách trùng lặp? Tôi đang gặp khó khăn trong việc giải quyết vấn đề này bằng một tờ giấy và theo dõi những gì MỘT SỐ y thực sự chỉ ra ở mỗi bước. – mat4nier

1

Ngoài những gì Jesper.Reenberg đề cập, tôi chỉ muốn đề cập đến một trận đấu trên bool cho truefalse có thể được thay thế bằng một if-then - else. Tuy nhiên, một số người xem xét nếu-thì-khác xấu hơn tuyên bố trường hợp

+1

Đúng vậy, tôi đoán tôi là một trong số những người đó :) –

0
fun same_string(s1: string, s2: string) = if String.compare(s1, s2) = EQUAL then true else false 


fun contains([], s: string) = false 
| contains(h::t, s: string) = if same_string(s, h) then true else contains(t, s) 


fun all_except_option_successfully(s: string, []) = [] 
| all_except_option_successfully(s: string, h::t) = if same_string(s, h) then t else (h :: all_except_option_successfully(s, t)) 


fun all_except_option(s: string, []) = NONE 
| all_except_option(s: string, h::t) = if same_string(s, h) then SOME t else if contains(t, s) then SOME (h :: all_except_option_successfully(s, t)) else NONE 
+0

Luôn có chỗ để tối ưu hóa "nếu .. thì đúng là sai" :-) – ShiDoiSi