You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@uima.apache.org by Marshall Schor <ms...@schor.com> on 2009/08/07 20:32:38 UTC

generics: createFilteredIterator

The createFilteredIterator method in CASImpl takes an FSIterator and an
FSMatchConstraint, and returns another iterator.

The generification of this is:
  public<T extends FeatureStructure> FSIterator<T>
createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons) {
    return new FilteredIterator<T>(it, cons);}

This means that the type of the objects being returned will be the same
as the type of the objects of the iterator passed in.

If the effect of the filtering is to filter the first iterator down to a
subset of the types of the original, this cannot be represented with
this signature.

An alternate generification might be as follows, with type T being the
type the input iterator gives out, and U being the type the filtered
iterator produces:

  public<T extends FeatureStructure, U extends T> FSIterator<U>
createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons) {
    return new FilteredIterator<T, U>(it, cons);}

with the corresponding changes to the class FilteredIterator, and the
CAS interface (to match this new signature).

With these changes, users can write code:
  public static void t3(CAS aCas, FSIterator<FeatureStructure> it,
FSMatchConstraint cons) {
    FSIterator<Subtype> s = aCas.createFilteredIterator(it, cons);
  }

Without these changes, users would be forced to have the filtered
iterator's generic type always equal to the original type.

Is this something we should change (given that we only get one chance to
do our generification)?

-Marshall (looking forward to increasing his understanding of generics... )


Re: generics: createFilteredIterator

Posted by Thilo Goetz <tw...@gmx.de>.
Jörn Kottmann wrote:
> Thilo Goetz wrote:
>> Jörn Kottmann wrote:
>>  
>>> Thilo Goetz wrote:
>>>    
>>>> Jörn Kottmann wrote:
>>>>  
>>>>      
>>>>> Adam Lally wrote:
>>>>>           
>>>>>> On Fri, Aug 7, 2009 at 2:32 PM, Marshall Schor<ms...@schor.com> wrote:
>>>>>>  
>>>>>>               
>>>>>>> The createFilteredIterator method in CASImpl takes an FSIterator
>>>>>>> and an
>>>>>>> FSMatchConstraint, and returns another iterator.
>>>>>>>
>>>>>>> The generification of this is:
>>>>>>>  public<T extends FeatureStructure> FSIterator<T>
>>>>>>> createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons) {
>>>>>>>    return new FilteredIterator<T>(it, cons);}
>>>>>>>
>>>>>>> This means that the type of the objects being returned will be the
>>>>>>> same
>>>>>>> as the type of the objects of the iterator passed in.
>>>>>>>
>>>>>>> If the effect of the filtering is to filter the first iterator down
>>>>>>> to a
>>>>>>> subset of the types of the original, this cannot be represented with
>>>>>>> this signature.
>>>>>>>
>>>>>>> An alternate generification might be as follows, with type T
>>>>>>> being the
>>>>>>> type the input iterator gives out, and U being the type the filtered
>>>>>>> iterator produces:
>>>>>>>
>>>>>>>  public<T extends FeatureStructure, U extends T> FSIterator<U>
>>>>>>> createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons) {
>>>>>>>    return new FilteredIterator<T, U>(it, cons);}
>>>>>>>
>>>>>>> with the corresponding changes to the class FilteredIterator, and
>>>>>>> the
>>>>>>> CAS interface (to match this new signature).
>>>>>>>
>>>>>>> With these changes, users can write code:
>>>>>>>  public static void t3(CAS aCas, FSIterator<FeatureStructure> it,
>>>>>>> FSMatchConstraint cons) {
>>>>>>>    FSIterator<Subtype> s = aCas.createFilteredIterator(it, cons);
>>>>>>>  }
>>>>>>>
>>>>>>> Without these changes, users would be forced to have the filtered
>>>>>>> iterator's generic type always equal to the original type.
>>>>>>>
>>>>>>> Is this something we should change (given that we only get one
>>>>>>> chance to
>>>>>>> do our generification)?
>>>>>>>
>>>>>>>                         
>>>>>> I'm not sure.  This user's code would compile regardless of whether
>>>>>> the FSMatchConstraint actually implemented the subtype constraint or
>>>>>> not.  It's quite possible that the code would compile and then fail
>>>>>> with a ClassCastException.
>>>>>>                   
>>>>> Yes, but if someone writes it intentional he would get the same
>>>>> exception during class casting. That means not doing it would only
>>>>> help
>>>>> someone who picks the wrong type for the variable by accident,
>>>>> since its
>>>>> likely that
>>>>> the code cannot run it will fail immediately.
>>>>>
>>>>> Another option would be to add a new createFilteredIterator method
>>>>> which
>>>>> takes a Class object as argument and then reduces its output to
>>>>> objects
>>>>> which
>>>>> have the type of the class.
>>>>>
>>>>> <T extends FeatureStructure> FSIterator<T> createFilteredIterator(...,
>>>>> Class<T> type)
>>>>>
>>>>> Since it only returns objects of the correct type T it should not
>>>>> fail.
>>>>>
>>>>> Jörn
>>>>>
>>>>>             
>>>> That would work only for the JCas, obviously.  However, the JCas
>>>> does not use Java classes to represent UIMA types (there's probably
>>>> a good reason for that, but I don't know what it is).
>>>>         
>>> It can work for both JCas and CAS. In the CAS case the implementation
>>> of the method could use Class.isInstance to filter out objects which
>>> have the wrong type.
>>>
>>> Jörn
>>>
>>>     
>>
>> In the CAS there are only FeatureStructures and AnnotationFSs.  If
>> you don't generate JCas classes, you don't have Java classes for
>> types.  Or am I missing something?
>>   
> And we have the array types. Sure if you work with a CAS
> you certainly almost want AnnotationFS if you don't want FeatureStructure.
> But working with annotations is a common case and should work well with
> generics.
> 

Whatever.  I don't think it's worth the added complexity of
the interface, but if you feel differently, go ahead.  I'm
thinking of defecting to Scala land anyway ;-)

