组织Julia源代码树的正确方法是什么?

时间:2016-10-25 19:11:27

标签: julia

我正在尝试为Julia应用程序组织源树的正确方法seqscan。现在我有以下树:

$ tree seqscan/
seqscan/
├── LICENSE
├── README.md
├── benchmark
├── doc
├── examples
├── src
│   └── seq.jl
└── test
    └── test_seq.jl

5 directories, 4 files

文件seq.jl包含

module SeqScan
module Seq

export SeqEntry

type SeqEntry
    id
    seq
    scores
    seq_type
end

end
end

test_seq.jl包含:

module TestSeq

using Base.Test
using SeqScan.Seq

@testset "Testing SeqEntry" begin
    @testset "test SeqEntry creation" begin
        seq_entry = SeqEntry("test", "atcg")
        @test seq_entry.id == "test"
        @test seq_entry.seq == "atcg"
    end
end

end

但是,运行测试代码会产生错误:

ERROR: LoadError: ArgumentError: Module SeqScan not found in current path.

即使将JULIA_LOAD_PATH环境变量设置为包含seqscanseqscan/src,我也一定做错了吗?

1 个答案:

答案 0 :(得分:3)

包的名称(本地树的根)需要与src目录下存在的文件的名称相匹配。试试这个:

SeqScan/
    |-- src/
         |-- SeqScan.jl (your seq.jl)

我不知道你为什么把SeqScan中的模块封装起来。如果没有重要的理由这样做,您可以更直接地访问该类型。您可以删除“module Seq”和配对的“end”。然后只需“使用SeqScan”就会引入SeqEntry类型。

所写的类型SeqEntry知道在给定四个字段值时要做什么,每个字段值对应一个字段值。如果要仅使用前两个字段初始化该类型,则需要包含双参数构造函数。例如,假设seq是某种数字类型的向量,而得分也是该数字类型的向量,而seq_type是数字类型:

 function SeqEntry(id, seq)
     seq_type = typeof(seq[1])
     scores   = zeros(seq_type, length(seq))
     return SeqEntry(id, seq, scores, seq_type)
 end   

Julia v0.5的内部模块包的示例。

该包名为MyPackage.jl;它包含两个内部模块:TypeModule和FuncModule;每个模块都有自己的文件:TypeModule.jl和FuncModule.jl。

TypeModule包含一个新类型MyType。 FuncModule包含一个新函数MyFunc,它对MyType的变量[s]进行操作。该函数有两种形式,1-arg和2-arg版本。

MyPackage使用两个内部模块。它将每个用于立即使用并初始化MyType的两个变量。然后MyPackage将MyFunc应用于它们并打印结果。

我认为Julia的包目录是“/you/.julia/v0.5”(Windows:“c:\ you.julia \ v0.5”),并将其称为PkgDir。您可以在Julia的交互式提示符下键入Pkg.dir()来查找真实的包目录。要做的第一件事是确保Julia的内部信息是最新的:> Pkg.update(),然后获得一个特殊的包裹调用PkgDev:> Pkg.add("PkgDev")

您可以在GitHub上启动您的软件包。如果您在本地启动它,则应使用PkgDev,因为它使用正确的结构创建基本包文件(和其他文件): > using PkgDev然后> PkgDev.generate("MyPackage","MIT") 这也创建了一个文件LICENSE.md,其中包含Julia的首选许可证。您可以保留,替换或删除它。

在目录PkgDir / MyPackage / src中,创建一个子目录“internal”。在目录PkgDir / MyPackage / src / internal中,创建两个文件:“TypeModule.jl”和“FuncModule.jl”,这些文件:

TypeModule.jl:

module TypeModule
    export MyType

    type MyType
        value::Int
    end

end # TypeModule

FuncModule.jl:

module FuncModule

    export MyFunc

    #=
     !important!
     TypeModule is included in MyPackage.jl before this module
     This module gets MyType from MyPackage.jl, not directly.
     Getting it directly would create mismatch of module indirection.
    =#
    import ..MyPackage: MyType

    function MyFunc(x::MyType)
        return x.value + 1
    end

    function MyFunc(x::MyType, y::MyType)
        return x.value + y.value + 1 
    end

end # FuncModule

在src目录中,编辑MyPackage.jl以使其匹配:

MyPackage.jl:

module MyPackage

    export MyType, MyFunc

    #=
      !important! Do this before including FuncModule
      because FuncModule.jl imports MyType from here.
      MyType must be in use before including FuncModule.
    =#       
    include( joinpath("internal", "TypeModule.jl") )
    using .TypeModule # prefix the '.' to use an included module

    include( joinpath("internal", "FuncModule.jl") ) 
    using .FuncModule # prefix the '.' to use an included module

    three = MyType(3)
    five  = MyType(5)

    four  = MyFunc(three)
    eight = MyFunc(three, five)

    # show that everything works
    println()
    println( string("MyFunc(three) = ", four) )   
    println( string("MyFunc(three, five)  = ", eight) )   

end # MyPackage

现在,运行Julia进入> using MyPackage应该会显示:

julia> using MyPackage

        4 = MyFunc(three)
        9 = MyFunc(three, five)

julia>