0
votes

I have been proferred this code snippet, which the author has not tested,

|> (fn l ->[?[, Enum.map(l, &([inspect(limit: :infinity), ?\n])), ?]] end).()

as part of a sequence of pipelined commands which converts data from a CSV file to a struct using the DataMorph library, and outputs the result as a regular Elixir list for input into Elixir source - ie adding the surrounding brackets, and separating the elements of the list with commas.

This is what the sequence is meant to look like:

File.stream!('tmp.csv') \
|> DataMorph.structs_from_csv("open-register", :iso_country) \
|> (fn l ->[?[, Enum.map(l, &([inspect(limit: :infinity), ?\n])), ?]] end).()
|> (&File.write('output.txt',&1)).()

This is the error message when it is run in iex:

* (CompileError) iex:55: invalid args for &, expected an expression in the format of &Mod.fun/arity, &local/arity or a capture containing at least one argument as &1, got: [inspect(limit: :infinity), 10]
    (elixir) expanding macro: Kernel.|>/2
             iex:55: (file)

Where is the fault in the snippet?

1
Does this work? |> (fn l ->[?[, Enum.map(l, &([inspect(&1, limit: :infinity), ?\n])), ?]] end).()Dogbert
@Dogbert It compiles correct and adds the opening and closing brackets but it is not including the separating commas. That is the tricky part because a test must be made to ensure it is not the last item before it is appended.vfclists
There is no code in that which will separate the items with a comma. How about |> (fn l ->[?[, Enum.map(l, &([inspect(&1, limit: :infinity), ?\n])) |> Enum.intersperse(?,), ?]] end).()? Can you post the data and the expected output?Dogbert
Your suggestion partly worked, but the comma is prepended to the subsequent entries, instead of being appended and causes a syntax error. ie ,%StructType.TplParams{xxx instead of the comma being appended to the previous line and the next one starting %StructType.TplParams{xxx. pastebin.com/DCrpNDUh I think the correct way is use the , in the inspect formula, then use the \n in the intersperse function. I will give that a try.vfclists
I've posted an answer which intersperses with ",\n". I think that's what you want.Dogbert

1 Answers

2
votes

The syntax error can be fixed by adding &1 as the first argument to the partial application syntax:

|> (fn l ->[?[, Enum.map(l, &([inspect(&1, limit: :infinity), ?\n])), ?]] end).()

This code doesn't include a separating comma. For that, if you want to stay with producing an iolist, I'd recommend using Enum.intersperse:

iex(1)> [1, 2, [3], [4, 5]] |> (fn l ->[?[, Enum.map(l, &inspect(&1, limit: :infinity)) |> Enum.intersperse(",\n"), ?]] end).() |> IO.puts
[1,
2,
[3],
[4, 5]]

I'd also break this into multiple lines for readability:

[1, 2, [3], [4, 5]]
|> (fn list ->
  elements = Enum.map(list, &inspect(&1, limit: :infinity)) |> Enum.intersperse(",\n")
  [?[, elements, ?]]
end).()
|> IO.puts