2012-06-10 24 views
9

Vì vậy, tôi đã bắt đầu học Erlang và tôi hơi bối rối với đoạn mã này.Nhận chọn lọc ở Erlang

-module(prior). 
-compile(export_all). 


    important() -> 
     receive 
    { Priority, Msg } when Priority > 10 -> 
     [Msg | important()] 
    after 0 -> 
    normal() 
    end. 

normal() -> 
    receive 
    { _, Msg } -> 
     [Msg | normal()] 
    after 0 -> 
     [] 
    end. 

Tôi đang gọi mã bằng cách sử dụng.

10> self() ! {15, high}, self() ! {7, low}, self() ! {1, low}, self() ! {17, high}. 
    {17,high} 
    11> prior:important(). 
     [high,high,low,low] 

Tôi hiểu rằng mã này sẽ đi qua tất cả các thông điệp ưu tiên cao trước và sau đó là các ưu tiên thấp. Tôi bối rối về cách giá trị trả về là [cao, cao, thấp, thấp], vì tôi không thấy chúng được nối với nhau ở đâu.

+1

Không được nối, được bảo vệ. nối là khi bạn có hai danh sách, 'L1' và' L2' và nối chúng: 'L1 ++ L2'. Consing là khi bạn có một phần tử 'E' và một danh sách' L' và sau đó tạo thành danh sách mở rộng '[E | L] '. –

Trả lời

14

Làm thế nào giá trị trả về thức được xây dựng ...

Khi [Msg | important()] đang được trả lại cho lần đầu tiên, hình thức giá trị trả về thức được xác định. Mối quan tâm duy nhất là, chúng tôi không biết tất cả các chi tiết của giá trị trả lại cuối cùng. Vì vậy, important() trong [Msg | important()] sẽ tiếp tục được đánh giá. Sau đây là minh họa về cách thức giá trị trả lại cuối cùng [high,high,low,low] được xây dựng.

[high | important(     )] <---- Defines the final form 
     --------------------------------- 
     [high | important(   )] <---- Adds more details 
       ------------------------ 
       normal(    ) <---- Adds more details 
       ------------------------ 
       [low | normal(  )] <---- Adds more details 
         ---------------- 
         [low | normal()]  <---- Adds more details 
           -------- 
           [  ]  <---- Adds more details 
------------------------------------------ 
[high | [high | [low | [low | []]]]] 
[high,high,low,low]       <---- The final return value 

Làm thế nào mã hoạt động ...

Trong chức năng important/0, after 0 chỉ có nghĩa là "Tôi không đợi đến khi thư đến" - nếu có bất kỳ tin nhắn trong hộp thư của tôi, tôi sẽ nhìn vào nó; nếu không có, tôi sẽ tiếp tục (thực hiện normal()) thay vì đợi ở đó.Trong hộp thư, có {15, cao}, {7, thấp}, {1, thấp}, {17, cao} đang ngồi ở đó. Trong Erlang, các thư trong hộp thư là Không phải được xếp hàng đợi theo thứ tự đến trước được phục vụ trước. Mệnh đề receive có thể là cầu kỳ. Nó quét qua tất cả các tin nhắn trong hộp thư và "chọn" những thông điệp mong muốn. Trong trường hợp của chúng tôi, {15, high}{17, high} được chọn trước theo số {Priority, Msg} when Priority > 10. Sau đó, chức năng normal/0 sẽ kết thúc. Và {7, low}, {1, low} được xử lý (được chấp nhận) theo thứ tự. Cuối cùng, chúng tôi đã nhận được [high,high,low,low].

Một phiên bản sửa đổi đó cho thấy trình tự chế biến ...

Chúng ta có thể thay đổi mã một chút để làm cho quá trình xử lý (consing) Để rõ ràng hơn:

-module(prior). 
-compile(export_all). 

important() -> 
    receive 
    {Priority, Msg} when Priority > 10 -> 
     [{Priority, Msg} | important()] % <---- Edited 
    after 0 -> 
    normal() 
    end. 

normal() -> 
    receive 
    {Priority, Msg} -> % <---- Edited 
     [{Priority, Msg} | normal()] % <---- Edited 
    after 0 -> 
     [] 
    end. 

Run trong vỏ:

4> c(prior). 
{ok, prior} 
5> self() ! {15, high}, self() ! {7, low}, self() ! {1, low}, self() ! {17, high}. 
{17,high} 
6> prior:important(). 
[{15,high},{17,high},{7,low},{1,low}] 
+2

Tôi đã viết mã OP hỏi về (Tôi tin rằng đây là ưu tiên của tôi nhận được trong Tìm hiểu Bạn Một số Erlang) và tôi chấp nhận câu trả lời này. –

4

họ đang concated đây

[Msg | important()] 

important() đây là một chức năng nên nó có một giá trị trả về, trong khi bạn chạy này trong REPL ông sẽ in giá trị trả về từ hàm. Giá trị này là ảnh hưởng của [Head | Tail] xây dựng danh sách từ import()

important() đây là một chức năng thường xuyên :)

Có hữu ích không?

+0

Cảm ơn bạn đã trả lời nhanh. Vì vậy, ngay cả những thông điệp ưu tiên thấp nhận được từ cuộc gọi bình thường() sau đó được nối với danh sách ưu tiên cao trong [Msg | mệnh đề quan trọng()]? – tkblackbelt

+0

mọi thứ. Ngoài ra có lẽ nó sẽ tràn ngập ram của bạn nếu bạn sẽ có như tải các tin nhắn, do đó bạn nên bí mật nó vào đuôi đệ quy chức năng. Tôi không biết những gì bạn đang cố gắng xây dựng bởi vì nó nói chung nên là một gen_server với một hàng đợi ưu tiên như bên trong cấu trúc dữ liệu. Bạn đang cố gắng làm điều đó bên trong một chuỗi tin nhắn quá trình và điều này bị giới hạn vì vậy nó là ý tưởng tồi nói chung. –

2

Tất cả các hàm Erlang luôn trả về một giá trị. Chức năng important/0 sẽ nhận được thông báo ưu tiên cao và sau đó gọi chính nó theo cách đệ quy trong biểu thức [Msg | important()] để tạo danh sách chứa Msg mới nhất và tất cả các tin nhắn khác mà important/0 sẽ nhận được. Đây là danh sách được trả về từ important/0. Khi không có thông báo ưu tiên cao hơn thì important/0 thay vào đó sẽ gọi normal/0 để đọc tất cả các tin nhắn còn lại. Các tin nhắn mà normal/0 đọc nó sẽ trở lại dưới dạng danh sách giống như cách important/0. Điều này sẽ được trả về important/0 và sau đó sẽ trả lại trong cùng một danh sách vì nó đã trả lại tin nhắn của nó.

Lưu ý rằng khi normal/0 được gọi thì sẽ không có xử lý đặc biệt các thư có mức độ ưu tiên cao vì important/0 không bao giờ được gọi lại. Ngoài ra important/0 sẽ chỉ thực sự xử lý các thư có mức độ ưu tiên cao đã có trong hàng đợi vì nó không thể tìm thấy bất kỳ thư nào nữa sau đó gọi là normal/0.

Giá trị thời gian chờ 0 đặc biệt ở chỗ nó hết thời gian ngay lập tức nhưng đảm bảo trước tiên tìm kiếm toàn bộ hàng đợi tin nhắn cho các thư phù hợp.

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