--Thilo

Re: generics: createFilteredIterator

Posted by Jörn Kottmann <ko...@gmail.com>.
Thilo Goetz wrote:
> Jörn Kottmann wrote:
>   
>> Thilo Goetz wrote:
>>     
>>> Jörn Kottmann wrote:
>>>  
>>>       
>>>> Adam Lally wrote:
>>>>    
>>>>         
>>>>> On Fri, Aug 7, 2009 at 2:32 PM, Marshall Schor<ms...@schor.com> wrote:
>>>>>  
>>>>>      
>>>>>           
>>>>>> The createFilteredIterator method in CASImpl takes an FSIterator
>>>>>> and an
>>>>>> FSMatchConstraint, and returns another iterator.
>>>>>>
>>>>>> The generification of this is:
>>>>>>  public<T extends FeatureStructure> FSIterator<T>
>>>>>> createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons) {
>>>>>>    return new FilteredIterator<T>(it, cons);}
>>>>>>
>>>>>> This means that the type of the objects being returned will be the
>>>>>> same
>>>>>> as the type of the objects of the iterator passed in.
>>>>>>
>>>>>> If the effect of the filtering is to filter the first iterator down
>>>>>> to a
>>>>>> subset of the types of the original, this cannot be represented with
>>>>>> this signature.
>>>>>>
>>>>>> An alternate generification might be as follows, with type T being the
>>>>>> type the input iterator gives out, and U being the type the filtered
>>>>>> iterator produces:
>>>>>>
>>>>>>  public<T extends FeatureStructure, U extends T> FSIterator<U>
>>>>>> createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons) {
>>>>>>    return new FilteredIterator<T, U>(it, cons);}
>>>>>>
>>>>>> with the corresponding changes to the class FilteredIterator, and the
>>>>>> CAS interface (to match this new signature).
>>>>>>
>>>>>> With these changes, users can write code:
>>>>>>  public static void t3(CAS aCas, FSIterator<FeatureStructure> it,
>>>>>> FSMatchConstraint cons) {
>>>>>>    FSIterator<Subtype> s = aCas.createFilteredIterator(it, cons);
>>>>>>  }
>>>>>>
>>>>>> Without these changes, users would be forced to have the filtered
>>>>>> iterator's generic type always equal to the original type.
>>>>>>
>>>>>> Is this something we should change (given that we only get one
>>>>>> chance to
>>>>>> do our generification)?
>>>>>>
>>>>>>             
>>>>>>             
>>>>> I'm not sure.  This user's code would compile regardless of whether
>>>>> the FSMatchConstraint actually implemented the subtype constraint or
>>>>> not.  It's quite possible that the code would compile and then fail
>>>>> with a ClassCastException.
>>>>>         
>>>>>           
>>>> Yes, but if someone writes it intentional he would get the same
>>>> exception during class casting. That means not doing it would only help
>>>> someone who picks the wrong type for the variable by accident, since its
>>>> likely that
>>>> the code cannot run it will fail immediately.
>>>>
>>>> Another option would be to add a new createFilteredIterator method which
>>>> takes a Class object as argument and then reduces its output to objects
>>>> which
>>>> have the type of the class.
>>>>
>>>> <T extends FeatureStructure> FSIterator<T> createFilteredIterator(...,
>>>> Class<T> type)
>>>>
>>>> Since it only returns objects of the correct type T it should not fail.
>>>>
>>>> Jörn
>>>>
>>>>     
>>>>         
>>> That would work only for the JCas, obviously.  However, the JCas
>>> does not use Java classes to represent UIMA types (there's probably
>>> a good reason for that, but I don't know what it is).
>>>   
>>>       
>> It can work for both JCas and CAS. In the CAS case the implementation
>> of the method could use Class.isInstance to filter out objects which
>> have the wrong type.
>>
>> Jörn
>>
>>     
>
> In the CAS there are only FeatureStructures and AnnotationFSs.  If
> you don't generate JCas classes, you don't have Java classes for
> types.  Or am I missing something?
>   
And we have the array types. Sure if you work with a CAS
you certainly almost want AnnotationFS if you don't want FeatureStructure.
But working with annotations is a common case and should work well with 
generics.

Re: generics: createFilteredIterator

Posted by Thilo Goetz <tw...@gmx.de>.
Jörn Kottmann wrote:
> Thilo Goetz wrote:
>> Jörn Kottmann wrote:
>>  
>>> Adam Lally wrote:
>>>    
>>>> On Fri, Aug 7, 2009 at 2:32 PM, Marshall Schor<ms...@schor.com> wrote:
>>>>  
>>>>      
>>>>> The createFilteredIterator method in CASImpl takes an FSIterator
>>>>> and an
>>>>> FSMatchConstraint, and returns another iterator.
>>>>>
>>>>> The generification of this is:
>>>>>  public<T extends FeatureStructure> FSIterator<T>
>>>>> createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons) {
>>>>>    return new FilteredIterator<T>(it, cons);}
>>>>>
>>>>> This means that the type of the objects being returned will be the
>>>>> same
>>>>> as the type of the objects of the iterator passed in.
>>>>>
>>>>> If the effect of the filtering is to filter the first iterator down
>>>>> to a
>>>>> subset of the types of the original, this cannot be represented with
>>>>> this signature.
>>>>>
>>>>> An alternate generification might be as follows, with type T being the
>>>>> type the input iterator gives out, and U being the type the filtered
>>>>> iterator produces:
>>>>>
>>>>>  public<T extends FeatureStructure, U extends T> FSIterator<U>
>>>>> createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons) {
>>>>>    return new FilteredIterator<T, U>(it, cons);}
>>>>>
>>>>> with the corresponding changes to the class FilteredIterator, and the
>>>>> CAS interface (to match this new signature).
>>>>>
>>>>> With these changes, users can write code:
>>>>>  public static void t3(CAS aCas, FSIterator<FeatureStructure> it,
>>>>> FSMatchConstraint cons) {
>>>>>    FSIterator<Subtype> s = aCas.createFilteredIterator(it, cons);
>>>>>  }
>>>>>
>>>>> Without these changes, users would be forced to have the filtered
>>>>> iterator's generic type always equal to the original type.
>>>>>
>>>>> Is this something we should change (given that we only get one
>>>>> chance to
>>>>> do our generification)?
>>>>>
>>>>>             
>>>> I'm not sure.  This user's code would compile regardless of whether
>>>> the FSMatchConstraint actually implemented the subtype constraint or
>>>> not.  It's quite possible that the code would compile and then fail
>>>> with a ClassCastException.
>>>>         
>>> Yes, but if someone writes it intentional he would get the same
>>> exception during class casting. That means not doing it would only help
>>> someone who picks the wrong type for the variable by accident, since its
>>> likely that
>>> the code cannot run it will fail immediately.
>>>
>>> Another option would be to add a new createFilteredIterator method which
>>> takes a Class object as argument and then reduces its output to objects
>>> which
>>> have the type of the class.
>>>
>>> <T extends FeatureStructure> FSIterator<T> createFilteredIterator(...,
>>> Class<T> type)
>>>
>>> Since it only returns objects of the correct type T it should not fail.
>>>
>>> Jörn
>>>
>>>     
>>
>> That would work only for the JCas, obviously.  However, the JCas
>> does not use Java classes to represent UIMA types (there's probably
>> a good reason for that, but I don't know what it is).
>>   
> It can work for both JCas and CAS. In the CAS case the implementation
> of the method could use Class.isInstance to filter out objects which
> have the wrong type.
> 
> Jörn
> 

In the CAS there are only FeatureStructures and AnnotationFSs.  If
you don't generate JCas classes, you don't have Java classes for
types.  Or am I missing something?

--Thilo

Re: generics: createFilteredIterator

Posted by Jörn Kottmann <ko...@gmail.com>.
Thilo Goetz wrote:
> Jörn Kottmann wrote:
>   
>> Adam Lally wrote:
>>     
>>> On Fri, Aug 7, 2009 at 2:32 PM, Marshall Schor<ms...@schor.com> wrote:
>>>  
>>>       
>>>> The createFilteredIterator method in CASImpl takes an FSIterator and an
>>>> FSMatchConstraint, and returns another iterator.
>>>>
>>>> The generification of this is:
>>>>  public<T extends FeatureStructure> FSIterator<T>
>>>> createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons) {
>>>>    return new FilteredIterator<T>(it, cons);}
>>>>
>>>> This means that the type of the objects being returned will be the same
>>>> as the type of the objects of the iterator passed in.
>>>>
>>>> If the effect of the filtering is to filter the first iterator down to a
>>>> subset of the types of the original, this cannot be represented with
>>>> this signature.
>>>>
>>>> An alternate generification might be as follows, with type T being the
>>>> type the input iterator gives out, and U being the type the filtered
>>>> iterator produces:
>>>>
>>>>  public<T extends FeatureStructure, U extends T> FSIterator<U>
>>>> createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons) {
>>>>    return new FilteredIterator<T, U>(it, cons);}
>>>>
>>>> with the corresponding changes to the class FilteredIterator, and the
>>>> CAS interface (to match this new signature).
>>>>
>>>> With these changes, users can write code:
>>>>  public static void t3(CAS aCas, FSIterator<FeatureStructure> it,
>>>> FSMatchConstraint cons) {
>>>>    FSIterator<Subtype> s = aCas.createFilteredIterator(it, cons);
>>>>  }
>>>>
>>>> Without these changes, users would be forced to have the filtered
>>>> iterator's generic type always equal to the original type.
>>>>
>>>> Is this something we should change (given that we only get one chance to
>>>> do our generification)?
>>>>
>>>>     
>>>>         
>>> I'm not sure.  This user's code would compile regardless of whether
>>> the FSMatchConstraint actually implemented the subtype constraint or
>>> not.  It's quite possible that the code would compile and then fail
>>> with a ClassCastException.
>>>   
>>>       
>> Yes, but if someone writes it intentional he would get the same
>> exception during class casting. That means not doing it would only help
>> someone who picks the wrong type for the variable by accident, since its
>> likely that
>> the code cannot run it will fail immediately.
>>
>> Another option would be to add a new createFilteredIterator method which
>> takes a Class object as argument and then reduces its output to objects
>> which
>> have the type of the class.
>>
>> <T extends FeatureStructure> FSIterator<T> createFilteredIterator(...,
>> Class<T> type)
>>
>> Since it only returns objects of the correct type T it should not fail.
>>
>> Jörn
>>
>>     
>
> That would work only for the JCas, obviously.  However, the JCas
> does not use Java classes to represent UIMA types (there's probably
> a good reason for that, but I don't know what it is).
>   
It can work for both JCas and CAS. In the CAS case the implementation
of the method could use Class.isInstance to filter out objects which
have the wrong type.

Jörn

Re: generics: createFilteredIterator

Posted by Thilo Goetz <tw...@gmx.de>.
Jörn Kottmann wrote:
> Adam Lally wrote:
>> On Fri, Aug 7, 2009 at 2:32 PM, Marshall Schor<ms...@schor.com> wrote:
>>  
>>> The createFilteredIterator method in CASImpl takes an FSIterator and an
>>> FSMatchConstraint, and returns another iterator.
>>>
>>> The generification of this is:
>>>  public<T extends FeatureStructure> FSIterator<T>
>>> createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons) {
>>>    return new FilteredIterator<T>(it, cons);}
>>>
>>> This means that the type of the objects being returned will be the same
>>> as the type of the objects of the iterator passed in.
>>>
>>> If the effect of the filtering is to filter the first iterator down to a
>>> subset of the types of the original, this cannot be represented with
>>> this signature.
>>>
>>> An alternate generification might be as follows, with type T being the
>>> type the input iterator gives out, and U being the type the filtered
>>> iterator produces:
>>>
>>>  public<T extends FeatureStructure, U extends T> FSIterator<U>
>>> createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons) {
>>>    return new FilteredIterator<T, U>(it, cons);}
>>>
>>> with the corresponding changes to the class FilteredIterator, and the
>>> CAS interface (to match this new signature).
>>>
>>> With these changes, users can write code:
>>>  public static void t3(CAS aCas, FSIterator<FeatureStructure> it,
>>> FSMatchConstraint cons) {
>>>    FSIterator<Subtype> s = aCas.createFilteredIterator(it, cons);
>>>  }
>>>
>>> Without these changes, users would be forced to have the filtered
>>> iterator's generic type always equal to the original type.
>>>
>>> Is this something we should change (given that we only get one chance to
>>> do our generification)?
>>>
>>>     
>>
>> I'm not sure.  This user's code would compile regardless of whether
>> the FSMatchConstraint actually implemented the subtype constraint or
>> not.  It's quite possible that the code would compile and then fail
>> with a ClassCastException.
>>   
> Yes, but if someone writes it intentional he would get the same
> exception during class casting. That means not doing it would only help
> someone who picks the wrong type for the variable by accident, since its
> likely that
> the code cannot run it will fail immediately.
> 
> Another option would be to add a new createFilteredIterator method which
> takes a Class object as argument and then reduces its output to objects
> which
> have the type of the class.
> 
> <T extends FeatureStructure> FSIterator<T> createFilteredIterator(...,
> Class<T> type)
> 
> Since it only returns objects of the correct type T it should not fail.
> 
> Jörn
> 

