Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nocost: rename fancyflow_trans + turn [pipe] & [maybe] pipes into zero-cost abstractions #2

Open
wants to merge 18 commits into
base: master
Choose a base branch
from

Conversation

fenollp
Copy link
Owner

@fenollp fenollp commented Jun 18, 2018

This PR has 2 goals:

  1. allowing user-defined pipes, e.g.: [{folder, knm_numbers, pipe}](T,F1,F2,F3)
  2. making the fancyflow-provided pipes abstractions runtime cost less than a remote call down to zero if possible.

Right now the parse transform only replaces the pipes with function calls.
Since the number of arguments to a pipe is known at compile time, I'd like to inline at least the fancyflow-provided pipes, with proper mapping of line numbers to function calls. The simplest one being fancyflow:pipe/2.

Do you think it is possible to make use of https://github.com/erlang/otp/blob/9d5af99762b3795c763fb62c1516247bd3f8e12f/lib/compiler/src/sys_core_fold_lists.erl#L209 or should I just be looking into manually inlining the fancyflow-provided pipes?

Note: I introduced 2 pipe kinds (mapper & folder). It should now be possible to no longer need to give undefined as a first arg for mapper pipes, but I have not looked into it yet.

@ferd
Copy link
Collaborator

ferd commented Jun 18, 2018

I'll have to think about it. I'm deeply uncomfortable with people relying on these constructs in any kind of production code. They were experiments to explore some semantics for pipe and pipe-equivalence in Erlang, and the library is clearly marked as experimental. It's part of the reason I have refused to publish it on Hex so far.

So seeing steps that seem towards making these things more production-friendly kind of rubs me the wrong way with regards to the spirit of this library. Specifically, letting user-specified pipes get in on this just makes everything over-rely on the shitty bad syntax chosen ([Desc](A, B, C)) and rather than adding flexibility here, it would be much nicer to have something better that does not rely on the compiler being way too lax about some of the things it allows.

I'm not too sure what [{folder,knm_numbers,pipe}](T,F1,F2,F3) means. Does it apply folder:knm_numbers with pipe semantics, or is it a folder type of pipe applying knm_numbers:pipe. If the latter, why not just use a regular fold?

@fenollp
Copy link
Owner Author

fenollp commented Jun 18, 2018

Oh I'm not using it at all. I am just experimenting with it, trying to learn some lessons to some day write an informed EEP and maybe get a pipe operator into Erlang :)

The syntax hack really doesn't matter and it's just "temporary".

Yes, with [{folder,knm_numbers,pipe}](T,F1,F2,F3) I meant "call knm_numbers:pipe/2 as a folder pipe on the value T with functions F1, F2, F3.
The function wouldn't just be a fold underneath, like fancyflow:maybe/2 isn't.
I just want a way for people to experiment with their own pipes in an easier way.

@fenollp
Copy link
Owner Author

fenollp commented Jun 19, 2018

yay I managed to inline fancyflow:pipe! which makes this PR ready for review :)

@fenollp fenollp changed the title nocost: rename fancyflow_trans + prepare inlining of supported pipes nocost: rename fancyflow_trans + turn [pipe] & [maybe] pipes into zero-cost abstractions Jun 19, 2018
@fenollp
Copy link
Owner Author

fenollp commented Jun 19, 2018

Ready! :)

Copy link
Collaborator

@ferd ferd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a few things I'm not quite sure are properly covered here.

@@ -1,5 +1,5 @@
{application, fancyflow,
[{description, "Experimental library to bring pipe and maybe operator equivalents in Erlang"},
[{description, "Experimental library to bring pipe and maybe operator equivalents to Erlang"},
{vsn, "0.1.0"},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should probably come with a version bump

op_new({atom,_,maybe}) -> #op{kind=folder, mname=?MODULE, fname=maybe};
op_new({atom,_,parallel}) -> #op{kind=mapper, mname=?MODULE, fname=parallel};
op_new({tuple, _, [{atom,_,K}, {atom,_,M}, {atom,_,F}]}) ->
#op{kind=K, mname=M, fname=F}.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

afaict this crashes hard on an unsupported form rather than just tunnelling it through


mixin_pipe_fold(Piped, {{var,_,LastVarName},Block}) ->
L = element(2, Piped),
Replacer = fun (T) -> replace_var(T, LastVarName) end,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this form of rewriting may break the cases where the var refers to an external scope thing vs. introducing a new one. In:

A = 5,
[pipe](Val, begin X = A + _, X*2 end, begin X = A - _, X*3 end)

we'd expect to rewrite X to avoid exporting what is currently scoped to a function, but not A, which comes from the parent scope.

I can't figure out if the error is there, but the lack of scope analysis in the inlining of the macro makes me think it's not there.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I'm getting it wrong and what this does is inline the call that the fancyflow module does, and all individual clauses are still walled within funs

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for reviewing!
You are right the inlining does mess up the internal scope (I'm adding your example as a test).
However, [{K,M,F}] is not inlined (mixin-ed) and should be enclosing each expr in a fun. Turns out that also fails the new tests.

I'm looking into this.

pipe_trans, maybe_trans, parallel_trans,
mixed_trans].
[F || {F,1} <- ?MODULE:module_info(exports)]
-- [module_info, id, ok_id].
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please be explicit, go back to just listing tests. Right now this would explode if init_per_suite would be added and exported.

@fenollp
Copy link
Owner Author

fenollp commented Aug 10, 2018

Got over the scoping issue with a somewhat dirty hack: a7396db

@fenollp
Copy link
Owner Author

fenollp commented Aug 13, 2018

Just added TravisCI too.

@fenollp fenollp closed this Aug 13, 2018
@fenollp fenollp reopened this Aug 13, 2018
@ferd
Copy link
Collaborator

ferd commented Aug 31, 2018

@fenollp would you like to get ownership of this repo? I think I've hit what I wanted in terms of experimentation with it, and you seem more interested in driving that stuff forwards than I am.

@fenollp
Copy link
Owner Author

fenollp commented Sep 1, 2018

Yes I’m fine with that.

@ferd
Copy link
Collaborator

ferd commented Sep 1, 2018

heh, I can't do it as long as fenollp/fancyflow already exists

@fenollp
Copy link
Owner Author

fenollp commented Sep 1, 2018

Okay I just deleted my fork.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants