在Julia中的一行中定义多个相同类型的变量? 在C++中你可以写: double x = 0.0, y = 0.0, z = 0.0;

在Julia中的一行中定义多个相同类型的变量? 在C++中你可以写: double x = 0.0, y = 0.0, z = 0.0;,julia,Julia,而不是: double x = 0.0; double y = 0.0; double z = 0.0; 要定义三个相同类型的变量,请在本例中选择double 在Julia中,类似的例子是: x::Float64 = 0.0, y::Float64 = 0.0, z::Float64 = 0.0 是否有一个语法糖,如上面的C++,允许我省略三个类型说明符,当它们全部相同时,用一个替换它们, 注意:我知道我会写 x = y = z = 0.0 让茱莉亚来推断类型。这不是我想要的。我想明确地说

而不是:

double x = 0.0; double y = 0.0; double z = 0.0;
要定义三个相同类型的变量,请在本例中选择double

在Julia中,类似的例子是:

x::Float64 = 0.0, y::Float64 = 0.0, z::Float64 = 0.0

是否有一个语法糖,如上面的C++,允许我省略三个类型说明符,当它们全部相同时,用一个替换它们,

注意:我知道我会写

x = y = z = 0.0

让茱莉亚来推断类型。这不是我想要的。我想明确地说,
x,y,z的类型是常量。

实际上,下面没有将它们声明为Julia中的变量

x::Float64, y::Float64, z::Float64
至少根据我的调查,你需要更像:

local x::Float64 = zero(Float64)
local y::Float64 = zero(Float64)
local z::Float64 = zero(Float64)
这样做没有语法上的甜头,好吧,在Julia中强制特定类型不是那么常见或必要

编辑:我应该更清楚,特别是在下面的@dpsanders评论之后,我觉得这不是Julia通常应该做的事情,即使类型断言在有限的情况下出于性能原因可能有用,如果你想用语法糖或宏来缩短代码,那么频繁地使用它们似乎是过早的优化

如果您真的很想这样做,您可以编写一个宏来处理它,如下所示:

macro dcl(T, args...)
    r = quote end
    for var in args
        push!(r.args, :( local $(esc(var))::$T = zero($T)) )
    end
    r
end
julia> function testdcl()
           println(y)
           x::Float64, y::String
           x = 1
           println(x)
       end
testdcl (generic function with 1 method)

julia> y = 1.234
1.234

julia> testdcl()
1.234
ERROR: UndefVarError: x not defined
 in testdcl() at ./REPL[131]:2
 in eval(::Module, ::Any) at ./boot.jl:226

julia> @code_warntype testdcl()
Variables:
  #self#::#testdcl
  x::Union{}

Body:
  begin  # REPL[131], line 1:
      (Main.println)(Main.y)::Any # REPL[131], line 2:
      (Core.tuple)((Core.typeassert)(x::Union{},Main.Float64)::Union{},(Core.typeassert)(Main.y,Main.String)::String)::Union{}
  end::Union{}
我相信一些朱利安的宏“fu”比我多,可以做得更好,但在我的测试中,它似乎确实有效,即:

@dcl(Float64, x, y, z)
编辑:以下内容说明语法根本没有声明任何变量,只是约束从封闭范围中获取的变量类型:

julia> function testdecl()
           x::Float64, y::Int, z::String
           println(x, y, z)
       end
testdecl (generic function with 1 method)

julia> @code_warntype testdecl()
Variables:
  #self#::#testdecl

Body:
  begin  # REPL[107], line 2:
      (Core.typeassert)(Main.x,Main.Float64)::Float64
      (Core.typeassert)(Main.y,Main.Int)::Int64
      (Core.typeassert)(Main.z,Main.String)::String # REPL[107], line 4:
      return (Main.println)(Main.x,Main.y,Main.z)::Any
  end::Any
我想知道这里是否也有bug,请查看以下内容:

macro dcl(T, args...)
    r = quote end
    for var in args
        push!(r.args, :( local $(esc(var))::$T = zero($T)) )
    end
    r
end
julia> function testdcl()
           println(y)
           x::Float64, y::String
           x = 1
           println(x)
       end
testdcl (generic function with 1 method)

julia> y = 1.234
1.234

julia> testdcl()
1.234
ERROR: UndefVarError: x not defined
 in testdcl() at ./REPL[131]:2
 in eval(::Module, ::Any) at ./boot.jl:226

julia> @code_warntype testdcl()
Variables:
  #self#::#testdcl
  x::Union{}

Body:
  begin  # REPL[131], line 1:
      (Main.println)(Main.y)::Any # REPL[131], line 2:
      (Core.tuple)((Core.typeassert)(x::Union{},Main.Float64)::Union{},(Core.typeassert)(Main.y,Main.String)::String)::Union{}
  end::Union{}

变量在Julia中没有类型。值具有类型

但是您可以使用
const
来确保不能为变量分配不同类型的值。这里有一种方法,尽管它可能不是最简洁的:

const a, b, c = (zeros(Float64, 3)...)

编辑:但你确定这是你真正想要的吗?Julia是一种动态类型语言,您所要求的是您通常在静态类型语言中执行的操作。

实际上
x::Float64
似乎确实有效,例如在函数内部。但是我从来没有见过人们在真正的Julia代码中实际使用这种东西。试着用我上面在函数中的内容,从OP开始,用3个变量“声明”,用逗号分隔。如果您使用
@code\u warntype
查看结果,您将看到它根本没有执行“声明”,它似乎将其视为创建一个元组,值的类型受到约束,并在函数之外查找这些变量的值(这就是为什么添加
local
非常重要,如果您真的想要声明的话)。好的,它似乎不是在创建元组,但它仍然没有在函数中“声明”变量。尝试使用分号而不是逗号?这使得类型断言可以工作(当您尝试
@code\u warntype
时,您确实会得到
x::Float64
),但同样,它们不是任何类型的声明,变量的范围由Julia非常困难的“软作用域”规则决定。虽然您所说的是正确的,但变量仍然可以键入。请参见
function g();local x::Int;x=2.0;x;end
,它返回2,而不是2.0。我认为这并不是说变量是类型化的,而是在其上放置了一个类型断言,这确保了每当将该变量分配给选中的转换时都会完成(可能是noop,例如,分配已知为同一类型的对象)这一点的困难和微妙之处难道不表明它在Julia中不是一种有用的思考方式吗?我认为类型断言在某些情况下出于性能原因是有用的,当您可能希望从一个类型不稳定的函数中为变量赋值时。