That would work only for the JCas, obviously.  However, the JCas
does not use Java classes to represent UIMA types (there's probably
a good reason for that, but I don't know what it is).

--Thilo

Re: generics: createFilteredIterator

Posted by Adam Lally <al...@alum.rpi.edu>.
On Wed, Aug 12, 2009 at 3:08 PM, Marshall Schor<ms...@schor.com> wrote:
> Jörn Kottmann wrote:
>> Adam Lally wrote:
>>> On Wed, Aug 12, 2009 at 5:54 AM, Jörn Kottmann<ko...@gmail.com>
>>> wrote:
>>>
>>>> Yes, but if someone writes it intentional he would get the same
>>>> exception during class casting. That means not doing it would only help
>>>> someone who picks the wrong type for the variable by accident, since
>>>> its
>>>> likely that
>>>> the code cannot run it will fail immediately.
>>>>
>>>>
>>>
>>> If ClassCastExceptions are going to happen I'd *much* rather they be
>>> on explicit casts in user code rather than in framework code.  It's
>>> more straightforward for the user to understand and fix the problem in
>>> that case.
>>>
>>> But really, it more comes down to philosophy. My understanding of how
>>> to use generics is that you should use them in places where the API
>>> guarantees it complies with the type constraint.  That way it makes
>>> the API more understandable than just using raw types.  I think that
>>> putting in things which may or may not work makes the API less
>>> understandable and is really not a good idea.  I don't believe that
>>> using generics just to avoid having to do typecasts is the right idea
>>> at all.  I'm not aware of cases where that has been done in the Java
>>> class libraries, for example - if there are, point them out.  This is
>>> why I'm fighting tooth and nail against taking UIMA in that direction.
>>>
>>>
>>>> Another option would be to add a new createFilteredIterator method
>>>> which
>>>> takes a Class object as argument and then reduces its output to objects
>>>> which
>>>> have the type of the class.
>>>>
>>>> <T extends FeatureStructure> FSIterator<T> createFilteredIterator(...,
>>>> Class<T> type)
>>>>
>>>> Since it only returns objects of the correct type T it should not fail.
>>>>
>>>>
>>>
>>> Yes, I wouldn't strenuously object to that but I doubt it's usefulness
>>> for createFilteredIterator.  I do think something like that is nice in
>>> JCas for getting an iterator over all instances of a specific type, as
>>> I suggested on another thread.
>>>
>> In the end that means that we can leave this method in CAS and JCas
>> like it is right now:
>> <T extends FeatureStructure> FSIterator<T>
>> createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons);
>>
> +1
>> A method like I proposed can be added to the CAS interface after the
>> next release if we decide
>> its necessary. Do we want to add the method proposed by Adam for 2.3.0
>> to JCas ?
> Adam's suggested method proposed in another thread was:
>
> FSIterator<T extends TOP> getAllIndexedFS(Class<T> jcasType)
>
> This method is on a particular index, or on an instance of the JFSIndexRepository (or the equivalent non-JCas one).
>
> Currently the JFSIndexRepository doesn't have methods for returning iterators picked by [Class<T> jcasType], but I think these could be easily added, and I'm +1 for this.
>
> There are also methods on the JCas itself for returning instances of AnnotationIndex
> public AnnotationIndex getAnnotationIndex(Type type)
>
> I would also be +1 for adding a version of this:
> public AnnotationIndex<T extends Annotation> getAnnotationIndex(Class<T> jcasType)
>
> I would also be +1 for adding versions of getAllIndexedFS to the JCasImpl itself, avoiding the need to do
> aJCas.getJFSIndexRepository().getAllIndexedFS...  which I think is more an implementation detail than a needed API feature. (please correct this impression if I'm mistaken...).
>

+1 to all.

BTW, see here for an implementation I posted previously of a method
for returning an Iterable over a specfic FS type.  Of course we can
also have a method that returns the iterator itself.
http://www.mail-archive.com/uima-dev@incubator.apache.org/msg04657.html

 -Adam

Re: generics: createFilteredIterator

Posted by Marshall Schor <ms...@schor.com>.
Jörn Kottmann wrote:
> Adam Lally wrote:
>> On Wed, Aug 12, 2009 at 5:54 AM, Jörn Kottmann<ko...@gmail.com>
>> wrote:
>>  
>>> Yes, but if someone writes it intentional he would get the same
>>> exception during class casting. That means not doing it would only help
>>> someone who picks the wrong type for the variable by accident, since
>>> its
>>> likely that
>>> the code cannot run it will fail immediately.
>>>
>>>     
>>
>> If ClassCastExceptions are going to happen I'd *much* rather they be
>> on explicit casts in user code rather than in framework code.  It's
>> more straightforward for the user to understand and fix the problem in
>> that case.
>>
>> But really, it more comes down to philosophy. My understanding of how
>> to use generics is that you should use them in places where the API
>> guarantees it complies with the type constraint.  That way it makes
>> the API more understandable than just using raw types.  I think that
>> putting in things which may or may not work makes the API less
>> understandable and is really not a good idea.  I don't believe that
>> using generics just to avoid having to do typecasts is the right idea
>> at all.  I'm not aware of cases where that has been done in the Java
>> class libraries, for example - if there are, point them out.  This is
>> why I'm fighting tooth and nail against taking UIMA in that direction.
>>
>>  
>>> Another option would be to add a new createFilteredIterator method
>>> which
>>> takes a Class object as argument and then reduces its output to objects
>>> which
>>> have the type of the class.
>>>
>>> <T extends FeatureStructure> FSIterator<T> createFilteredIterator(...,
>>> Class<T> type)
>>>
>>> Since it only returns objects of the correct type T it should not fail.
>>>
>>>     
>>
>> Yes, I wouldn't strenuously object to that but I doubt it's usefulness
>> for createFilteredIterator.  I do think something like that is nice in
>> JCas for getting an iterator over all instances of a specific type, as
>> I suggested on another thread.
>>   
> In the end that means that we can leave this method in CAS and JCas
> like it is right now:
> <T extends FeatureStructure> FSIterator<T>
> createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons);
>
+1
> A method like I proposed can be added to the CAS interface after the
> next release if we decide
> its necessary. Do we want to add the method proposed by Adam for 2.3.0
> to JCas ?
Adam's suggested method proposed in another thread was:

