This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Bizarre initialization within TraversableOnce.reduceLeft

3 replies
Chris Marshall
Joined: 2009-06-17,
User offline. Last seen 44 weeks 3 days ago.
It's been pointed out on StackOverflow [1] that there is a rather bizarre and totally superfluous piece of code inside TraversableOnce.reduceLeft which appears to have the overhead of causing the boxing of an integer on each call to the method, regardless of the types involved.
Presumably this is a bug?
def reduceLeft[B >: A](op: (B, A) => B): B = {
  if (isEmpty)
    throw new UnsupportedOperationException("empty.reduceLeft")

  var first = true
  var acc: B = 0.asInstanceOf[B]

  for (x <- self) {
    if (first) {
      acc = x
      first = false
    }
    else acc = op(acc, x)
  }
  acc
}

Chris

1: http://stackoverflow.com/questions/8465356/what-is-happening-with-0-asinstanceofb-in-scala-reduceleft-implementation
DaveScala
Joined: 2011-03-18,
User offline. Last seen 1 year 21 weeks ago.
Re: Bizarre initialization within TraversableOnce.reduceLeft

If you mean:
ObjectRef acc$1 = new ObjectRef(BoxesRunTime.boxToInteger(0));
For -optimise it is the same.

I think it is an ObjectRef and not an IntRef, because of type erasure
and ObjectRef expects an Object as argument.
I think it would not be sound to do:
IntRef acc$1 = new IntRef(0);
otherwise you make a guarantee about the type that is not there.

trait Test[A] {
val isEmpty = false
val self : List[A]

def reduceLeft[B >: A](op: (B, A) => B): B = {

if (isEmpty)
throw new UnsupportedOperationException("empty.reduceLeft")
var first = true
var acc: B = 0.asInstanceOf[B]
for (x <- self) {
if (first) {
acc = x
first = false
}
else
acc = op(acc, x)
}
acc
}
}

Test$class.class
================
import scala.Function2;
import scala.collection.LinearSeqOptimized;
import scala.runtime.BooleanRef;
import scala.runtime.BoxesRunTime;
import scala.runtime.ObjectRef;

public abstract class Test$class
{
public static Object reduceLeft(Test $this, Function2 op$1)
{
if ($this.isEmpty())
throw new UnsupportedOperationException("empty.reduceLeft");
BooleanRef first$1 = new BooleanRef(true);
ObjectRef acc$1 = new ObjectRef(BoxesRunTime.boxToInteger(0));
$this.self().foreach(new Test..anonfun.reduceLeft.1($this, op$1,
first$1, acc$1));

return acc$1.elem;
}

public static void $init$(Test $this)
{
$this.Test$_setter_$isEmpty_$eq(false);
}
}

On 11 dec, 17:53, Chris Marshall wrote:
> It's been pointed out on StackOverflow [1] that there is a rather bizarre and totally superfluous piece of code inside TraversableOnce.reduceLeft which appears to have the overhead of causing the boxing of an integer on each call to the method, regardless of the types involved.
> Presumably this is a bug?
> def reduceLeft[B >: A](op: (B, A) => B): B = {
>   if (isEmpty)
>     throw new UnsupportedOperationException("empty.reduceLeft")
>
>   var first = true
>   var acc: B = 0.asInstanceOf[B]
>
>   for (x <- self) {
>     if (first) {
>       acc = x
>       first = false
>     }
>     else acc = op(acc, x)
>   }
>   acc}
>
> Chris
>
> 1:http://stackoverflow.com/questions/8465356/what-is-happening-with-0-a...

H-star Development
Joined: 2010-04-14,
User offline. Last seen 2 years 26 weeks ago.
Re: Re: Bizarre initialization within TraversableOnce.reduceLef

i noticed that too and wondered "why not simply null?"

