Phoenix Elixir: не может выйти из функции в компиляторе эликсира - PullRequest
0 голосов
/ 20 июня 2019

Из этого урока , у меня есть несколько элегантных:

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

Погуглив это, я отправил на эту страницу , где говорится, что я не могу делать то, что хочу. Я читал, что это связано с выражениями в кавычках , поэтому я пытался понять, как это может быть полезно, но все же нет.

Я попытался передать анонимную функцию в списке ключевых слов в параметре функции в консоли, и это сработало.

Полагаю, что здесь он ломается, потому что поведение get больше meta .

В любом случае, я уверен, что мне будет удобнее работать глубже с Elixir, и однажды я пойму, почему он не работает (объяснения приветствуются, конечно!), Но к тому времени, как я могу написать Что я хочу сделать?

Не похоже, что я делаю что-то трудное для эликсира, но, очевидно, это ...

Приветствия


РЕДАКТИРОВАТЬ: спасибо за ответ.

Я сделал то, что ты предложил @ Джастин-Вуд, но это не сработало:

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 Ответ

1 голос
/ 20 июня 2019

не может выйти из #Function <5.71083082 / 2 in: elixir_compiler_10. <strong>MODULE / 1>.Поддерживаемые значения: ... удаленные функции в формате & Mod.fun / arity

Если вы используете именованную функцию вместо анонимной, она должна работать.Так что в случае

defmodule Foo do
  def bar do
    :baz
  end
end

Вы бы использовали &Foo.bar/0 для ссылки на функцию.

...