Les Namespaces
#1
Sir_Fz a écrit :Written by BarkerJr. Source: http://barkerjr.net/irc/eggdrop/Scripting/namespaces.
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.
  Avertir
#2
Sir_Fz a écrit :Ecrit par BarkerJr. Source: http://barkerjr.net/irc/eggdrop/Scripting/namespaces.
Pourquoi utiliser des namespaces ? Si vous avez déjà eu des problèmes avec des variables globales ou des procédures dans votre script interférant avec d'autres scripts, vous avez besoin des namespaces.
Les namespaces représentent ce qui rapproche le plus le Tcl de la programmation orientée objet. Ils permettent au programmeur de placer des variables et des procédures dans un sous-environnement clairement délimité et avec un nom distinct, de façon à ne pas créer de conflits avec quoi que ce soit d'autre dans le namespace global.

Commençons.
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 est le nom du namespace. Ce sera le préfixe utilisé dans le nom des variables et des procédures si elles sont appelées depuis d'autres namespaces (tels quel le namespace global).
Notez que le bind spécifie le nom complet pour la procédure.
Notez également que la variable $response réside à l'intérieur du namespace. Cela signifie qu'il ne s'agit pas d'une variable globale. Donc à l'intérieur de la procédure, elle est déclarée comme variable plutôt que comme global.
Notez que les variables doivent être déclarées sur des lignes séparées si vous en utilisez plusieurs. Elles ne peuvent pas être déclarées en une seule longue ligne comme les 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
  }
}
Plutôt que d'obliger les utilisateurs à .restart pour désinstaller les scripts, désinstallons le nôtre lorsqu'un rehash est détecté.
Si l'utilisateur a toujours le script dans le .conf, il sera automatiquement chargé après le rehash. Avant tout, les binds ne sont pas directement associés au namespace donc ils doivent être unbind séparément. Enfin, le namespace lui-même peut être supprimé. N'oubliez pas d'arrêter tous les timers que vous pourriez avoir dans votre script.
De plus, dans le but de désinstaller/réinstaller également pour les utilisateurs qui ont chargé le script au moyen de la commande .tcl source, ajoutez la 1ère ligne ( catch blablabla... ) pour appeler la procédure de désinstallation. Le catch est là afin que le bot ne plante pas si la procédure de désinstallation n'existe pas encore (premier lancement).
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]
  }
}
Si vous vous inquiétez en ce qui concerne la possibilité que des conflits surviennent entre votre namespace et un autre, faites ceci :
Premièrement, définissez le namespace dans une variable globale. Ceci n'est utilisé que dans les deux premières lignes, donc on peut ensuite unset la variable globale de manière à ne pas encombrer le namespace global.
Après cela, [namespace current] doit être utilisé partout où MyScript était utilisé. Cela rend pratiquement impossible l'occurrence d'un conflit entre votre script et un autre.

Et voilà !


-----------------------------------------------------------------------------------------------------
Edit: remplacé les commandes [set] par [variable] à l'intérieur du namespace après avoir lu les notes des lecteurs.
  Avertir
#3
Merci bien, je n'ai le temps de rien en ce moment, voila qui m'avance bien Smile
Je relirais ça et je le mettrais en ligne très vite.
  Avertir
#4
Traduction en ligne ici
  Avertir


Atteindre :


Utilisateur(s) parcourant ce sujet : 1 visiteur(s)