2009-12-08 44 views
6

Tôi có một hàm trong đó tôi có một loạt các câu lệnh riêng lẻ.Erlang: Trả về từ một hàm

case ... of 
    ... 
end, 

case ... of 
    ... 
end, 

... 

, vv

Tôi muốn trở về từ chức năng ngay lập tức khi một điều kiện trường hợp đặc biệt xảy ra ở một trong những báo cáo trường hợp - vì vậy mà báo cáo trường hợp sau không được chọn, và các chức năng chỉ lối thoát hiểm/trả về. Làm thế nào để làm điều đó?

Trả lời

13

Tôi khuyên bạn nên cấu trúc lại để khai thác toàn bộ sức mạnh của Erlang và khả năng khớp mẫu của nó.

Không có nhà điều hành return. Ngoài ra, một thực tế ít được biết đến là bạn có thể làm một cái gì đó như:

Return=case ... of

một tuyên bố case có thể có một "trở lại" giá trị.

+1

Đó là lý do tại sao nó được gọi là một biểu hiện trường hợp. – Christian

+0

Vâng, đó là điều khá đáng biết! cảm ơn. – jeffreyveon

+0

@jeffreyveon: câu trả lời của tôi có đáp ứng được câu hỏi của bạn không? – jldupont

4

Erlang không có nhà điều hành return. Bạn sẽ cần phải cấu trúc lại mã của bạn thành các hàm nhỏ hơn.

Mã ban đầu của bạn có hai biểu thức trường hợp bị xích với toán tử dấu phẩy. Tôi đoán bạn có một số tác dụng phụ trong biểu thức trường hợp đầu tiên mà bạn muốn bảo tồn. Dưới đây, tôi đang sử dụng một tưởng tượng return điều hành:

case ... of 
    P1 -> return E1; 
    P2 -> E2; 
end, 

case ... of 
    ... 
end 

Một biểu hiện như thế này có thể được chuyển đổi sang mã Erlang thực sử dụng chức năng nhỏ và mô hình kết hợp với một cái gì đó giống như này:

case1(P1, ...) -> E1; 
case1(P2, ...) -> E2, case2(...). 
case2(...) -> ... 

Disclaimer: Đó là đã 10 năm kể từ khi tôi viết mã Erlang, vì vậy cú pháp của tôi có thể bị tắt.

+0

Vui lòng cung cấp ví dụ về làm như vậy. –

+0

Ví dụ được thêm vào, tôi hy vọng nó sẽ giúp ích. –

2

Trong Erlang bạn chỉ cần sử dụng đối sánh mẫu để kích hoạt chức năng thích hợp. Nếu bạn có quá nhiều mệnh đề để đề cập và giải quyết, tôi cũng sẽ đề xuất cấu trúc lại mã một chút.

0

sử dụng catch/ném

Người gọi nói:

 
X = (catch foo(A, B)). 

sau đó viết

 
foo(A, B) -> 
    case ... of 
    ...throw(X) .. 
    end, 

    case ... of 
    ... throw (Y) 
    end, 
    ... 

này thường được coi thực hành lập trình kém - kể từ khi chương trình có nhiều điểm xuất cảnh, là khó khăn để grock

+2

Ném vào Erlang là đặc biệt cho lợi nhuận không phải địa phương, không xử lý lỗi - vì vậy về nguyên tắc đây là một cách tiếp cận hợp lệ. Trong thực tế tôi nghi ngờ rằng tái cấu trúc để tránh nó sẽ tốt hơn ở đây, nhưng không nhìn thấy mã nó khó biết. – cthulahoops

+2

Về nguyên tắc nó có thể là một cách tiếp cận hợp lệ, và nó thực sự là cho lợi nhuận phi địa phương, nhưng nó vẫn là thực hành xấu để sử dụng nó rộng rãi trong mã của bạn. Việc sử dụng các trả về không cục bộ làm cho các lập trình viên khác khó hiểu mã, và làm cho việc gỡ lỗi trở nên khó khăn hơn. Mặc dù nó không được thiết kế đặc biệt để xử lý lỗi, nhưng việc xử lý lỗi thường là nơi duy nhất bạn nên sử dụng nó. Ngoài ra, nếu bạn đang viết mã để xử lý lỗi, bạn không tuân theo triết lý cốt lõi của Erlang, đó là "mã để thành công": bạn đang suy nghĩ giống như một lập trình viên bắt buộc hơn. – Tim

12

P khớp attern là một cách tốt để cấu trúc lại một tuyên bố trường hợp - bạn có thể làm một cái gì đó như thế này

testcase(1, X, Y) -> .... passed1; 
testcase(2, X, Y) -> .... passed2; 
testcase(N, X, Y) when N > 2 -> .... passedlarge; 
testcase(_, X, Y) -> defaultcase. 

và sau đó tuyên bố trường hợp của bạn chỉ đơn giản là kết thúc tốt đẹp lên đến:

X = testcase(Number, Param1, Param2). 

(X sẽ là một trong hai passed1, passed2 , passedlarge hoặc defaultcase trong ví dụ giả tạo này)

+1

Ok, trông thật tuyệt vời, cảm ơn! – jeffreyveon

2

Một cách là thác báo cáo trường hợp của bạn:

my_fun(X) -> 
    case cond1(X) of 
    true -> ret1; 
    _ -> 
     case cond2(X) of 
     true -> ret2; 
     _ -> 
      ... 
     end 
    end. 

Một cách khác là phân tách các tuyên bố trường hợp của bạn thành các mệnh đề:

my_fun(X) -> 
    my_fun(cond1, X). 

my_fun(cond1, X) -> 
    case cond1(X) of 
    true -> ret1; 
    _ -> my_fun(cond2, X) 
    end; 

my_fun(cond2, X) -> 
    case cond2(X) of 
    true -> ret2; 
    _ -> my_fun(cond3, X) 
    end; 

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