Adds a property or method to an existing Type.
Since version v0.9.2 an initial value is no longer required when having active instances of the given Type. If the initial value is omitted, then a single default value according the Type definition will be created and applied to all instances. See section “init using callback” for information on how to create a new initial value for each instance.
mod_type(type, 'add', name, definition/closure, [init])
Argument | Type | Description |
---|---|---|
type | str | Name of the Type where the property has to be added to. |
'add' |
str | Passing this argument will result in an add action. |
name | str | Name of the property or method that has to be added. |
definition/closure | str/closure | Type definition of the property or closure for the method that has to be added |
init | any/closure | The default value to set on existing instances of this Type. If a closure is used, then the closure will be called on each existing instance, see init using callback. The init argument is only accepted when adding a new property on a type with wrap-only mode disabled and must be omitted when adding a new method or changing a type with wrap-only mode enabled. |
The value nil
.
This code shows how to use the action add:
// Create type `Person`
set_type('Person', {
name: 'str',
age: 'int'
});
// Add `hobbies` to type `Person`
mod_type('Person', 'add', 'hobbies', '[str]');
// Add a `whoami` method to type `Person`
mod_type('Person', 'add', 'whoami', |this| `My name is {this.name} and I am {this.age} years old.`);
Return value in JSON format
null
Instead of a fixed initial value, a closure may be used. The closure will be called on each instance of the Type, with the instance as it’s first argument.
For types with wrap-only mode enabled there are no instances to migrate. Therefore it is not possible to use the init
argument in combination with a wrap-only type.
The return value of the closure will be used as the new value, unless:
nil
is returned by the closure.mod_type(..)
has finished.mod_type(..)
has finished.In all three cases above, the value will be untouched after the callback. Thus, unless you have changed the property yourself, the default will be applied.
Suppose we want to add a chat
property or type Chat
to type Room
:
set_type('Chat', {
messages: '[str]'
});
set_type('Room', {
name: 'str'
});
.room_a = Room{
name: 'room A'
};
.room_b = Room{
name: 'room B'
};
/*
* Suppose we want to add a `chat` property or type `Chat` to type `Room` and
* used the following code:
*
* mod_type('Room', 'add', 'chat', 'Chat');
*
* This would give `room A` and `room B` both the SAME instance of type Chat.
* Thus when adding for example a message to room A, the message would also
* appear in room B.
*
* This can be solved using a closure to assign a new instance to each instance of room.
*
* mod_type('Room', 'add', 'chat', 'Chat', || Chat{});
*
* Alternatively, you could also perform some additional work based on the room, see code below:
*/
mod_type('Room', 'add', 'chat', 'Chat', |room| {
room.chat = Chat{
messages: [`Welcome in {room.name}`]
};
nil; // Return `nil` since we have chosen to set `chat` inside the closure
});
.room_a.chat.messages; // Return the chat messages of room A
Return value in JSON format
[
"Welcome in room A"
]