View previous topic :: View next topic |
Author |
Message |
Sir_Fz Revered One

Joined: 27 Apr 2003 Posts: 3793 Location: Lebanon
|
Posted: Sat Dec 30, 2006 9:33 am Post subject: Namespaces |
|
|
Written by BarkerJr. Source: http://www.barkerjr.net/irc/eggdrop/Scripting/namespaces.php.
-----------------------------------------------------------------------------------------------------
Why namespaces? If you've ever had issues with global variables or procedures in your script conflicting with other scripts, you need namespaces. Namespaces are the closest that Tcl gets to object oriented programming. They allow the programmer to place variables and procedures inside one neat named-package in Tcl so as not to conflict with anything in the global namespace.
Lets Begin!
Code: | namespace eval MyScript {
variable response "Hello World!"
bind pub - "hi" MyScript::respond
proc respond {nick uhost hand chan text} {
variable response
puthelp "PRIVMSG $nick :$response"
return 1
}
} |
MyScript is the name of the namespace. This will be the prefix used in the name of variables and procedures if they are being called from other namespaces (such as the global). Notice that the bind specifies the full name in the procedure parameter. Another thing to note is that the variable $response resides within the namespace. That means it's not a global variable. So, inside the procedure, it is declared as a variable, rather than global. Note that variables must be declared on separate lines if you have more than one. They cannot be declared in one long line like globals. Code: | catch MyScript::uninstall
namespace eval MyScript {
variable 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
}
} |
Rather than forcing users to .restart to uninstall scripts, lets uninstall on rehash. If the user still has the script in the conf, it'll be loaded automatically after the rehash. First of all, binds are not directly associated with the namespace, so they have to be unbound separatly. Then the namespace itself can be deleted. Don't forget to kill any timers that may be in your script here, too. Also, in order to also uninstall/reinstall for users that .tcl source the script, add the top line to call the uninstall procedure. The catch is there so that the bot doesn't crash if the uninstall procedure doesn't exist yet (first run).
Code: | set ns "MyScript"
catch ${ns}::uninstall
namespace eval $ns {
unset ::ns
variable 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]
}
} |
If you are worried about the the namespace possibly conflicting with another namespace, do something like this. First, set the namespace in a global variable. It's only used in the first two lines, so we unset the global variable after, so as not to clutter up the global namespace. After that, [namespace current] should be used anywhere MyScript was used. Doing this will make it practically impossible for your script to conflict with someone else's.
All Done!
-----------------------------------------------------------------------------------------------------
Edit: Replaced [set] commands with [variable] inside namespace after reading user's tip. _________________ Follow me on GitHub
- Opposing
Public Tcl scripts
Last edited by Sir_Fz on Thu Jan 11, 2007 10:35 pm; edited 1 time in total |
|
Back to top |
|
 |
user

Joined: 18 Mar 2003 Posts: 1452 Location: Norway
|
Posted: Sat Dec 30, 2006 11:59 am Post subject: slight error |
|
|
To create a variable inside a namespace you have to use 'variable', not 'set'. If a variable by that name exists in a parent namespace, you'll change the existing one outside your namespace (which defeats the purpose of this whole name conflict avoiding thing )
Code: | % set test 1; namespace eval test {set test 2}; set test
2
% set test2 1; namespace eval test2 {variable test2 2}; set test2
1 |
You can assign a value to scalar variables using 'variable' (like i did in test 2), but if your variable is an array, do 'variable theArray', then 'set' / 'array set' to create elements. Just make sure you use 'variable' the first time you address a variable inside your namespace if you want to make sure you're not messing with parent namespaces. _________________ Have you ever read "The Manual"? |
|
Back to top |
|
 |
nml375 Revered One
Joined: 04 Aug 2006 Posts: 2854
|
Posted: Sat Feb 28, 2009 1:21 pm Post subject: |
|
|
When dealing with namespaces, and making sure bindings work correctly, I'd create a separate namespace called eggdrop with a replacement for the bind function, utilizing the namespace code along with uplevel to capture the actual namespace. No more hazzle with namespace current..
Keep in mind that your binds will look a little messy however.
Code: | namespace eval eggdrop {
#First export functions for easy access:
namespace export bind
proc bind {type flag mask proc} {
::bind $type $flag $mask [uplevel 1 [list namespace code $proc]]
}
} |
To use this, you'd simply do something like this:
Code: | namespace eval myspace {
#import the namespace along with bind, so we don't have to use the long version ::eggdrop::bind
namespace import ::eggdrop::*
proc myproc {nick host handle text} {
puthelp "PRIVMSG $nick :Hello $nick! I see you from $host, know you as $handle, and recieved $text from you."
}
bind msg - foo myproc
} |
_________________ NML_375, idling at #eggdrop@IrcNET |
|
Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|