Spec-Zone.ru › Tcl/Tk

namespace

NAME
namespace — создание и управление контекстами для команд и переменных
SYNOPSIS
DESCRIPTION
namespace children ?namespace? ?pattern?
namespace code script
namespace current
namespace delete ?namespace namespace ...?
namespace ensemble subcommand ?arg ...?
namespace eval namespace arg ?arg ...?
namespace exists namespace
namespace export ?-clear? ?pattern pattern ...?
namespace forget ?pattern pattern ...?
namespace import ?-force? ?pattern pattern ...?
namespace inscope namespace script ?arg ...?
namespace origin command
namespace parent ?namespace?
namespace path ?namespaceList?
namespace qualifiers string
namespace tail string
namespace upvar namespace ?otherVar myVar ...?
namespace unknown ?script?
namespace which ?-command? ?-variable? name
ЧТО ТАКОЕ ПРОСТРАНСТВО ИМЕН?
КВАЛИФИЦИРОВАННЫЕ ИМЕНА
РАЗРЕШЕНИЕ ИМЕН
ИМПОРТ КОМАНД
ЭКСПОРТ КОМАНД
ОГРАНИЧЕННЫЕ СКРИПТЫ
АНСАМБЛИ
namespace ensemble create ?option value ...?
namespace ensemble configure command ?option? ?value ...?
namespace ensemble exists command
ПАРАМЕТРЫ АНСАМБЛЯ
-map
-parameters
-prefixes
-subcommands
-unknown
-command
-namespace
ПОВЕДЕНИЕ ОБРАБОТЧИКА НЕИЗВЕСТНЫХ
ПРИМЕРЫ
СМОТРИТЕ ТАКЖЕ
КЛЮЧЕВЫЕ СЛОВА

Имя

namespace — создание и управление контекстами для команд и переменных

Синтаксис

namespace ?подкоманда? ?арг ...?

Описание

Команда namespace позволяет создавать, получать доступ к и уничтожать отдельные контексты для команд и переменных. Подробное описание пространств имен см. в разделе ЧТО ТАКОЕ ПРОСТРАНСТВО ИМЕН? ниже. Допустимые значения для подкоманда перечислены ниже. Обратите внимание, что вы можете сократить подкоманды.
пространство имён children ?пространство имён? ?шаблон?
Возвращает список всех дочерних пространств имён, которые принадлежат пространству имён пространство имён. Если пространство имён не указано, то возвращаются дочерние элементы для текущего пространства имён. Эта команда возвращает полные имена, которые начинаются с двойного двоеточия (::). Если необязательный шаблон задан, то эта команда возвращает только имена, соответствующие шаблону в стиле glob. Фактически используемый шаблон определяется следующим образом: шаблон, начинающийся с двойного двоеточия (::), используется напрямую, в противном случае пространство имён пространство имён (или полное имя текущего пространства имён) добавляется в начало шаблона.
пространство имён code скрипт
Захватывает текущий контекст пространства имён для последующего выполнения скрипта скрипт. Он возвращает новый скрипт, в котором скрипт обернут в команду пространство имён inscope. Новый скрипт имеет два важных свойства. Во-первых, его можно оценить в любом пространстве имён, и это приведет к оценке скрипта в текущем пространстве имён (в том, где была вызвана команда пространство имён code). Во-вторых, к результатному скрипту можно добавить дополнительные аргументы, и они будут переданы скрипту в качестве дополнительных аргументов. Например, предположим, что команда set script [пространство имён code {foo bar}] вызвана в пространстве имён ::a::b. Тогда eval $script [list x y] можно выполнить в любом пространстве имён (предполагая, что значение script было корректно передано) и это будет иметь тот же эффект, что и команда ::namespace eval ::a::b {foo bar x y}. Эта команда необходима, потому что расширения, такие как Tk, обычно выполняют скрипты обратного вызова в глобальном пространстве имён. Команда с областью действия захватывает команду вместе с её контекстом пространства имён таким образом, что её можно выполнить позднее. См. раздел СКРИПТЫ С ОБЛАСТЬЮ ДЕЙСТВИЯ для некоторых примеров использования этого для создания скриптов обратного вызова.
пространство имён current
Возвращает полное имя для текущего пространства имён. Фактическое имя глобального пространства имён — «» (т.е. пустая строка), но эта команда возвращает :: для глобального пространства имён для удобства программистов.
пространство имён delete ?пространство имён пространство имён ...?
Каждое пространство имён пространство имён удаляется, и все переменные, процедуры и дочерние пространства имён, содержащиеся в пространстве имён, удаляются. Если процедура выполняется внутри пространства имён, пространство имён будет сохранено до возврата процедуры; однако пространство имён помечается для предотвращения поиска его по имени другим кодом. Если пространство имён не существует, эта команда возвращает ошибку. Если имена пространств имён не указаны, эта команда ничего не делает.
пространство имён ensemble подкоманда ?арг ...?
Создаёт и управляет командой, которая формируется из набора подкоманд. Подробнее см. раздел НАБОРАМИ ниже.
пространство имён eval пространство имён arg ?arg ...?
Активирует пространство имён под названием пространство имён и выполняет код в этом контексте. Если пространство имён ещё не существует, оно создаётся. Если указано более одного аргумента arg, аргументы объединяются вместе с пробелом между каждым из них так же, как и в команде eval, и результат оценивается.

