Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / First Aid / March 2006

Tip: Looking for answers? Try searching our database.

Once again problems with wildcards/generic methods

Thread view: 
Hendrik Maryns - 27 Feb 2006 12:28 GMT
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
NotDashEscaped: You need GnuPG to verify this message

Hi,

I have successfully applied generics a few times now, but once again, it
gets a bit more complicated, and Eclipse?s error messages are a bit too
cryptic.

So I have this method
public <T extends State> List<Set<List<T>>> arrangeStates(Set<T> states)

Here, I need the parameter T, because I want to be able to give subtypes
of State to the method, and get a result with the same subtypes (as in
Sun?s Generics Tutorial: parametrised methods should be used if you want
to express a relation between the types of the arguments and/or return
type.)  I had to introduce the T, because I want to invoke the method
with a subtype of State (worked fine with State before).

Now another method,
public List<Set<FunctionInputTuple>> sortForArities(Set<? extends State>
states)
invokes arrangeStates like so:

List<Set<List<State>>> arrangedStates = this.arrangeStates(states);

and then goes on doing stuff with it.  Here, I did not use a type
parameter, as wildcards are sufficient.  But as the knowledgeable will
have noticed, the above line does not compile.  How can I change it such
that I can invoke arrangeStates on Set<? extends State>?

The compiler message is this:
Error    Type mismatch: cannot convert from List<Set<List<capture-of ?
extends State>>> to List<Set<List<State>>>    Signature.java

Eclipse?s Quick Fix proposes to change the type of arrangedStates to
List<Set<List<? extends State>>>, but that gives another warning, and
its suggestions stay the same...

Thanks, H.
Signature

Hendrik Maryns

==================
www.lieverleven.be
http://aouw.org

Hendrik Maryns - 27 Feb 2006 12:32 GMT
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
NotDashEscaped: You need GnuPG to verify this message

Hendrik Maryns schreef:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
[quoted text clipped - 35 lines]
> List<Set<List<? extends State>>>, but that gives another warning, and
> its suggestions stay the same...

I should add to this that I do not need arrangedStates to be anything
more specific than a list of sets of lists of states (indeed, this is
something cartesian-product like).  Whether they are a subtype of states
is not important.

H.
Signature

Hendrik Maryns

==================
www.lieverleven.be
http://aouw.org

Hendrik Maryns - 28 Feb 2006 12:54 GMT
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
NotDashEscaped: You need GnuPG to verify this message

Is there no Knowledgeable Person (TM), that can give me a hand here?
Please, I?ve been reading FAQs about generics for some hours now, and
did not find anything helpful (yet).

TIA, H.

>> Hi,
>>
[quoted text clipped - 38 lines]
>
> H.

Signature

Hendrik Maryns

==================
www.lieverleven.be
http://aouw.org

Bart Cremers - 28 Feb 2006 13:29 GMT
List<Set<List<? extends State>>> arrangedStates =
this.arrangeStates(states);

Bart
Bart Cremers - 28 Feb 2006 13:31 GMT
Oops, didn't read carefull enough. Could you post a complete code
example?

Bart
Hendrik Maryns - 01 Mar 2006 10:16 GMT
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
NotDashEscaped: You need GnuPG to verify this message

Bart Cremers schreef:
> Oops, didn't read careful enough.

Indeed:-)

Could you post a complete code
> example?

My pleasure, should?ve done that from the start, I guess.  The
additional class SignatureSymbol is just a wrapper around a String
(getName) and an int (getArity), whereas FunctionInputTuple is a wrapper
around a SignatureSymbol and a list of States, which checks that the
length of the list is the same as the symbol?s arity.  State is a class
that does nothing special except existing.

FunctionInputTuple.getInstance(symbol, states) is a factory method.  It
returns the single instance with the given symbol and states.  (Sort of
cache management).

import java.util.*;

