Как подавить возвращаемое значение proc в приглашении tcl
Я относительно новичок в TCL, в приглашении TCL, когда мы вызываем proc с некоторым возвращаемым значением, возвращаемое значение proc возвращается в tcl. Есть ли способ остановить его (не затрагивая путы или аналогичные функции) в качестве примера
bash$ tclsh
% proc a {} { puts "hello"; return 34; }
% a
hello
34
%
Теперь, как я могу подавить 34 прихода на экран? Любая помощь приветствуется.
Обновление: на самом деле proc является частью другого инструмента, раньше у него не было возвращаемого значения, но теперь условно он может возвращать значение. он может быть вызван из скрипта, и проблем не будет (как отметил Брайан). и он может быть вызван из интерактивной подсказки, после чего после всех необходимых выходных данных возвращаемое значение печатается без необходимости. Итак, 1) у меня нет возможности изменить tclshrc пользователя 2) существующие скрипты должны продолжать работать. И кажется странным, что при каждом вызове proc после всех необходимых выходных данных печатается число. Для пользователя это ненужная информация, если он не уловил ценность и не хочет что-то делать. Поэтому я хотел, чтобы значение было доставлено пользователю, но без печати в подсказку / пользовательский интерфейс (надеюсь, мне понятно)
3 ответа
Интерактивный код оболочки в tclsh
а также wish
напечатает любой непустой результат. Чтобы ничего не печатать, вам нужно, чтобы последняя команда в "строке" выдавала пустой результат. Но какую команду использовать?
Многие команды приведут к пустому результату:
if 1 {}
subst ""
format ""
Однако самое короткое, вероятно, это:
list
Таким образом, вы можете написать свой код так:
a;list
Конечно, это действительно становится полезным только тогда, когда ваша команда на самом деле дает большой результат, который вы не хотите видеть. В этих случаях я часто нахожу, что наиболее полезно использовать что-то, что измеряет размер результата, например:
set tmp [something_which_produces a_gigantic result]; string length $tmp
Самые полезные команды, которые я нахожу для этого: string length
, llength
а также dict size
,
Если вам абсолютно не нужно печатать результат команды, вы должны написать свой собственный интерактивный цикл. Есть два способа сделать это, в зависимости от того, работаете ли вы в цикле обработки событий или нет:
Без цикла событий
Эта упрощенная версия просто проверяет, соответствует ли имя команды тому, что набрал пользователь. В противном случае произвольно выбрасывать результаты - не очень хорошая идея!
set accum ""
while {[gets stdin line] >= 0} {
append accum $line "\n"
if {[info complete $accum]} {
if {[catch $accum msg]} {
puts stderr $msg
} elseif {$msg ne "" && ![string match *TheSpecialCommand* $accum]} {
puts $msg
}
set accum ""
}
}
С циклом событий
Это просто обработка блокирующего случая ввода-вывода; это правильно, когда ввод с готового терминала (то есть по умолчанию)
fileevent stdin readable handleInput
set accum ""
proc handleInput {} {
global accum
if {[gets stdin line] < 0} {
exit; # Or whatever
}
append accum $line "\n"
if {[info complete $accum]} {
if {[catch {uplevel "#0" $accum} msg]} {
puts stderr $msg
} elseif {$msg ne "" && ![string match *TheSpecialCommand* $accum]} {
puts $msg
}
set accum ""
}
}
vwait forever; # Assuming you're not in wish or have some other event loop...
Как обнаружить, что команда выполняется
Код выше использует ![string match *TheSpecialCommand* $accum]
решить, следует ли выбрасывать результаты команды, но это очень некрасиво. Более элегантный подход, использующий собственные встроенные хуки Tcl, заключается в использовании трассировки выполнения для определения того, была ли вызвана команда (для краткости я просто покажу здесь версию без цикла обработки событий). Другое преимущество этого заключается в том, что его легко распространить на подавление вывода из нескольких команд: просто добавьте трассировку к каждой из них.
trace add execution TheSpecialCommand enter SuppressOutput
proc SuppressOutput args {
# Important; do not suppress when it is called inside another command
if {[info level] == 1} {
set ::SuppressTheOutput 1
}
}
# Mostly very similar from here on
set accum ""
while {[gets stdin line] >= 0} {
append accum $line "\n"
if {[info complete $accum]} {
set SuppressTheOutput 0; # <<<<<< Note this!
if {[catch $accum msg]} {
puts stderr $msg
} elseif {$msg ne "" && !$SuppressTheOutput} { # <<<<<< Note this!
puts $msg
}
set accum ""
}
}
Чтобы было ясно, я бы никогда не сделал это в своем собственном коде! Я бы просто подавил вывод вручную, если бы он имел значение.
Вы можете сделать пустую процедуру в.tclshrc...
proc void {} {}
... и когда вам не нужно возвращаемое значение, завершите строку ;void
,
Используйте переменную tcl_interactive, чтобы включить возврат значения, хотя я не уверен, где это было бы полезно...
proc a {} {
puts "hello"
if { [info exist tcl_interactive] } {
return {};
} else {
return 34;
}
}