Существует ли define/paramter(такой же, как в языке verilog) в скрипте TCL?

#tcl

#tcl

Вопрос:

Есть ли какая-либо команда в TCL, которая совпадает с #define параметром or в C? Я хочу сократить свой код в скрипте с помощью define, как показано ниже:

 lappend links [lindex $all_list $i] $j $k 0
 

-> эта команда используется много раз в моем скрипте.
Как мне определить его define lap_lk lappend links [lindex $all_list $i] $j $k 0 как verilog и использовать его в скрипте TCL с помощью короткой команды lap_lk ?

Большое вам спасибо :).

Комментарии:

1. Откуда берутся i, j и k? Что вы хотите сделать, чего не может сделать процедура?

Ответ №1:

Tcl не совсем такой, как в C (или других языках, использующих этот препроцессор). Однако вы можете создавать процедуры, которые имеют желаемые эффекты. Тип процедуры, которую вы хотите создать, зависит от того, передаете ли вы какие-либо аргументы.

Простой, без параметров

В простейшем случае, без аргументов, вы можете просто использовать uplevel внутри процедуры для запуска некоторого кода в контексте вызывающего:

 proc lap_lk {} {
    uplevel 1 {
        lappend links [lindex $all_list $i] $j $k 0
    }
}
 

Код внутри uplevel ( 1 необязательный, но я рекомендую его для наглядности) просто выполняется так, как если бы он выполнялся вместо вызова lap_lk ; он использует переменные, которые видны вызывающему.

С параметрами

Однако, если вы принимаете аргументы, все становится сложнее. Давайте предположим, что вы вводите индекс в $all_list , $i , и части $j и $k , и давайте предположим, что они не слишком ужасны…

 # Using A B C to make it clear that these are different things
proc lap_lk {A B C} {
    uplevel 1 [subst {
        lappend links [lindex $all_list $A] [list $B] [list $C] 0
    }]
}
 

Ключевым моментом здесь является то, что я использую subst для ввода чего-либо в скрипт (вместо этого я мог бы также использовать двойные кавычки вокруг скрипта), и я использую list , чтобы точно добавлять кавычки $B и $C делать их безопасными для подстановки; Я действительно должен это сделать, за $A исключением того, что индексы обычно являются заменой-в любом случае безопасно. Затем вы бы вызвали код следующим образом:

 lap_lk $i $j $k
 

К Дао Tcl

Однако в более сложном случае (например, когда требуется нетривиальный цикл) вы будете использовать uplevel и upvar делать что-то более тонкое. Вот где вы почти полностью выходите за рамки того, что может элегантно выполнять препроцессор C. (Использование целевого уровня, отличного от 1 того, где вы полностью выходите за рамки возможностей препроцессора.) В этом случае использование upvar позволяет нам полностью избежать использования uplevel .

 proc lap_lk {targetList sourceList A B C} {
    upvar 1 $targetList tgt $sourceList src
    lappend tgt [lindex $src $A] $B $C 0
}
 
 # Calling pattern
lap_lk links all_list $i $j $k
 

Рекомендуется, если вы работаете таким образом, передавать имена всех (соответствующих) локальных переменных в качестве аргументов, а не жестко кодировать контекст. Обычно считается хорошей практикой делать процедуры как можно более независимыми от контекста их вызова. Конечно, это не всегда возможно.

Изменение приведенного выше кода для работы без передачи явных аргументов (путем жесткого кодирования имен переменных) оставлено в качестве упражнения.