Julia 朱莉娅:“导入”和“使用”的用例`
所以我读了朱莉娅的书。然而,这并没有告诉我应该如何在实践中使用这两个语句(而且,考虑到缺乏正交性,这并不太容易) 举个例子:让我们在Julia 朱莉娅:“导入”和“使用”的用例`,julia,Julia,所以我读了朱莉娅的书。然而,这并没有告诉我应该如何在实践中使用这两个语句(而且,考虑到缺乏正交性,这并不太容易) 举个例子:让我们在“myfile.jl”中放入以下琐碎的代码: 如果在最后一行使用import,则f不会导出到Main命名空间。但是,当我更改“myfile.jl”(例如修改f的返回值)然后重新包含它时,该函数将被替换(这是我希望的行为)。(请注意,我可以显式地导入.MyModule:f,但这会引入不必要的冗余;而且,现实生活中的情况将涉及一长串具有长名称的函数。好的,我也可以编写
“myfile.jl”
中放入以下琐碎的代码:
- 如果在最后一行使用
,则import
不会导出到f
命名空间。但是,当我更改Main
(例如修改“myfile.jl”
的返回值)然后重新包含它时,该函数将被替换(这是我希望的行为)。(请注意,我可以显式地f
,但这会引入不必要的冗余;而且,现实生活中的情况将涉及一长串具有长名称的函数。好的,我也可以编写一个使用导入.MyModule:f
的宏,但我不知何故觉得这应该更简单。)名称(Main.MyModule)
- 如果使用替换
,则情况相反:导入
现在导出,但更改模块中的任何内容都需要重新启动Julia解释器f
- 同时使用
和import
只将using
的第一个版本导出到主命名空间:当我更新代码时,只使用第一个返回值f()
import
和using
这两个语句的行为,它们都记录在链接页面中(如果没有解释的话),而是关于它们背后的意图。一句话就够了,为什么还要说两句?为什么其中一个会忽略所有export
指令?在哪种情况下,我应该在实践中使用每一个语句
(版本是1.1.0。此外,它在没有easy
Pkg
访问权限的系统上运行,因此我还没有尝试Revision
。Julia中的惯例是使用使用PackageName
,除非您有特定的理由这样做
这种语言设计决策仅仅是出于用户的舒适感。Julia使用多个分派,通常包导出对类型化参数进行操作的函数(但这些参数通常是抽象类型,因此函数功能不受限制)
在这种设计中,实现它们的所有函数和方法都可以位于同一名称空间中,因为它们在特定于其包的参数类型上有所不同。因此,使用
将覆盖现有方法实现的包带到命名空间的场景非常罕见(然后Julia报告警告)。此过程由包作者通过使用export
关键字进行额外控制
我认为这对您来说很奇怪,因为您已经习惯了Python之类的语言。例如,numpy
具有与默认函数完全相同的函数名,并且没有好的方法对它们进行不同的命名(例如,尝试想想对于名为sin
:-)的函数,什么是好的替代方法)。因此,在Python中,您总是需要将函数导入到它们自己的名称空间中,可能需要使用一个别名,例如import numpy as np
。在对两种语言都有了几年的经验之后,我想说朱莉娅这样做是很自然的,而Pytonish的方式是很奇怪的:-)
关于import
以及将单个函数从包中引入命名空间的可能性,我将其视为发生名称冲突的情况下的变通方法。如果您想向其他包中添加新的方法实现(比如为+
操作符定义新的含义),那么还需要显式地这样做。除此之外,您只需使用
键入,并且永不回头。除了Przemyslaw Szufel的答案之外,还有一点需要补充。当您扩展一个方法时,可以在不使用所扩展函数的import
的情况下进行扩展。例如,如果我想从模块Foo
扩展f
,我可以使用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
这种方法的优点是,当您阅读代码时,更容易看到您正在扩展的函数的起源。为什么在使用.Foo
的中有一个点?Foo
在Main
的命名空间中声明,而不是在它自己的包中声明using.Foo
是使用Main.Foo
BTW的一个较短版本,在此代码中编写import.Foo
就足够了,尽管在这里使用更自然。如果这个代码在一个包中,我宁愿使用import
。通常在实际代码中,您也希望在没有限制的情况下使用Foo
中的一些函数。换句话说,我通常有这样的代码:在一个部分中,我使用Foo.blah()
而没有限定,即只使用blah()
,然后我需要从Foo
扩展一个函数bar
,然后我扩展限定的形式Foo.bar
@Cameron Bieganek我同意:-)
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