2017-10-28 214 views
1

我有這個模塊用於檢查號碼的奇偶:如何寫入Elixir的標準輸入?

defmodule Parity do 
    def start() do 
    continue() 
    end 

    defp continue() do 
    get_number() 
    |> parse() 
    |> even?() 
    |> print_output() 
    continue() 
    end 

    defp get_number() do 
    IO.gets("Type a number: ") 
    end 

    defp parse(input) do 
    String.trim(input) 
    |> Integer.parse 
    end 

    defp even?({ number, _ }) do 
    Integer.mod(number, 2) == 0 
    end 

    defp print_output(_is_even = true) do 
    IO.puts("This number is even!") 
    end 

    defp print_output(_is_odd) do 
    IO.puts("This number is odd!") 
    end 
end 

而且它的工作原理是這樣的:

$ mix run -e Parity.start 
Type a number: 4 
This number is even! 
Type a number: 3 
This number is odd! 
Type a number: 68 
This number is even! 
Type a number: 1 
This number is odd! 
Type a number: ... 

現在,我希望能有另外一個模塊,這將能夠寫號碼Parity模塊的標準輸入。所以我需要有一些東西來執行Parity.start(),然後爲IO.gets()函數提供數字。 我試過這樣的:

defmodule Bot do 
    def start() do 
    Parity.start() 
    provide_number() 
    end 

    defp provide_number() do 
    random_number() 
    |> IO.puts 
    provide_number() 
    end 

    defp random_number() do 
    Enum.random(0..100) 
    end 
end 

而且它不起作用。

它只啓動Parity模塊,但沒有來自provide_number()函數的輸入。

+0

你們都在運行此一個單一的線程。當你調用'Bot.start/0'時,它會調用'Parity.start/0',最終調用'IO.gets/2'。您的程序現在處於等待輸入狀態,無法繼續執行代碼到您實際生成數字的部分。 –

+0

你想要做什麼?是否用於測試目的? –

+0

@RyanBigg我只是想用另一個模塊來模擬人的輸入。 – Walerian

回答

1

如果你想寫stdin(就像僞造一個CLI輸入一樣),你幾乎需要一種在不同系統進程之間交換信息的方法。 Porcelain做得相當不錯:

defmodule OtherModule do 
    alias Porcelain.Process, as: Proc 
    alias Porcelain.Result 

    proc = %Proc{pid: pid} = 
    Porcelain.spawn_shell("mix run -e Parity.start", in: :receive, out: {:send, self()}) 

    Proc.send_input(proc, "1") 
    receive do 
    {^pid, :data, :out, data} -> IO.inspect data #=> "This number is odd!" 
    end 
end 

未經測試書寫,但應該給你一個粗略的想法。瓷器有很多比這更好地處理System.cmd/3。另外,如果你不需要標準輸入,你應該對他們own Elixir node運行的每個模塊:

iex --sname parity -S mix 

然後在你的OtherModule你可以寫這樣的:

pid = Node.spawn_link :"[email protected]", fn -> ... end