Если пространство имён имеет ведущие квалификаторы пространства имён и какие-либо ведущие пространства имён не существуют, они автоматически создаются.

пространство имён exists пространство имён
Возвращает 1, если пространство имён является допустимым пространством имён в текущем контексте, возвращает 0 в противном случае.
пространство имён export ?-clear? ?шаблон шаблон ...?
Указывает, какие команды экспортируются из пространства имён. Экспортированные команды — это те, которые могут быть импортированы в другое пространство имён с помощью команды пространство имён import. Экспортироваться могут как команды, определённые в пространстве имён, так и команды, которые были импортированы в это пространство ранее. Команды не обязательно должны быть определены в момент выполнения команды пространство имён export. Каждый шаблон может содержать специальные символы в стиле glob, но он не может содержать никаких квалификаторов пространства имён. То есть, шаблон может указывать только команды в текущем (экспортирующем) пространстве имён. Каждый шаблон добавляется в список шаблонов экспорта пространства имён. Если задан флаг -clear, список шаблонов экспорта пространства имён сбрасывается в пустое значение перед добавлением любых аргументов шаблон. Если не указаны шаблоны и флаг -clear не задан, эта команда возвращает текущий список экспорта пространства имён.
пространство имён forget ?шаблон шаблон ...?
Удаляет ранее импортированные команды из пространства имён. Каждый шаблон — это простое или квалифицированное имя, такое как x, foo::x или a::b::p*. Квалифицированные имена содержат двойные двоеточия (::) и квалифицируют имя с именем одного или нескольких пространств имён. Каждый «квалифицированный шаблон» квалифицируется именем экспортирующего пространства имён и может иметь специальные символы в стиле glob в имени команды в конце квалифицированного имени. Символы glob не могут появляться в имени пространства имён. Для каждого «простого шаблона» эта команда удаляет соответствующие команды текущего пространства имён, которые были импортированы из другого пространства имён. Для «квалифицированных шаблонов» эта команда сначала находит соответствующие экспортированные команды. Затем она проверяет, были ли какие-либо из этих команд ранее импортированы текущим пространством имён. Если это так, эта команда удаляет соответствующие импортированные команды. По сути, это отменяет действие команды пространство имён import.
пространство имён import ?-force? ?шаблон шаблон ...?
Импортирует команды в пространство имён или запрашивает набор импортированных команд в пространстве имён. При отсутствии аргументов пространство имён import возвращает список команд в текущем пространстве имён, которые были импортированы из других пространств имён. Команды в возвращаемом списке имеют формат простых имён без каких-либо квалификаторов пространства имён. Этот формат подходит для работы с пространство имён forget (см. ПРИМЕРЫ ниже).

