Behaviour of require (static + dynamic) [ RAKU ] - require

My question is related to the behaviour of require when used with static or dynamic resolution of the desired namespace.
I'll try to present my understanding of things:
[ 1 ] Use "require" with a literal
{ require MODULE; }
In this case the compiler checks to see if MODULE has already been declared as a symbol.
If it hasn't, the compiler declares it, and binds it to an empty placeholder package it's just created for this "require"
{
my $response = ::('MODULE'); # this happens at runtime
say $response.^name; # MODULE doesn't exist so the lookup results in the compilation-phase placeholder package: MODULE
try require MODULE; # although the execution order of require comes after the lookup,
# the placeholder package creation was done during compilation and the package is present in the current scope during run-time
}
[ 2 ] Use "require" with a String
{ try require 'FILE_PATH'; }
In this case "require" is trying to find (at run-time) a file that is defined by the filename declared in the string.
If found (with appropriate content: modules, packages etc.) then it creates a namespace(s) in the current scope and loads it with the content(s) of the file.
[ 3 ] Use "require" with a dynamic lookup
{ try require ::('MODULE'); }
It seems to me that in that case "require" behaves NOT as a "normal" subroutine.
When we use "require" with "dynamic lookup" then the core functionality of the dynamic lookup is "melted" in a new routine that behaves differently than we would expect.
The fact is that the result of the "dynamic lookup" routine is either a symbol or a Failure.
If "require" behaves like a "normal" subroutine, then the only input it could use, would be the result of the dynamic lookup that followed it (Namespace or Failure).
But it is also a fact that in the case of a Failure (as the result of dynamic lookup), "require" continues searching the repositories for a proper package (as is normally the case, using nevertheless the argument we gave to dynamic lookup: 'MODULE').
So obviously "require" isn't behaving like a "normal" subroutine in that sense.
As the result of my line of thought the combination of require + dynamic lookup resembles the following construct:
{ modified_dynamic_lookup('MODULE') :if_symbol_not_found_search_repositories_and_if_appropriate_package_found_create_namespace_and_load_package_contents; }
My concern is my understanding of case [3].
How does require + dynamic lookup work? (analytically speaking - what are the steps followed by the compiler at first and then by the runtime?)
[ Post Scriptum ]
I agree with #raiph that "require" is NOT a subroutine and that it is deeply integrated in the language.
In that sense the "dynamic lookup construct" that follows the require "instruction" is used for 2 things:
To notify the compiler that the construct is "dynamic" (so don't
bother fixing anything at compile time)
To provide the string that will be used to search for symbols,
namespaces, files or repository content
#raiph states that he thinks that "require" does a lookup after a successful load.
My only objection about that is that when we load the same library "require" doesn't throw any exception.
Is it silently ignoring the loaded library?
Why bother doing so much work when it can check first that the same namespace is already in use?
In contrary when we pretend that we load a different library then it throws an Exception : "duplicate definition" of the symbol in use.
To demostrate that I conducted the following:
In ./lib directory I place two libraries, the "foo.pm6" which is a unit definition of "foo" with a class A defined in it:
file "foo.pm6" contents:
-----------------------------------
unit module foo;
class A is export {}
and another library "other.pm6" that has inside a definition of "foo" this time with a different class B defined in it.
file "other.pm6" contents:
-----------------------------------
module foo {
class B is export {}
}
The raku program file contains the following:
use lib <lib>;
my $name = 'other'; # select one of {'other', 'foo'}
require ::('foo') <A>; ########> Initial package loading
my $a = try ::('foo::A').new;
say '(1) ' ~ $a.^name; # (1) foo::A
$a = ::('A').new;
say '(2) ' ~ $a.^name; # (2) foo::A
try require ::($name); # if $name eq 'other' => throws exception, if $name eq 'foo' => does nothing
with $! {.say}; # P6M Merging GLOBAL symbols failed: duplicate definition of symbol foo ...
$a = try ::('foo::A').new;
say '(3) ' ~ $a.^name; # (3) foo::A
$a = ::('A').new;
say '(4) ' ~ $a.^name; # (4) foo::A
From the example above we see that when we try to reload the foo namespace, hidden in a file with a different name (just to trick raku) it throws an exception.
Therefore I conclude that maybe "require" checks first for a namespace that has the same name as the provided string.
By the way, checking about this, I stumbled upon a strange behaviour. It's the following:
If we use "use foo;" in line: "Initial package loading" instead of "require ::('foo') ;", we get the following results:
(1) foo::A
(2) foo::A
No such symbol 'other' ...
(3) Any
(4) foo::A
The lookup of 'foo::A' in (3) doesn't find anything !!!
Furthermore if I change the library file: "other.pm6" with the following (class A instead of B - as in the foo.pm6)
file "other.pm6" contents:
-----------------------------------
module foo {
class A is export {}
}
the result seem to revert to the expected:
(1) foo::A
(2) foo::A
No such symbol 'other' ...
(3) foo::A
(4) foo::A
Is it a bug or something else that I'm missing?

