Generics - Is this possible?

L

lstephen

Hi,

I'm looking at the signature for something like a 'map' function.

For List it may be something like:

List<B> map(List<A> a, UnaryFunction<A, B> f)

But, I want I'd rather it not be List specific, so I was after
something like:

T<B> map(T<A> a UnaryFunction<A, B> f)

But, the compiler doesn't like this ;)

Any ideas on how or whether this is possible?

Thanks,
Levi
 
A

Andreas Leitgeb

If you won't specify anything about T itself, you
wouldn't be able to do anything at all with it.
Inside your "map" method, T would be like Object,
and that has no method to retrieve any "A" from it :)
public static <A, B>
Collection <B> xform( Collection <A> a, UnaryFunction <A, B> f )
(untried, untested, uncompiled, one of several solutions [...])

Another problem is, that xform has the "burden" of picking some
implementation of a Collection, an instance of which it then
returns, filled with all the "B"-objects.
If you have a class called 'UnaryFunction', shouldn't it overload its "unary
function" method with one that takes a Collection? Having a "friend" method
like that shown breaks encapsulation.

That would just shift the problems from xform to UnaryFunction's
overloaded(or just additional) method. If "UnaryFunction" was
an interface, it would mean that any implementation would also
need to care for an implementation of the Collection-handling
method.
Imho "map" or "xform" are rather the type of methods that
would belong into a "Collections"-like toolkit class.
 
J

Jan Thomä

If that were possible, java.util.Collections would not
need the methods synchronizedList, synchronizedSet,
and synchronizedSortedSet. It would only need
synchronizedCollection.

On a side note, something like this is possible in C#:


// function that creates a T
public T create<T>() {
return new T();
}

and you can call this like: Foo foo = create<Foo>(); Doesn't work for java
though, but nicely shows the different approach in C#...
 
L

lscharen

Hi,

I'm looking at the signature for something like a 'map' function.

For List it may be something like:

List<B> map(List<A> a, UnaryFunction<A, B> f)

But, I want I'd rather it not be List specific, so I was after
something like:

T<B> map(T<A> a UnaryFunction<A, B> f)

But, the compiler doesn't like this ;)

Any ideas on how or whether this is possible?

I've implemented a functional library that addresses this issue. I
just use the Iterable<T> type unless the operation specifically
depends on list ordering. Here's a skeleton of my class declarations
adapted to your notation. Note, my implementation uses lazy
evaluation so you can do things like sum up an infinite list.

For example, I can create a Range class that takes a starting and
finishing value and implements Iterable<Integer>. I can write code
like this:

Range r = new Range(0, Integer.MAX_VALUE);
UnaryFunction sqr = new Square();

Iterable<Integer> squares = map( sqr, r );

for ( Integer x : squares )
{
// do something
if ( x > 100 )
break;
}


Here is the code outline:

public class UnaryFunction<R, T> {
public R eval( T arg ) { ... }
}

public static <R, T> Iterable<R> map( final UnaryFunction<R, T> f,
final Iterable<? extends T> list )
{
return new Iterable<R>() {
public Iterator<R> iterator() {
return map_iterator( f, list.iterator() );
}
}
}

