Изменение значений глобальных переменных не обновляется сразу?

В следующем коде я попытался изменить все глобальные переменные (_1 _, _ 2 _, _ 3 _, _ 4_) из функции test(). Поскольку u и v находятся внутри модуля, Mod.u и Mod.v являются переменными только для чтения, поэтому я попытался изменить их значения с помощью функций установки (set_u и set_v).

s = 1
const t = 2

module Mod
u = 3
const v = 4

set_u( u_ ) = ( global u ; u = u_ )
set_v( v_ ) = ( global v ; v = v_ )
end

function test()
    global s, t

    s = "S" ; t = 200
    @show s, t

    Mod.set_u( "U" ) ; Mod.set_v( 400 )
    @show Mod.u, Mod.v
end

test()
@show s, t
@show Mod.u, Mod.v

Результат (полученный с Julia v0.4.0):

WARNING: redefining constant t
(s,t) = ("S",2)                          # (1)
WARNING: redefining constant v
(Mod.u,Mod.v) = ("U",4)                  # (2)
(s,t) = ("S",200)                        # (3)
(Mod.u,Mod.v) = ("U",400)                # (4)

Здесь (3) и (4) - мои ожидаемые результаты (при условии, что const исправляет только тип переменных). Но я не могу понять, почему значения t и Mod.v не обновляются в (1) и (2). Я делаю большую ошибку или недопонимаю насчет изменения значения глобальных переменных ...? Или это из-за какого-то другого механизма обращения к глобальным переменным изнутри или вне функции?


person roygvib    schedule 18.10.2015    source источник


Ответы (1)


Единственные константы, которые не обновляются в теле функции, - это те, которые вы пометили const.

(при условии, что const исправляет только тип переменных)

Это предположение неверно. Хотя Джулия позволяет вам изменять значения const привязок, переопределение const переменных определенно может вызвать проблемы. Обратите внимание: это предупреждение о том, что это плохая идея.

Вот простой пример, демонстрирующий, что происходит:

julia> const t = 3
       f() = t
f (generic function with 1 method)

julia> @code_llvm f()

define i64 @julia_f_21636() {
top:
  ret i64 3
}

julia> t = 4
       @code_llvm f()
WARNING: redefining constant t

define i64 @julia_f_21636() {
top:
  ret i64 3
}

Вам не нужно быть очень опытным в чтении LLVM IR, чтобы увидеть, что он возвращает целое число 3 и не выполняет поиск. Он увидел, что t был помечен как константа, и использовал эту информацию для оптимизации при компиляции функции. Нарушение const и изменение значения t не приведет к перекомпиляции f, поэтому возвращается старое значение. LLVM сложнее для непостоянного глобального, но все же очень читабельно. Вы можете видеть, что он откуда-то загружает значение:

julia> s = 2
       g() = s
       @code_llvm g()

define %jl_value_t* @julia_g_21649() {
top:
  %0 = load %jl_value_t** inttoptr (i64 4417498392 to %jl_value_t**), align 8
  ret %jl_value_t* %0
}

Вкратце: если вы лжете о const -ности ваших переменных, вы не должны удивляться, когда Джулия даст вам старый ответ.

person mbauman    schedule 18.10.2015
comment
Ах, хорошо, теперь я понимаю ... Я всегда предполагал, что const исправляет только тип переменных (потому что он позволяет изменять значения), но это кажется опасным, потому что компиляция кода использует предполагаемую константу ... Я пытался использовать глобальные переменные const в модулях Julia в качестве изменяемых параметров при моделировании (следуя популярному способу в модулях Fortran), но это кажется не очень хорошей идеей. Спасибо большое :) - person roygvib; 19.10.2015
comment
Только что протестировал использование const t=[3] в качестве практического обходного пути для оптимизации LLVM. информация о типе сохраняется: typeof(t[1])==Int64 и содержимое может быть изменено. Опять же, это обходной путь, но он работает. - person Dan Getz; 19.10.2015
comment
@ user3580870 Привет, я только что подтвердил, что ваш подход работает. Кроме того, похоже, что можно использовать тот же трюк для константных, глобальных составных типов (т.е. Any не распространяется, пока его поля все еще изменяемы). Так что такой глобальный тип const может быть полезен для моей цели ... Но я также постараюсь подумать о более юлианских способах хранения параметров, а не просто о переводе с других языков. Спасибо :) - person roygvib; 20.10.2015