2016-05-14 3 views
3

В C++ вы можете написать:Определить несколько переменных одного типа в одной строке в Джулии?

double x = 0.0, y = 0.0, z = 0.0; 

вместо:

double x = 0.0; double y = 0.0; double z = 0.0; 

определить три переменные одного и того же типа, double в этом примере.

В Джулии, аналогичное бы:

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

Есть ли синтаксический сахар, как и выше для C++, что позволяет мне опустить три спецификаторов типа, заменив их только один, когда все они тоже самое?

Примечание: Я знаю, что могу просто написать

x = y = z = 0.0 

и пусть Джулия определить тип. Это не то, что я хочу. Я хочу прямо указать, что типы x,y,z являются постоянными.

ответ

2

На самом деле, следующий не объявлять их как переменные в Джулии

x::Float64, y::Float64, z::Float64 

По крайней мере, на основе моего исследования, вам нужно что-то больше похоже:

local x::Float64 = zero(Float64) 
local y::Float64 = zero(Float64) 
local z::Float64 = zero(Float64) 

Там нет синтаксической сахар для этого, AFAIK, вызывая определенный тип, не является общим или необходимым в Джулии.

EDIT: Я должен быть яснее, особенно. после комментария @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 

Я уверен, что некоторые Джулиан с большим количеством макро "фу "чем я могу сделать гораздо лучше, но это не похоже на работу, в моем тестировании, а именно:

@dcl(Float64, x, y, z) 

Edit: Ниже показано, что синтаксис не объявлять переменные вообще, только сдерживает типы переменных, взятые из охватывающей области:

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 

мне интересно, если там может быть ошибка здесь, глядя на следующее:

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{} 
+0

Фактически 'x :: Float64', похоже, работает, например. внутри функции. Но я никогда не видел (?) Людей, которые действительно использовали это в реальном коде Юлии. –

+0

Попробуйте то, что у меня было выше в функции, из OP, с тремя переменными «объявлено», разделенными запятыми. Если вы посмотрите результат с помощью '@ code_warntype', вы увидите, что он вообще не выполняет« объявления », он, похоже, рассматривает это как создание кортежа, с типами ограничений значений и ищет значения этих переменных * вне * функции (поэтому добавление «local» важно, если вы действительно хотите объявление). –

+0

ОК, похоже, не делает кортеж, но он все еще не «объявляет» переменную в функции. –

1

Переменные не имеют типов в Джулию. Значения есть типы.

Но вы можете использовать const, чтобы гарантировать, что переменной нельзя присвоить значение другого типа.Вот один из способов, хотя это может быть не самым кратким:

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

Edit: Но вы уверены, что это то, что вы действительно хотите? Джулия - динамически типизированный язык, и то, что вы просите, - это то, что вы обычно делаете на статически типизированном языке.

+1

Хотя то, что вы сказали, верно, переменные все еще могут быть напечатаны. См. 'Function g(); локальный x :: Int; x = 2,0; Икс; end', который возвращает 2, а не 2.0. –

+0

Я думаю, что это не так много, что переменная набирается, а скорее на то, что на нее ставится утверждение типа, которое гарантирует, что всякий раз, когда эта переменная назначается проверенному преобразованию, (что может быть noop, например, присваивание то, что уже известно о том же типе) –

+2

Разве это не сложность и тонкость этого не свидетельствует о том, что это не очень полезный способ думать в Джулии? –

Смежные вопросы