/**
* A class representing a signature of an automaton.  It holds the
alphabet of
* symbols on which the automaton works.  Signatures are immutable.
*/
public class Signature implements Iterable<SignatureSymbol> {

/**
* Initialise a new signature, with given set of symbols.
*
* @param symbols
*/
public Signature(Set<SignatureSymbol> symbols) {
 this.symbols = new ArrayList<SignatureSymbol>(symbols);
 Collections.sort(this.symbols, new Comparator<SignatureSymbol>() {

   public int compare(SignatureSymbol sym1, SignatureSymbol sym2) {
     return sym1.getArity() - sym2.getArity();
   }

 });
}

/**
* The symbols of the signature.  They are stored in a list, sorted by
* arity.
*/
final private List<SignatureSymbol> symbols;

/**
* Return a list of sets, where every symbol in the ith set has arity i.
*
* @return  Every symbol with arity i belongs to the ith set.
*     | for each symbol in this
*     |  result.get(symbol.getArity()).contains(symbol)
* @return  The ith set in the list contains only elements of arity i.
*     | for 0 <= i < result.size()
*     |   for each symbol in result.get(i)
*     |    symbol.getArity() == i
*/
public List<Set<SignatureSymbol>> getSymbolsSorted() {
 List<Set<SignatureSymbol>> result = new ArrayList<Set<SignatureSymbol>>();
 for (int i = 0; i <= getMaximalArity(); i++) {
   result.add(i, new HashSet<SignatureSymbol>());
 }
 for (SignatureSymbol symbol : this) {
   result.get(symbol.getArity()).add(symbol);
 }
 // make all sets unmodifiable
 for (int i = 0; i < result.size(); i++) {
   result.set(i, Collections.unmodifiableSet(result.get(i)));
 }
 return result;
 // TODO: improve/remove this for list
}

/**
* Return the maximal arity of an element in this signature.
*/
public int getMaximalArity() {
 return symbols.get(symbols.size()-1).getArity();
}

/**
* Arrange the states in lists, such that every combination of i states is
* in a list in the ith set.

* THIS FUNCTION WORKS FINE (I THINK)

* @param states
*       The states to arrange.
* @return  The ith set represents the ith power of the set of states
*       (cartesian product).  It goes on until getMaximalArity().
*/
public <T extends State> List<Set<List<T>>> arrangeStates(Set<T> states) {
 List<Set<List<T>>> result = new ArrayList<Set<List<T>>>();
 Set<List<T>> setI = new HashSet<List<T>>();
 setI.add(new ArrayList<T>());
 result.add(0, setI);
 for (int i = 1; i <= getMaximalArity(); i++) {
   setI = new HashSet<List<T>>();
   result.add(i, setI);
   for (T state : states) {
     for (List<T> list : result.get(i - 1)) {
       List<T> newList = new ArrayList<T>();
       newList.add(0, state);
       // copy list into newList from position 1
       newList.addAll(1, list);
       setI.add(newList);
     }
   }
 }
 return result;
}

/**
* Sort the given states such that for each symbol of this signature, if its
* arity is i, all possible FunctionInputTuples with combinations of states
* of length i are in the ith set in the resulting list.
*
* @param states
*       The states to sort.
* @return  Every tuple in set i has a symbol of arity i.
*     | for each 0 < i <= result.size()
*     |  for each tuple in result.get(i)
*     |    tuple.getSymbol().getArity() == i
* @return  Every possible combination of i states is in set i for each
*       symbol of arity i.
*     | for each 0 < i <= result.size()
*     |  for each symbol in this
*     |    if (symbol.getArity() == i)
*     |     then for each s_1 ... s_i in states
*     |      result.get(i).contains(
*     |        FunctionInputTuple.getInstance(symbol, s_1, ... s_i)
*/
public List<Set<FunctionInputTuple>> sortForArities(Set<? extends State>
states) {
 List<Set<SignatureSymbol>> sortSyms = getSymbolsSorted();
 List<Set<FunctionInputTuple>> result = new
ArrayList<Set<FunctionInputTuple>>();

// HERE IS THE PROBLEM
 List<Set<List<State>>> arrangedStates = this.arrangeStates(states);

 for (Set<SignatureSymbol> set : sortSyms) {
   Set<FunctionInputTuple> aritySet = new HashSet<FunctionInputTuple>();
   result.add(aritySet); // to the end!
   for (SignatureSymbol symbol : set) {
     for (List<State> stateArr : arrangedStates.get(symbol.getArity())) {
       try {
         aritySet.add(FunctionInputTuple.getInstance(symbol,
             stateArr));
       } catch (FunctionArgumentsMismatchException e) {
         // should not occur
       }
     }
   }
 }
 return result;
}

}

I hope it is readable, if necessary, I can trim down some more.
Thanks for any help, H.

Signature

Hendrik Maryns

==================
www.lieverleven.be
http://aouw.org

Hendrik Maryns - 01 Mar 2006 12:29 GMT
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
NotDashEscaped: You need GnuPG to verify this message