Когда присутствуют аргументы шаблон, каждый шаблон — это квалифицированное имя, например foo::x или a::p*. То есть, он включает имя экспортирующего пространства имён и может иметь символы в стиле glob в имени команды в конце квалифицированного имени. Символы glob не могут появляться в имени пространства имён. Когда имя пространства имён не полностью квалифицировано (т.е. не начинается с разделителя пространства имён), оно разрешается так, как описано в разделе РАЗРЕШЕНИЕ ИМЁН; если не удаётся найти пространство имён с таким именем, возникает ошибка.

Все команды, которые соответствуют строке шаблон и которые в настоящее время экспортированы из своего пространства имён, добавляются в текущее пространство имён. Это делается путём создания новой команды в текущем пространстве имён, которая указывает на экспортированную команду в её исходном пространстве имён; когда вызывается новая импортированная команда, она вызывает экспортированную команду. Эта команда обычно возвращает ошибку, если импортированная команда конфликтует с существующей командой. Однако, если задан параметр -force, импортированные команды будут молча заменять существующие команды. Команда пространство имён import имеет семантику снимка: т.е. импортируются только запрошенные команды, которые в настоящее время определены в экспортирующем пространстве имён. Другими словами, вы можете импортировать только те команды, которые находятся в пространстве имён в момент выполнения команды пространство имён import. Если другая команда будет определена и экспортирована в этом пространстве имён позднее, она не будет импортирована.

пространство имён inscope пространство имён скрипт ?арг ...?
Выполняет скрипт в контексте указанного пространства имён. Не ожидается, что программисты будут использовать эту команду напрямую; вызовы к ней генерируются неявно, когда приложения используют команды пространство имён code для создания скриптов обратного вызова, которые приложения затем регистрируют, например, в виджетах Tk. Команда пространство имён inscope очень похожа на команду пространство имён eval, за исключением того, что пространство имён должно уже существовать, и пространство имён inscope добавляет дополнительные аргументы как элементы списка.
namespace inscope ::foo $script $x $y $z

эквивалентно

namespace eval ::foo [concat $script [list $x $y $z]]

следовательно, дополнительные аргументы не будут подвергнуты повторной подстановке, как это происходит с пространство имён eval.

пространство имён origin команда
Возвращает полное имя исходной команды, к которой относится импортированная команда команда. Когда команда импортируется в пространство имён, в этом пространстве имён создается новая команда, которая указывает на фактическую команду в экспортирующем пространстве имён. Если команда импортируется в последовательность пространств имён a, b,...,n, где каждое последующее пространство имён просто импортирует команду из предыдущего пространства имён, эта команда возвращает полное имя исходной команды в первом пространстве имён a. Если команда не относится к импортированной команде, возвращается собственное полное имя команды.
пространство имён parent ?пространство имён?
Возвращает полное имя родительского пространства имён для пространства имён пространство имён. Если пространство имён не указано, возвращается полное имя родителя текущего пространства имён.
пространство имён path ?список пространств имён?
Возвращает путь разрешения команд текущего пространства имён. Если список пространств имён указан как список именованных пространств имён, путь разрешения команд текущего пространства имён устанавливается на эти пространства имён и возвращает пустой список. Путь разрешения команд по умолчанию всегда пустой. См. раздел РАЗРЕШЕНИЕ ИМЁН ниже для объяснения правил разрешения имён.
пространство имён qualifiers строка
Возвращает любые ведущие квалификаторы пространства имён для строки. Квалификаторы — это имена пространств имён, разделенные двойными двоеточиями (::). Для строки ::foo::bar::x эта команда возвращает ::foo::bar, а для :: она возвращает пустую строку. Эта команда — дополнение к команде пространство имён tail. Обратите внимание, что она не проверяет, являются ли имена пространств имён фактически именами определённых пространств имён.
пространство имён tail строка
Возвращает простое имя в конце квалифицированной строки. Квалификаторы — это имена пространств имён, разделенные двойными двоеточиями (::). Для строки ::foo::bar::x эта команда возвращает x, а для :: она возвращает пустую строку. Эта команда — дополнение к команде пространство имён qualifiers. Она не проверяет, являются ли имена пространств имён фактически именами определённых пространств имён.
пространство имён upvar пространство имён ?другаяПеременная мояПеременная ...?
Эта команда организует, чтобы ноль или более локальных переменных в текущей процедуре ссылались на переменные в пространстве имен namespace. Имя пространства имен разрешается, как описано в разделе РАЗРЕШЕНИЕ ИМЕН. Команда namespace upvar $ns a b имеет тот же эффект, что и upvar 0 ${ns}::a b, за исключением правил разрешения для квалифицированных имен пространства имен или переменных. Команда namespace upvar возвращает пустую строку.
namespace unknown ?script?
Устанавливает или возвращает обработчик неизвестной команды для текущего пространства имен. Обработчик вызывается, когда команда, вызываемая изнутри пространства имен, не может быть найдена в текущем пространстве имен, пути пространства имен или в глобальном пространстве имен. Аргумент script, если он задан, должен быть правильно сформированным списком, представляющим имя команды и необязательные аргументы. Когда вызывается обработчик, полная строка вызова добавляется к скрипту, а результат вычисляется в контексте пространства имен. По умолчанию обработчик для всех пространств имен является ::unknown. Если аргумент не задан, возвращается обработчик для текущего пространства имен.
namespace which ?-command? ?-variable? name
Ищет name как команду или переменную и возвращает ее полное квалифицированное имя. Например, если name не существует в текущем пространстве имен, но существует в глобальном пространстве имен, эта команда возвращает полное квалифицированное имя в глобальном пространстве имен. Если команда или переменная не существует, эта команда возвращает пустую строку. Если переменная была создана, но не определена, например, с помощью команды variable или через trace на переменной, эта команда вернёт полное квалифицированное имя переменной. Если не задан ни один флаг, name обрабатывается как имя команды. См. раздел РАЗРЕШЕНИЕ ИМЕН ниже для объяснения правил разрешения имен.

