2016-11-04 65 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