Skip to content

Instantly share code, notes, and snippets.

@Qqwy
Last active June 24, 2020 15:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Qqwy/47b2bed1d307babf31113d41716dd3fc to your computer and use it in GitHub Desktop.
Save Qqwy/47b2bed1d307babf31113d41716dd3fc to your computer and use it in GitHub Desktop.
Elixir example of a pipe-operator that uses some simple metaprogramming to allow piping into capture-syntax. Version with slightly more verbose `&`-prefixed syntax. Naive implementation that does not allow using multiple captures in the same pipeline.
defmodule Capturepipe do
@doc """
A pipe-operator that extends the normal pipe
in one tiny way:
It allows the syntax of having a bare `&1` capture
to exist inside a datastructure as one of the pipe results.
This is useful to insert the pipe's results into a datastructure
such as a tuple.
What this pipe-macro does, is if it encounters a bare `&1` capture,
it wraps the whole operand in `(&(...)).()` which is the
anonymous-function-call syntax that the Kernel pipe accepts,
that (argubably) is much less easy on the eyes.
So `10 |> {:ok, &1}` is turned into `10 |> (&({:ok, &1})).()`
To use this operator in one of your modules, you need to add the following to it:
import Capturepipe
import Kernel, except: [|>: 2]
## Examples
Still works as normal:
iex> [1,2,3] |> Enum.map(fn x -> x + 1 end)
[2,3,4]
Insert the result of an operation into a tuple
iex> 42 |> &{:ok, &1}
{:ok, 42}
Unfortunately, the following does _not_ work
because a `&` will capture all following `|>`'s as well.
:-(
iex> 20 |> &{:ok, &1} |> &[&1, 2, 3]
** (CompileError)
"""
defmacro prev |> (capture = {:&, _, _}) do
quote do
Kernel.|>(unquote(prev), (unquote(capture)).())
end
end
defmacro prev |> other do
quote do
Kernel.|>(unquote(prev), unquote(other))
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment