ECLiPSe structure notation provides a way to use structures with field names. It is intended to make programs more readable and easier to modify, without compromising efficiency (it is implemented by macro expansion).
A structure is declared by specifying a template like this
:- local struct( book(author, title, year, publisher) ).Structures with the functor book/4 can then be written as
book with [] book with title:'tom sawyer' book with [title:'tom sawyer', year:1886, author:twain]which translate to the corresponding forms
book(_, _, _, _) book(_, 'tom sawyer', _, _) book(twain, 'tom sawyer', 1886, _)This transformation is done by macro expansion, therefore it can be used in any context and is as efficient as using the structures directly.
The argument index of a field in a structure can be obtained using a term of the form
FieldName of StructNameE.g. to access (ie. unify) a single argument of a structure, use arg/3 like this:
arg(year of book, B, Y)which is translated into
arg(3, B, Y)
The arity of the structure can also be obtained using of/2 as follow:
property(arity) of StructNameFor example, the arity could be used if the structure is used in a portray transformation (portray/3, see section 12.2), e.g.:
:- local portray(book/(property(arity) of book), book_out/2, []).
Similarly, the whole StructName/Arity specification can be written as:
property(functor) of StructNameand the portray transformation example can be shorten to:
:- local portray(property(functor) of book), book_out/2, []).
To construct an updated structure, i.e. a structure which is similar to an existing structure except that one or more fields have new values, use the update_struct/4 built-in, which allows to do that without having to mention all the other field names in the structure.
If a program is consistently written using with and of syntax, then the struct-declaration can be modified (fields added or rearranged) without having to update the code anywhere else.
A good way to control printing of big structures is to write special purpose portray-transformations for them, for instance
:- functor(book with [],N,A), local(portray(N/A, tr_book_out/2, [])). tr_book_out(book with [author:A,title:T], no_macro_expansion(book with [author:A,title:T])).which will cause book/4 structures to be printed like
book with [author:twain, title:tom sawyer]while the other two arguments remain hidden.
:- local struct(person(name,address,age)). :- local struct(employee(p:person,salary)).The
employee
structure contains a field p
which is a
person
structure.
Field names of the person
structure can now be used as if
they were field names of the employee
structure:[eclipse 1]: Emp = employee with [name:john,salary:2000]. Emp = employee(person(john, _105, _106), 2000) yes.Note that, as long as the
with
and of
syntax is used,
the employee
structure can be viewed either as nested or as flat,
depending on what is more convenient in a given situation.
In particular, the embedded structure can still be accessed as a whole:[eclipse 1]: Emp = employee with [name:john,age:30,salary:2000,address:here], arg(name of employee, Emp, Name), arg(age of employee, Emp, Age), arg(salary of employee, Emp, Salary), arg(address of employee, Emp, Address), arg(p of employee, Emp, Person). Emp = employee(person(john, here, 30), 2000) Name = john Age = 30 Salary = 2000 Address = here Person = person(john, here, 30) yes.Implementation note: The indices of nested structures expand into lists of integers rather than simple integers, e.g.
age of employee
expands into [1,3]
.
:- export struct(...).in the module.