Re: clarifying a generics issue

2009-08-12 Thread Adam Lally
On Wed, Aug 12, 2009 at 5:36 AM, Jörn Kottmann wrote:
> Jörn Kottmann wrote:
>>
>> Marshall Schor wrote:
>>>
>>> I'll probably stop trying to convince others if they continue to feel
>>> that the tradeoffs here should be in the direction of returning only
>>> specific types (disallowing users from specifying downcasting in that
>>> manner), versus using types of the form T extends X,
>>> which allows users to specify downcasting.
>>>
>>
>> The case of FSIndexRepository is maybe more clear
>> then the other cases in our API.
>>
>> With down casting it could be changed to
>>
>> interface FSIndexRepository {
>>  FSIndex getIndex(String label);
>>  FSIterator getAllIndexedFS(Type aType);
>> ...
>> }
>>
>> and then a user could write
>>
>> FSIndex index = repo.getIndex(...);
>> FSIterator it = repo.getAllIndexedFS(...);
>
> Any opinions on this ? Right now the class is not generified but I
> would like to change that before the release.
>

I say no since like our other discussions, I don't like cases where
there's no guarantee of correctness.  A user can write:
FSIterator it = repo.getAllIndexedFS(someNonAnnotationTypeCode);

and it would compile even though it doesn't make sense.

Something like this for JCas, on the other hand, does make sense to me:

FSIterator getAllIndexedFS(Class jcasType)

which is called like
FSIterator it = jcas.getAllIndexedFS(MyAnnotationType.class);

 -Adam


Re: clarifying a generics issue

2009-08-12 Thread Thilo Goetz
Jörn Kottmann wrote:
> Jörn Kottmann wrote:
>> Marshall Schor wrote:
>>> I'll probably stop trying to convince others if they continue to feel
>>> that the tradeoffs here should be in the direction of returning only
>>> specific types (disallowing users from specifying downcasting in that
>>> manner), versus using types of the form T extends X,
>>> which allows users to specify downcasting.
>>>   
>> The case of FSIndexRepository is maybe more clear
>> then the other cases in our API.
>>
>> With down casting it could be changed to
>>
>> interface FSIndexRepository {
>>  FSIndex getIndex(String label);
>>  FSIterator getAllIndexedFS(Type aType);
>> ...
>> }
>>
>> and then a user could write
>>
>> FSIndex index = repo.getIndex(...);
>> FSIterator it = repo.getAllIndexedFS(...);
> Any opinions on this ? Right now the class is not generified but I
> would like to change that before the release.
> 
> Jörn

Will our average user know what this means?  If you
think the answer to that is "yes", then I'm for it.
I personally believe the answer is probably "no".

--Thilo


Re: clarifying a generics issue

2009-08-12 Thread Jörn Kottmann

Jörn Kottmann wrote:

Marshall Schor wrote:

I'll probably stop trying to convince others if they continue to feel
that the tradeoffs here should be in the direction of returning only
specific types (disallowing users from specifying downcasting in that
manner), versus using types of the form T extends X,
which allows users to specify downcasting.
  

The case of FSIndexRepository is maybe more clear
then the other cases in our API.

With down casting it could be changed to

interface FSIndexRepository {
 FSIndex getIndex(String label);
 FSIterator getAllIndexedFS(Type aType);
...
}

and then a user could write

FSIndex index = repo.getIndex(...);
FSIterator it = repo.getAllIndexedFS(...);

Any opinions on this ? Right now the class is not generified but I
would like to change that before the release.

Jörn


Re: clarifying a generics issue

2009-08-11 Thread Adam Lally
On Tue, Aug 11, 2009 at 10:44 AM, Jörn Kottmann wrote:
> Adam Lally wrote:
>>
> Lets say we have an interface Box{Number getNumber()}
> then we could have a class BoxImpl implements Box{Integer getNumber(){...}}.
>
> Now I only would have to cast once
> Box box = ...;
> BoxImpl boxImpl = (BoxImpl) box;
>
> now
> Integer number = boxImpl.getNumber()
> would work. Sure if you do the same for CAS and CASImpl
> you safe lots of casts.
>
> The same does not work for a getNumbers which
> returns a List or Iterator
> without also allowing down casting.
>

Well, true, but it does not really create an analogous solution if you do:
interface Box{List getNumberList()}
class BoxImpl{List numberList()}

Because a client could call
List x = box.getNumberList()

whether or not box was actually a BoxImpl.

 -Adam


Re: clarifying a generics issue

2009-08-11 Thread Jörn Kottmann

Adam Lally wrote:

On Mon, Aug 10, 2009 at 9:00 PM, Marshall Schor wrote:
  

