Julia预定义函数

Julia预定义函数,julia,Julia,我目前正在通过命令行会话在Julia上编程 我知道Julia中的预定义函数(例如sqrt)可以具有可变值,但在特定会话中,我尝试将该函数用作sqrt(25),它给了我5.0,但在同一会话中,当我编写sqrt=9时,它说 “错误:无法从主模块分配变量Base.sqrt” 如果我必须实现这一点,我必须重新打开一个新会话,并为sqrtsqrt=9指定一个变量值,当我这样做时,它会再次显示 ERROR:MethodError:Int64类型的对象不可调用 当我尝试使用sqrt作为函数时 同样的事情也发生

我目前正在通过命令行会话在Julia上编程

我知道Julia中的预定义函数(例如sqrt)可以具有可变值,但在特定会话中,我尝试将该函数用作
sqrt(25)
,它给了我
5.0
,但在同一会话中,当我编写
sqrt=9
时,它说

错误:无法从主模块分配变量Base.sqrt

如果我必须实现这一点,我必须重新打开一个新会话,并为sqrt
sqrt=9指定一个变量值,当我这样做时,它会再次显示

ERROR:MethodError:Int64类型的对象不可调用

当我尝试使用sqrt作为函数时


同样的事情也发生在
pi

你要问的话题有点棘手。虽然我同意委员会的一般建议,但有时并不那么明显

您的问题可以分解为两个问题:

ERROR:MethodError:Int64类型的对象不可调用

我想,这一点非常清楚,如果您有其他编程语言的经验,这一点应该是意料之中的。这种情况是,当前范围中的name
sqrt
绑定到value
9
,类型为
Int64
的对象不可调用

另一个错误

“错误:无法从主模块分配变量Base.sqrt”

更复杂,可能不明显。在调用或引用
sqrt
函数之前,您可以在当前范围内为自己的变量自由使用name
sqrt
。只有在这些操作之后,
sqrt
的绑定才会在当前范围内得到解决(只是最近一些与何时解决绑定相关的死角错误才得到修复)。从现在起,您不允许更改
sqrt
的值,因为Julia不允许为从其他模块导入的变量赋值

Julia手册中的相关段落如下():

语句
使用Lib
意味着名为
Lib
的模块将可用于根据需要解析名称。当遇到在当前模块中没有定义的全局变量时,系统将在
Lib
导出的变量中搜索该全局变量,如果找到该全局变量,则将其导入。这意味着当前模块中对该全局变量的所有使用将解析为
Lib
中该变量的定义

通过
使用
导入
使变量可见后,模块可能无法使用相同的名称创建自己的变量。导入的变量是只读的;分配给全局变量始终会影响当前模块拥有的变量,否则会引发错误

为了更好地理解这些规则的含义,我认为最好用一个例子来说明:

julia> module A
       export x, y
       x = 10
       y = 100
       end
Main.A

julia> using .A

julia> x = 1000
1000

julia> y
100

julia> y = 1000
ERROR: cannot assign variable A.y from module Main
另一方面,通过显式调用
import
而不是使用
可以立即解析绑定:

julia> module A
       export x, y
       x = 10
       y = 100
       end
Main.A

julia> import .A: x, y

julia> x = 1000
ERROR: cannot assign variable A.x from module Main
您可以看到,它不是特定于
Base
或函数的东西,而是任何模块和任何变量。实际上,在实践中可能会遇到这个问题,因为很明显,
sqrt
是一个预定义的函数,但是像
SOME\u CONSTANT
这样的东西可能会也可能不会由您使用
on调用的
模块定义和导出,并且在您第一次在全局范围内分配
SOME\u CONSTANT
时和您第一次读取
SOME\u CONSTANT
时,Julia代码的行为会有所不同


最后,有一种特殊情况,当您想向另一个模块中定义的函数添加方法时-这是允许的还是不允许的,这取决于您在当前范围中如何引入名称,您可以阅读详细信息,在这种情况下,规则是什么。

Bogumił的回答是正确的,但我认为可以更简洁地描述它

Julia—与大多数编程语言一样—允许您使用与内置内容相同的名称定义自己的变量(或者更一般地说,由
使用
包提供)。这是一件很棒的事情,因为如果不是这样,你就必须对Julia及其软件包提供的数百个名字指手画脚

不过,有两个陷阱:

  • 一旦使用了内置名称或任何包中的名称,就不能再使用相同的名称(在相同的范围内)定义自己的变量。这就是
    错误:无法从模块Main分配变量Base.sqrt
    :您已经使用了
    sqrt(4)
    ,现在正在尝试定义
    sqrt=2
    。解决办法?只需为变量使用不同的名称即可
  • 您可以使用与内置名称相同的名称来定义自己的变量,如果您还没有使用任何包中的名称,则可以使用该名称来定义自己的变量,但随后它将接受您给定的定义。
    ERROR:MethodError:Int64类型的对象是不可调用的
    :您定义了类似于
    sqrt=2
    的内容,然后尝试使用
    sqrt(4)
    。解决办法?您仍然可以通过使用其他定义的模块名对其进行限定来引用该定义。在这种情况下,
    sqrt
    Base
    提供,因此您仍然可以调用
    Base.sqrt
    。您甚至可以重新分配
    sqrt=Base.sqrt
    ,以恢复其原始定义

通过这种方式,
Base
和您正在使用的
其他包提供的名称有点像薛定谔猫:它们处于这种状态,但在您对它们做一些操作之前,它们并不是真正的状态。如果先看它们,它们就存在,但如果先定义自己的变量,它们就不存在。

我真的不理解这个问题。你所描述的似乎是预期的行为。如果要避免这种情况,请使用Base.sqrt,而不是使用sqrt或