How can I properly call functions within Enum.map?

I am quite new to Elixir, so I apologize for my ineptitude. I am trying to convert a string timestamp into unix time, however, I run into the following error:

(CompileError) nested captures via & are not allowed: &(NativeDateTime.diff(&1, ~N[1970-01-01 00:00:00]))

I am unfamiliar with how & functions in Elixir and tried to do my best simulating what I see online. The code fragment that I am trying to fix is:

|> Enum.map(fn 
  [user_id, state, timestamp] -> 
    unix = &NativeDateTime.from_iso8601(&1, timestamp) 
    |> &NativeDateTime.diff(&1,~N[1970-01-01 00:00:00])

Thank you for your assistance!

Hi @alex_preci
Welcome to the forums.

Do not use function captures if you are starting. Until you fully grasp what they are about.

fn x -> {:ok, x} end CAN be expressed as &({:ok, &1})

fn y -> {y, fn z -> {:ok, z} end} end CANNOT be expressed as &({&1, &({:ok, &1})}) because you are nesting captures, so the second &1 refers to y or z? So it will have to be expressed as:

  • &{&1, fn z -> {:ok, z} end}; or as
  • fn y -> {y, &{:ok, &1}} end

PS: Your code is not complete so I cannot give you a more detailed answer.

2 Likes

Crossposted elixir - How can I properly call functions within Enum.map? - Stack Overflow

2 Likes

& is a shortcut to declare anonymous functions.

& &1 is equal to fn x -> x end

It is useful when You have a function that takes function as argument, like Enum.map…

You can have a function, that takes a function, that takes a function as argument. You might be tempted to use capture twice, but You cannot nest captures.

When dealing with usual functions, there is no need to use capture, just do a normal function call.

We don’t have the full code, but your code could look like this…

|> Enum.map(fn 
  [_user_id, _state, timestamp] -> 
    timestamp
    |> NaiveDateTime.from_iso8601() 
    |> NaiveDateTime.diff(~N[1970-01-01 00:00:00])

fn x -> {:ok, x} end CAN be expressed as &({:ok, &1})

can also be expressed as &{:ok, &1} :slightly_smiling_face: