Signature of FunctionalPrimitives.zip

5 views
Skip to first unread message

Christian Semrau

unread,
Apr 22, 2011, 3:53:22 AM4/22/11
to jedi
Hi,

is there a specific reason why FunctionalPrimitives.zip() has this
signature?

public static List zip(final Iterable<List> lists);

It forces me to have unchecked and raw conversions when I try to use
it. E.g. when solving Project Euler problem 8, I am given a
List<Integer> digits and wish to create a List<List<Integer>>, of 5-
tuples starting at each index in the digits list. This is what I came
up with.

final List<List<Integer>> digitTuples = zip(list((List)
drop(0, digits),
drop(1, digits),
drop(2, digits),
drop(3, digits),
drop(4, digits)
));

Note the explicit raw cast to List (inside list(), because I could not
directly cast the result of list() from List<List<Integer>> to
List<List>), and the implicit unchecked cast from List (the result of
zip()) to List<List<Integer>>.

If zip() had this signature, I could leave out the raw type.

public static <T> List<List<T>> zip(final Iterable<List<T>> lists);

I still have the unchecked varargs conversion from list(), but that
could be prevented if I did not use list() but created the drop-list
some other way. E.g. by mapping drop() over a list of Integer (just
created a dropFrom Functor for that), I can create the digitTuples
like this:

final List<List<Integer>> digitTuples = zip(map(list(0, 1, 2, 3, 4),
dropFrom(digits)));

Oh, and by adding a Functor foldIterable(iv, f2) that folds its
argument with given initial value and functor2, I can finish Project
Euler problem 8 in three lines.

final List<Integer> digits = map(charactersOf(digitsString),
getNumericValue);
final List<List<Integer>> digitTuples = zip(map(list(0, 1, 2, 3, 4),
dropFrom(digits)));
return reduce(map(digitTuples, foldIterable(1, product)), max);

Here charactersOf is a Guava method to produce a List<Character> from
a String, digitsString is the input String from the problem
description, getNumericValue is a @SithFunctor on Character, product
and max are Functor2 with the obvious meaning. I'm taking on the habit
of providing Functor constants for @SithFunctor and @JediFunctor on
static functions to get rid of the generated $receiver argument.

Lance Walton

unread,
Apr 22, 2011, 9:10:52 AM4/22/11
to jed...@googlegroups.com
Hi.


On 22 Apr 2011, at 08:53, Christian Semrau wrote:

Hi,

is there a specific reason why FunctionalPrimitives.zip() has this
signature?

public static List zip(final Iterable<List> lists);



This is because the Lists that zip produces can contain arbitrary types. e.g. you could zip(list(list(1, 2, 3), list("a", "b", c"))) and then the result list would be list(list(1, "a"), list(2, "b"), list(3, "b")).

Try using the overload zip(List<A> listA, List<B> listB) here: zip



Oh, and by adding a Functor foldIterable(iv, f2) that folds its
argument with given initial value and functor2, I can finish Project
Euler problem 8 in three lines.

final List<Integer> digits = map(charactersOf(digitsString),
getNumericValue);
final List<List<Integer>> digitTuples = zip(map(list(0, 1, 2, 3, 4),
dropFrom(digits)));
return reduce(map(digitTuples, foldIterable(1, product)), max);


I think you should have commit rights :-) Want to join the project?

Regards,

Lance

Christian Semrau

unread,
Apr 22, 2011, 1:40:50 PM4/22/11
to jedi
On 22 Apr., 15:10, Lance Walton <lance.c.wal...@googlemail.com> wrote:
> On 22 Apr 2011, at 08:53, Christian Semrau wrote:
> > is there a specific reason why FunctionalPrimitives.zip() has this
> > signature?
>
> > public static List zip(final Iterable<List> lists);
>
> This is because the Lists that zip produces can contain arbitrary types. e.g. you could zip(list(list(1, 2, 3), list("a", "b", c")))
> and then the result list would be list(list(1, "a"), list(2, "b"), list(3, "b")).

I see your point. Zips of different types are difficult to make
typesafe. Surely someone somewhere did already come up with a usable
Java signature?!

The original zip variant does not compile when used with the any one
of these source lines:
zip(list(list(1, 2, 3), list("a", "b", "c")));
zip(list(list(1, "a"), list(2, "b"), list(3, "b")));

It seems that the problem of mixed types is not the zip function's
alone, but also the list function's: What is the type of the following
expression?
list(list(1, 2, 3), list("a", "b", "c"))

The original variant works when using a raw cast:
public static List zip(final Iterable<List> lists); // original
List result = zip(list((List)list(1, 2, 3), list("a", "b", "c")));

The typed variant also works with a cast:
public static <T> List<List<T>> zip(final Iterable<List<T>> lists); //
typed
List<List<Object>> result = zip(list(list((Object)1, 2, 3), list("a",
"b", "c")));
List<List<Serializable>> result = zip(list(list((Serializable)1, 2,
3), list("a", "b", "c")));

Signatures that seem to work without casts for mixed types are these:
public static List zip(final Iterable lists); // raw
public static List<List<?>> zip(final Iterable<? extends List<?>>
lists); // wildcards
public static <T> List<List<T>> zip(final Iterable<? extends List<?
extends T>> lists); // extended-type

The extended-type variant must be invoked with explicitly stated type
parameter if one wants to assign the result to a variable, like so:
List<List<Object>> result = FunctionalPrimitivesTest.<Object>
zip(list(list(1, 2, 3), list("a", "b", "c")));
The type Object could be replaced by Serializable or Comparable<?> --
these are all the common super classes and interfaces of String and
Integer.
This would be the most flexible variant, but it usually cannot be used
when statically imported due to the explicit type parameter.

The wildcards version has the most general parameter type, but its
return type is difficult to work with.
So, as a first step towards a better signature, how about this?

public static List zip(final Iterable<? extends List<?>> lists); //
wildcard argument with raw result

> I think you should have commit rights :-) Want to join the project?
>
> Regards,
> Lance

Thank you for the invitation. I'll be glad to join.

Christian

Channing Walton

unread,
Apr 23, 2011, 1:32:23 PM4/23/11
to jed...@googlegroups.com

On 22 Apr 2011, at 14:10, Lance Walton wrote:

> I think you should have commit rights :-) Want to join the project?

+1 Christian knows a lot more than I do about this stuff.

Channing

Lance Walton

unread,
Apr 23, 2011, 3:39:53 PM4/23/11
to jed...@googlegroups.com
Just trying to figure out how to do that at Codehaus.

Christian Semrau

unread,
May 2, 2011, 4:45:25 PM5/2/11
to jed...@googlegroups.com
Hi Lance,

I have now registered a Codehaus account and have applied to become a
developer (via some Codehaus Xircles page).

Regards,
Christian

Reply all
Reply to author
Forward
0 new messages