Cannot invoke remote function Module1.var1/0 inside a match -- why not?

defmodule Module1 do
  @var1 "fdsafds"
  def var1, do: @var1


  @var2 "222"
  def var2, do: @var2

  @var3 "333"
  def var3, do: @var3
end


# [.................]
some_var = get_some_var()
case some_var do
  Module1.var1 -> IO.puts("var111")
  Module1.var2 -> IO.puts("var222")

  # ............
end

Error:

cannot invoke remote function Module1.var1/0 inside a match

Why not? How to fix it?

The clauses in a case statement are compile time concerns, which disallow calling functions during them.

You’ll need to call the functions outside the case and then pin the variables inside the match.

 var1 = Module.var1
 var2 = Module.var2

 case some_var do
  ^var1 -> IO.puts("var111")
  ^var2 -> IO.puts("var222")

  # ............
end
1 Like

For compile time shared constants see:

i.e.:

defmodule Constants do
  #
  # See: https://gist.github.com/smpallen99/9995893
  #
  defmacro constant(name, value) do
    quote do
      defmacro unquote(name), do: unquote(value)
    end
  end

  # this is the macro used to define
  # compile time constants
  defmacro define(name, value) do
    quote do
      constant(unquote(name), unquote(value))
    end
  end

  # Support for "use Constants"
  # https://hexdocs.pm/elixir/Kernel.html#use/2

  defmacro __using__(_opts) do
    quote do
      import Constants
    end
  end
end

defmodule Module1 do
  use Constants

  define(var1, "fdsafds")
  define(var2, "222")
  define(var3, "333")
end

defmodule Module2 do
  require Module1

  def run(some_var) do
    case some_var do
      Module1.var1() ->
        IO.puts("var1")

      Module1.var2() ->
        IO.puts("var2")

      Module1.var3() ->
        IO.puts("var3")
    end
  end
end

Module2.run("fdsafds")
Module2.run("222")
Module2.run("333")

or

defmodule Constants do
  defmacro constant(name, value) do
    quote bind_quoted: [name: name, value: value] do
      defmacro unquote(name)(), do: unquote(value)
    end
  end

  defmacro __using__(_opts) do
    quote do
      import Constants
    end
  end
end

defmodule Module1 do
  use Constants

  @consts [var1: "fdsafds", var2: "222", var3: "333"]

  for {name, value} <- @consts,
    do: constant(name, value)
end

defmodule Module2 do
  require Module1

  def run(some_var) do
    case some_var do
      Module1.var1() ->
        IO.puts("var1")

      Module1.var2() ->
        IO.puts("var2")

      Module1.var3() ->
        IO.puts("var3")
    end
  end
end

Module2.run("fdsafds")
Module2.run("222")
Module2.run("333")

Patterns are compile time artifacts. Also:

http://erlang.org/doc/reference_manual/expressions.html#guard-sequences

https://hexdocs.pm/elixir/guards.html

1 Like