FSIterator<T extends TOP> getAllIndexedFS(Class<T> jcasType)

This method is on a particular index, or on an instance of the JFSIndexRepository (or the equivalent non-JCas one).

Currently the JFSIndexRepository doesn't have methods for returning iterators picked by [Class<T> jcasType], but I think these could be easily added, and I'm +1 for this.

There are also methods on the JCas itself for returning instances of AnnotationIndex
public AnnotationIndex getAnnotationIndex(Type type)

I would also be +1 for adding a version of this:
public AnnotationIndex<T extends Annotation> getAnnotationIndex(Class<T> jcasType)

I would also be +1 for adding versions of getAllIndexedFS to the JCasImpl itself, avoiding the need to do
aJCas.getJFSIndexRepository().getAllIndexedFS...  which I think is more an implementation detail than a needed API feature. (please correct this impression if I'm mistaken...).

-Marshall


>
> Jörn
>

Re: generics: createFilteredIterator

Posted by Jörn Kottmann <ko...@gmail.com>.
Adam Lally wrote:
> On Wed, Aug 12, 2009 at 5:54 AM, Jörn Kottmann<ko...@gmail.com> wrote:
>   
>> Yes, but if someone writes it intentional he would get the same
>> exception during class casting. That means not doing it would only help
>> someone who picks the wrong type for the variable by accident, since its
>> likely that
>> the code cannot run it will fail immediately.
>>
>>     
>
> If ClassCastExceptions are going to happen I'd *much* rather they be
> on explicit casts in user code rather than in framework code.  It's
> more straightforward for the user to understand and fix the problem in
> that case.
>
> But really, it more comes down to philosophy. My understanding of how
> to use generics is that you should use them in places where the API
> guarantees it complies with the type constraint.  That way it makes
> the API more understandable than just using raw types.  I think that
> putting in things which may or may not work makes the API less
> understandable and is really not a good idea.  I don't believe that
> using generics just to avoid having to do typecasts is the right idea
> at all.  I'm not aware of cases where that has been done in the Java
> class libraries, for example - if there are, point them out.  This is
> why I'm fighting tooth and nail against taking UIMA in that direction.
>
>   
>> Another option would be to add a new createFilteredIterator method which
>> takes a Class object as argument and then reduces its output to objects
>> which
>> have the type of the class.
>>
>> <T extends FeatureStructure> FSIterator<T> createFilteredIterator(...,
>> Class<T> type)
>>
>> Since it only returns objects of the correct type T it should not fail.
>>
>>     
>
> Yes, I wouldn't strenuously object to that but I doubt it's usefulness
> for createFilteredIterator.  I do think something like that is nice in
> JCas for getting an iterator over all instances of a specific type, as
> I suggested on another thread.
>   
In the end that means that we can leave this method in CAS and JCas like 
it is right now:
<T extends FeatureStructure> FSIterator<T> 
createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons);

