sodapopcan

sodapopcan

Improve this `unpipe` function?

I go through bouts of playing around with re-writing source-code using Sourceror. It generally goes: I learn a whole bunch, start getting comfortable with it, stop doing it for many months and forget everything :expressionless:

I’m back at it and just finished creating a function that will inline single pipes. IE:

socket
|> assign(:foo, "foo")

becomes:

assign(socket, :foo, "foo")

I was looking to get some feedback on my solution.

I initially thought I could get away with simply pre- or postwalking with some clever pattern-matching, but that proved to be difficult for me. I ended up using a zipper which made life a LOT easier getting me to a solution quite quickly. There are still a few issues with line-length but I’m otherwise quite happy with the clarity of it.

Still, I’m wondering:

  • Is this possible using walking with an accumulator?
  • Do you have a solution that’s different/better than mine?
  • Do you have any other feedback?

TIA

def unpipe(ast) do
  Sourceror.Zipper.zip(ast)
  |> Sourceror.Zipper.traverse(fn
    %{node: {:|>, _, _} = node} = zipper ->
      prev = Sourceror.Zipper.prev(zipper)
      next = Sourceror.Zipper.next(zipper)

      with false <- match?(%{node: {:|>, _, _}}, prev),
           false <- match?(%{node: {:|>, _, _}}, next),
           {:|>, _, [var, {func, meta, args}]} <- node do
        Sourceror.Zipper.replace(zipper, {func, meta, [var | args]})
      else
        _ ->
          zipper
      end

    zipper ->
      zipper
  end)
  |> Sourceror.Zipper.topmost_root()
end

Most Liked

sodapopcan

sodapopcan

Ok, I may be celebrating early but simply setting empty meta solved it.

       {:|>, _, [var, {func, _, args}]} <- node do
    Sourceror.Zipper.replace(zipper, {func, [], [var | args]})
slouchpie

slouchpie

You can also use styler | Hex to fix single pipes.

zachdaniel

zachdaniel

Creator of Ash

Ah, right. I think what you can do is check if the node previous to the top node is {:__block__, meta, [just_one_thing]} and if so, replace that node instead? Might mess w/ your traversal though.

Last Post!

sodapopcan

sodapopcan

That’s good to know! I’ve been thinking of polishing and focusing up that package for a while now, even just for learnings, but have been spending my time on other ventures. I made it at a time where I was prototyping a new Phoenix app weekly and I don’t do that anymore. I will certainly look to igniter for inspiration, though. I remember a convo where you and Ben were talking about using closures in module attributes which was the big piece of refactoring I wanted to do, even just to see it work. I’m currently using a GenServer to get around not being able to figure that out for myself but anyway, that is a bit off topic :sweat_smile:

Where Next?

Popular in Questions Top

JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New

Other popular topics Top

jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New

We're in Beta

About us Mission Statement