Что такое пространство имен?

Пространство имен — это коллекция команд и переменных. Оно инкапсулирует команды и переменные, чтобы гарантировать, что они не будут конфликтовать с командами и переменными других пространств имен. Tcl всегда имел одну такую коллекцию, которую мы называем глобальным пространством имен. Глобальное пространство имен содержит все глобальные переменные и команды. Команда namespace eval позволяет создавать новые пространства имен. Например,
namespace eval Counter {
    namespace export bump
    variable num 0

    proc bump {} {
        variable num
        incr num
    }
}

создаёт новое пространство имен, содержащее переменную num и процедуру bump. Команды и переменные в этом пространстве имен отделены от других команд и переменных в той же программе. Если, например, есть команда с именем bump в глобальном пространстве имен, она будет отличаться от команды bump в пространстве имен Counter.

Переменные пространства имен напоминают глобальные переменные в Tcl. Они существуют вне процедур в пространстве имен, но к ним можно получить доступ в процедуре с помощью команды variable, как показано в примере выше.

Пространства имен динамичны. Вы можете добавлять и удалять команды и переменные в любое время, поэтому вы можете строить содержимое пространства имен со временем, используя серию команд namespace eval. Например, следующая серия команд имеет тот же эффект, что и определение пространства имен, показанное выше:

namespace eval Counter {
    variable num 0
    proc bump {} {
        variable num
        return [incr num]
    }
}
namespace eval Counter {
    proc test {args} {
        return $args
    }
}
namespace eval Counter {
     rename test ""
}

Обратите внимание, что процедура test добавлена в пространство имен Counter, а затем удалена с помощью команды rename.

Пространства имен могут содержать другие пространства имен, поэтому они вложены иерархически. Вложенное пространство имен инкапсулировано внутри родительского пространства имен и не может конфликтовать с другими пространствами имен.

Квалифицированные имена

Каждое пространство имен имеет текстовое имя, такое как history или ::safe::interp. Поскольку пространства имен могут быть вложены, для ссылки на команды, переменные и дочерние пространства имен, содержащиеся внутри пространств имен, используются квалифицированные имена. Квалифицированные имена похожи на иерархические имена путей для файлов Unix или виджетов Tk, за исключением того, что :: используется в качестве разделителя вместо / или .. Самое верхнее или глобальное пространство имен имеет имя «» (т. е. пустую строку), хотя :: является синонимом. Например, имя ::safe::interp::create относится к команде create в пространстве имен interp, которое является дочерним пространством имен ::safe, которое, в свою очередь, является дочерним пространством глобального пространства имен ::.

