Phoenix Elixir:无法在Elixir编译器中转义函数

时间:2019-06-20 14:04:46

标签: elixir metaprogramming phoenix-framework

this tutorial开始,我有些优雅:

get("/old-path", Redirector, to: "/new-path")
get("/old-path/:id", Redirector, to: "/new-path?object=:id")

在我的router.ex中。

但是我现在有一个更复杂的情况,这要求我的重定向是动态的。我想去:

get("/other-old-path", Redirector, to: fn conn, options -> "/whatever-path" end)

并在我的Redirector模块上写道:

to = if is_function(to), do: to.(conn, Keyword.drop(options, :to)), else: to

我对我的代码非常有信心,但是当我尝试执行它时,出现以下错误:

== Compilation error in file web/router.ex ==
** (ArgumentError) cannot escape #Function<5.71083082/2 in :elixir_compiler_10.__MODULE__/1>. The supported values are: lists, tuples, maps, atoms, numbers, bitstrings, PIDs and remote functions in the format &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

谷歌搜索将我发送到this page,其中提到我无法做自己想做的事。我读到这与quoted expressions有关,所以我试图了解它如何有用,但仍然没有用。

我试图在控制台中某个函数的参数的关键字列表中传递一个匿名函数,并且它起作用了。

我猜想这里会中断,因为get的行为是 meta

无论如何,我相信与Elixir进行更深入的合作会更加舒适,并且有一天我会清楚地理解为什么它不起作用(当然,欢迎解释!),但是到那时,我该怎么写我想做的事?

感觉好像我在做些难以解决的事情,但显然是...

欢呼


编辑:感谢您的答复。

我按照你的建议做了@ justin-wood,但是不起作用:

get("/other-old-path", Redirector, to: &MyApp.Router.do_redirect/2)

并在文件底部

def do_redirect(conn, options), do: "/youpi"

但是我收到一个可怕的错误:

== 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]

1 个答案:

答案 0 :(得分:1)

  

无法在:elixir_compiler_10中转义#Function <5.71083082 / 2。 MODULE / 1>。支持的值包括:...远程函数,格式为&Mod.fun / arity

如果您使用命名函数而不是匿名函数,它应该可以工作。因此,对于

defmodule Foo do
  def bar do
    :baz
  end
end

您将使用&Foo.bar/0来引用该函数。