cjm2671
cjm2671

Reputation: 19496

How do I pipeline an if?

I'm trying to decode a websocket response. If it contains the key 'symbol', I'd like to print it out.

I've done this:

msg                                                                                                                                   
|>Poison.decode!                                                                                                                      
|>Enum.member?("symbol")                                                                                                              
|>if                                             
|>IO.inspect

Unsurprisingly, it didn't like my 'if'. Is there a pipeline way of achieving this?

Upvotes: 0

Views: 2104

Answers (3)

voger
voger

Reputation: 676

Kernel.if/2 is defined with an arity of 2. In your pipe you call it with an arity of 1. This means there is no match for Kernel.if/1.

Also your if should return something for IO.inspect to inspect

[true, false] 
|> Enum.random() 
|> if(do: 42, else: "You can't handle the truth") 
|> IO.inspect

or maybe

[true, false]
|> Enum.random()
|> if do
        42
      else
        "You can't handle the truth"
      end
|> IO.inspect

or if you wish to return the result of the expression itself

["My random data", nil] 
|> Enum.random() 
|> (fn item -> if(item, do: item, else: "Sorry... no data!") end).() 
|> IO.inspect

or even better

value
|> something(42)
|> something_else()
|> case do
     page where limit_size == nil -> page
     page -> page |> limit(size)
   end
|> some_more_things()

The last example is taken from elixir forum

If you wan't your enumerable to go through the pipeline and get an occasional print, if there is a specific key, here is one approach

[a: 1, b: 3, c: 15]
|> (fn enumerable -> if(a = Access.get(enumerable, :a), do: IO.inspect(a, label: "The :a")); enumerable end ).()
|> (fn enumerable -> if(f = Access.get(enumerable, :f), do: IO.inspect(f, label: "This shouldn't be printed")); enumerable end ).()
|> IO.inspect(label: "The enumerable")

Still the best way is to use functions with multiple heads.

Upvotes: 3

Is your response actually a List or a Map? Because Enum.member? won't work on a Map. If it is a Map, you can take advantage of the special pattern matching elixir does for maps to accomplish this in a much easier fashion

def show_result(%{"symbol" => _value} = msg) do 
  IO.inspect(msg) 
end 

def show_result(msg) do 
   msg
end 

Results in this code:

msg                                                                                                                                   
|> Poison.decode!                                                                                                                      
|> show_result

Upvotes: 0

PatNowak
PatNowak

Reputation: 5812

Sadly you can't do it, because You can't pipeline into macros! To achieve what you need just put this if into the proper function. Or even better - you do the conditional branching using different heads of the functions thanks to the pattern matching!

Enum.member/2 will return true or false, so all you need is:

defp processing_the_response(true) do
  # something
end

defp processing_the_response(false) do
  # something ELSE
end

Upvotes: 3

Related Questions