Difference between revisions of "Multiple constraints"

Line 2: Line 2:
 
{{Warning|'''Warning''': Article under development}}
 
{{Warning|'''Warning''': Article under development}}
 
==Description==
 
==Description==
This article discusses issues which arise in conjunction with multiple constrained type parameters.
+
This article discusses issues which arise with multiple constrained type parameters.
 
==Multiple constraints for generic type parameters==
 
==Multiple constraints for generic type parameters==
  
With the new [http://www.ecma-international.org/publications/standards/Ecma-367.htm ECMA standard] for Eiffel multiple constraints for type parameters were introduced.
+
The new [http://www.ecma-international.org/publications/standards/Ecma-367.htm ECMA standard] for Eiffel introduces multi-constraint generic type parameters.
  
 
{|border="0" cellpadding="2" cellspacing="0" align="center"
 
{|border="0" cellpadding="2" cellspacing="0" align="center"
Line 43: Line 43:
 
</code>
 
</code>
 
|}
 
|}
Let's first have a look at the qualified feature call ''g.f'' of the example feature. The standard defines in section ''8.12.23'' what the base type of such a multiple constrained type parameter is. It is a fictitious class (denoted as a dashed class ''FICT'' in the diagram) which inherits from all constraint classes and to which a possible renaming is applied. Dynamic binding requires a clear notion of what the static type of a target (here g) is. To obtain the correct feature, one needs the static and dynamic type of the target at runtime. Normally the base type of the target is taken as the static type. But we cannot take this fictitious base type as our static type, because, as can be seen in the diagram, it is outside of the conformance paths to X and therefore not usable with the current definition of dynamic binding in section ''8.16.11''.
+
Our interest is focused on the qualified feature call ''g.f'' of the example feature. With the dynamic binding semantics defined in section ''8.16.11'' of the ECMA standard, it makes a difference whether the static type of ''g'' is ''A'', ''B'' or ''C''. An illustration of the differences can be found in the [[Transposition]] article.
  
If B and/or C redefine the feature ''f'' the problem is resolved by renaming and one can chose for which conformance path the feature is called. If until the level of ''{B,C}'' no redefinition of feature ''f'' has occurred, the decision which static type to use is getting more complicated: The feature ''f'' could for example be redefined in ''B2'' and/or ''C2''.
+
The standard defines in section ''8.12.23'' what the base type of such a multiple constrained type parameter is. It is a fictitious class (denoted as a dashed class ''FICT'' in the diagram) which inherits from all constraint classes and to which a possible renaming is applied. Dynamic binding requires a clear notion of what the static type of a target (here g) is. To obtain the correct feature, one needs the static and dynamic type of the target at runtime. Normally the base type of the target is taken as the static type. But we cannot take this fictitious base type as our static type, because, as can be seen in the diagram, it is outside of the conformance paths to X and therefore not usable with the current definition of dynamic binding.
In that case ''X'' would then have to select one of them. This yields somehow in an ambiguity which the current ECMA Standard (version 2) does not resolve because no obvious proper definition for the static type is given in this case.
+
  
 
The definition of this fictitious type ''FICT'' can only be used to clearly define the set of available features to instances of type G. It can not be used to define the semantic of a qualified feature call (like f.a).
 
The definition of this fictitious type ''FICT'' can only be used to clearly define the set of available features to instances of type G. It can not be used to define the semantic of a qualified feature call (like f.a).
Line 52: Line 51:
 
==Possible solutions==
 
==Possible solutions==
  
====User selects static type: Local variables or type cast.====
+
To be able to use the type G one must resolve all ambiguities which may arise because of multiple constraints.
  
One possible solution would be to define no static type for ''g''.
+
We must ensure that:
  
One could of course for unambiguous cases relax this rule.
+
* there are no name clashes of features.
  
The programmer would in an ambiguous case resolve the problem as follows:
+
* there is exactly one static type per feature (used for dynamic binding).
 +
 
 +
There may exist several features which are ambiguous.
 +
 
 +
====The programmer selects a static type by using local variables or the object test====
 +
 
 +
The idea is now to disallow such calls. One would 'not' be able to do a call like ''g.f'' because the feature ''f'' has ambiguities regarding dynamic binding.
 +
 
 +
The extreme case would be to say that there is no feature applicable to instances of ''G'' in case where G has mulitple constraints.
 +
 
 +
The solution is, taht the programmer would in an ambiguous case resolve the problem in one of the following ways:
  
 
<code>[eiffel,N]
 
<code>[eiffel,N]
Line 70: Line 79:
 
</code>
 
</code>
  
What the programmer does is basically a type cast to a known static type.
+
What the programmer does is basically a down cast to a single known static type (here ''B'').
 
The way he does it, is over a local variable.
 
The way he does it, is over a local variable.
  
Line 76: Line 85:
 
   example is
 
   example is
 
       do  
 
       do  
         {B} g.f     -- qualified feature call with static type B
+
         if {bg: B | g } then
 +
            bg.f -- qualified feature call with static type B
 +
        end
 
       end
 
       end
 
</code>
 
</code>
  
This is how the syntax could look like too.
+
This is another way to disambiguate the qualified call.
 +
 
 +
The idea is alos applicable to name clashes, but it's not a necessity.
  
 
'''Properties of this soultion:'''
 
'''Properties of this soultion:'''
* The renaming clause for multi-constraint types could be made obsolete because one defines name clashes as ambiguous cases and the user must resolve it by chosing a static type explicitly.
+
* The renaming clause for multi-constraint types could be removed from the standard because one defines name clashes as ambiguous cases and the user must resolve it by chosing a static type explicitly.
  
 
* Not all feature calls can be applied to a target whose type is a multi-constraint generic.
 
* Not all feature calls can be applied to a target whose type is a multi-constraint generic.
Line 94: Line 107:
  
 
In our example we would set the static type of ''f'' to ''A'' and then execute the qualified feature call.
 
In our example we would set the static type of ''f'' to ''A'' and then execute the qualified feature call.
 
This is somehow reasonable because if there would not be any children, we would execute the feature ''f'' defined in ''A''. If we set the static type to A we ensure that whatever occurs to ''f'' we will always execute the feature which the programmer selects to be the right feature for static type A.
 
  
 
'''Properties of this soultion:'''
 
'''Properties of this soultion:'''
  
* With this soultion the renaming clause is necessary to avoid name clashes/
+
* With this soultion the renaming clause is necessary to avoid name clashes.
  
* All features can be applied to ''g''.
+
* All features can be directly applied to ''g''.
  
* The static type of ''g'' can change depending on which feature is called.
+
* The static type of ''g'' may change depending on which feature is called.

Revision as of 10:05, 13 November 2006

Warning.png Warning: Warning: Article under development

Description

This article discusses issues which arise with multiple constrained type parameters.

Multiple constraints for generic type parameters

The new ECMA standard for Eiffel introduces multi-constraint generic type parameters.

Example:

class C [G -> {A, B }]
end

Class C expects a type parameter that conforms to A and B.

Explanation of the issue

Consider this example inheritance hierarchy together with the following code:

Class diagram for multiple constraints explanation.png

Example:

class GENERIC_CLASS [G -> {B, C}]
 
feature
 
   g: G
 
   example is
      do       
         g.f      -- qualified feature call
      end
 
end

Our interest is focused on the qualified feature call g.f of the example feature. With the dynamic binding semantics defined in section 8.16.11 of the ECMA standard, it makes a difference whether the static type of g is A, B or C. An illustration of the differences can be found in the Transposition article.

The standard defines in section 8.12.23 what the base type of such a multiple constrained type parameter is. It is a fictitious class (denoted as a dashed class FICT in the diagram) which inherits from all constraint classes and to which a possible renaming is applied. Dynamic binding requires a clear notion of what the static type of a target (here g) is. To obtain the correct feature, one needs the static and dynamic type of the target at runtime. Normally the base type of the target is taken as the static type. But we cannot take this fictitious base type as our static type, because, as can be seen in the diagram, it is outside of the conformance paths to X and therefore not usable with the current definition of dynamic binding.

The definition of this fictitious type FICT can only be used to clearly define the set of available features to instances of type G. It can not be used to define the semantic of a qualified feature call (like f.a).

Possible solutions

To be able to use the type G one must resolve all ambiguities which may arise because of multiple constraints.

We must ensure that:

  • there are no name clashes of features.
  • there is exactly one static type per feature (used for dynamic binding).

There may exist several features which are ambiguous.

The programmer selects a static type by using local variables or the object test

The idea is now to disallow such calls. One would 'not' be able to do a call like g.f because the feature f has ambiguities regarding dynamic binding.

The extreme case would be to say that there is no feature applicable to instances of G in case where G has mulitple constraints.

The solution is, taht the programmer would in an ambiguous case resolve the problem in one of the following ways:

example is
      local
         b: B
      do 
         b := g
         b.f      -- qualified feature call with static type B
      end

What the programmer does is basically a down cast to a single known static type (here B). The way he does it, is over a local variable.

example is
      do 
         if {bg: B | g } then
            bg.f  -- qualified feature call with static type B
         end
      end

This is another way to disambiguate the qualified call.

The idea is alos applicable to name clashes, but it's not a necessity.

Properties of this soultion:

  • The renaming clause for multi-constraint types could be removed from the standard because one defines name clashes as ambiguous cases and the user must resolve it by chosing a static type explicitly.
  • Not all feature calls can be applied to a target whose type is a multi-constraint generic.
  • The definition of the static type of every call remains straight forward.

Common ancestor

Another possible solution is the following: If we have a multi-constraint generic type parameter and a qualified feature call on a target of that type, we define the static type to be the type of the class which introduced the current version of the called feature body. This must be a common ancestor of the constraining classes which contain the feature f (in our case B and C).

In our example we would set the static type of f to A and then execute the qualified feature call.

Properties of this soultion:

  • With this soultion the renaming clause is necessary to avoid name clashes.
  • All features can be directly applied to g.
  • The static type of g may change depending on which feature is called.