Если вы хотите получить доступ к командам и переменным из другого пространства имен, вам необходимо использовать дополнительную синтаксическую конструкцию. Имена должны быть квалифицированы пространством имен, которое их содержит. Из глобального пространства имен мы можем получить доступ к процедурам Counter следующим образом:

Counter::bump 5
Counter::Reset

Мы могли бы получить доступ к текущему счету следующим образом:

puts "count = $Counter::num"

Когда одно пространство имен содержит другое, для доступа к его элементам может потребоваться более одного квалификатора. Если у нас есть пространство имен Foo, которое содержит пространство имен Counter, вы можете вызвать его процедуру bump из глобального пространства имен так:

Foo::Counter::bump 3

Вы также можете использовать квалифицированные имена при создании и переименовании команд. Например, вы можете добавить процедуру в пространство имен Foo следующим образом:

proc Foo::Test {args} {return $args}

И вы можете перенести ту же процедуру в другое пространство имен следующим образом:

rename Foo::Test Bar::Test

Есть несколько оставшихся моментов относительно квалифицированных имён, которые мы должны рассмотреть. Пространства имён имеют непустые имена, за исключением глобального пространства имён. :: запрещено в простых именах команд, переменных и пространств имён, за исключением разделителя пространства имён. Дополнительные двоеточия в любой части разделителя квалифицированного имени игнорируются; то есть два или более двоеточия обрабатываются как разделитель пространства имён. Конец :: в квалифицированном имени переменной или команды относится к переменной или команде с именем {}. Однако окончательный :: в имени квалифицированного пространства имён игнорируется.

Разрешение имён

Вообще, все команды Tcl, которые принимают имена переменных и команд, поддерживают квалифицированные имена. Это означает, что вы можете задавать квалифицированные имена таким командам, как set, proc, rename и interp alias. Если вы предоставляете полностью квалифицированное имя, начинающееся с ::, нет никаких вопросов о том, какую команду, переменную или пространство имен вы имеете в виду. Однако, если имя не начинается с :: (т. е. является относительным), Tcl следует основным правилам для его поиска:
  • Имена переменных всегда разрешаются, сначала в текущем пространстве имен, а затем в глобальном пространстве имен.
  • Имена команд всегда разрешаются, сначала в текущем пространстве имен. Если они не найдены там, они ищутся в каждом пространстве имен в пути команд текущего пространства имен (который по умолчанию пуст). Если они не найдены там, имена команд ищутся в глобальном пространстве имен (или, если это не удается, обрабатываются соответствующим обработчиком namespace unknown).
  • Имена пространств имен всегда разрешаются, только в текущем пространстве имен.

В следующем примере,

set traceLevel 0
namespace eval Debug {
    printTrace $traceLevel
}

Tcl ищет traceLevel в пространстве имен Debug, а затем в глобальном пространстве имен. Он ищет команду printTrace аналогичным образом. Если имя переменной или команды не найдено ни в одном контексте, имя не определено. Чтобы сделать этот момент совершенно ясным, рассмотрим следующий пример:

set traceLevel 0
namespace eval Foo {
    variable traceLevel 3

    namespace eval Debug {
        printTrace $traceLevel
    }
}

Здесь Tcl ищет traceLevel сначала в пространстве имен Foo::Debug. Поскольку оно не найдено там, Tcl ищет его в глобальном пространстве имен. Переменная Foo::traceLevel полностью игнорируется во время процесса разрешения имён.

Вы можете использовать команду namespace which, чтобы развеять любые сомнения относительно разрешения имён. Например, команда:

namespace eval Foo::Debug {namespace which -variable traceLevel}

возвращает ::traceLevel. С другой стороны, команда

namespace eval Foo {namespace which -variable traceLevel}

возвращает ::Foo::traceLevel.

