So wie eine Prozedur oder Funktion eine Anweisungsfolge mit einem Namen versieht, fasst ein Modul eine Gesamtheit von Variablen, Prozeduren und Funktionen unter einem Namen zusammen. Deren Funktionalität kann damit mehreren Skripten oder Modulen verfügbar gemacht werden, ohne die zugehörigen Variablendeklarationen und Prozedurdefinitionen in jedem einzelnen Quelltext wiederholen zu müssen. Skripte und Module, die auf solche modular implementierte Funktionalität zurückgreifen wollen, brauchen lediglich das Laden des Moduls zu veranlassen.
Module sind daher auch das Mittel der Wahl bei arbeitsteiliger Entwicklung eines Skriptprojektes, da sich damit anderen Entwicklern eine Funktionalität gebrauchsfertig bereitstellen lässt.
Module sind wie Skripte in Textdateien zu speichern, wie sie beispielsweise der Windows-Editor Notepad erzeugen und bearbeiten kann. In einer Datei kann nur ein Modul definiert werden. Der Dateiname ist mit der Extension hsm zu versehen. Moduldateien sind im Moduleverzeichnis des Hamsters zu speichern. Dieses ist in der Voreinstellung das Hamster-Hauptverzeichnis. In der hamster.ini, Sektion [Directories] können Sie mit dem Schlüssel Modules ein anderes Verzeichnis festlegen.
Die Sprache der Hamsterskripte findet auch in Modulen unverändert Anwendung.
Anders als ein Skript sollte ein Modul einen durch die Preprozessor-Anweisung #!initialize einzuleitenden Initialisierungsteil besitzen (er ist dennoch optional). Dieser enthält Anweisungen, die nach dem ersten Laden des Moduls ausgeführt werden und wird durch eine return()-Anweisung abgeschlossen. In deren Klammern ist ein Ausdruck anzugeben, dessen Wert für den Erfolg der Initialisierung steht. Jeder Wert ungleich 0 bedeutet, dass die Initialisierung des Modules nicht erfolgreich war und die Ausführung des gesamten Skripts abgebrochen wird.
Optional kann beginnend mit #!finalize auch ein Finalisierungsabschnitt eingefügt werden, der Anweisungen enthält, die bei Beendigung des Skriptes ausgeführt werden. Sinnvoll ist dieser Abschnitt besonders dann, wenn im Initialisierungsteil Anweisungen verwendet wurden, die Speicher reservieren (siehe z. B. ArtAlloc, ListAlloc oder MemAlloc), der im Finalisierungsteil wieder freigegeben werden kann, so dass man nicht in den Skripten Sorge dafür tragen muss. Wird ein Finalisierungsabschnitt benutzt, muss auch ein Initialisierungsabschnitt vorhanden sein. Der Initialisierungsabschnitt muss sich vor dem Finalisierungsabschnitt befinden. Sollen aus irgendwelchen Gründen noch Anweisungen nach dem Finalisierungsabschnitt folgen, so muss auch dieser mit einer return()-Anweisung abgeschlossen werden.
Ein Modul ist prinzipiell wie folgt aufgebaut:
#!hs2 #!initialize <Deklaration globaler Variablen> <initialisierende Anweisungen> return( <InitResult> ) <Prozedur- und Funktionsdefinitionen> #!finalize <abschließende Anweisungen> [return( <FinalResult> ) <weitere Anweisungen>]
Es empfiehlt sich, alle in einem Module definierten Bezeichner mit dessen Namen beginnen zu lassen, um Überschneidungen mit den Bezeichnern anderer Entwickler zu vermeiden. Wer Module veröffentlichen möchte, sollte dem Modulnamen ein (Namens-)Kürzel voranstellen, um auch insoweit Überschneidungen zu verhüten.
Module können durch Skripte und andere Module mit Hilfe der Preprozessor-Anweisung #!load genutzt werden. Jede #!load-Anweisung stellt das Laden eines Moduls sicher, dessen Dateiname ohne Pfad, aber mit Extension anzugeben ist:
#!load MyModule.hsm
Die Datei MyModule.hsm wird im Moduleverzeichnis des Hamsters gesucht.
In einem Skript müssen #!load-Anweisungen vor der ersten Anweisung stehen, in einem Modul können sie auch noch im Initialisierungsteil vorkommen.
Da Module keinen eigenen Sichtbarkeitsbereich haben, sind Prozeduren und Funktionen eines Moduls direkt nach dem Laden global verfügbar, d. h. im Modul selbst und in allen Skripten und Modulen, in welchen dieses Modul geladen wird. Die im Initialisierungsteil deklarierten Variablen sind erst ab der Initialisierung des betreffendes Modules global verfügbar.
Die Initialisierungsteile der Module werden in umgekehrter Lade-Reihenfolge ausgeführt. Das zuletzt geladene Modul wird also zuerst initialisiert. Ein Skript wird erst ausgeführt, wenn alle geladenen Module auch initialisiert worden sind.
Auch wenn der Interpretierer auf mehrere #!load-Anweisungen für das gleiche Modul stößt, lädt er dennoch jedes Modul nur einmal und initialisiert es auch nur einmal.
Dabei sollten genutzte Module immer nach den sie nutzenden Modulen geladen werden. Sie werden dann so initialisiert, dass genutzte Module vor dem Zugriff anderer Module betriebsbereit sind. Wenn beispielsweise ein Modul MyHighLib Bezeichner aus einem Modul MyLib nutzt und dieses wiederum auf MyBaseLib aufsetzt, empfiehlt sich im Skript oder anderen Modulen folgende Ladereihenfolge:
#!load MyHighLib.hsm #!load MyLib.hsm #!load MyBaseLib.hsm
Sollte ein Skript oder Modul nur Bezeichner aus MyHighLib und MyBaseLib nutzen, kann die Ladeanweisung für MyLib allerdings entfallen.