Tcl/Tk: использование массива с выражением

У меня возникают проблемы при попытке доступа к array внутри expr. Ниже показан код, который воспроизводит ошибку, адаптированный из ответа Донала Феллоуза на мой -a-cross-between-radiobutton-and/6799235#6799235">предыдущий вопрос.

namespace eval Ns {
}

proc Ns::main_routine {} {
  global cb

  array set cb {
    c1 0
    c2 0
    c3 0
    c4 0
  }

  checkbutton .c1 -text "C1" -variable     cb(c1)
  checkbutton .c2 -text "C2" -variable     cb(c2)
  checkbutton .c3 -text "C3" -variable     cb(c3)
  checkbutton .c4 -text "C4" -variable     cb(c4)

  grid .c1 -sticky w
  grid .c2 -sticky w
  grid .c3 -sticky w
  grid .c4 -sticky w

  # _After_ initializing the state...
  trace add variable cb(c1) write Ns::reconfigureButtons
  trace add variable cb(c2) write Ns::reconfigureButtons
  trace add variable cb(c3) write Ns::reconfigureButtons
  trace add variable cb(c4) write Ns::reconfigureButtons
}

proc Ns::reconfigureButtons args {
  global cb

  # this one works
  set state "normal"
  if { $cb(c1) } {
    set state "disabled"
  }
  .c2 configure -state $state

  # this one does not
  #.c2 configure -state [expr $cb(c1) ? "disabled" : "normal"]
  #.c4 configure -state [expr $cb(c1)||$cb(c3) ? "disabled" : "normal"]
}

Ns::main_routine

Я хочу исправить следующую строку в приведенном выше коде

.c2 configure -state [expr $cb(c1) ? "disabled" : "normal"]

Когда я использую указанную выше строку, я получаю следующую ошибку:

can't set "cb(c1)": invalid bareword "disabled" in expression "1? disabled : normal";


person Anand    schedule 10.08.2011    source источник


Ответы (2)


Вы всегда должны ставить {скобки} вокруг выражений, так как это останавливает двойную замену, оставляя "кавычки" для выполнения их надлежащей цели. Вы также повышаете безопасность и скорость своего кода, делая это, и это делалось, по крайней мере, начиная с Tcl 8.0 (более десяти лет назад); до этого из соображений производительности многие люди опускали фигурные скобки, но это была поистине ужасная привычка.

Короче говоря, не используйте:

.c2 configure -state [expr  $cb(c1) ? "disabled" : "normal" ]

Но лучше используйте это:

.c2 configure -state [expr {$cb(c1) ? "disabled" : "normal"}]
person Donal Fellows    schedule 10.08.2011

Вы пробовали .c2 configure -state [expr {$cb(c1) ? "disabled" : "normal"}]

person Sander van Knippenberg    schedule 10.08.2011
comment
хотя этот ответ намекает на решение, было бы намного лучше (и, возможно, получить больше голосов), если бы вы объяснили, почему ваше решение работает. - person Bryan Oakley; 10.08.2011
comment
Ты прав, @Bryan Oakley. Сделаю это в следующий раз. Это прекрасно объяснил Донал Феллоуз. Это необходимо для того, чтобы последняя часть выполнялась первой, прежде чем к ней будет применено expr. - person Sander van Knippenberg; 11.08.2011