Here's a new thread to discuss just one particular issue - a generics
tradeoff.

In other posts, people have expressed misgivings about letting users
"downcast" List to List, if it cannot be
*guaranteed* at compile time that this is valid.

Here's a simple example, for instance, using two built-in Java classes:
 Number
   Integer (a subtype of Number)

If we have a method which returns a List, and you happen to know
it only contains Integers, and you want to use a for-each on it with a
method that only exists in the Integer class, you have to do manual
casting within the loop.

An alternative might have been to do:
 List numbers = ...;
 List int_version = numbers;  // not allowed, gives compile error

So once we're given the "numbers" object, as far as I can see, we're
stuck with its typing.  (Please tell me if I'm wrong here).

I see that there is a trade-off between specifying return types as
specific types, and specifying them as T extends X, and letting the user
specify a possibly incorrect downcast.  The tradeoff on the plus side is
that the user gets to write the new style for-each loops, and have code
without casts inside loops, etc., and on the minus side, the user when
doing this gets that warning about the possibility that at runtime a
casting error could be thrown.  But of course, that same casting error
could be thrown in restricted style, too, at the point of the explicit
user cast.

I'll probably stop trying to convince others if they continue to feel
that the tradeoffs here should be in the direction of returning only
specific types (disallowing users from specifying downcasting in that
manner), versus using types of the form T extends X,
which allows users to specify downcasting.

I'd be interested in any literature pointers discussing this trade-off
issue, if anyone has good ones :-)




One other way to look at this - why are Collections any different than
methods that return single elements?  If I have a method
Number getNumber()

and I "know" in some situation that the Number is really an Integer,
should I be able to call:

Integer x = getNumber()?

Normally such a thing is not allowed without an explicit cast.  And
for me at least I just take that for granted as part of what a
strongly-typed language does, so it's very bizarre to think of it not
doing that.

  

Lets say we have an interface Box{Number getNumber()}
then we could have a class BoxImpl implements Box{Integer getNumber(){...}}.

Now I only would have to cast once
Box box = ...;
BoxImpl boxImpl = (BoxImpl) box;

now
Integer number = boxImpl.getNumber()
would work. Sure if you do the same for CAS and CASImpl
you safe lots of casts.

The same does not work for a getNumbers which
returns a List or Iterator
without also allowing down casting.

Jörn


Re: clarifying a generics issue

2009-08-11 Thread Adam Lally
On Tue, Aug 11, 2009 at 7:50 AM, Marshall Schor wrote:
> A small correction: allowing downcasting doesn't generate a warning
> about unchecked casting.
>
> Here's a small test case in case you want to play with this:
>
> package generics;
>
> import java.util.List;
>
> public class TestG {
>
>  class Box {  // version returning down-castable thing
>     U get() {return null;}
>     List getL() {return null;}
>  }
>
>  class StrictBox {  // version returning just type T
>    T get() {return null;}
>    List getL() {return null;}
>  }
>
>  Box box = new Box();
>  StrictBox sbox = new StrictBox();
>
>  void test() {
>    // returning elements
>    Number n = box.get();   // OK
>    Integer n2 = box.get(); // OK
>
>    Number sn = sbox.get();   // OK
>    Integer sn2 = sbox.get(); // fails
>    Integer sn3 = (Integer) sbox.get(); // OK
>
>    // returning lists
>    List ln = box.getL();   // OK
>    List ln2 = box.getL(); // OK
>
>    List sln = sbox.getL(); // OK
>    List sln2 = sbox.getL(): // fails, no fix available
>  }
> }
>

For a complete picture you should also try to implement the methods to
return something other that null.  For example how to you implement
 U get() such that it returns an instance of U regardless
of what U is?  You could only do this with a typecast.  And you'd have
to expectation that the typecast would actually succeed.

  -Adam


Re: clarifying a generics issue

