Automatic anonymous classes generation, meant to be used as data structures.
Do this:
Metacello new
baseline: 'AutoType';
repository: 'github://maxwills/auto-type:main';
load.
AutoType is a system that can be used to automatically generate a class from setter expressions. The new class is not installed in the system, and is not registered in the logs.
|t name lastname|
name := 'ACleverFistName'.
lastname := 'ADissapointingLastName'.
t := AutoType new.
item := t newWith
firstName: name;
lastName: lastname;
fullName: name , ' ' , lastname;
endWith
Will create a new class with setters and getters for #firstName
, #lastName
, #fullName
, and will return an instance of the class, ie., item
responds to the the following messages: item firstName
, item firstName:
, item lastName
, etc.
Additionaly, the generated class replies to the at:
, at:put:
and keysDo:
messages, like dictionaries. Eg., you can use item at: #lastName put: 'newLastName'
.
Dictionaries seem to be slightly slow for some usages (Completely subjective and not tested). It is faster to access instance variables throught getters than finding keys in a dictionary, in the current implementation. Also, the notation for instantiation is a lot cleaner with AutoType.
The first time newWith
is executed, it will crate a builder to define the class from the following setters received, until endWith
, returning an instance of the new class with the assigned values.
After the first time, it will directly create a new instance of the auto defined class.
Dont put the AutoType new
statement inside a block that is executed repeatedly.
DONT DO THIS
myCollection collect: [:each|
|t|
t := AutoType new "bad usage!".
t newWith
firstName: (each at: 1);
lastName: (each at: 2);
fullName: (each at: 1) , ' ' , (each at: 2);
endWith ]
Doing that will execute the definition logic on every iteration of the collect: method. Instead, use it like this:
DO THIS INSTEAD
|t|
t := AutoType new "placed instead in a scope out of the iteration".
myCollection collect: [:each|
t newWith
firstName: (each at: 1);
lastName: (each at: 2);
fullName: (each at: 1) , ' ' , (each at: 2);
endWith ]
This will execute the definition logic only during the first iteration, and then the new class is reused.
See AutoTypeTest >> testNominal
.
To create more instances of the class, use the newWith
/endWith
cascade construct. Or you can also do:
t type new
, or if you already have an instance of your auto gereated class, you can do your_instance class new
.