private static <R, T> Iterator<R> map_iterator( final UnaryFunction<R,
T> f, final Iterator<? extends T> iterator )
{
return new Iterator<R>()
{
public boolean hasNext() {
return list.hasNext();
}
public R next() {
return f.eval( list.next() );
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
 
A

Andreas Leitgeb

public static <R, T> Iterable<R> map(
final UnaryFunction<R, T> f,
final Iterable<? extends T> list )

I'm just curious, why you chose to return an
Iterable, rather than an Iterator.

I haven't found any standard class that would
take an Iterable as argument, so the only thing
to do with the returnvalue is to obtain an
Iterator... did I miss something?

Even if you obtain an Iterator more than once,
each such Iterator will just recalculate the
same values.
 
P

Patricia Shanahan

Andreas Leitgeb wrote:
....
I haven't found any standard class that would
take an Iterable as argument, so the only thing
to do with the returnvalue is to obtain an
Iterator... did I miss something?
....

There is one thing you can do with an Iterable but not an Iterator - use
it in an enhanced for-loop.

Patricia
 
R

Roedy Green

But, I want I'd rather it not be List specific, so I was after
something like:

What methods are you planning to use inside your map method? If it is
to be used on List, it must either be the List, Collection or Iterable
methods. So you must pass something of type of one of those three.

Java is a strongly typed language!
 
A

Andreas Leitgeb

Patricia Shanahan said:
There is one thing you can do with an Iterable but not an Iterator - use
it in an enhanced for-loop.

Heck, I really missed *something* :-}

Thanks also to Peter Duniho.
 
P

Patricia Shanahan

Andreas said:
Heck, I really missed *something* :-}

Thanks also to Peter Duniho.

Incidentally, does anyone understand *why* it has to be an Iterable, not
an Iterator? Of course, an Iterator based for loop would only process
the elements from the Iterator's current position on.

Patricia
 
L

lstephen

What methods are you planning to use inside your map method? If it is
to be used on List, it must either be the List, Collection or Iterable
methods. So you must pass something of type of one of those three.

Sorry, I wasn't clear that map would have more than one
implementation. I'm enjoy playing around with translating concepts
from one language to others. In this case it's the Functor type class
from Haskell. So map would be an abstract method of a Functor class.
Then I could create ListFunctor, SetFunctor, MapFuctor etc. Then to
take more from Haskell MaybeFunctor, EitherFunctor etc.
So there is no practical problem to solve, just experimenting.
Java is a strongly typed language!

Yep. I'm trying to express that if you pass in a List<A> you would get
back a List<B>, pass in Set<A> you get back Set<B>. i.e., the type of
collection you pass in, is what you get back.


Thanks,
Levi
 
L

lstephen

I've implemented a functional library that addresses this issue. I
just use the Iterable<T> type unless the operation specifically
depends on list ordering.

Thanks for the example. I was experimenting with functional like
concepts, but I wanted to be more specific that Iterable, i.e., if you
pass in List<A> you get back List<B>, if you pass in a Set, you get
back a Set etc. Also I was hoping this would allow map to be used on
non collection types (e.g., something like Haskell's Maybe or Either
but translated to Java.)

As I mentioned elsewhere there is no practical reason for me doing
this, just experimenting :)

Thanks,
Levi
 
L

lstephen

'map' is a somewhat unfortunate variable name, since you aren't actually
associating it with the wildly popular 'Map' type.







What you want to accomplish is possible, what you're trying to say isn't.
You're trying to indicate a type parameter that takes a type parameter; that
doesn't exist.

By doesn't exist, do you mean not possible in Java?
Type parameters exist to restrict the range of acceptable
types; what you wrote, 'T<A>', is equivalent to merely 'T'.

What is the restriction that you actually want to place on T? Do you want it
to be a Collection?

The restriction I want to place on T is that it's a generic class that
takes one type parameter.
public static <A, B>
Collection <B> xform( Collection <A> a, UnaryFunction <A, B> f )

(untried, untested, uncompiled, one of several solutions that differ subtly in
semantics)

Yep, I could definately cover the most common case by using Iterable
or Collection, but I was trying to see how general I could make this.
If you have a class called 'UnaryFunction', shouldn't it overload its "unary
function" method with one that takes a Collection? Having a "friend" method
like that shown breaks encapsulation.

UnaryFunction wouldn't be passed a collection, it would be passed an
element form a collection - it wouldn't even know the element was part
of a collection.
 
L

lstephen

If that were possible, java.util.Collections would not
need the methods synchronizedList, synchronizedSet,
and synchronizedSortedSet. It would only need
synchronizedCollection.

Good point. I think this is a strong indication that the answer is no.

Thanks,
Levi
 
P

Patricia Shanahan

Peter said:
Only the language designers could tell you the actual reason why. But I
would agree with anyone who felt it wise to not allow user code access
to the actual iterator being used for the loop. The potential for
adding bugs seems to me to outweigh any potential convenience. It keeps
the semantics of the for:)) syntax nice, simple, and easy-to-predict.

