Difference between revisions of "Language Reference/Generic Interfaces and Classes"
(New page: {{Preliminary Documentation}} {{languageReferenceNavbar|Generic Interfaces and Classes}}) |
(Initial) |
||
Line 2: | Line 2: | ||
{{languageReferenceNavbar|Generic Interfaces and Classes}} | {{languageReferenceNavbar|Generic Interfaces and Classes}} | ||
Interfaces and classes can be paramtereized with type parameters so that they can be used in different instantiations in different contexts. | |||
The pragmatic reason to use generic classes and interfaces is to declare '''parametrized object facts''' and implement operations on these facts. | |||
== Example: Queue == | |||
Consider this interface | |||
<vip>interface queue_integer | |||
predicates | |||
insert : (integer Value). | |||
tryGet : () -> integer Value. | |||
end interface queue_integer</vip> | |||
An object of this type is a queue of integers, if you replace "integer" with "string" you would have a type describing queues of strings. | |||
A generic interface can be used to describe all such interfaces in a single interface definition: | |||
<vip>interface queue{@Elem} | |||
predicates | |||
insert : (@Elem Value). | |||
tryGet : () -> @Elem Value. | |||
end interface queue</vip> | |||
<vp>@Elem</vp> is a ''scope type variable'' (destinguished from local type variables by the <vp>@</vp>). | |||
<vp>queue{integer}</vp> represents integer-queues; <vp>queue{string}</vp> represents string-queues; and so forth. | |||
We can declare a generic queue class like this: | |||
<vip>class queueClass{@Elem} : queue{@Elem} | |||
end class queueClass</vip> | |||
<vp>queueClass{@Elem}</vp> constructs objects type <vp>queue{@Elem}</vp> for any instantiation of <vp>@Elem</vp>. | |||
The implementation can look like this: | |||
<vip>implement queueClass{@Elem} | |||
facts | |||
queue_fact : (@Elem Value). | |||
clauses | |||
insert(Value) :- | |||
assert(queue_fact(Value)). | |||
clauses | |||
tryGet() = Value :- | |||
retract(queue_fact(Value)), | |||
!. | |||
end implement queueClass</vip> | |||
This piece of code illustrates how to create an integer queue and insert an element in it: | |||
<vip>..., Q = queueClass{integer}::new(), Q:insert(17), ...</vip> | |||
It is not necessary to apply the type explictly, instead the compiler can infer it from the context: | |||
<vip>..., Q = queueClass::new(), Q:insert(17), ...</vip> | |||
The compiler sees that <vp>Q</vp> must be an integer queue, because we insert 17 into it. | |||
== Generic Interfaces == | |||
=== Syntax === | |||
Generic interfaces have a list of type parameters: | |||
<vipbnf><InterfaceDeclaration> : | |||
interface <InterfaceName> { <ScopeTypeVariable>-comma-sep-list-opt } <ScopeQualifications> <Sections> end interface <InterfaceName>-opt | |||
... | |||
<ScopeTypeParameter> : | |||
@ <UppercaseName></vipbnf> | |||
The scope type parameters can be used in any declaration/definition in the interface. | |||
=== Semantics === | |||
A generic interface defines all the interfaces that can be obtained by instantiating the type parameters with actual types. The scope type parameters from the opening are bound in the entire interface. | |||
=== Restrictions === | |||
Then closing name should not have parameters: | |||
<vip>interface xxx{@A} | |||
... | |||
end interface xxx % no parameters here</vip> | |||
It is illegal to use same interface name for interfaces with different arity (in the same namespace): | |||
<vip>interface xxx % xxx/0 | |||
... | |||
end interface xxx | |||
interface xxx{@A, @B} % error: Several classes, interfaces and/or namespaces have the same name 'xxx' | |||
... | |||
end interface xxx</vip> | |||
Parameters can be used in supported interfaces: | |||
<vip>interface xxx{@P} supports yyy{@P} % legal: @P is bound | |||
... | |||
end interface xxx | |||
interface xxx supports yyy{@P} % illegal: @P must be bound | |||
... | |||
end interface xxx</vip> | |||
Supported interfaces can be instantiated with any type expressions (as long as parameters are bound): | |||
<vip>interface xxx{@A} supports yyy{integer, @A*} | |||
...</vip> | |||
== Generic Classes == | |||
=== Syntax === | |||
Generic classes have a list of type parameters, and constructs objects of an interface type uses the these parameters. | |||
<vipbnf><ClassDeclaration> : | |||
class <ClassName> { <ScopeTypeVariable>-comma-sep-list-opt } <ConstructionType> <ScopeQualifications> <Sections> end class <ClassName>-opt | |||
... | |||
<ScopeTypeParameter> : | |||
@ <UppercaseName> | |||
<ConstructionType> : | |||
: <TypeExpression></vipbnf> | |||
The construction type must be generic (i.e. a generic interface). | |||
=== Semantics === | |||
A generic class declares a class with a generic constructor. The type of the constructed object will be inferred from the usage of the constructor. | |||
=== Restrictions === | |||
Then closing name should not have parameters: | |||
<vip>class xxx{@A} : xxx{@AAA} | |||
... | |||
end class xxx % no parameters here</vip> | |||
It is illegal to use same class name for class with different arity (in the same namespace): | |||
<vip>class xxx % xxx/0 | |||
... | |||
end class xxx | |||
class xxx{@A} : yyy{@A} % error: Several classes, interfaces and/or namespaces have the same name 'xxx' | |||
... | |||
end class xxx</vip> | |||
If a class and interface can have the same name, the class must construct objects of that interface. | |||
<vip>interface xxx{@A} | |||
... | |||
end interface xxx | |||
class xxx{@Q, @P} : object % error: Several classes, interfaces and/or namespaces have the same name 'xxx' | |||
... | |||
end class xxx</vip> | |||
Parameters in the construction type, etc must be bound: | |||
<vip>class bbb : xxx{@Q} % error: Free parameter '@Q' is used in type expression | |||
...</vip> | |||
All the parameters from the class must be used in the construction type: | |||
<vip>class xxx{@P} : object % error: Unused type parameter '@P' | |||
...</vip> | |||
In class declarations scope parameter can only be used in constructors, domains and constants. | |||
<vip>class xxx{@P} : xxx{@P} | |||
domains | |||
list = @P*. % legal | |||
constants | |||
empty : @P* = []. % legal | |||
constructors | |||
new : (@P Init). % legal | |||
predicates | |||
p : (@P X). % error: Scope parameter '@P' used in a class entity | |||
end class xxx</vip> | |||
== Generic Implmentations == | |||
=== Syntax === | |||
Generic implementations have a list of type parameters. | |||
<vipbnf><ClassImplementation> : | |||
implement <ClassName> { <ScopeTypeVariable>-comma-sep-list-opt } <ScopeQualifications> <Sections> end implement <ClassName>-opt | |||
... | |||
<ScopeTypeParameter> : | |||
@ <UppercaseName></vipbnf> | |||
=== Semantics === | |||
A generic class declares a class with a generic constructor. The type of the constructed object will be inferred from the usage of the constructor. | |||
=== Restrictions === | |||
Then closing name should not have parameters: | |||
<vip>implement xxx{@A} | |||
... | |||
end implement xxx % no parameters here</vip> | |||
The parameters must be the same as in the corresponding class declaration and have same order. | |||
<vip>class xxx{@A} : aaa{@A} | |||
... | |||
end class xxx | |||
implement xxx{@B} % error: The parameter '@B' is not the same as in the declaration '@A' | |||
... | |||
end implement xxx</vip> | |||
In class implementations scope parameter can be used in constructors, domains, constants and in object entities (i.e. object facts, object predicates and object properties). | |||
<vip>implement xxx{@P} | |||
domains | |||
list = @P*. % legal | |||
constants | |||
empty : @P* = []. % legal | |||
constructors | |||
new : (@P Init). % legal | |||
predicates | |||
op : (@P X). % legal | |||
class predicates | |||
cp : (@P X). % error: Scope parameter '@P' used in a class entity | |||
facts | |||
ofct : (@P). % legal | |||
class facts | |||
cfct : (@P). % error: Scope parameter '@P' used in a class entity | |||
... | |||
end implement xxx</vip> |
Revision as of 11:43, 15 March 2010
Template:Preliminary Documentation
Interfaces and classes can be paramtereized with type parameters so that they can be used in different instantiations in different contexts.
The pragmatic reason to use generic classes and interfaces is to declare parametrized object facts and implement operations on these facts.
Example: Queue
Consider this interface
interface queue_integer predicates insert : (integer Value). tryGet : () -> integer Value. end interface queue_integer
An object of this type is a queue of integers, if you replace "integer" with "string" you would have a type describing queues of strings.
A generic interface can be used to describe all such interfaces in a single interface definition:
interface queue{@Elem} predicates insert : (@Elem Value). tryGet : () -> @Elem Value. end interface queue
@Elem is a scope type variable (destinguished from local type variables by the @).
queue{integer} represents integer-queues; queue{string} represents string-queues; and so forth.
We can declare a generic queue class like this:
class queueClass{@Elem} : queue{@Elem} end class queueClass
queueClass{@Elem} constructs objects type queue{@Elem} for any instantiation of @Elem.
The implementation can look like this:
implement queueClass{@Elem} facts queue_fact : (@Elem Value). clauses insert(Value) :- assert(queue_fact(Value)). clauses tryGet() = Value :- retract(queue_fact(Value)), !. end implement queueClass
This piece of code illustrates how to create an integer queue and insert an element in it:
..., Q = queueClass{integer}::new(), Q:insert(17), ...
It is not necessary to apply the type explictly, instead the compiler can infer it from the context:
..., Q = queueClass::new(), Q:insert(17), ...
The compiler sees that Q must be an integer queue, because we insert 17 into it.
Generic Interfaces
Syntax
Generic interfaces have a list of type parameters:
InterfaceDeclaration : interface InterfaceName { ScopeTypeVariable-comma-sep-list-opt } ScopeQualifications Sections end interface InterfaceName-opt ... ScopeTypeParameter : @ UppercaseName
The scope type parameters can be used in any declaration/definition in the interface.
Semantics
A generic interface defines all the interfaces that can be obtained by instantiating the type parameters with actual types. The scope type parameters from the opening are bound in the entire interface.
Restrictions
Then closing name should not have parameters:
interface xxx{@A} ... end interface xxx % no parameters here
It is illegal to use same interface name for interfaces with different arity (in the same namespace):
interface xxx % xxx/0 ... end interface xxx interface xxx{@A, @B} % error: Several classes, interfaces and/or namespaces have the same name 'xxx' ... end interface xxx
Parameters can be used in supported interfaces:
interface xxx{@P} supports yyy{@P} % legal: @P is bound ... end interface xxx interface xxx supports yyy{@P} % illegal: @P must be bound ... end interface xxx
Supported interfaces can be instantiated with any type expressions (as long as parameters are bound):
interface xxx{@A} supports yyy{integer, @A*} ...
Generic Classes
Syntax
Generic classes have a list of type parameters, and constructs objects of an interface type uses the these parameters.
ClassDeclaration : class ClassName { ScopeTypeVariable-comma-sep-list-opt } ConstructionType ScopeQualifications Sections end class ClassName-opt ... ScopeTypeParameter : @ UppercaseName ConstructionType : : TypeExpression
The construction type must be generic (i.e. a generic interface).
Semantics
A generic class declares a class with a generic constructor. The type of the constructed object will be inferred from the usage of the constructor.
Restrictions
Then closing name should not have parameters:
class xxx{@A} : xxx{@AAA} ... end class xxx % no parameters here
It is illegal to use same class name for class with different arity (in the same namespace):
class xxx % xxx/0 ... end class xxx class xxx{@A} : yyy{@A} % error: Several classes, interfaces and/or namespaces have the same name 'xxx' ... end class xxx
If a class and interface can have the same name, the class must construct objects of that interface.
interface xxx{@A} ... end interface xxx class xxx{@Q, @P} : object % error: Several classes, interfaces and/or namespaces have the same name 'xxx' ... end class xxx
Parameters in the construction type, etc must be bound:
class bbb : xxx{@Q} % error: Free parameter '@Q' is used in type expression ...
All the parameters from the class must be used in the construction type:
class xxx{@P} : object % error: Unused type parameter '@P' ...
In class declarations scope parameter can only be used in constructors, domains and constants.
class xxx{@P} : xxx{@P} domains list = @P*. % legal constants empty : @P* = []. % legal constructors new : (@P Init). % legal predicates p : (@P X). % error: Scope parameter '@P' used in a class entity end class xxx
Generic Implmentations
Syntax
Generic implementations have a list of type parameters.
ClassImplementation : implement ClassName { ScopeTypeVariable-comma-sep-list-opt } ScopeQualifications Sections end implement ClassName-opt ... ScopeTypeParameter : @ UppercaseName
Semantics
A generic class declares a class with a generic constructor. The type of the constructed object will be inferred from the usage of the constructor.
Restrictions
Then closing name should not have parameters:
implement xxx{@A} ... end implement xxx % no parameters here
The parameters must be the same as in the corresponding class declaration and have same order.
class xxx{@A} : aaa{@A} ... end class xxx implement xxx{@B} % error: The parameter '@B' is not the same as in the declaration '@A' ... end implement xxx
In class implementations scope parameter can be used in constructors, domains, constants and in object entities (i.e. object facts, object predicates and object properties).
implement xxx{@P} domains list = @P*. % legal constants empty : @P* = []. % legal constructors new : (@P Init). % legal predicates op : (@P X). % legal class predicates cp : (@P X). % error: Scope parameter '@P' used in a class entity facts ofct : (@P). % legal class facts cfct : (@P). % error: Scope parameter '@P' used in a class entity ... end implement xxx