Как упоминалось выше, имена пространств имён разрешаются по-другому, чем имена переменных и команд. Имена пространств имён всегда разрешаются в текущем пространстве имён. Это означает, например, что команда namespace eval, которая создаёт новое пространство имён, всегда создаёт дочернее пространство имён текущего пространства имён, если имя нового пространства имён не начинается с ::.

Tcl не имеет механизмов контроля доступа, чтобы ограничить, какие переменные, команды или пространства имён вы можете ссылаться. Если вы предоставляете квалифицированное имя, которое разрешается согласно правилу разрешения имён выше, вы можете получить доступ к элементу.

Вы можете получить доступ к переменной пространства имен из процедуры в том же пространстве имен, используя команду variable. Подобно команде global, это создаёт локальную ссылку на переменную пространства имен. При необходимости это также создаёт переменную в текущем пространстве имен и инициализирует её. Обратите внимание, что команда global создаёт ссылки только на переменные в глобальном пространстве имен. Нет необходимости использовать команду variable, если вы всегда обращаетесь к переменной пространства имен с помощью соответствующего квалифицированного имени.

Импорт команд

Пространства имен часто используются для представления библиотек. Некоторые команды библиотек используются настолько часто, что написание их квалифицированных имён — это утомительно. Например, предположим, что все команды в пакете BLT содержатся в пространстве имен под названием Blt. Тогда вы можете получить доступ к этим командам следующим образом:
Blt::graph .g -background red
Blt::table . .g 0,0

Если вы часто используете команды graph и table, вы можете получить доступ к ним без префикса Blt::. Вы можете сделать это, импортировав команды в текущее пространство имен, как показано ниже:

namespace import Blt::*

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

graph .g -background red
table . .g 0,0

Команда namespace import импортирует команды только из пространства имен, которое экспортировало эти команды с помощью команды namespace export.

Импорт всех команд из пространства имен, как правило, плохая идея, так как вы не знаете, что получите. Лучше импортировать только необходимые команды. Например, команда

namespace import Blt::graph Blt::table

импортирует только команды graph и table в текущий контекст.

Если вы пытаетесь импортировать команду, которая уже существует, вы получите ошибку. Это предотвращает импорт одной и той же команды из двух разных пакетов. Но иногда (возможно, во время отладки) вы захотите обойти это ограничение. Возможно, вы захотите повторно выполнить команду namespace import, чтобы получить новые команды, которые появились в пространстве имен. В этом случае вы можете использовать опцию -force, и существующие команды будут молча перезаписаны:

namespace import -force Blt::graph Blt::table

Если по какой-то причине вы хотите перестать использовать импортированные команды, вы можете удалить их с помощью команды namespace forget, как показано ниже:

namespace forget Blt::*

Это ищет в текущем пространстве имен любые команды, импортированные из Blt. Если она находит какие-либо, она их удаляет. В противном случае ничего не делает. После этого к командам Blt необходимо обращаться с префиксом Blt::.

Когда вы удаляете команду из экспортирующего пространства имен так:

rename Blt::graph ""

команда автоматически удаляется из всех пространств имен, которые ее импортируют.

Экспорт команд

Вы можете экспортировать команды из пространства имен так:
namespace eval Counter {
    namespace export bump reset
    variable Num 0
    variable Max 100

    proc bump {{by 1}} {
        variable Num
        incr Num $by
        Check
        return $Num
    }
    proc reset {} {
        variable Num
        set Num 0
    }
    proc Check {} {
        variable Num
        variable Max
        if {$Num > $Max} {
            error "too high!"
        }
    }
}

Процедуры bump и reset экспортированы, поэтому они включаются при импорте из пространства имен Counter, как показано ниже:

namespace import Counter::*

Однако процедура Check не экспортирована, поэтому она игнорируется операцией импорта.

Команда namespace import импортирует только те команды, которые были объявлены экспортированными своим пространством имен. Команда namespace export указывает, какие команды могут быть импортированы другими пространствами имен. Если команда namespace import указывает команду, которая не экспортирована, эта команда не импортируется.

Ограниченные скрипты