Rewritten to correspond to the third version of your answer.
[ 1 ] Use "require" with a literal
In this case the compiler checks to see if MODULE has already been declared as a symbol. If it hasn't, the compiler declares it, and binds it to an empty placeholder package it's just created for this "require"
To be a bit more specific, the require keyword, and the code generated by it4, does the work.
And the only reason it's created the symbol is so that one can write that identifier and the code will compile. If require didn't do that then code that uses the identifier would fail to compile even if the require FOO would have succeeded:
require FOO;
my FOO $bar; # Type 'FOO' is not declared
# MODULE doesn't exist so the lookup results in the compilation-phase placeholder package: MODULE
MODULE does exist. And the lookup succeeds. It returns the value bound to the MODULE symbol, which is the placeholder package that require put there during the compilation phase.
# although the execution order of require comes after the lookup
The execution of require's compilation-phase actions came before the lookup which happens during the run phase.
[ 2 ] Use "require" with a String**
If found (with appropriate content: modules, packages etc.) then it creates a namespace(s) in the current scope and loads it with the content(s) of the file.
I think the only declaration of symbols require does is the ones the code writer has explicitly written as static identifiers as part of the require statement. Examples:
require MODULE <A>; --> MODULE and A.
require 'MODULE.pm6' <A>; --> A.
require ::('MODULE') <A>; --> A.
Aiui the MLS1, as part of symbol merging (P6M), declares further symbols as necessary. But this work isn't being done by require. It's done by MLS on its behalf. And it isn't peculiar to require. It's the same (sort of) work that happens during the compile-phase as a result of a use statement.
[ 3 ] Use "require" with a dynamic lookup
{ try require ::('MODULE'); }
I have code that is an attempt to demonstrate that this does not do a lookup before attempting to load the module.2
It seems to me that in that case "require" behaves NOT as a "normal" subroutine.
require is not a routine, normal or otherwise.
say require MODULE; # Undeclared name:
MODULE used at line 1
# Undeclared routine:
require used at line 1
If you search for require in the official doc you'll see it's not listed in the Routine Reference section but rather the Modules part of the Language Reference. It's a keyword, a statement, a special part of the language that the compiler understands.
If "require" behaves like a "normal" subroutine, then the only input it could use, would be the result of the dynamic lookup that followed it (Namespace or Failure).
The result of a dynamic lookup is the value bound to a Symbol, if it's declared, or Failure otherwise:
my $variable = 42;
say ::('$variable'); # 42
say ::('nonsense') ~~ Failure; # True
$variable is not a Namespace.
But it is also a fact that in the case of a Failure (as the result of dynamic lookup), "require" continues searching the repositories for a proper package (as is normally the case, using nevertheless the argument we gave to dynamic lookup: 'MODULE').
Given the code I wrote tracking dynamic lookup of the value of ::('MODULE')2 it looks likely to me that there is no dynamic lookup of it by any code, whether require or the MLS, if the module loading fails.
That in turn implies that it only happens, if at all, during or after (successful) loading of a module. So either the MLS is doing it (seems most likely), or, perhaps, require is doing it after the module has been successfully loaded (seems unlikely but I'm not yet ready to 100% eliminate it).
{ modified_dynamic_lookup('MODULE') :if_symbol_not_found_search_repositories_and_if_appropriate_package_found_create_namespace_and_load_package_contents; }
I think I've proven that there is either no lookup at all by require or the MLS, or, if it does it, it's only after a module has been successfully loaded.
what are the steps followed by the compiler at first and then by the runtime?
This answer is of course an attempt to answer that but my brief compiler code analysis may be of some help.3 (Though clicking the link to see the actual code in Actions.nqp is not for the faint of heart!)
[ Post Scriptum ]
In that sense the "dynamic lookup construct" that follows the require "instruction" is used for 2 things:
To notify the compiler that the construct is "dynamic" (so don't bother fixing anything at compile time)
To provide the string that will be used to search for symbols, namespaces, files or repository content
I think it only does 2, just a package name that's passed to the MLS.
when we load the same library "require" doesn't throw any exception. Is it silently ignoring the loaded library?
I don't think require knows anything about it. It hands it off to the MLS and then picks up after the MLS has done its thing. I don't think require can tell the difference between when MLS does a successful fresh load and when it just skips the load. All it knows is whether MLS says all is good or there's an exception.
Why bother doing so much work when it can check first that the same namespace is already in use?
Why bother doing any work when the MLS already does it, and require is going to invoke the MLS anyway? Doing anything is wasted effort.
All require has to do is deal with the compile-phase symbols the user has explicitly typed in the require statement. It can't ask the MLS to deal with those because it's got nothing to do with a successful module load, and that's the only scenario in which the MLS goes fiddling with symbols.
In contrary when we pretend that we load a different library then it throws an Exception : "duplicate definition" of the symbol in use.
Try this:
require ::('foo');
require ::('other');
Now try it again when you change the unit module foo; in foo.pm6 and other.pm6 to unit module bar;. You'll still get the same exception, but the symbol will be bar. How can require know about bar? It can't. The exception is coming from the MLS and the symbol is only known about by the MLS.
Therefore I conclude that maybe "require" checks first for a namespace that has the same name as the provided string.
Unless you count the MLS as part of require, I trust you can now see that your "maybe" qualification was wise. :)
I stumbled upon a strange behaviour ... The lookup of 'foo::A' in (3) doesn't find anything !!!
I've got an explanation for that. I'm not saying it's right, but it doesn't seem too strange to me as I write this:
The use statement loads the foo.pm6 package. It defines a package foo, which contains a class A, and exports A. That results in a symbol in the importing lexical scope foo, which is bound to a package, which package contains a symbol A. It also results in another symbol in the importing lexical scope, A.
The require statement loads the other.pm6 package. It defines a package foo, which contains a class B, and exports B. That results in rebinding the foo symbol in the importing lexical scope to a different package, namely the new package containing the symbol B. It also results in another symbol in the importing lexical scope, B.
The earlier A hangs around. (In other words the P6M symbol merging process doesn't include removing symbols.) But foo::A, which is looked up in the package bound to the foo symbol, no longer exists, because the package bound to the foo symbol is now the one from the other.pm6 package, having overwritten the one from the foo.pm6 package.
In the meantime there's another oddity:
try require ::($name);
with $! {.say}; # No such symbol 'other' ...
I think this reflects require doing a (failed) lookup after a successful module load.
Note that this message does not appear if the module fails to load; this seems to again confirm my thinking (and code2) that require does not do any lookup until after a successful load (if that; I still don't have a strong sense about whether it's the MLS that's doing this stuff or the require; the code4 is too complex for me atm).
Responses to your comments
From your comments on this answer:
Its like we get as the result of the amalgamation of require + 'dynamic lookup formulation' an enhanced dynamic lookup like this { ::('something') :if_not_found_as_namespace_check_repositories_and_load }
That doesn't ring true for me for various reasons.
For example, presume there's a package foo declared as module foo { our sub bar is export { say 99 } } that will successfully load if required. Now consider this code:
my \foo = 42;
say ::('foo'); # 42
require ::('foo') <&bar>;
say foo; # 42
bar; # 99
This makes sense to me. It won't have loaded a package whose name is42. It won't have looked up the symbol foo. It will have loaded the package whose name is foo. And while it presumably will have looked up symbol foo after loading the package, it won't have installed a symbol foo because there's already one.
Footnotes
1 By Module Loading Subsystem I mean the various parts that, given a module name, do things like searching the local file system, or a database, checking precompilation directories, invoking compilation, and merging symbols if a module successfully loads. I don't know where the boundaries are between the parts, and the parts and the compiler. But I'm confident they are not part of require but merely invoked by it.
2 Run this code:
my \MODULE =
{ my $v;
Proxy.new:
FETCH => method { say "get name: $v"; $v },
STORE => method ($n) { say "set name: $n"; $v = $n }}();
MODULE = 'unseen by `require`';
say ::('MODULE');
use lib '.';
say 'about to `require`';
require ::('MODULE');
3 We start with the relevant match in Raku's Grammar.nqp file:
rule statement_control:sym<require> {
<sym>
[
| <module_name>
| <file=.variable>
| <!sigil> <file=.term>
]
<EXPR>?
}
The code seems to follow what we expect -- a require keyword followed by either:
a package identifier (<module_name>); or
a <variable> (eg $foo); or
a <term> that doesn't start with a <sigil>.
We're interested in the <module_name> branch. It calls token module_name which calls token longname which calls token name:
token name {
[
| <identifier> <morename>*
| <morename>+
]
}
Clearly ::('foo') doesn't begin with an <identifier>. So it's token morename. I'll cut out a few uninteresting lines to leave:
token morename {
'::'
[
|| <?before '(' | <.alpha> >
[
| <identifier>
| :dba('indirect name') '(' ~ ')' [ <.ws> <EXPR> ]
]
]?
}
Bingo. That'll match ::(, in particular the :dba('indirect name') '(' ~ ')' [ <.ws> <EXPR> ] bit.
So at this point we'll have captured:
statement_control:sym<require><module_name><longname><name><morename><EXPR>
A short while later the statement_control:sym<require> token will be about to succeed. So at that point it will call the corresponding action method in Actions.nqp...
4 In Actions.nqp we find the action corresponding to token statement_control:sym<require>, namely method statement_control:sym<require>. The opening if $<module_name> { conditional will be True, leading to running this code:
$longname := $*W.dissect_longname($<module_name><longname>);
$target_package := $longname.name_past;
It looks to me like this code is dissecting the result of parsing ::('foo'), and binding AST corresponding to that dissection to $target_package, rather than bothering to do a lookup or prepare a run-time lookup.
If I'm right, the ::('foo') does not need to be anything more than 9 characters that require gets to interpret however it fancies interpreting them. There's no necessary implication here it does any particular thing, such as a lookup, as it constructs the package loading code.
The latter half of the action does do lookups. There are lines like this:
?? self.make_indirect_lookup($longname.components())
and given the routine name I presume that that is doing a lookup, perhaps as part of where require attempts to add a package symbol if the package load succeeds.

require does some things during compilation if it can.
require Module;
say Module;
It assumes that loading that module will give you something with the name of Module.
So it installs a temporary symbol with that name at compile time.
That is the only thing it does at compile time.
(So I fibbed when I said “some things”.)
if Bool.pick {
require module-which-does-not-exist;
module-which-does-not-exist.method-call()
}
About half of the time the above does nothing.
The other half of the time it complains at run-time that it can't find the module.
(I chose Bool.pick instead of False so the compile-time optimizer definitely can't optimize it away.)
When you call it with something other than an identifier, it doesn't know at compile-time what the module will be.
So it can't create a temporary namespace.
require 'Module';
say Module; # COMPILE ERROR: undeclared name
require Module; # RUNTIME ERROR: can't find 'Module'
say Module;
require 'Module'; # RUNTIME ERROR: can't find 'Module'
say ::('Module');
if False {
require Module;
say Module;
}
# no error at all
if False {
require 'Module';
say ::('Module');
}
# no error at all

Related

How to refrence a dependancies variable description in terraform?

When writing terraform modules, one is commonly writing pass through variables/inputs for dependent objects.
How can I write the variable so that the description/type just references the dependent description?
I imagine something like
variable "foo" {
type = dependant.resource.foo.var.type
description = dependant.resource.foo.var.description
default = "module default"
}
Variable descriptions are metadata used by Terraform itself (specifically: by documentation mechanisms like Terraform Registry) and are not data visible to your module code.
Each module's input variables and output values must be entirely self-contained. Mechanisms like the Terraform Registry rely on this so that they are able to generate the documentation for a module only by reference to that module, without any need to fetch and analyze any other modules or other dependencies.
If you do intend to have a variable just "pass through" to a child module or to a resource configuration then you will need to redeclare its type and description in your module.
I would also suggest considering the advice in the documentation section When to write a module; directly passing through a variable to a child object isn't necessarily a wrong thing to do, but it can result from a module not raising the level of abstraction and therefore not passing the test described there.
In such cases, it can be better to use module composition instead of nested modules.
In this case would mean that the caller of your module would themselves call the other module you are currently wrapping. Instead of your module taking that other module's input variables as its own, it would be declared to accept the other module's output values as its input, so that the caller can pass the object representing the first module result into the second module:
module "first" {
# ...
}
module "second" {
# ...
first = module.first
}
Inside this "second" module, the input variable first would be declared as requiring an object type with attributes matching whatever subset of the output values of "first" that the second module depends on.

Generating paths in submodule context given path in parent module context

I am creating an attribute macro that can be invoked with (a path to) some type amongst its attributes:
#[my_macro(path::to::SomeType)]
This macro generates a module, within which the specified type is to be used:
mod generated {
use path::to::SomeType;
}
However, from within that generated module, the path as provided may no longer be correct:
if the path is prefixed with ::, it remains correct—I can determine this within the proc macro;
otherwise, if the path starts with an identifier that is in a prelude (such as that of an external crate), it remains correct—I can't see any way to determine this within the proc macro;
otherwise it must now be prefixed with super:: for resolution to succeed.
Of course, I could require users of the macro to provide a path that will be correct from within the generated module, but that would not be very ergonomic.
Instead, I'm currently generating a type alias within the parent module:
type __generated_SomeType = path::to::SomeType;
mod generated {
use super::__generated_SomeType as SomeType;
}
However this is not only a tad clunky, but it furthermore pollutes the parent namespace.
Is there a better way?
I don't think there's a satisfying solution. But there's an alternative, and a way to improve your current approach.
The alternative is to use a const item:
const _: () = {
// ... your generated code here
};
It can still cause name collisions with items from the parent scope, but at least the generated items aren't visible outside of the const. This is what most macro authors do.
If you don't want to do that, you can go with your current approach, but you should add #[doc(hidden)] to the __generated_SomeType type, so it doesn't show up in documentation. Also, you should use an import instead of a type alias to support generic types, as suggested by #ChayimFriedman:
#[doc(hidden)]
use path::to::SomeType as __generated_SomeType;
I was just about to suggest combining these to approaches by putting a module inside a const item, but it doesn't work:
const _: () = {
use path::to::SomeType as __generated_SomeType;
mod generated {
// doesn't work :(
use super::__generated_SomeType as SomeType;
}
};
Rust complains that __generated_SomeType doesn't exist in the parent module.

SELinux syntax error when optional is used inside a tunable_policy macro

TLDR: An interface I'm trying to use contains a few "optional_policy" macros. Using it (or any form of "optional") inside a tunable_policy macro results in a syntax error. What is the correct way to accomplish this? See update below.
Long Version: I'm new to SELinux and currently working on a module to constrain a user application on Debian. One of the things I'd like to do is add a boolean to toggle network access. I created a basic policy module using the something similar to the following:
sepolicy generate --application -n mymodule /usr/share/foo/foo
I added a new tunable to the generated module.
gen_tunable(mymodule_use_network,false)
tunable_policy(`mymodule_use_network',`
sysnet_dns_name_resolve(mymodule_t)
')
The interface call shown above was generated by sepolicy and I just moved it into the tunable_policy macro. Once I get the DNS working I'll move the rest of the network permissions in.
I have experimented using both the optional_policy macro and the plain optional statement directly. When using the generated script to build and load my module I get the following output in all cases:
Building and Loading Policy
+ make -f /usr/share/selinux/devel/Makefile mymodule.pp
Compiling default mymodule module
mymodule.te:65:ERROR 'syntax error' at token 'optional' on line 4858:
optional {
#line 65
/usr/bin/checkmodule: error(s) encountered while parsing configuration
make: *** [/usr/share/selinux/devel/include/Makefile:166: tmp/mymodule.mod] Error 1
+ exit
I have noticed that the file that defines these macros has a helper function regarding commented lines and m4, but I have no idea what it's doing. Is something like that my issue here? As a workaround I can copy the contents of the interface into my macro but that defeats the purpose. What am I missing here? Is it really the case that this is expected and no other tunable in the reference policy contains a nested optional statement?
Update:I've boiled it down to the following if/optional statement combination. According to the SELinux Notebook optional statements are valid within if statements in policy modules so I'm really at a loss.
if(`mymodule_use_network'){
optional {
require {
type fonts_t;
}
allow mymodule_t fonts_t:dir getattr;
}
}
Actually, it only now starts to sink in here that according to documentation "optional" statement is not allowed in conditionals.
A workaround is to wrap the "tunable_policy","if" or "booleanif" construct with an "optional" instead.
native module policy, something like:
module myfoo 1.0;
bool foo true;
type bar;
require { class process signal; }
if (foo) {
allow bar self:process signal;
} else {
dontaudit bar self:process signal;
}
optional {
if (foo) {
require { type baz; class file read; }
allow bar baz:file read;
}
}
or refpolicy, something along the lines of:
policy_module(myfoo, 1.0)
gen_tunable(foo, true)
type bar;
tunable_policy(`foo',`
allow bar self:process signal;
',`
dontaudit bar self:process signal;
')
optional_policy(`
tunable_policy(`foo',`
gen_require(` type baz; ')
allow bar baz:file read;
')
')
or native common intermediate language:
(boolean foo true)
(type bar)
(booleanif foo
(true
(allow bar self (process (signal))))
(false
(dontaudit bar self (process (signal)))))
(optional foo_optional
(booleanif foo
(true
(allow bar baz (file (read))))))
Syntax error maybe? Your stuff does not look like what is documented
What is the compiler telling you?
Do note though that not all statements are allowed in conditionals. You are for example not allowed to declare/associate type attributes in conditionals. Ensure that any interfaces you call in conditionals do not declare/associate type attributes (or any other things that aren't allowed)
The only statements and rules allowed within the if / else construct are:
allow, auditallow, auditdeny, dontaudit, type_member, type_transition (except file_name_transition), type_change and require.
By the way: sysnet_dns_name_resolve() is not realistically optional.
It is kind of confusing because you are essentially using two policy languages (the reference policy abstraction and the native module policy) The `' is specific to reference policy (refpolicies' use of M4 to be precise) That is not something that native module policy uses.

Is it possible to take the name of a variable and turn it into a string in ActionScript 3.0?

I am making a simple debugger window in ActionScript for myself where I can add and remove variables I want to track. I was to be able to add variables to the list by just doing something like
DebuggerMonitor.trackVar(variable).
My question is, is there any way I can turn "variable" itself (the name, not the value) into a String to be added into a text field?
Depending on how "intelligent" your debugger should be, you could just pass the name along:
DebuggerMonitor.trackVar( variable, "variable" );
since obviously, when used in a context like this, the name should be known at the time you are writing the program.
You can also do some reflection magic to get instance variable names, but it won't work for temp variables (their names are dropped at compilation time):
public function getVariableName( instance:*, match:* ):String {
var typeDescription:XML = describeType( instance );
var variables:XMLList = typeDescription..variable;
var accessors:XMLList = typeDescription..accessor;
for each(var variable:XML in variables)
if(matchesXMLName( instance, variable, match ))
return variable.#name;
for each(var accessor:XML in accessors)
if(matchesXMLName( instance, accessor, match ))
return accessor.#name;
return "No name found.";
}
private function matchesXMLName( instance:*, xml:XML, match:* ):Boolean {
return match == instance[xml.#name.toString()];
}
var varName:String = getVariableName ( myObject, variable );
Using reflections like this will also be quite costly, if used often - you will have to think of a way to cache the type descriptions.
I recommend you check out the as3commons reflections package - there is a lot of useful functionality in there...
Short answer - No :(
You can access the type name but not individual instance names, as these are lost at run-time.
There is a confusion caused by the keyword 'var' because it is used to create several types of bindings.
Lexical bindings (the keyword 'var' was used inside a function).
Dynamic bindings (the keyword 'var' was used to declare a class' field).
Lexical bindings are interpreted by the compiler at compile time as addresses of the registers of the registers space occupied by the function. The names given to lexical bindings perish at this time and it is not possible to restore them at runtime - therefore you can't get the "name" of the variable.
Dynamic bindings are a kind of "public API" of the objects that declare them, they may be accessed from the code that was not compiled together with the code that created them, this is why, for the purpose of reflection the names of these bindings are stored in compiled code. However, ActionScript has no way of referencing LHS values, so you cannot, even if you know the name of the variable and the object declaring it, pass it to another function. But you can look it up in the debugger or by calling describeType on the object declaring the variable. Note that describeType will not show information on private variables even if you are calling it from the scope of the object in question.

Why can I not create a new subclass and use it in the same sentence?

I am wondering why the following does not work in GNU Smalltalk:
Object subclass: Foo [ ] new printNl
I was expecting a printout of something like "a Foo", but instead gst prints "nil". Doesn't this seem a bit odd?
Object subclass: Foo [] is not “usual” Smalltalk syntax, it's a recent addition designed to make it practical to code in files. Prior to that there was no dedicated syntax to declare class, since they would be created by a command in the image. Interpreting this code as you expected would be wrong for a couple reasons:
First, if subclass: was a real message sent to Object, then Foo should resolve to something, which is not possible since it is just being declared. However, behind the scenes, the compiler does something similar Object subclass: #Foo where #Foo is a symbol for the name of a new class to be created. It would be possible to write all code like that, except then you could not use class names directly (since they don't exist yet when the code is read). You would have to do (Smalltalk at: #Foo) new printNl all over the place. So the whole form Object subclass: Foo [ ] is pure syntax that just declares that this class should be created, and does not mean that at this moment a message should be sent to Object, etc
Second, you don't want to create classes in the middle of an algorithm and send them messages immediately, that would be pretty ugly as a development practice. Note that classes have to be registered in the system so that the browser can display them, that the compiler can automatically recompile dependancies, that the version control can record them, etc. Also, what if your code accidentally runs this twice? Should you get a second class Foo and forget about the previous one? So, typically, only the compiler, browser, and other meta-programming tools create new classes, and only at the programmer's request.
This is interpreted as two statements. The first is
Object subclass: Foo [ ]
and the second is
new printNl
where the new variable is undefined so it is nil.

Resources