A method like I proposed can be added to the CAS interface after the 
next release if we decide
its necessary. Do we want to add the method proposed by Adam for 2.3.0 
to JCas ?

Jörn

Re: generics: createFilteredIterator

Posted by Adam Lally <al...@alum.rpi.edu>.
On Wed, Aug 12, 2009 at 5:54 AM, Jörn Kottmann<ko...@gmail.com> wrote:
> Yes, but if someone writes it intentional he would get the same
> exception during class casting. That means not doing it would only help
> someone who picks the wrong type for the variable by accident, since its
> likely that
> the code cannot run it will fail immediately.
>

If ClassCastExceptions are going to happen I'd *much* rather they be
on explicit casts in user code rather than in framework code.  It's
more straightforward for the user to understand and fix the problem in
that case.

But really, it more comes down to philosophy. My understanding of how
to use generics is that you should use them in places where the API
guarantees it complies with the type constraint.  That way it makes
the API more understandable than just using raw types.  I think that
putting in things which may or may not work makes the API less
understandable and is really not a good idea.  I don't believe that
using generics just to avoid having to do typecasts is the right idea
at all.  I'm not aware of cases where that has been done in the Java
class libraries, for example - if there are, point them out.  This is
why I'm fighting tooth and nail against taking UIMA in that direction.