Команда namespace code — это способ упаковать скрипт для выполнения в пространстве имен, отличном от того, в котором он был создан. Она чаще всего используется для создания обработчиков событий, привязок Tk и отслеживания для выполнения в глобальном контексте. Например, следующий код показывает, как направить обратный вызов переменной trace в текущее пространство имен:
namespace eval a {
    variable b
    proc theTraceCallback { n1 n2 op } {
        upvar 1 $n1 var
        puts "the value of $n1 has changed to $var"
        return
    }
    trace add variable b write [namespace code theTraceCallback]
}
set a::b c

При выполнении он выведет сообщение:

the value of a::b has changed to c

Ансамбли

Пространство имен namespace ensemble используется для создания и управления командами ансамбля, которые представляют собой команды, сформированные путём объединения подкоманд. Команды обычно берутся из текущего пространства имен при создании ансамбля, хотя это настраивается. Обратите внимание, что любое количество ансамблей может быть связано с любым пространством имен (включая ноль, что по умолчанию верно для всех пространств имен), однако все ансамбли, связанные с пространством имен, удаляются при удалении этого пространства имен. Связь между командой ансамбля и её пространством имен сохраняется, даже если ансамбль переименован.

Определены три подкоманды команды namespace ensemble:

namespace ensemble create ?option value ...?
Создаёт новую команду ансамбля, связанную с текущим пространством имен, возвращая полное имя созданной команды. Аргументы команды namespace ensemble create позволяют настроить команду так же, как с помощью команды namespace ensemble configure. Если не переопределено с помощью опции -command, эта команда создаёт ансамбль с именем, точно совпадающим с именем связанного пространства имен. Полный список поддерживаемых опций и их эффектов см. в разделе ВАРИАНТЫ АНСАМБЛЯ ниже.
namespace ensemble configure command ?option? ?value ...?
Возвращает значение опции, связанной с командой ансамбля с именем command, или обновляет некоторые опции, связанные с этой командой ансамбля. Полный список поддерживаемых опций и их эффектов см. в разделе ВАРИАНТЫ АНСАМБЛЯ ниже.
namespace ensemble exists command
Возвращает логическое значение, описывающее, существует ли команда command и является ли она командой ансамбля. Эта команда возвращает ошибку только в случае неправильного количества аргументов.

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

Варианты ансамбля

Следующие варианты, поддерживаемые командами namespace ensemble create и namespace ensemble configure, управляют поведением команды ансамбля:
-map
Если не пусто, эта опция предоставляет словарь, который устанавливает соответствие между именами подкоманд и списком префиксных слов для подстановки вместо слов команды ансамбля и подкоманды (аналогично псевдониму, созданному с помощью interp alias; слова не перекомпилируются после подстановки); если первое слово любого целевого объекта не является полностью квалифицированным при установке, оно считается относительным к текущему пространству имен и изменяется точно так (то есть оно всегда является полностью квалифицированным при чтении). Если эта опция пуста, соответствие будет установлено между локальным именем подкоманды и её полным именем. Обратите внимание, что если эта опция не пуста, а опция -subcommands пуста, имена подкоманд ансамбля будут точно соответствовать словам, имеющим соответствия в словаре.
-parameters
Эта опция задаёт список именованных аргументов (имена используются при генерации сообщений об ошибках), которые передаются вызывающей стороной ансамбля между именем ансамбля и аргументом подкоманды. По умолчанию он пуст.
-prefixes
Эта опция (по умолчанию включена) определяет, распознаёт ли команда ансамбля недвусмысленные префиксы своих подкоманд. Если она выключена, команда ансамбля требует точного совпадения имён подкоманд.
-subcommands
Если не пуста, эта опция перечисляет все подкоманды ансамбля. Соответствие для каждой из этих команд будет либо тем, что определено в опции -map, либо команде с таким же именем в пространстве имен, связанном с ансамблем. Если эта опция пуста, подкоманды пространства имен будут либо ключами словаря, перечисленного в опции -map, либо экспортированными командами связанного пространства имен на момент вызова команды ансамбля.
-unknown
Если не пуста, эта опция предоставляет частичную команду (к которой добавляются все слова, являющиеся аргументами команды ансамбля, включая полное квалифицированное имя ансамбля), чтобы обработать случай, когда подкоманда ансамбля не распознаётся и в противном случае генерирует ошибку. Если она пуста (по умолчанию), генерируется ошибка (в стиле Tcl_GetIndexFromObj) всякий раз, когда ансамбль не может определить, как реализовать определённую подкоманду. Дополнительные сведения см. в разделе ПОВЕДЕНИЕ ОБРАБОТЧИКА НЕИЗВЕСТНЫХ.