Hendrik Maryns schreef:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
[quoted text clipped - 45 lines]
> something cartesian-product like).  Whether they are a subtype of states
> is not important.

Hi all,

After reading in the very interesting Java Generics FAQ from Angelika
Langer, I finally found the answer in the article about multilevel
wildcards:
http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#What%20
do%20multilevel%20wildcards%20mean
?
or http://tinyurl.com/h3j8y.

Also the part about Type System
http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#Type
%20System

explains what happens in nested type arguments (stuff like List<?
extends Set<? super Long>>).

Roedy, might be something interesting to link to...

The problem is that the type arguments are nested, and wildcard capturing.

Anyway, the solution was to make sortForArities a parametrised method,
like this:

public <T extends State> List<Set<FunctionInputTuple>> sortForArities(
   Set<T> states) {
 List<Set<SignatureSymbol>> sortSyms = getSymbolsSorted();
 List<Set<FunctionInputTuple>> result = new
ArrayList<Set<FunctionInputTuple>>();
 List<Set<List<T>>> arrangedStates = this.arrangeStates(states);
 for (Set<SignatureSymbol> set : sortSyms) {
   Set<FunctionInputTuple> aritySet = new HashSet<FunctionInputTuple>();
   result.add(aritySet); // to the end!
   for (SignatureSymbol symbol : set) {
     for (List<T> stateArr : arrangedStates.get(symbol
         .getArity())) {
       try {
         aritySet.add(FunctionInputTuple.getInstance(symbol,
             stateArr));
       } catch (FunctionArgumentsMismatchException e) {
         // should not occur
       }
     }
   }
 }
 return result;
}

That works.  I have to think a bit more about why exactly this is
necessary and whether this would be possible with wildcards, because
only seeing the method signature, it seems unnecessary to use the
generic method form.  This should be possible with wildcards.  This
breaks encapsulation: by changing this into a generic method, I give
away that I cannot implement it with wildcards, which says something
about the constructs used.

Thanks to all, and to Angelika Langer specifically.

H.

Signature

Hendrik Maryns

==================
www.lieverleven.be
http://aouw.org

Hendrik Maryns - 02 Mar 2006 20:35 GMT
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
NotDashEscaped: You need GnuPG to verify this message

Hendrik Maryns uitte de volgende tekst op 03/01/2006 01:29 PM:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
[quoted text clipped - 101 lines]
> away that I cannot implement it with wildcards, which says something
> about the constructs used.

Forget that.  The trick is, to make the method above private, then
invoke that one from the public one which uses wildcards.  A bit
unclean, but works and the only way.  See http://tinyurl.com/o4a82, in
Angelika?s FAQ again.

> Thanks to all, and to Angelika Langer specifically.
again.

H.
Signature

Hendrik Maryns

==================
www.lieverleven.be
http://aouw.org

Roedy Green - 28 Feb 2006 17:36 GMT
On Mon, 27 Feb 2006 13:28:31 +0100, Hendrik Maryns
<hendrik_maryns@despammed.com> wrote, quoted or indirectly quoted
someone who said :

>public List<Set<FunctionInputTuple>> sortForArities(Set<? extends State>
>states)
>invokes arrangeStates like so:

To better understand what you are doing, please define State,
FunctionTuple and tell us what is a subset of what.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Hendrik Maryns - 01 Mar 2006 10:21 GMT
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
NotDashEscaped: You need GnuPG to verify this message

Roedy Green schreef:
> On Mon, 27 Feb 2006 13:28:31 +0100, Hendrik Maryns
> <hendrik_maryns@despammed.com> wrote, quoted or indirectly quoted
[quoted text clipped - 6 lines]
> To better understand what you are doing, please define State,
> FunctionTuple and tell us what is a subset of what.

Ok, sorry.  As I answered to Bart?s post:
State is just a dummy class that represents a state of an automaton, but
does nothing.  It just registers a name.  It does have a subclass, not
mentioned here, which I want to be able to use the method with, too.
(StateSet, a state which contains other states.)

FunctionInputTuple is a wrapper around a SignatureSymbol and a list of
states.  It checks that the length of the list is the same as the arity
of the symbol.

A SignatureSymbol is a wrapper around a String (its name) and an int
(its arity), with appropriate getters.  It also does nothing.

Hope this helps, the whole class can be seen in the other post.

TIA, H.

Signature

Hendrik Maryns

==================
www.lieverleven.be
http://aouw.org



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.