> Another option would be to add a new createFilteredIterator method which
> takes a Class object as argument and then reduces its output to objects
> which
> have the type of the class.
>
> <T extends FeatureStructure> FSIterator<T> createFilteredIterator(...,
> Class<T> type)
>
> Since it only returns objects of the correct type T it should not fail.
>

Yes, I wouldn't strenuously object to that but I doubt it's usefulness
for createFilteredIterator.  I do think something like that is nice in
JCas for getting an iterator over all instances of a specific type, as
I suggested on another thread.

  -Adam

Re: generics: createFilteredIterator

Posted by Jörn Kottmann <ko...@gmail.com>.
Adam Lally wrote:
> On Fri, Aug 7, 2009 at 2:32 PM, Marshall Schor<ms...@schor.com> wrote:
>   
>> The createFilteredIterator method in CASImpl takes an FSIterator and an
>> FSMatchConstraint, and returns another iterator.
>>
>> The generification of this is:
>>  public<T extends FeatureStructure> FSIterator<T>
>> createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons) {
>>    return new FilteredIterator<T>(it, cons);}
>>
>> This means that the type of the objects being returned will be the same
>> as the type of the objects of the iterator passed in.
>>
>> If the effect of the filtering is to filter the first iterator down to a
>> subset of the types of the original, this cannot be represented with
>> this signature.
>>
>> An alternate generification might be as follows, with type T being the
>> type the input iterator gives out, and U being the type the filtered
>> iterator produces:
>>
>>  public<T extends FeatureStructure, U extends T> FSIterator<U>
>> createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons) {
>>    return new FilteredIterator<T, U>(it, cons);}
>>
>> with the corresponding changes to the class FilteredIterator, and the
>> CAS interface (to match this new signature).
>>
>> With these changes, users can write code:
>>  public static void t3(CAS aCas, FSIterator<FeatureStructure> it,
>> FSMatchConstraint cons) {
>>    FSIterator<Subtype> s = aCas.createFilteredIterator(it, cons);
>>  }
>>
>> Without these changes, users would be forced to have the filtered
>> iterator's generic type always equal to the original type.
>>
>> Is this something we should change (given that we only get one chance to
>> do our generification)?
>>
>>     
>
> I'm not sure.  This user's code would compile regardless of whether
> the FSMatchConstraint actually implemented the subtype constraint or
> not.  It's quite possible that the code would compile and then fail
> with a ClassCastException.
>   
Yes, but if someone writes it intentional he would get the same
exception during class casting. That means not doing it would only help
someone who picks the wrong type for the variable by accident, since its 
likely that
the code cannot run it will fail immediately.

