This is library defines a "macro"
(user:term_expansion/2) for defining "struct"s.
"Struct"s are like functors with "named fields".
They are supposed to remind structs from C.
To use, add the following to the top of the file:
:- use_module(struct).and define your "struct" with:
:- struct(struct_name, [field1, field2, ..., fieldN]).where struct_name is an atom: the name of your struct,
and field1, field2, ..., fieldN form a list of fields.
Usually, a field is only an atom telling its name.
The library also supports name:type,
but THE LIBRARY DOES NO TYPE CHECKING.
This feature is for readability purposes.
Then, the library will generate two helper predicates
with the same name as your struct:
an "view" (struct_name/3)
and an "update" (struct_name/5).
struct_name(F, V, S) :- struct_name(F, V, V, S, S).
struct_name(field1, V0, V,
struct_name(V0, F2, ..., FN),
struct_name(V , F2, ..., FN)
).
struct_name(field2, V0, V,
struct_name(F1, V0, ..., FN),
struct_name(F1, V , ..., FN)
).
% ...
struct_name(fieldN, V0, V,
struct_name(F1, F2, ..., V0),
struct_name(F1, F2, ..., V )
).The "view" predicate struct_name(Field, Value, Struct)
is true iff Struct is a "struct" struct_name
and Struct has Value at field Field.
The "update" predicate
struct_name(Field, Value0, Value, Struct0, Struct)
is true iff Struct0 and Struct are "struct"s struct_name,
Struct0 has Value0 at field Field,
Struct has Value at field Field,
and all other fields of Struct0 are
the same as the respective fields of Struct.
One can add extra "fields" right after the "struct" declaration.
Here, we are adding a "virtual field" length to vector2d.
:- struct(vector2d, [x, y]).
vector2d(length, Length, Length, Vec2d, Vec2d) :-
Vec2d = vector2d(X, Y), Length is sqrt(X ** 2 + Y ** 2).This "virtual field" is "read-only",
because it cannot "update" an vector2d object.
Observe that it is still possible to
access the Length of a Vec2d with
the "view" predicate:
vector2d(length, Length, Vec2d).
One can also abuse this feature to implement "objects".
The virtual field is the message (possibly with arguments),
Value0 is some old value related to Struct0,
Value is some new value related to Struct
(maybe the message response),
Struct0 is the old "object" (before the message) and
Struct0 is the new "object" (after the message).