Пространства имен — различия между версиями
Deniska (обсуждение | вклад) (Новая: Зачем нужны пространства имен - namespace? Если Вы когда-нибудь писали свои скрипты - Вы знаете о возможных ...) |
Deniska (обсуждение | вклад) |
||
Строка 3: | Строка 3: | ||
namespace eval MyScript { | namespace eval MyScript { | ||
− | |||
set response "Hello World!" | set response "Hello World!" | ||
− | |||
bind pub - "hi" MyScript::respond | bind pub - "hi" MyScript::respond | ||
− | |||
proc respond {nick uhost hand chan text} { | proc respond {nick uhost hand chan text} { | ||
variable response | variable response | ||
Строка 18: | Строка 15: | ||
catch MyScript::uninstall | catch MyScript::uninstall | ||
− | |||
namespace eval MyScript { | namespace eval MyScript { | ||
set response "Hello World!" | set response "Hello World!" | ||
− | |||
bind pub - "hi" MyScript::respond | bind pub - "hi" MyScript::respond | ||
− | |||
proc respond {nick uhost hand chan text} { | proc respond {nick uhost hand chan text} { | ||
variable response | variable response | ||
Строка 29: | Строка 23: | ||
return 1 | return 1 | ||
} | } | ||
− | |||
bind evnt - prerehash MyScript::uninstall | bind evnt - prerehash MyScript::uninstall | ||
− | |||
proc uninstall {args} { | proc uninstall {args} { | ||
unbind pub - "hi" MyScript::respond | unbind pub - "hi" MyScript::respond | ||
Строка 42: | Строка 34: | ||
set ns "MyScript" | set ns "MyScript" | ||
− | |||
catch ${ns}::uninstall | catch ${ns}::uninstall | ||
− | |||
namespace eval $ns { | namespace eval $ns { | ||
− | |||
unset ::ns | unset ::ns | ||
− | |||
set response "Hello World!" | set response "Hello World!" | ||
− | |||
bind pub - "hi" [namespace current]::respond | bind pub - "hi" [namespace current]::respond | ||
− | |||
proc respond {nick uhost hand chan text} { | proc respond {nick uhost hand chan text} { | ||
variable response | variable response | ||
Строка 58: | Строка 44: | ||
return 1 | return 1 | ||
} | } | ||
− | |||
bind evnt - prerehash [namespace current]::uninstall | bind evnt - prerehash [namespace current]::uninstall | ||
− | |||
proc uninstall {args} { | proc uninstall {args} { | ||
unbind pub - "hi" [namespace current]::respond | unbind pub - "hi" [namespace current]::respond |
Версия 07:42, 25 марта 2009
Зачем нужны пространства имен - 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а. Во-первых, bindы не являются частью пространства имен, поэтому их нужно удалять отдельно. Во-вторых, есть возможность полностью удалить пространство имен со всеми объявленными переменными и процедурами. Не забудьте так же удалить все активные таймеры, присутствующие в скрипте! Чтобы позволить пользователям удалять/устанавливать скрипт через DCC команду .tcl source script.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. Использование такого подхода позволяет избежать многих проблем, связанных с именованием пользовательских пространств имен.