Reputation: 605
I'd like to write the code like this:
def boundary do
:crypto.rand_bytes(8)
|> Base.encode16
|> &("--------FormDataBoundary" <> &1)
end
But it doesn't work.
Upvotes: 48
Views: 14995
Reputation: 797
Elixir 1.12 introduced macro then(value, fun)
. Citing the docs:
then(value, fun)
Pipes value into the given fun.
In other words, it invokes fun with value as argument. This is most commonly used in pipelines, allowing you to pipe a value to a function outside of its first argument.
Your code becomes:
:crypto.strong_rand_bytes(8)
|> Base.encode16
|> then(&("--------FormDataBoundary" <> &1))
I'm using :crypto.strong_rand_bytes/1
above because :crypto.rand_bytes/1
was deprecated in Erlang/OTP 18.
Upvotes: 6
Reputation: 9791
You can also use something like this:
def boundary do
:crypto.rand_bytes(8)
|> Base.encode16
|> (fn chars -> "--------FormDataBoundary" <> chars end).()
end
One advantage of this form over others is that you can easily write simple 'case' statements:
def do_some_stuff do
something
|> a_named_function()
|> (
fn
{:ok, something} -> something
{:error, something_else} ->
Logger.error "Error"
# ...
end
).()
end
From:
Using fn
as above is a tiny bit clearer than couchemar's answer:
def boundary do
:crypto.rand_bytes(8)
|> Base.encode16
|> (&("--------FormDataBoundary" <> &1)).()
end
... but, for your particular example, the above form using &
is probably best. If the pipeline expression was more complicated, naming the anonymous function parameters might be more useful.
My answer is also a little more concise than Nathan Long's answer:
def boundary do
add_marker = fn (s) ->
"--------FormDataBoundary" <> s
end
:crypto.rand_bytes(8)
|> Base.encode16
|> add_marker.()
end
... tho his answer would be nicer if, for some reason, you needed to call that function more than once in the pipeline.
Upvotes: 2
Reputation: 562
can't you literally just go?
thing
|> func_one()
|> fn input -> do_stuff_here() end)
You can do stuff like piping things directly into case like
thing
|> func_one()
|> case do
so, I would think you can just pipe into an anonymous function.
Upvotes: 1
Reputation: 2434
The accepted answer works, but you can do this a bit more elegantly by using
(&"--------FormDataBoundary#{&1}").()
instead of
(&("--------FormDataBoundary" <> &1)).()
Here is the full function:
def boundary do
:crypto.strong_rand_bytes(8)
|> Base.encode16()
|> (&"--------FormDataBoundary#{&1}").()
end
Bonus: I've also replaced :crypto.rand_bytes/1
(which doesn't exist in elixir 1.6+) with :crypto.strong_rand_bytes/1
.
Upvotes: 4
Reputation: 125902
Related: if the "anonymous" function has been assigned to a variable, you can pipe to it like this:
def boundary do
add_marker = fn (s) ->
"--------FormDataBoundary" <> s
end
:crypto.rand_bytes(8)
|> Base.encode16
|> add_marker.()
end
Upvotes: 17
Reputation: 1947
It will look bit weird but must work:
def boundary do
:crypto.rand_bytes(8)
|> Base.encode16
|> (&("--------FormDataBoundary" <> &1)).()
end
Upvotes: 80