Am 11.12.2011 19:20, schrieb Dave:
> If you mean:
> ObjectRef acc$1 = new ObjectRef(BoxesRunTime.boxToInteger(0));
> For -optimise it is the same.
>
> I think it is an ObjectRef and not an IntRef, because of type erasure
> and ObjectRef expects an Object as argument.
> I think it would not be sound to do:
> IntRef acc$1 = new IntRef(0);
> otherwise you make a guarantee about the type that is not there.
>
> trait Test[A] {
> val isEmpty = false
> val self : List[A]
>
> def reduceLeft[B >: A](op: (B, A) => B): B = {
>
> if (isEmpty)
> throw new UnsupportedOperationException("empty.reduceLeft")
> var first = true
> var acc: B = 0.asInstanceOf[B]
> for (x <- self) {
> if (first) {
> acc = x
> first = false
> }
> else
> acc = op(acc, x)
> }
> acc
> }
> }
>
> Test$class.class
> ================
> import scala.Function2;
> import scala.collection.LinearSeqOptimized;
> import scala.runtime.BooleanRef;
> import scala.runtime.BoxesRunTime;
> import scala.runtime.ObjectRef;
>
> public abstract class Test$class
> {
> public static Object reduceLeft(Test $this, Function2 op$1)
> {
> if ($this.isEmpty())
> throw new UnsupportedOperationException("empty.reduceLeft");
> BooleanRef first$1 = new BooleanRef(true);
> ObjectRef acc$1 = new ObjectRef(BoxesRunTime.boxToInteger(0));
> $this.self().foreach(new Test..anonfun.reduceLeft.1($this, op$1,
> first$1, acc$1));
>
> return acc$1.elem;
> }
>
> public static void $init$(Test $this)
> {
> $this.Test$_setter_$isEmpty_$eq(false);
> }
> }
>
>
>
> On 11 dec, 17:53, Chris Marshall wrote:
>> It's been pointed out on StackOverflow [1] that there is a rather bizarre and totally superfluous piece of code inside TraversableOnce.reduceLeft which appears to have the overhead of causing the boxing of an integer on each call to the method, regardless of the types involved.
>> Presumably this is a bug?
>> def reduceLeft[B >: A](op: (B, A) => B): B = {
>> if (isEmpty)
>> throw new UnsupportedOperationException("empty.reduceLeft")
>>
>> var first = true
>> var acc: B = 0.asInstanceOf[B]
>>
>> for (x <- self) {
>> if (first) {
>> acc = x
>> first = false
>> }
>> else acc = op(acc, x)
>> }
>> acc}
>>
>> Chris
>>
>> 1:http://stackoverflow.com/questions/8465356/what-is-happening-with-0-a...

Naftoli Gugenheim
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Bizarre initialization within TraversableOnce.reduceLef
Because B may be an AnyVal. 0.asInstanceOf[B] means 0, false, or null, depending on whether B is a numeric AnyVal, Boolean, or AnyRef, IIRC.

On Sun, Dec 11, 2011 at 2:17 PM, HamsterofDeath <h-star@gmx.de> wrote:
i noticed that too and wondered "why not simply null?"

Am 11.12.2011 19:20, schrieb Dave:
> If you mean:
> ObjectRef acc$1 = new ObjectRef(BoxesRunTime.boxToInteger(0));
> For -optimise it is the same.
>
> I think it is an ObjectRef and not an IntRef, because of type erasure
> and ObjectRef expects an Object as argument.
> I think it would not be sound to do:
> IntRef acc$1 = new IntRef(0);
> otherwise you make a guarantee about the type that is not there.
>
> trait Test[A] {
>     val isEmpty = false
>     val self : List[A]
>
>     def reduceLeft[B >: A](op: (B, A) => B): B = {
>
>       if (isEmpty)
>         throw new UnsupportedOperationException("empty.reduceLeft")
>       var first = true
>       var acc: B = 0.asInstanceOf[B]
>       for (x <- self) {
>         if (first) {
>             acc = x
>             first = false
>         }
>         else
>             acc = op(acc, x)
>       }
>       acc
>     }
> }
>
> Test$class.class
> ================
> import scala.Function2;
> import scala.collection.LinearSeqOptimized;
> import scala.runtime.BooleanRef;
> import scala.runtime.BoxesRunTime;
> import scala.runtime.ObjectRef;
>
> public abstract class Test$class
> {
>   public static Object reduceLeft(Test $this, Function2 op$1)
>   {
>     if ($this.isEmpty())
>       throw new UnsupportedOperationException("empty.reduceLeft");
>     BooleanRef first$1 = new BooleanRef(true);
>     ObjectRef acc$1 = new ObjectRef(BoxesRunTime.boxToInteger(0));
>     $this.self().foreach(new Test..anonfun.reduceLeft.1($this, op$1,
> first$1, acc$1));
>
>     return acc$1.elem;
>   }
>
>   public static void $init$(Test $this)
>   {
>     $this.Test$_setter_$isEmpty_$eq(false);
>   }
> }
>
>
>
> On 11 dec, 17:53, Chris Marshall <oxbow_la...@hotmail.com> wrote:
>> It's been pointed out on StackOverflow [1] that there is a rather bizarre and totally superfluous piece of code inside TraversableOnce.reduceLeft which appears to have the overhead of causing the boxing of an integer on each call to the method, regardless of the types involved.
>> Presumably this is a bug?
>> def reduceLeft[B >: A](op: (B, A) => B): B = {
>>   if (isEmpty)
>>     throw new UnsupportedOperationException("empty.reduceLeft")
>>
>>   var first = true
>>   var acc: B = 0.asInstanceOf[B]
>>
>>   for (x <- self) {
>>     if (first) {
>>       acc = x
>>       first = false
>>     }
>>     else acc = op(acc, x)
>>   }
>>   acc}
>>
>> Chris
>>
>> 1:http://stackoverflow.com/questions/8465356/what-is-happening-with-0-a...


Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland