Skip to content

Instantly share code, notes, and snippets.

@adrianomitre
Last active July 15, 2020 03:13
Show Gist options
  • Save adrianomitre/cc3be6118b9bad25d663946acd7c1c13 to your computer and use it in GitHub Desktop.
Save adrianomitre/cc3be6118b9bad25d663946acd7c1c13 to your computer and use it in GitHub Desktop.
uniformly stream from IO and File in Elixir (akin to Ruby's ARGF)
defmodule App do
defmodule CLI do
def main(argv) do
io_stream_from_file_args_or_stdin(argv)
|> App.process_stream()
end
defp io_stream_from_file_args_or_stdin(argv) do
get_io_source(argv)
|> IO.stream(:line)
end
defp get_io_source([]) do
:stdio
end
defp get_io_source([path]) do
{:ok, file} = File.open(path)
file
end
end
@doc """
stream - should have side effects in the sense of the Iterator design
pattern or database Cursor, as IO.Stream does and File.Stream does not.
IO.stream/2 documentation reads "Note that an IO stream has side effects
and every time you go over the stream you may get different results."
"""
def process_stream(stream = %IO.Stream{}) do
[first_line] = Enum.take(stream, 1)
header_result = process_first_line(first_line)
stream
|> Stream.chunk_every(2)
|> Stream.each(fn [odd_line, even_line] ->
process_line_pairs(odd_line, even_line, header_result)
end)
|> Stream.run()
end
def process_first_line(line) do
# ...
end
def process_line_pairs(odd_line, second_line, header_result) do
# ...
end
end
# Thanks to @fcevado and @bamorim for the fruitful discussion on https://telegram.me/elixirbr
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment