Last active
June 24, 2020 15:38
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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