I certainly agree that not allowing user code access to the actual
iterator would be desirable, if it were possible. It isn't. The
following, horrible, program prints "1", then "3", then gets a
java.util.NoSuchElementException.

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class WildFor {
public static void main(String[] args) {
List<Integer> myList = Arrays.asList(1, 2, 3, 4, 5);
RememberingIterable<Integer> myIterable =
new RememberingIterable<Integer>(myList);
for (Integer i : myIterable) {
myIterable.getLastIterator().next();
System.out.println(i);
}
}

static class RememberingIterable<T> implements
Iterable<T> {
private Iterable<T> baseIterable;

private Iterator<T> lastIterator;

public RememberingIterable(Iterable<T> iterable) {
baseIterable = iterable;
}

public Iterator<T> iterator() {
lastIterator = baseIterable.iterator();
return lastIterator;
}

public Iterator<T> getLastIterator() {
return lastIterator;
}
}

}
 
P

Patricia Shanahan

Peter said:
But it would be if Java supported using an Iterator in the for() statement.


Right. But if you can provide an actual iterator in the for()
statement, then the code has access to the iterator implicitly. It
wouldn't be nearly so much work to reproduce the example of bad usage
you provided if Java allowed an Iterator instead of an Iterable
implementation in the for() statement. Your example would instead look
like this:
....

The point is that not allowing Iterator does not prevent access to it,
just makes it a bit harder. Meanwhile, it also makes legitimate uses harder.

Patricia
 
H

Hendrik Maryns

(e-mail address removed) schreef:
I've implemented a functional library that addresses this issue. I
just use the Iterable<T> type unless the operation specifically
depends on list ordering. Here's a skeleton of my class declarations
adapted to your notation. Note, my implementation uses lazy
evaluation so you can do things like sum up an infinite list.

Very nice, but…
private static <R, T> Iterator<R> map_iterator( final UnaryFunction<R,

Please, please don’t. It hurts me so much to see such beautiful code
and then not following naming conventions.

Sorry, had to get this off my heart.

H.
--
Hendrik Maryns
http://tcl.sfs.uni-tuebingen.de/~hendrik/
==================
http://aouw.org
Ask smart questions, get good answers:
http://www.catb.org/~esr/faqs/smart-questions.html


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.4-svn0 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org

iD8DBQFIBcy1e+7xMGD3itQRAn38AJwNeBqOsEV551I1HIA+ij+8PronVACfbA4T
ciBWXRMu15rCQCNiZxiolQ4=
=ql66
-----END PGP SIGNATURE-----
 
L

lstephen

would you flesh this example out?

It would probably be something like (without compiling or testing it):

public interface UnaryFunction<A, B> {
B apply(A a);
}

public List<B> map(List<A> as, UnaryFunction<A, B> f) {
List<B> bs = new ArrayList<B>();
for (A a : as) {
bs.add(f.apply(a));
}
return bs;
}

thanks,

Thufir

Levi
 
A

Andreas Leitgeb

Peter Duniho said:
Peril? Something bad will happen to me? What? What bad thing will
happen?
And I mean, other than Java zealots harrassing me about my naming.

Zealots are not just here in c.l.j.p, but you may also meet some
in real world - e.g. those who review your code and rate it poorly.
The zealots *here* rather help you be prepared for the others :)
 
R

RedGrittyBrick

Peter said:
Java _is_ "just a language". There may also be a "Java community", but
the language itself doesn't enforce any particular naming convention and
there's no requirement to comply with "community standards" in order to
be a successful Java programmer.

This is true but misses the point that if you wish to enlist the help of
the community in fixing some problem you are having with your Java
source code, you'll get a better response from the community if your
source code follows the community conventions that make it easier for
community members to follow.

Using underscore connected words instead of camelCase isn't much of a
hindrance, it's when people use wild indentation or initial upper-case
for variables that my reading speed tends to slow down dramatically. I
tend to lose motivation a bit when I think the author is wilfully making
it harder for helpers to help.

bI awrl menes beeYidIosYnCRAT.IC wern ryEtAng koid fore eeyore Owen
prusell Owen Lee.

When communicating with others, I think it helps to follow the conventions.

Just my EUR 0.00000002 worth.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top