2017-03-06 3 views
1

저는 이것이 언어에 대해 이해하지 못하는 부분이있는 아주 간단한 문제 중 하나라고 생각합니다. 하지만 나는 Elixir를 배우려고 노력 중이며, 제 프로그램이 완전히 끝나지 않았습니다. 여기에 최소한의 예가 있습니다. 내가 맨 아래에있는 Foo.go 행의 주석을 해제하고 elixir minimal.exs 그것을 실행하는 경우 I 만 spawn &Foo.go/0 행의 주석을 해제하면프로그램 종료가 조기에 끝나는 것 같습니다.

defmodule Foo do 
    def run(0) do 
    IO.puts("0") 
    end 
    def run(n) do 
    IO.puts(to_string n) 
    run(n - 1) 
    end 
    def go do 
    run(100) 
    end 
end 

# Foo.go 
# spawn &Foo.go/0 

지금, 그때는 0으로 아래로 100에서 모든 숫자입니다 의도 된 출력을 얻을 , 나는 일관되게 출력을 전혀 얻지 못한다.

그러나 두 행의 주석 처리를 제거하고 프로그램을 실행하면 프로그램이 종료되기 전에 첫 번째 줄에서부터 100까지 숫자를 얻은 다음 처음 몇 자리 숫자 (일반적으로 약 100에서 96 정도)를 얻습니다. 몇몇 이유. 그래서 나는 그 과정이 무작위로 종료되는 원인을 정확히 알지 못합니다.

이 혼란이 생겨난 이유는 내가 큰 프로젝트를 컴파일하려고 할 때 mix을 사용하려고 시도했기 때문입니다. 프로그램이 시작된 것처럼 보였고, 작업의 일부를 수행 한 다음 종료했습니다. mix 조금 후에 실행이 중지됩니다. 그래서 나는 어쨌든 잠시 후 어쨌든 mix이 그것을 끝내는 것처럼 보이면, Elixir 프로그램을 실행하는 관용적 인 방법이 어느 것인지는 확실하지 않다.

답변

3

spawn/1이 기능을 실행하기위한 새로운 프로세스가 생성됩니다. 그것들은 동일하지는 않지만 Erlang/Elixir 프로세스를 대부분의 다른 언어로 쓰레드라고 생각할 수 있습니다.

따라서 프로그램을 시작하면 "기본"프로세스가 작동합니다. 귀하의 경우에는 새로운 프로세스 (프로세스 A라고 함)를 작성하여 100에서 0으로 숫자를 출력합니다. 그러나 문제는 spawn/1이 차단되지 않습니다. "main"프로세스가 계속 실행되고 "프로세스 A"가 리턴되기를 기다리지 않음을 의미합니다.

그래서 "주"프로세스가 전체 프로그램을 종료하는 실행을 완료하고 있습니다. 이것은 내가 사용 해본 모든 언어에서 정상입니다.

다른 프로세스에서 일부 작업을 생성하고 프로그램을 끝내기 전에 실행이 완료되도록하려면 몇 가지 옵션이 있습니다.

Task 모듈을 사용할 수 있습니다. 이것의 라인을 따라 뭔가가 작동합니다.

task = Task.async(&Foo.go/0) 
Task.await(task) 

사용자 수를 명시 적으로 send and receive 메시지

defmodule Foo do 
    def run(0, pid) do 
    IO.puts("0") 

    # This will send the message back to the "main" thread upon completion. 
    send pid, {:done, self()} 
    end 
    def run(n, pid) do 
    IO.puts(to_string n) 
    run(n - 1, pid) 
    end 

    # We now pass along the pid of the "main" thread into the go function. 
    def go(pid) do 
    run(100, pid) 
    end 
end 

# Use spawn/3 instead so we can pass in the "main" process pid. 
pid = spawn(Foo, :go, [self()]) 

# This will block until it receives a message matching this pattern. 
receive do 
    # The^is the pin operator. It ensures that we match against the same pid as before. 
    {:done, ^pid} -> :done 
end 

이 달성의 다른 방법이 있습니다. 불행히도 해결하려는 문제에 대해 더 많이 알지 못하면서 나는 기본적인 제안 만 할 수 있습니다.

이 모든 것을 말하면 mix은 실행중인 프로그램을 임의로 중지하지 않습니다. 어떤 이유로 든 "주"프로세스가 실행을 완료해야합니다. 또한 mix은 빌드 도구이기 때문에 실제로 응용 프로그램을 실행하는 방식이 아닙니다 (그래도 가능합니다). 다시 말하지만, 당신이하려고하는 것을 알지 못하거나 코드를 보지 못한다면 나는 이것 이상으로 당신에게 아무것도 줄 수 없습니다.

+0

대단히 감사합니다. '믹스'에 관한 나의 문제는 엘릭서 프로세스에 대한 오해와 다른 언어가 프로세스라고 부르는 것에 대해 직접적으로 발생했습니다. –

+0

또 다른 가능한 해결책은'elixir --ho-halt foo '로 프로그램을 실행하는 것입니다.실행 후 Erlang VM을 중단시키지 않습니다 "라는 메시지가 표시됩니다. 그런 다음 Ctrl-C를 두 번 입력하여 프로그램을 종료 할 수 있습니다. –