首页 文章

带有前导下划线的函数名称

提问于
浏览
0

在我的代码中,出于某些目的,我使用带有前导下划线的函数名称,例如 _foo() ,但是想知道这是否可能产生副作用,例如干扰从基本库导出的函数 . 例如,我看到错误消息

ERROR: LoadError: ...
Stacktrace:
 [1] _printf(::String, ::Expr, ::String, ::Tuple{Symbol,Expr,Symbol,Expr}) at ./printf.jl:1209
 ...
 [7] _start() at ./client.jl:432

虽然我猜这些是库中的内部函数(未导出),但是对于用户定义的函数使用这样的前导下划线是否安全(至少在仅使用标准库时)?

1 回答

  • 2

    通常,以下划线开头的名称用于内部函数或变量,但这只是一种风格约定 . 在您自己的代码中使用它们是安全的,除了以下规则:

    仅由 ___ 等下划线组成的名称用作黑洞(您可以写入它们,但不能从它们读取) .

    通常,不会导出具有前导 _ 的名称 . Base中的一个例外是 __precompile__ 函数 .

    下面我给出一个更一般的评论,但与你的要求和我的经验有关,值得了解 .

    函数和变量名称在模块范围中定义,这意味着如果您创建自己的模块,您可以在另一个模块中使用与同一名称冲突的名称,这不会有问题(无论您是否具有前导下划线)是不是) . 您只需要对该名称进行限定:

    julia> module MyModule
           export sin
           sin(x) = "sin($x)"
           end
    Main.MyModule
    
    julia> using .MyModule
    
    julia> sin(1)
    WARNING: both MyModule and Base export "sin"; uses of it in module Main must be qualified
    ERROR: UndefVarError: sin not defined
    Stacktrace:
     [1] top-level scope at none:0
    
    julia> Base.sin(1)
    0.8414709848078965
    
    julia> MyModule.sin(1)
    "sin(1)"
    

    唯一通常棘手的极端情况是,只有当该名称未从其他模块导入并被引用时,才允许您在模块中定义自己的函数名称(特别是在 Main 模块中) . 这是一个例子:

    julia> sin(x) = "sin($x)"
    sin (generic function with 1 method)
    
    julia> sin(10)
    "sin(10)"
    
    julia> cos(10)
    -0.8390715290764524
    
    julia> cos(x) = "cos($x)"
    ERROR: error in method definition: function Base.cos must be explicitly imported to be extended
    Stacktrace:
     [1] top-level scope at none:0
    

    这里 sincos 都是从 Base 导入的 . 您在使用它之前在模块 Main 中定义了 sin ,因此它没问题 . 但是,在尝试定义之前,您使用了 cos 来自 Base ,因此这是一个错误 .

相关问题