2012-06-10 11 views
9

그래서 얼랭 (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. 

나는 코드를 사용하여 호출하고있다.

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

나는이 코드를 먼저 한 다음 우선 순위가 낮은 사람의 모든 우선 순위가 높은 메시지를 통해 갈 것이라는 점을 이해합니다. 반환 값이 [높게, 높게, 낮게, 낮게] 어떻게 관련되어 있는지 혼란 스럽습니다. 왜냐하면 어디서 연결되어 있는지를 알지 못하기 때문입니다.

+1

consed, consed. 연결은 두 개의리스트,''L1''과''L2''가 있고 그것들을 연결합니다 :'L1 ++ L2'. Consumer는 요소 'E'와리스트 L이 있고 확장 목록'[E | L]'. –

답변

14

... [Msg | important()] 처음 반환되는

는 최종 리턴 값의 형태가 결정된다. 유일한 관심사는 최종 수익 가치의 모든 세부 사항을 아직 알지 못한다는 것입니다. 따라서 [Msg | important()]에있는 important()은 계속 평가됩니다. 다음은 최종 반환 값 [high,high,low,low]이 생성되는 방법을 보여주는 그림입니다. 기능 important/0의 코드가 작동하는 방법

[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 

...

after 0 단순히 "메시지가 오기를 기다릴하지 않는다"를 의미 - 내 사서함에있는 모든 메시지가있는 경우, I 그것을 볼 것이다; 어떤 것이 없다면 거기에서 기다리는 대신 계속 (normal()을 실행하십시오).사서함에는 이미 {15, 높음}, {7} 낮음, {1, 낮음}, {17, 높음}이 이미 있습니다. Erlang에서 사서함의 메시지는 이 아니며은 선착순으로 대기 중입니다. receive 절은 까다 롭습니다. 그것은 사서함의 모든 메시지를 스캔하여 원하는 메시지를 "선택"합니다. 이 경우 {Priority, Msg} when Priority > 10에 따라 {15, high}{17, high}이 먼저 선택됩니다. 그 후에, 기능 normal/0가 인수합니다. 그리고 {7, 낮은}, {1, 낮은} 주문 처리 (consed). 마지막으로 [high,high,low,low]이 있습니다.

처리 순서를 보여준다 수정 된 버전 ...

우리는 처리 (consing) 순서가 더 명확하게하기 위해 코드를 조금 수정할 수 있습니다

:

-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. 

실행을 그것은 껍질 안에 :

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

OP가 물었던 코드를 작성했습니다 (이 코드는 내가 당신에게 얼랭 (Erlang) 강의를 배울 때 가장 우선적으로 생각합니다). 나는이 대답을 승인합니다. –

4

그들은 여기

[Msg | important()] 

important() concated는 반환 값을 가지고 있도록이 REPL에서 실행되는 동안 그가 함수에서 반환 값을 출력합니다, 함수된다. 이 값은 여기 import()

important()에서 [Head | Tail] 목록 구축의 효과가 일반 기능 :

이 도움이됩니다이다?

+0

빠른 답장을 보내 주셔서 감사합니다. 따라서 after()에서 normal() 호출로부터 수신 된 낮은 우선 순위 메시지조차도 [Msg | important()] 절? – tkblackbelt

+0

모든 것. 또한 많은 양의 메시지가 있다면 RAM을 홍수에 빠뜨릴 수 있으므로 꼬리 재귀 함수로 변환해야합니다. 나는 일반적으로 내부 데이터 구조로 우선 순위 que와 gen_server해야하기 때문에 당신이 무엇을 만들려고하는지 모르겠어요. 당신은 프로세스 메시지 큐 안에 그것을하려고 노력하고 있으며,이 것은 제한되어 있으므로 일반적으로 나쁜 아이디어입니다. –

2

모든 얼랑 함수는 항상 값을 반환합니다. important/0 함수는 우선 순위가 높은 메시지를 수신 한 다음 Msg이라는 최신 메시지와 important/0이 수신하는 모든 메시지를 포함하는 목록을 작성하는 [Msg | important()]이라는 식으로 재귀 적으로 호출합니다. important/0에서 반환되는 것은이 목록입니다. 높은 우선 순위 메시지가 없으면 important/0 대신 normal/0을 호출하여 나머지 모든 메시지를 읽습니다. normal/0이 읽는 메시지는 같은 방식으로 목록으로 반환됩니다 important/0. 이 메시지는 important/0으로 반환되며 메시지를 반환 한 것과 동일한 목록에서 메시지를 반환합니다.

normal/0이 호출되면 important/0이 다시 호출되지 않으므로 우선 순위가 높은 메시지를 특별히 처리 할 필요가 없습니다. 또한 important/0은 큐에 이미있는 우선 순위가 높은 메시지 만 처리합니다. 더 이상 찾을 수 없으면 normal/0을 호출합니다.

타임 아웃 값 0은 즉시 타임 아웃되지만 메시지를 찾기 위해 전체 메시지 대기열을 먼저 검색한다는 점에서 특별합니다. 최종 리턴 값이 어떻게 구성되는지