SourceForge.net LogoThe Eiffel Compiler / Interpreter (tecomp)

doc/papers/lang/catcall comparable

Discussion of the catcall problem with COMPARABLE

A proposal named "The world is covariant. Is it safe?" to resolve catcall issues has been posted on the Eiffel Software mailing list. At first reading it seems to be sound. However: Does it compromise the Eiffel language too much?

Some issues are discussed below.

The class COMPARABLE has some issues related to catcalls.

Asumptions

It is assumed for the following discussion, that COMPARABLE is defined like

deferred class COMPARABLE feature
	is_less alias "<" convert (other: like Current): BOOLEAN
		deferred
		end
	is_less_equal alias "<=" convert (other: like Current): BOOLEAN
		do
			Result := Current ~ other or else Current < other
		end
	is_greater alias ">" convert (other: like Current): BOOLEAN
		do
			Result := other < Current
		end
	...
end
 

and that the basic numeric classes like INTEGER, REAL etc. inherit from COMPARABLE.

Issues

Issue 1

       local
	   a,b: COMPARABLE
       do
	  a := 1
	  b := 2.0
 
	  if 2.0 > 1 then
	     -- ok, because INTEGER converts to real, so
             -- (|2.0|).is_greater( {REAL}[1] ) will be called
          elseif 1 < 2.0 then
             -- ok, target conversion applies, because REAL is not 
	     -- compatible with INTEGER and target conversion from
	     -- INTEGER to REAL results in a valid call, i.e.
	     -- {REAL}[1].is_less(2.0) will be called
	  elseif a < b then
	     -- catcall
	  elseif b > a then
	     -- catcall
	  end
       end
 

The above proposal (with frozen and variant types) would make the calls a<b and b>a invalid, because they are not valid for any descendant of COMPARABLE.

So the proposal would allow polymorphic attachments to entities of type comparable but disallow calling any features of comparable. The above catcalls are not valid Eiffel code.

Conclusion: Issue 1 is resolved with the proposal.

Issue 2

The problem can be buried in generic types, e.g.

class SORTED_SEQUENCE[G->COMPARABLE] feature
      extend ( e: G )  do ... end
end
 
       local
          a: SORTED_SEQUENCE[COMPARABLE]
       do
          create a ....
	  a.extend ( 2.0 )
	  a.extend ( 1 )   -- internally, comparisons between 1 and 2.0 has to
       	  	       	   -- be called => catcall
       end
 

In the above proposal, the class SORTED_SEQUENCE would not compile, because internally it has to call comparison features <, <=, etc. on entities of type COMPARABLE. This would be invalid, because they are not valid for any combination of COMPARABLEs.

Conclusion: A sorted sequence is not possible any longer or in general, a formal generic G->COMPARABLE is not useful any longer. The solution cuts off meaningful classes. Issue 2 is not resolved.

What is the problem?

The proposed solution still allows polymorphic attachments but it disallows all calls of features with arguments, where the argument type has been covariantly redefined. This is somewhat in conflict with constrained genericity.

Constraint genericity has been invented to allow feature calls on formal generics. The constraints are often behaviour classes like COMPARABLE which have implicit covariance because of arguments anchored to Current. A similar issue arises with NUMERIC.

Therefore constrained genericity will become nearly useless in cases like COMPARABLE if the proposal were implemented.

Proposed solution

There seem to be two facts responsible for the problem:

The first one can be attacked by inheriting form COMPARABLE in a nonconformant manner. This disallows attachments to entities of type COMPARABLE. Attachments to entities of type COMPARABLE are in most cases usesless anyhow. So this might not be a serious limitation.

But another issue arises, because the constraint G->COMPARABLE will become unfulfillable if the actual generic (e.g. INTEGER or REAL) inherits nonconformant from COMPARABLE.

But: Is it really necessary that G->COMPARABLE is tied to conformance? Are there cases, there conformance is important? My first thinking and checking of already existing generic classes having this type of constraint says no.

So why base G->COMPARABLE on conformance? Why not on simple .... inheritance? I.e. base the definition of constraint to a weaker concept.

The reason for having a constraint on a generic is usually not because conformance is required. Usually just "behavioural conformance" (for picking just a word) is required. The actual generic should "behave" like the constraint, i.e. have the same features and contracts as the constraint.

So the proposal is:

Consequences:

Discussion

Feel free to comment on that topic at http://sourceforge.net/projects/tecomp/forums/forum/1034481.

 Local Variables: 
 mode: outline
 coding: iso-latin-1
 outline-regexp: "=\\(=\\)*"
 End:
Table of contents

- Asumptions

- Issues

- Issue 1

- Issue 2

- What is the problem?

- Proposed solution

- Discussion


ip-location