Пространства имен — различия между версиями

Материал из Egghelp.ru - TCL/TK Eggdrop Wiki
Перейти к: навигация, поиск
(Новая: Зачем нужны пространства имен - namespace? Если Вы когда-нибудь писали свои скрипты - Вы знаете о возможных ...)
 
Строка 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. Использование такого подхода позволяет избежать многих проблем, связанных с именованием пользовательских пространств имен.