2009-08-11 Thread Adam Lally
On Mon, Aug 10, 2009 at 9:00 PM, Marshall Schor wrote:
> Here's a new thread to discuss just one particular issue - a generics
> tradeoff.
>
> In other posts, people have expressed misgivings about letting users
> "downcast" List to List, if it cannot be
> *guaranteed* at compile time that this is valid.
>
> Here's a simple example, for instance, using two built-in Java classes:
>  Number
>    Integer (a subtype of Number)
>
> If we have a method which returns a List, and you happen to know
> it only contains Integers, and you want to use a for-each on it with a
> method that only exists in the Integer class, you have to do manual
> casting within the loop.
>
> An alternative might have been to do:
>  List numbers = ...;
>  List int_version = numbers;  // not allowed, gives compile error
>
> So once we're given the "numbers" object, as far as I can see, we're
> stuck with its typing.  (Please tell me if I'm wrong here).
>
> I see that there is a trade-off between specifying return types as
> specific types, and specifying them as T extends X, and letting the user
> specify a possibly incorrect downcast.  The tradeoff on the plus side is
> that the user gets to write the new style for-each loops, and have code
> without casts inside loops, etc., and on the minus side, the user when
> doing this gets that warning about the possibility that at runtime a
> casting error could be thrown.  But of course, that same casting error
> could be thrown in restricted style, too, at the point of the explicit
> user cast.
>
> I'll probably stop trying to convince others if they continue to feel
> that the tradeoffs here should be in the direction of returning only
> specific types (disallowing users from specifying downcasting in that
> manner), versus using types of the form T extends X,
> which allows users to specify downcasting.
>
> I'd be interested in any literature pointers discussing this trade-off
> issue, if anyone has good ones :-)
>

One other way to look at this - why are Collections any different than
methods that return single elements?  If I have a method
Number getNumber()

and I "know" in some situation that the Number is really an Integer,
should I be able to call:

Integer x = getNumber()?

Normally such a thing is not allowed without an explicit cast.  And
for me at least I just take that for granted as part of what a
strongly-typed language does, so it's very bizarre to think of it not
doing that.

 -Adam


Re: clarifying a generics issue

2009-08-11 Thread Jörn Kottmann

Marshall Schor wrote:

I'll probably stop trying to convince others if they continue to feel
that the tradeoffs here should be in the direction of returning only
specific types (disallowing users from specifying downcasting in that
manner), versus using types of the form T extends X,
which allows users to specify downcasting.
  

The case of FSIndexRepository is maybe more clear
then the other cases in our API.

With down casting it could be changed to

interface FSIndexRepository {
 FSIndex getIndex(String label);
 FSIterator getAllIndexedFS(Type aType);
...
}

and then a user could write

FSIndex index = repo.getIndex(...);
FSIterator it = repo.getAllIndexedFS(...);

Jörn


Re: clarifying a generics issue

2009-08-11 Thread Marshall Schor
A small correction: allowing downcasting doesn't generate a warning
about unchecked casting.

Here's a small test case in case you want to play with this:

package generics;

import java.util.List;

public class TestG {

  class Box {  // version returning down-castable thing
 U get() {return null;}
 List getL() {return null;}
  }
 
  class StrictBox {  // version returning just type T
T get() {return null;}
List getL() {return null;}
  }

  Box box = new Box(); 
  StrictBox sbox = new StrictBox();
 
  void test() {
// returning elements
Number n = box.get();   // OK
Integer n2 = box.get(); // OK
   
Number sn = sbox.get();   // OK
Integer sn2 = sbox.get(); // fails
Integer sn3 = (Integer) sbox.get(); // OK
   
// returning lists
List ln = box.getL();   // OK
List ln2 = box.getL(); // OK
   
List sln = sbox.getL(); // OK
List sln2 = sbox.getL(): // fails, no fix available  
  }
}

-Marshall

Marshall Schor wrote:
> Here's a new thread to discuss just one particular issue - a generics
> tradeoff.
>
> In other posts, people have expressed misgivings about letting users
> "downcast" List to List, if it cannot be
> *guaranteed* at compile time that this is valid.
>
> Here's a simple example, for instance, using two built-in Java classes:
>   Number
> Integer (a subtype of Number)
>
> If we have a method which returns a List, and you happen to know
> it only contains Integers, and you want to use a for-each on it with a
> method that only exists in the Integer class, you have to do manual
> casting within the loop.
>
> An alternative might have been to do:
>   List numbers = ...;
>   List int_version = numbers;  // not allowed, gives compile error
>
> So once we're given the "numbers" object, as far as I can see, we're
> stuck with its typing.  (Please tell me if I'm wrong here).
>
> I see that there is a trade-off between specifying return types as
> specific types, and specifying them as T extends X, and letting the user
> specify a possibly incorrect downcast.  The tradeoff on the plus side is
> that the user gets to write the new style for-each loops, and have code
> without casts inside loops, etc., and on the minus side, the user when
> doing this gets that warning about the possibility that at runtime a
> casting error could be thrown.  But of course, that same casting error
> could be thrown in restricted style, too, at the point of the explicit
> user cast.
>
> I'll probably stop trying to convince others if they continue to feel
> that the tradeoffs here should be in the direction of returning only
> specific types (disallowing users from specifying downcasting in that
> manner), versus using types of the form T extends X,
> which allows users to specify downcasting.
>
> I'd be interested in any literature pointers discussing this trade-off
> issue, if anyone has good ones :-)
>
> -Marshall
>
>
>