Another option would be to add a new createFilteredIterator method which
takes a Class object as argument and then reduces its output to objects 
which
have the type of the class.

<T extends FeatureStructure> FSIterator<T> createFilteredIterator(..., 
Class<T> type)

Since it only returns objects of the correct type T it should not fail.

Jörn

Re: generics: createFilteredIterator

Posted by Adam Lally <al...@alum.rpi.edu>.
On Fri, Aug 7, 2009 at 2:32 PM, Marshall Schor<ms...@schor.com> wrote:
> The createFilteredIterator method in CASImpl takes an FSIterator and an
> FSMatchConstraint, and returns another iterator.
>
> The generification of this is:
>  public<T extends FeatureStructure> FSIterator<T>
> createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons) {
>    return new FilteredIterator<T>(it, cons);}
>
> This means that the type of the objects being returned will be the same
> as the type of the objects of the iterator passed in.
>
> If the effect of the filtering is to filter the first iterator down to a
> subset of the types of the original, this cannot be represented with
> this signature.
>
> An alternate generification might be as follows, with type T being the
> type the input iterator gives out, and U being the type the filtered
> iterator produces:
>
>  public<T extends FeatureStructure, U extends T> FSIterator<U>
> createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons) {
>    return new FilteredIterator<T, U>(it, cons);}
>
> with the corresponding changes to the class FilteredIterator, and the
> CAS interface (to match this new signature).
>
> With these changes, users can write code:
>  public static void t3(CAS aCas, FSIterator<FeatureStructure> it,
> FSMatchConstraint cons) {
>    FSIterator<Subtype> s = aCas.createFilteredIterator(it, cons);
>  }
>
> Without these changes, users would be forced to have the filtered
> iterator's generic type always equal to the original type.
>
> Is this something we should change (given that we only get one chance to
> do our generification)?
>

I'm not sure.  This user's code would compile regardless of whether
the FSMatchConstraint actually implemented the subtype constraint or
not.  It's quite possible that the code would compile and then fail
with a ClassCastException.

In general it seems to me like we only want to use generics in our API
when the API is guaranteed to actually adhere to the type constraints
that we put in the method signature.  We shouldn't use generics when
the API *sometimes* adheres to the constraints and sometimes does not.

  -Adam