Intro to Packages and NameSpaces
In GNU Smalltalk package loading and namespaces are separate.
If like me you've come from Java, it takes an example to see what this means in practice.
Here is a very simple example using sockets (found in TCP package up to 3.0.x, and Sockets package in 3.1). The example below is for 3.1 so the Sockets package is used. Sockets package documentation is at...
What I tried to do first was this...
#!/usr/local/bin/gst -f PackageLoader fileInPackage: 'Sockets'. "Extremely small test (try to receive SMTP header)" s := Socket remote: '192.168.0.1' port: 25. (s upTo: Character cr) printNl. s close.
and the output looks like this...
Object: nil error: did not understand #remote:port: MessageNotUnderstood(Exception)>>signal UndefinedObject(Object)>>doesNotUnderstand: #remote:port: UndefinedObject>>executeStatements Object: nil error: did not understand #upTo: MessageNotUnderstood(Exception)>>signal UndefinedObject(Object)>>doesNotUnderstand: #upTo: UndefinedObject>>executeStatements Object: nil error: did not understand #close MessageNotUnderstood(Exception)>>signal UndefinedObject(Object)>>doesNotUnderstand: #close UndefinedObject>>executeStatements
This program works:-
#!/usr/local/bin/gst -f PackageLoader fileInPackage: 'Sockets'. "the fix: add TCP namespace to Socket, i.e. Sockets.Socket" s := Sockets.Socket remote: '192.168.0.1' port: 25. (s upTo: Character cr) printNl. s close.
'220 ourserver.net.nz ESMTP Postfix'
- In the example above, the line, "PackageLoader fileInPackage: 'Sockets'" loads the Sockets package in from disk so it is available to be used.
- Then when the program uses a class from the Sockets package, e.g. Socket, the reference to Socket must be prefixed with the package name, i.e. Sockets.Socket. So in summary, loading the package doesn't automatically mean the "Sockets" namespace is available to the script.
Summary: Java compared to Smalltalk
- Java packages are actually namespaces and classes are loaded as needed from disk.
- Smalltalk classes are not loaded automatically and have to be requested explicitly, so packages are there as a loading mechanism.
And for comparison, a session with the Smalltalk Interpreter...
st> PackageLoader fileInPackage: 'Sockets' "Global garbage collection... done" Loading package Sockets PackageLoader st> Sockets.Socket Sockets.Socket st> Sockets.Socket remote: '127.0.0.1' port: 25 Sockets.Socket[local nil:nil, remote 127.0.0.1:25]
Questions and Answers
Question: Is it possible to add in the Sockets namespace at the top of the program so that one doesn't have to refer to Socket as Sockets.Socket?
Answer: In a class, you use... (Aside: I couldn't stop the Wiki from interpreting the less than sign , '<' and greater than sign '>' so had to quote them; remove the quotes in practice... )
In "loose" methods such as the Sockets script example above, no.
Question: Re the file on my machine, (/usr/local/src/smalltalk-3.1/packages/sockets/Tests.st), there are no PackageLoader and namespace lines in the file. After unpacking the Sockets.st file in /usr/local/share/smalltalk/Sockets.star, there is no extra info in there either.
How does the package and namespace information get added to Tests.st (is it a consequence of the .star packaging)?
Answer: Yes, Tests.st is part of Sockets.star (TCP.star in 3.0.x) and packages/sockets/package.xml says that:
- Tests.st should be loaded as part of the star package,
- The package is loaded in the Sockets namespace
Besides, Tests.st defines the methods as part of the Sockets.Socket class, so the Sockets namespace is automatically included in the methods it defines.
Thanks to Paolo for assistance