Marshall Schor commented on UIMA-1524:

Thanks, Richard, for your thoughtful dialog on these topics.  It's nice to find 
someone else interested in the arcana of principled API design :-).  

1) re: Fluctuating between positional-style and keyword style: the keyword 
style is the most "factored" style - lets one build what you want with a 
"minimal" set of keys.  So it's useful to list these as separate things (as 
done in the diagram), to see the totality of what one might reasonably "build" 
out of a minimal set of primitives, and what those primitives might be.

But the keyword style is verbose, so it seems good design to support positional 
for frequently-used idioms, for more concise/compact code.

2) Yes, your understanding of the Gliffy diagram is correct re: the object 
without a "terminal" is something supporting special methods for UIMA and also 
the stream interface.  My thought is that when you use a stream method, that 
will result in the creation of a Stream object, based on everything you've 
specified, up to that point, and from then on, it will act like a stream.

This "automatic" conversion to stream is a "convenience"; we could dispense 
with it, and require the user to explicitly write ....x().y().stream().a().b(). 
  where x, y are the uima specific methods, and a, b are stream methods.  It 
seems better (more concise/compact) to leave out the stream(), though.  Maybe 
it could be optional, and the documentation (for learning) could start with it 
explicitly present, and only later drop it; this could demystify the API 

3) It seems right that having more than one "type" spec is more likely an 
error, than a useful feature, so I agree it would be more helpful to throw an 
exception if that happened.

4) Because "type" is used frequently, I think it's a good candidate to allow it 
as a positional argument.

5) When moving keyword arguments into positional ones, should we drop the 
keyword form?  I'm a bit on the fence.  Sometimes I think users prefer an API 
style which lists arguments with their keys (as in the form type(aTypeSpec), 
uniformly, even if there are positional forms.  I don't think there's a cost to 
keeping this option, so I'm on the side of keeping it.

**Decision requirement::** dropping the *type* call - I'd say to keep it; 
throwing an exception if called twice: I'd say yes (because it's more likely an 
error than a wanted feature).

6) multiple location requirements.  I agree it would be nice, but it might be 
difficult to (efficiently) implement.   People might write forms like 
within(span1).within(span2), where the spans had some overlap.  It seems we'd 
have to go through and figure out the semantics for lots of combinations of 
method (keyword) chains...  So maybe we could not do this in version 1, and 
later figure out some often requested instances of this as a version 2 

These are perhaps "tricky".  In the example of 
.within(sentence).following(predicateVerb), even though this sounds sensible, I 
think it's somewhat misleading.  The following(predicateVerb) completely 
specifies the position, and the .within(sentence) just serves as a boolean 
switch - is the predicateVerb location is within(sentence),   I think this is a 
confusing way to represent this versus something like:
if (sentence.contains(predicateVerb))
or something similar that does boolean operations on spans (with or without 

**Decision requirement:** allowing multiple location specs - I would severely 
restrict this in version 1 to just those easily supported by the current 
indexes/iterators, which in my mind would be just one of the 
covered/covering/moveTo(fs) kind, and one displacement kind; the semantics 
would be that the displacement operation follows the other.

7) I like "displacement" instead of "offset", I'd like even better a shorter 
word :-) ; some possibilities:  shift, shifted, shiftedBy, move, moved, movedBy 
 (the "ed" forms are more declarative, but sound a bit clumsy to me).  Of 
these, my choice is "shifted":  e.g.   
cas.select(Token.type).within(fs).shifted(3), but not a strong preference.

8) Semantics of displacement: I had not thought of the complexity of having it 
operate with respect to some other index/type; I thought of it as moving the 
point where you start by iterating moveToNext or moveToPrevious.  Our current 
mechanisms support this trivially, I think.  Also, in the form 
"cas.select(Token.type).following(predicateVerb)", the "type" of predicateVerb 
(surprised) need not even be a subtype of Token.  

**Decision requirement::** displacement meaning: I'd prefer making it just an 
interated MoveToNext or Previous.

9) Re: supporting enhanced for loop: I agree it would be good to support this.  
I think the implementation could do this, so your example would work. It would 
switch to the "stream" alternative only if some stream operation was specified.

> JFSIndexRepository should be enhanced with new generic methods
> --------------------------------------------------------------
>                 Key: UIMA-1524
>                 URL: https://issues.apache.org/jira/browse/UIMA-1524
>             Project: UIMA
>          Issue Type: Improvement
>          Components: Core Java Framework
>    Affects Versions: 2.3
>            Reporter: Joern Kottmann
> Existing methods should be overloaded with an additional Class argument to 
> specify the exact return type. This changes make down casting of returned 
> objects unnecessary. 

This message was sent by Atlassian JIRA

Reply via email to