- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Bizarre initialization within TraversableOnce.reduceLeft
Sun, 2011-12-11, 17:53
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?
Chris
1: http://stackoverflow.com/questions/8465356/what-is-happening-with-0-asinstanceofb-in-scala-reduceleft-implementation
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
Sun, 2011-12-11, 20:21
#2
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...
Tue, 2011-12-13, 06:41
#3
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:
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...
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...