Numeric

Remi Forax forax at univ-mlv.fr
Fri Sep 14 14:42:02 PDT 2012


On 09/14/2012 11:10 PM, Brian Goetz wrote:
>> Long-term, we need primitive specialization of generics.  But shorter
>> term, there's an intermediate solution that reduces both boxing and
>> combinatorial explosions of special forms. The tradeoff is to accept
>> some virtualness, plus a bit of tedium on the part of components
>> implementing it:
>>
>> /**
>>   * Interface defining access methods for classes that provide numeric
>>   * results. A {@code Numeric} is not itself an instance of {@link
>>   * java.lang.Number}, but provides numeric methods to access its
>>   * primary result or property; normally via the method corresponding
>>   * to the listed {@code PreferredType} parameter. However, any
>>   * implementation of this interface must define the non-preferred
>>   * methods as well (typically by casting the results of the
>>   * preferred form).
>>   */
>> public interface Numeric<PreferredType extends Number> {
>>      long getLong();
>>      int getInt();
>>      short getShort();
>>      byte getByte();
>>      double getDouble();
>>      float getFloat();
>> }
>
> These guys also need companion classes that are mutable, so that 
> reductions can have O(1) boxing costs instead of O(n).
>
> class IntMutableNumeric implements Numeric<Integer> {
>     private int value;
>
>     public setInt(int value) { this.value = value; }
>
>     // obvious getter implementations
> }
>
> This would be really useful in the groupBy+reduce case:
>
> Map<Name, Numeric<Integer>> highScoresByName =
>     scores.foldBy(s -> s.getName(),
>                   () -> new IntMutableNumeric(),
>                   (bx, s) -> bx.setValue(Math.max(bx.getValue, s)));

I suppose it's more something like that:
Map<Name, Numeric<Integer>> highScoresByName =
     scores.foldBy(s -> s.getName(),
                   () -> new IntMutableNumeric(),
                   (bx, s) -> bx.setValue(Math.max(bx.getValue(), 
s.length())));

>
> The knowledge that the values are mutable does not escape from the 
> initializing computation.
>

There is two problems, the first one is how exchange values between the 
threads
in fork/join if we have lambda.
Here creating an object that store the lambda to apply, an Object and a long
to store the result (object or primitive) is enough.
i think it's an error to try to specify the Fork/join internal operation 
as a lambda
that return a box of value, it's easier to specify it as an inner-class.

The second problem, the Brian's one can be solved by specializing reduce and
fold for int/long/double instead of using mutable box that will be hard 
to use
in parallel world.

About the primitive specialization, we can easily specialize the eager 
operations
like fold or reduce. specializing Stream or StreamMap is far harder because
it requires or specialization to be done by the VM or tagged value
(here, Jim Laskey's array of tagged value can be great but anyway, we 
haven't
enough time to play with that idea before the release of lambdas.

Rémi









More information about the lambda-libs-spec-observers mailing list