朱莉娅:“导入”和“使用”

时间:2020-10-08 10:24:36

标签: julia

所以我读了茱莉亚的documentation for using and import。但是,这并没有告诉我,我应该如何在实践中使用这两个语句(而且,由于缺乏正交性,这不太容易。)

关键点:让我们在"myfile.jl"中添加以下简单代码:

module MyModule
f() = 1
export f
end
import .MyModule # or: using .MyModule
  • 如果我在最后一行使用import,则f不会导出到Main命名空间。但是,当我更改"myfile.jl"(例如,修改f的返回值)然后重新include时,该函数将被替换(这是我希望的行为)。 (请注意,我可以显式import .MyModule: f,但这会引入不必要的冗余;此外,实际情况将涉及一长串带有长名称的函数。好的,我也可能会编写一个使用{ {1}},但我不知何故应该更简单。)

  • 如果我将names(Main.MyModule)替换为import,则相反:using现在已导出,但是更改模块中的任何内容现在都需要重新启动Julia解释器。

  • 同时使用fimport会将using的第一个版本导出到主命名空间:更新代码时,仅使用第一个返回值。 / p>

所以我的问题不是关于链接页面中记录的语句f()import的行为(如果不是解释),而是关于意图。这些背后。为什么要用两个陈述就足够了?为什么其中之一会忽略所有using指令?在实践中,我应该在哪种情况下使用每个语句?

(版本为1.1.0。此外,它运行在无法轻松访问export的系统上,所以我还没有尝试Pkg。)

2 个答案:

答案 0 :(得分:9)

Julia的约定是使用using PackageName,除非您出于某些特殊原因需要这样做。

此语言设计决策仅出于用户的舒适感。 Julia正在使用多个分派,通常会打包对类型化的参数进行操作的导出功能(但是这些类型通常为abstract类型,因此功能不受限制)。

通过这种设计,实现它们的所有函数和方法都可以在相同的名称空间中,因为它们在特定于其软件包的参数类型上有所不同。因此,using将程序包带到覆盖现有方法实现的名称空间的情况非常少见(然后Julia报告警告)。软件包作者还通过使用export关键字来控制此过程。

我认为这对您来说看起来很奇怪,因为您已经习惯了Python之类的语言。例如,numpy与默认函数具有完全相同的函数名称,并且没有很好的方法来对它们进行不同的命名(例如,尝试思考对于名为sin的函数来说,这将是一个很好的选择): -))。因此,在Python中,您始终需要将函数导入其自己的名称空间,也许使用诸如import numpy as np之类的别名。在使用这两种语言都有数年的经验之后,我会说朱莉娅的做法很自然,而Pytonish的方法很奇怪:-)

关于import以及将单个功能从程序包带到名称空间的可能性,我将其视为解决名称冲突情况的解决方法。如果要将新的方法实现添加到其他程序包中(例如,为+运算符定义新的含义),也需要明确地执行此操作。除此之外,您只需输入using,再也不回头。

答案 1 :(得分:2)

除了Przemyslaw Szufel的答案外,还需要添加一件事。扩展方法时,无需对扩展函数使用import就可以做到这一点。例如,如果我想从模块f扩展Foo,我可以做using Foo,然后为Foo.f定义一个新方法。这是一个完整的示例:

module Foo
    struct A
        x::Int
    end

    f(a::A) = a.x + 1

    export A, f
end

using .Foo

struct B
    x::Int
end

Foo.f(b::B) = b.x + 2

这种方法的优势在于,当您阅读代码时,更容易看到要扩展的函数的来源。