如何在Elixir中写入标准输入?

时间:2017-10-28 23:17:07

标签: io 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()函数没有输入。

1 个答案:

答案 0 :(得分:2)

如果你想写入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具有更多更好的处理能力。或者,如果您不需要 stdin ,则应在own Elixir node上运行每个模块:

iex --sname parity -S mix

然后在你的OtherModule中你可以写出类似的内容:

pid = Node.spawn_link :"parity@computer-name", fn -> ... end