2014-12-29 40 views
11

我想知道是否有一種以編程方式或動態地將一組模塊導入到Julia的方法?舉例來說,如果我有符合一些命名慣例是出現在啓動文件的列表,能搶我使用類似:以編程方式/動態導入Julia的模塊

module_files = filter(r"^mod[0-9][0-9].jl$", readdir()) 

可能返回文件["mod00.jl", "mod02.jl", "mod05.jl"]的名單,是有辦法然後導入這些文件中的每個模塊。這將相當於:

import mod00 
import mod02 
import mod05 

在代碼中,如果我知道這些模塊在編寫代碼時可用。或者也許還有其他方法可以做得更好。任何建議將不勝感激。

更新

我試圖通過宏來做到這一點,但沒有運氣。例如:

macro import_mod(modn) 
    quote 
     import $modn 
    end 
end 

function test_mimport() 
    module_files = filter(r"^mod[0-9][0-9].jl$", readdir()) 
    println(module_files) 
    for modname in factor_files 
     modn = modname[1:end-3] 
     println(modn) 
     @import_mod modn 
    end 
end 

當我運行這個,我得到ERROR: syntax: invalid "import" statement。我嘗試了各種逃避策略,但都失敗了。

+0

因爲'import'是一個關鍵字,而不是一個函數,所以我想說你需要爲它定義一個[macro](http://julia.readthedocs.org/en/latest/manual/metaprogramming/)。 – Jubobs

+0

@Jubobs我通過一個宏來玩弄了一下,但Julia似乎不喜歡宏中的'import'語句。 – JoshAdel

回答

3

import X功能版本require("X"),所以你應該能夠做到:

function test_mimport() 
    module_files = filter(r"^mod[0-9][0-9].jl$", readdir()) 
    println(module_files) 
    for modname in factor_files 
     modn = modname[1:end-3] 
     println(modn) 
     require(modn) 
    end 
end 

然後,假設每一種定義一個同名模塊,可以將它們收集到一個數組中:

modules = Module[] 
... 
if isdefined(Main, symbol(modn)) 
    push!(modules, getfield(Main, symbol(modn)) 
else 
    warn("importing $modn did not defined a module") 
end 
... 
return modules 
+1

「import X'和'require(」X「)''是否等價的文檔? 'include' vs'require' vs'import' vs'using'是我遇到過的Julia更混亂的一個方面。 – JoshAdel

+1

http://docs.julialang.org/en/release-0.3/stdlib/base/#Base.require。 – tholy

+0

如果您發現本文檔不足以提供幫助,請考慮自行打開問題或編輯文檔(在GitHub的Web瀏覽器中打開相關文件並單擊小鉛筆圖標)。 – tholy

0

我對這個解決方案並不興奮,但它似乎工作。基本上我動態地創建一個包含導入語句的臨時文件,然後我就是include吧。所以:

function test_mimport() 
    module_files = filter(r"^mod[0-9][0-9].jl$", readdir()) 
    path, f = mktemp() 
    for modname in module_files 
     modn = splitext(modname)[1] 
     write(f, "import $modn\n") 
    end 

    close(f) 
    include(path) 
    rm(path) 

end 

我會很好奇,想知道是否有一個更慣用的策略,因爲我是新來的朱莉婭,只是通過其功能絮。

編輯

建立一個臨時文件的策略可能是不必要的,因爲朱還提供了一種方法include_string

在朱莉婭 - 用戶列表,@Isaiah也suggests使用eval(Expr(:import, symbol(modn)))

7

注:請參考user1712368的(傑姆遜納什,朱莉婭DEV)的答案,這discussion朱莉婭用戶郵件列表和朱莉婭manual的這個條目,要知道這是爲什麼正確的答案。

這是多重導入表達式的樣子,使用Julia版本0.3。4:

julia> parse("import Foo, Bar") 
:($(Expr(:toplevel, :($(Expr(:import, :Foo))), :($(Expr(:import, :Bar)))))) 

julia> dump(ans) 
Expr 
    head: Symbol toplevel 
    args: Array(Any,(2,)) 
    1: Expr 
     head: Symbol import 
     args: Array(Any,(1,)) 
     1: Symbol Foo 
     typ: Any 
    2: Expr 
     head: Symbol import 
     args: Array(Any,(1,)) 
     1: Symbol Bar 
     typ: Any 
    typ: Any 

這裏是一個做到這一點編程宏,它需要一個modules說法,可能是一個:call:vcatExprSymbol,其評價爲Vector{Symbol}

julia> macro dynamic_import(modules) 
      (modules = eval(modules))::Vector{Symbol} 
      ex = Expr(:toplevel) 
      for m in modules 
       push!(ex.args, Expr(:import, m)) 
      end 
      return ex 
     end 

您也可以推廣此行:

module_files = filter(r"^mod[0-9][0-9].jl$", readdir()) 

通過抽象成接受一個Regex和作爲參一String目錄路徑,並返回一個Vector{Symbol}功能:

julia> function needed_modules(rx::Regex, dir::String=".") 
      module_files = filter(rx, readdir(dir)) 
      module_syms = map(m -> symbol(split(m, '.')[1]), module_files) 
     end 
needed_modules (generic function with 2 methods) 

所以,你可以使用這樣的:

julia> @dynamic_import [:Mod01, :Mod02] # :vcat expression 

julia> rx = r"^Mod[0-9][0-9].jl$"; 

julia> @dynamic_import needed_modules(rx) # :call expression 

julia> modules = needed_modules(rx) 
2-element Array{Symbol,1}: 
:Mod01 
:Mod02 

julia> @dynamic_import modules # Symbol 

最後你可以將它全部包裝到 module中,因此您可以使用 using DynamicImport

注:目前我得到這個試圖從一個模塊運行相同的例子時:

julia> using DynamicImport 

julia> @dynamic_import [:mod01, :mod02] 

julia> rx = r"^mod[0-9][0-9].jl$"; 

julia> @dynamic_import needed_modules(rx) 
ERROR: rx not defined 

julia> modules = needed_modules(rx) 
2-element Array{Symbol,1}: 
:mod01 
:mod02 

julia> @dynamic_import modules 
ERROR: modules not defined 

但是如果我定義了REPL裏面的物體,它工作正常,我想這是涉及衛生的問題,這是我沒有經歷過的事情,所以我會在julia-users郵件列表中詢問。