title: Phoenix Elixir : cannot escape function in elixir compiler
body: <p>From <a href="https://www.viget.com/articles/how-to-redirect-from-the-phoenix-router/" rel="nofollow noreferrer">this tutorial</a>, I have some elegant:</p>
  
  <pre><code>get("/old-path", Redirector, to: "/new-path")
  get("/old-path/:id", Redirector, to: "/new-path?object=:id")
  </code></pre>
  
  <p>in my <code>router.ex</code>.</p>
  
  <p>But I now have a more complex case, which requires my redirection to be dynamic. I wanted to go for:</p>
  
  <pre><code>get("/other-old-path", Redirector, to: fn conn, options -&gt; "/whatever-path" end)
  </code></pre>
  
  <p>And wrote on my <code>Redirector</code> module:</p>
  
  <pre><code>to = if is_function(to), do: to.(conn, Keyword.drop(options, :to)), else: to
  </code></pre>
  
  <p>I was pretty confident with my code, but when I tried to execute it, I received the following error:</p>
  
  <pre><code>== Compilation error in file web/router.ex ==
  ** (ArgumentError) cannot escape #Function&lt;5.71083082/2 in :elixir_compiler_10.__MODULE__/1&gt;. The supported values are: lists, tuples, maps, atoms, numbers, bitstrings, PIDs and remote functions in the format &amp;Mod.fun/arity
      (elixir) src/elixir_quote.erl:122: :elixir_quote.argument_error/1
      (elixir) src/elixir_quote.erl:259: :elixir_quote.do_quote/3
      (elixir) src/elixir_quote.erl:310: :elixir_quote.do_escape/3
      (phoenix) lib/phoenix/router/route.ex:136: Phoenix.Router.Route.build_dispatch/1
      (phoenix) lib/phoenix/router/route.ex:73: Phoenix.Router.Route.exprs/1
      (phoenix) lib/phoenix/router.ex:334: anonymous fn/1 in Phoenix.Router."MACRO-__before_compile__"/2
      (elixir) lib/enum.ex:1327: Enum."-map/2-lists^map/1-0-"/2
      (elixir) lib/enum.ex:1327: Enum."-map/2-lists^map/1-0-"/2
      (phoenix) expanding macro: Phoenix.Router.__before_compile__/1
      web/router.ex:1: MyApp.Router (module) 
      (elixir) lib/kernel/parallel_compiler.ex:208: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/6
  </code></pre>
  
  <p>Googling it sent me to <a href="https://groups.google.com/forum/#!topic/elixir-lang-talk/7FXDKJ_Lpzg" rel="nofollow noreferrer">this page</a> which mentions I can't do what I want to do. I read this has to do with <a href="https://elixir-lang.org/getting-started/meta/quote-and-unquote.html" rel="nofollow noreferrer">quoted expressions</a> so I tried to understand how this can be useful, but still don't.</p>
  
  <p>I tried to pass an anonymous function in a keyword list in a parameter of a function in the console and it worked.</p>
  
  <p>I'm guessing it breaks here because the behavior of <code>get</code> is more <em>meta</em>.</p>
  
  <p>Anyway, I'm sure I'll get more comfortable along working deeper with Elixir, and one day I'll clearly understand why it did not work (explanations welcome of course!), but by then, how can I write what I want to do? </p>
  
  <p>It doesn't feel like I am doing something elixir-difficult but it apparently is...</p>
  
  <p>Cheers</p>
  
  <hr>
  
  <p>EDIT: thanks for reply.</p>
  
  <p>I did what you suggested @justin-wood but it doesn't work:</p>
  
  <pre><code>get("/other-old-path", Redirector, to: &amp;MyApp.Router.do_redirect/2)
  </code></pre>
  
  <p>and at the bottom of the file</p>
  
  <pre><code>def do_redirect(conn, options), do: "/youpi"
  </code></pre>
  
  <p>But I get a hideous error:</p>
  
  <pre><code>== Compilation error in file web/router.ex ==
  ** (FunctionClauseError) no function clause matching in :v3_core.pattern/2    
  
      The following arguments were given to :v3_core.pattern/2:
  
          # 1
          {:fun, 0, {:function, {:atom, 0, Vae.Router}, {:atom, 0, :do_redirect}, {:integer, 0, 2}}}
  
          # 2
          {:core, 2, 0, {:redirector_path, 2}, ... [more uglyness]
  </code></pre>