Следующая дополнительная опция допускается командой namespace ensemble create:

-command
Эта опция только для записи позволяет задать имя ансамбля, созданного командой namespace ensemble create, любым существующим именем в любом пространстве имен. По умолчанию значение этой опции равно полному квалифицированному имени пространства имен, в котором вызвана команда namespace ensemble create.

Следующая дополнительная опция допускается командой namespace ensemble configure:

-namespace
Эта только для чтения опция позволяет получить полное квалифицированное имя пространства имен, в котором был создан ансамбль.

Поведение обработчика неизвестных

Если для ансамбля указан обработчик неизвестных, этот обработчик вызывается, когда команда ансамбля в противном случае возвращает ошибку, так как не может определить, какую подкоманду вызвать. Точные условия, при которых это происходит, управляются опциями -subcommands, -map и -prefixes, как описано выше.

Для выполнения обработчика неизвестных механизм ансамбля берёт указанную опцию -unknown и добавляет к ней каждый аргумент попытки вызова команды ансамбля (включая саму команду ансамбля, выраженную полным квалифицированным именем). Он вызывает полученную команду в контексте попытки вызова. Если выполнение обработчика неизвестных завершается нормально, движок ансамбля перекомпилирует подкоманду (как описано ниже) и пытается выполнить её снова, что идеально подходит для случаев, когда конфигурация ансамбля обновлена обработчиком неизвестных подкоманд. Любой другой тип завершения обработчика неизвестных обрабатывается как ошибка.

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

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

Если указан пустой обработчик -unknown (по умолчанию), команда ансамбля сгенерирует сообщение об ошибке, основанное на списке команд, определённых ансамблем (форматированное аналогично сообщению об ошибке от Tcl_GetIndexFromObj). Это ошибка, которая будет выброшена, если подкоманда по-прежнему не распознаётся во время повторной компиляции. Также ошибкой является удаление пространства имен обработчиком -unknown.

Примеры

Создайте пространство имен, содержащее переменную и экспортированную команду:
namespace eval foo {
    variable bar 0
    proc grill {} {
        variable bar
        puts "called [incr bar] times"
    }
    namespace export grill
}

Вызовите команду, определённую в предыдущем примере, различными способами.

# Direct call
::foo::grill

# Use the command resolution path to find the name
namespace eval boo {
    namespace path ::foo
    grill
}

# Import into current namespace, then call local alias
namespace import foo::grill
grill

# Create two ensembles, one with the default name and one with a
# specified name.  Then call through the ensembles.
namespace eval foo {
    namespace ensemble create
    namespace ensemble create -command ::foobar
}
foo grill
foobar grill

Выясните, откуда была импортирована команда из предыдущего примера:

puts "grill came from [namespace origin grill]"

Удалите все импортированные команды из текущего пространства имен:

namespace forget {*}[namespace import]

Создайте ансамбль для простой работы с числами, используя опцию -parameters, чтобы разрешить размещение оператора между первым и вторым аргументами.

namespace eval do {
    namespace export *
    namespace ensemble create -parameters x
    proc plus  {x y} {expr { $x + $y }}
    proc minus {x y} {expr { $x - $y }}
}

# In use, the ensemble works like this:
puts [do 1 plus [do 9 minus 7]]

См. также

interp, upvar, variable

Licensed under Tcl/Tk terms
https://www.tcl.tk/man/tcl/TclCmd/namespace.htm

Licensed under Tcl/Tk terms
https://www.tcl.tk/man/tcl/TclCmd/namespace.htm

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API