2016-11-04 67 views
0

GenServer呼叫我這樣定義一個宏:內宏觀

defmodule Test do 
    defmacro __using__ do 
    quote do 
     require Test 
     import Test 
    end 
    end 

    defmacro my_macro do 
    quote do 
     Gernserver.call() # generic server call from other module 
    end 
    end 
end 

我有我建立一個lib這裏面的代碼。當在另一個應用程序中測試這個庫時,我在具有use Test的文件上出現編譯錯誤。

錯誤:exited in: GenServer.call ...exit no process(在my_macro調用的行上,更具體地說是在genserver調用中)。就好像genserver沒有運行,這不是因爲它是編譯時間。

使用宏將一個簡單的Application.ensure_all_started(:lib_name)添加到似乎解決了這個問題。但是,再次,在編譯時代碼不應該運行,對嗎?或者在這裏,我沒有看到?也許我不能在宏上使用genserver調用?

謝謝。

+0

你能張貼在那裏你調用這個宏的代碼從? – Dogbert

+0

@Dogbert當然,這裏是:https://gist.github.com/jbernardo95/7f1b6fc604f485af1a237a28ffc5669e – jbernardo

回答

1

您正在編輯階段在您的TestScheduler中致電every

你要麼把所有的日程初始化代碼的函數裏面,將被明確在運行階段叫,或者乾脆 引入新的GenServer,將其添加到監督名單(使藥劑自動運行它應用程序啓動,),並執行該every初始化在它的start_link(或將被後顯式調用任何其它功能):

defmodule Test.Scheduler do 
    use GenServer 
    use Cronex.Scheduler 

    def start_link ... do 
    every :minute do 
     IO.puts "every minute job" 
    end 

    every :minute do 
     IO.puts "every minute job 2" 
    end 
    end 
end 

輪(另一種方式,如果你想保留上述文件儘可能乾淨,)將收集在中的數據宏在運行階段產生所有呼叫


爲了更加熟悉階段,把下面的代碼到/tmp/test.ex

defmodule A do 
    IO.puts "Here 「every」 macro was called: compilation" 

    def a do 
    IO.puts "Is not called during compilation stage" 
    end 
end 
IO.puts "=== compilation finished ===" 
A.a 

及發行elixir /tmp/test.ex

Here 「every」 macro was called: compilation 
=== compilation finished === 
Is not called during compilation stage 
+0

這正是問題所在,謝謝你的解釋! – jbernardo

+0

我想我完全不瞭解編譯階段的工作原理。 一切都在編譯階段運行,除了在def電話裏面的代碼我是對的嗎? – jbernardo

+0

歡迎。無論您是來自ruby,您可能會發現相似之處:頂層的所有內容(例如類聲明中的DSL)都會在解析階段執行,並且函數只是被編譯。 'IO.puts end'是編譯完成的,而'IO.puts'是直接執行的(實際上,它也被編譯,但編譯它會導致執行。)我希望我沒有使一切更加糾結。 – mudasobwa