Пространства имен
Зачем нужны пространства имен - namespace? Если Вы когда-нибудь писали свои скрипты - Вы знаете о возможных конфликтах имен переменных, созданных в глобальном пространстве имен. Пространства имен позволяют скриптеру помещать переменные и процедуры в единый именованный "блок" Tcl, так, чтобы они не конфликтовали с глобальным пространством имен. Рассмотрим простейшие пример пользовательского пространства имен
namespace eval MyScript { set response "Hello World!" bind pub - "hi" MyScript::respond proc respond {nick uhost hand chan text} { variable response puthelp "PRIVMSG $nick :$response" return 1 } }
MyScript - это имя созданного пространства имен. Оно будет использоваться в качестве префиксов в именах переменных и процедур, если они будут использоваться вне этого пространства (например, из глобального пространства имен или из других скриптов с собственными пространствами имен). Обратите внимание, что команда bind требует указания полного имени процедуры, в том числе и префикса, даже если она используется внутри этого пространства. Переменная response находится внутри пользовательского пространства, не пересекаясь с глобальным. Команда variable позволяет использовать переменные, заданные в текущем пространстве имен. В отличии от глобальных переменных, команда variable может использовать только одну переменную в качестве параметра. Если Вам нужно вызвать несколько переменных из пользовательского пространства - разместите конструкции variable <varName> на отдельных строках (или разделите точкой с запятой ";").
catch MyScript::uninstall namespace eval MyScript { set response "Hello World!" bind pub - "hi" MyScript::respond proc respond {nick uhost hand chan text} { variable response puthelp "PRIVMSG $nick :$response" return 1 } bind evnt - prerehash MyScript::uninstall proc uninstall {args} { unbind pub - "hi" MyScript::respond unbind evnt - prerehash MyScript::uninstall namespace delete MyScript } }
Чтобы пользователям не приходилось использовать команду .restart для удаления скрипта, хорошим тоном будет создать процедуру удаления по команде rehash. Если пользователь не удалит загрузку скрипта из конфигурационного файла Eggdrop - он будет спокойно загружен после rehash. Во-первых, триггеры не являются частью пространства имен, поэтому их нужно удалять отдельно. Во-вторых, есть возможность полностью удалить пространство имен со всеми объявленными переменными и процедурами. Не забудьте так же удалить все активные таймеры, присутствующие в скрипте! Чтобы позволить пользователям удалять/устанавливать скрипт через DCC команду .tcl source scripts/myscript.tcl необходимо добавить вызов процедуры деинсталляции в начало скрипта. Ключевое слово catch используется, чтобы бот не отключился если процедуры деинсталляции еще не объявлено (при первом запуске).
set ns "MyScript" catch ${ns}::uninstall namespace eval $ns { unset ::ns set response "Hello World!" bind pub - "hi" [namespace current]::respond proc respond {nick uhost hand chan text} { variable response puthelp "PRIVMSG $nick :$response" return 1 } bind evnt - prerehash [namespace current]::uninstall proc uninstall {args} { unbind pub - "hi" [namespace current]::respond unbind evnt - prerehash [namespace current]::uninstall namespace delete [namespace current] } }
Если Вы хотите избежать потенциального конфликта имен с другими пользовательскими пространствами имен - попробуйте воспользоваться этим способом. Во-первых, объявите имя переменной в глобальном пространстве имен. Оно необходимо только для первых двух строчек скрипта, так что мы удаляем его позже, чтобы не засорять глобальное пространство имен. После этого мы можем использовать команду [[[namespace]] current] внутри пространства имен MyScript. Использование такого подхода позволяет избежать многих проблем, связанных с именованием пользовательских пространств имен.