是否有理由把@static放在if VERSION语句之前?



例如在前面:

@static if v"0.2" <= VERSION < v"0.3-"
    # do something specific to 0.2 release series
end

@static是必要的吗?

除了@DVNold的回答,这里有更多的解释…

首先,两者的区别:

  • if在全局作用域中,条件和选择的分支都在代码运行时计算;
  • @static if在解析代码时(在宏展开期间)计算条件,并被条件选择的分支的代码替换-宏展开后不留下if

在顶级全局作用域中,这两者之间没有太大的区别,因为求值只发生一次,就在代码被解析、宏展开和降低之后。但是,在某些情况下,您不能在语法上放置if表达式。一个很好的例子是,如果您希望结构中字段的存在或不存在以某些东西为条件:

have_baz_field = rand(Bool)
struct Foo
    bar::Int
    @static if have_baz_field
        baz::Int
    end
end

下面是这段代码的两种不同的求值:

julia> have_baz_field = rand(Bool)
false
julia> struct Foo
           bar::Int
           @static if have_baz_field
               baz::Int
           end
       end
julia> fieldnames(Foo)
(:bar,)
julia> have_baz_field = rand(Bool)
true
julia> struct Foo
           bar::Int
           @static if have_baz_field
               baz::Int
           end
       end
julia> fieldnames(Foo)
(:bar, :baz)

当然,随机有或没有字段并不是很有用;在实践中,您可能希望有一个更有意义的条件来决定是否有字段,可能是基于您在尝试匹配C结构体布局时所处的平台。

在局部作用域中,if@static if之间的差异更大,因为代码可以多次求值,而只解析一次。由于条件是在解析时在表达式出现的全局作用域中求值的,因此@static if表单不能访问任何局部变量,因为在展开宏时它们不存在。另一方面,如果非静态if的条件仅基于全局常量,则编译器很有可能可以预测条件的值,因此仍然可能没有任何有效的区别,因为编译器将消除除taken分支之外的所有代码。然而,如果你想确保这在解析/编译时发生,那么你可以使用@static if来强制它。

希望这能澄清两者的区别。简而言之,您很少需要@static if,因为它通常在顶级作用域中甚至在局部作用域中都是等效的,在可以使用@static if的情况下,编译器可能已经做了等效的工作。在一些情况下,全局作用域中需要@static if,因为分支在语法上是不允许的。在局部作用域中,通常不需要这样做,但可能希望确实确保在运行时不计算条件。在大多数代码中,不需要@static if。例如,在问题中给出的示例中,我个人只使用if并省略@static,因为表达式出现在顶层,并且条件只以任何方式计算一次。

是的,在某些上下文中不允许使用if语句,但是可以使用宏,或者不能在if语句中定义结构体。在函数内部,这可能通常是不必要的,但有时您希望绝对确保消除if语句。

最新更新