Found old idea for pipe. What do you think?

Hey, as you know I have lots of ideas. Most of my time takes normal job, so last time I’m quite busy. This night I can’t even sleep, because I thought about more and more enhancements for my ExApi library. :smile:

This morning I found one example when I was looked at my old projects, snippets, plans and other related things.

defmodule Something do
  def first(a, b), do: a + b
  def second(tuple, b, c) when is_tuple(tuple) do
    a = elem(tuple, 0)
    second(a, b, c)
  end
  def second(a, b, c), do: {:ok, a + b + c, a, b, c}
  def third(_a, _b), do: {:error, :fake}
end

defmodule Example do
  use ExPipe

  # 5 is initial data
  # 10 is data before call function with error
  # if not defined msg is nil

  def_handle sample(5, 10, _error, msg), do: throw(msg)

  # defining message is optional

  def_msg sample(5, 10, {:error, atom}), do: Atom.to_string(atom)

  def_process sample do
    Something.first(&_, 2)
    Something.second(1, &_, 2) # as second argument
    Something.third(&_, 3) # function that stops processing
    Something.second(&_, 2, 1) # function with custom ok tuple
    elem(0) # by default as first argument, same as: $0
  end

  def_process sample2 do
    Something.first(&_, 2)
    Something.second(1, &_, 2) # as second argument
    Something.second(&_, 2, 1) # function with custom ok tuple
    elem(0) # by default as first argument, same as: $0
  end
end

ExPipe.run(5, Example, :sample) # handled: throws "fake"
ExPipe.run(5, Example, :sample2) # result: 13

It was probably based on @OvermindDL1 example.

Since this is quite old idea I don’t expect much interest, but maybe someone would be interested in such library. Please let me know what do you think about it.

How would you achieve that? Default piping is slightly limited I admit, with it being based on currying and all, but it’s not fatal and it adds only a little extra code.

Could you give an example of how would you achieve piping that doesn’t exclusively rely on currying (namely using the output of a function as the first argument of the next function)?

If I misunderstood, my apologies.

Because of the “underscore as a target”:

Where each expression can be a valid Erlang expression, with the state substituted by the _ variable.

I’m reminded of Fred Hebert’s FancyFlow which contains pipe, maybe, and parallel functions.

@dimitarvp: This is really simple. There will be simple macros that I will parse. In quoted expression I will look for quoted $_ and simply replace it.

If you are interested I can create a library that will work like in this example, but can’t give you code in next “5 mins.”.

I don’t like it because it doesn’t look like Elixir and adds a feeling of magic. You could be tricked into adding generic Elixir code between the statements, but the result would be undefined or prone to many “interesting” discussions.

I believe something like this would be better:

def sample do
  super_pipeline do
    Something.first(&_, 2)
    |> Something.second(1, &_, 2) # as second argument
    |> Something.third(&_, 3) # function that stops processing
    |> Something.second(&_, 2, 1) # function with custom ok tuple
    |> elem(0) 
  end
end

That being said, this is just to clarify my opinion on this, the code above has not been thought through at all.

:slight_smile:

We really need a bikeshedding category, bikeshedding is so fun. ^.^

But yeah, I’d keep |>, and as I said in my original post, it is very easy to overwrite |> or use something else like ~> or so. ^.^

@OvermindDL1: Now I’m thinking about it like a little pipe framework. :slight_smile:

@tallakt: For me start was good, but I don’t finished this idea yet. I agree that it should not look like a magic.

I wanted to have a two scenarios/versions:

  1. “Pipe module”
  2. Something before normal pipe

For first of course my example was not best (again: it’s old draft / idea).
Now I’m mostly in direction to something like:

def_process :name, [
  # just simple list of tuples with args list
  # no magic - ok, maybe only: `$_` part
  {module, :func_name, [arg1, $_, arg3]}
]

Second scenario I imagine like:

raw_value
~> ExPipe.prepare(&handle_fun/4, &optional_message_func/4) # optional
~> Something.first(4, $_)
# ...

I’m still not sure about 1st def_process format. Please let me know if you have a better idea for this case.