Can't use function calls in pattern matching

Given

f = fn -> 2 end
g = fn -> 2 end

How can I match the result of g with f’s ?
If I do it like this, it fails because function calls are not allowed in pattern matching.

case g.() do
  f.() -> 1
  4 -> 2,
   5 -> 3,
  _ -> 6
end

Note:
This is dummy version of what I need to do in my project. Basically I need to pattern match the result of a function with the result of other functions. But don’t know how to go about it.

What about this?

case {f.(), g.()} do
  {x, y} -> #whatever
end
8 Likes
f_result = f.()

case g.() do
  ^f_result -> 1
  4 -> 2,
   5 -> 3,
  _ -> 6
end
9 Likes

Given that you can just assign the result of a function call to a variable and match on that it’s always seemed surprising to me that the compiler doesn’t do this for you. Is there a technical reason for this not being supported or is it something that might happen at some point?

1 Like

Matches are run in linear time, they can’t allow for arbitrary function calling or anything of the sort as they get compiled to a fairly efficient jumplist (sometimes).

2 Likes
a = fast_op()
b = long_running_thing()

case c do
  ^a -> 1
  ^b -> 2
end

Is very explicit that no matching would happen before both calls have returned, whereas the “sugared” version you suggest might hide this fact and a naive reader would assume that long_running_thing() never gets called when cmatches the result of fast_op().

5 Likes

And of course you’d generally want to run this one as this anyway:

cond do
  ^c = fast_op() -> 1
  ^c = long_running_thing() -> 2
end

^.^

1 Like

Doesn’t this crash as soon as fast_op/0s return value isn’t matching cs value?

I think its this you mean:

cond do
  c === fast_op() -> 1
  c === long_running_thing() -> 2
end
2 Likes

Er, right, my bad, I meant this:

cond do
  match?(^c, fast_op()) -> 1
  match?(^c, long_running_thing()) -> 2
end

^.^;

Although using == would probably be better in this specific case, since it’s not a complex match at all:

cond do
  c == fast_op() -> 1
  c == long_running_thing() -> 2
end

That’s exactly what I was looking for as a replacement for the

which keeps getting over-verbose especially when more than two options are at play :slight_smile: