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.

2 Likes

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.

2 Likes

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.

2 Likes

@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.”.

2 Likes

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:

3 Likes

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. ^.^

1 Like

@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.

1 Like