SIP 15: Value classes taking shape

416 views
Skip to first unread message

martin odersky

unread,
Feb 17, 2012, 10:16:40 AM2/17/12
to scala...@googlegroups.com
I have now a proposal I am quite happy with. I changed the array
handling scheme to FlatArrays that take implicit parameters
representing box/unbox conversions. This went well. I have a version
of FlatArray which is fully integrated in Scala collectionns.

What needs to be done short-term: Auto-generate BoxingConversion
objects. Enforce the restrictions laid down in the SIP. More testing.
Converting selective library classes to be value classes.

Longer term: Try to get specialization to a point where common
FlatArray operations need lead to boxing anymore. Right now, every
time you select an element in a FlatArray it is boxed, because
FlatArray's interface is generic. The boxed object is typically
short-lived because we often store it in unboxed form afterwards.
Specialization is something that should be doable here. It will
require effort, so it might arrive after 2.10. But I think the basic
value classes scheme is validated and usable now.

Cheers

-- Martin

Jason Zaugg

unread,
Feb 17, 2012, 10:33:08 AM2/17/12
to scala...@googlegroups.com

Is the proposal limited to value classes with a single constructor
parameter? If so, how would it interact with future work to model
structs, e.g. Complex(r: Double, i: Double).

These are supported on .NET, and might be added to the JVM one day. I
suppose a JVM compiler could encode them as groups of
fields/parameters, too.

-jason

Daniel Sobral

unread,
Feb 17, 2012, 10:45:33 AM2/17/12
to scala...@googlegroups.com
Is the SIP updated? I see that the change history has stuff all the
way to today, but the date at the beginning still says February 7.

--
Daniel C. Sobral

I travel to the future all the time.

Ismael Juma

unread,
Feb 17, 2012, 10:50:21 AM2/17/12
to scala...@googlegroups.com
Great to see such quick progress on this.

On Fri, Feb 17, 2012 at 3:33 PM, Jason Zaugg <jza...@gmail.com> wrote:
Is the proposal limited to value classes with a single constructor
parameter? If so, how would it interact with future work to model
structs, e.g. Complex(r: Double, i: Double).

I was wondering about the same. This would be an even bigger win, but I realise that there is no plausible implementation for the JVM.

Best,
Ismael

Rex Kerr

unread,
Feb 17, 2012, 11:02:13 AM2/17/12
to scala...@googlegroups.com

That's not _quite_ true.  It just requires a lot of extra compiler work and wouldn't perform as well as a JVM-supported version.

The basic idea is that if you have a value class V with fields x, y, every time you see
  v: V
you actually write
  v$x: X
  v$y: Y
if you can, and box only if you cannot.  You can extend this to flat arrays (better stay clear of real arrays except in boxed form), so
  av: FlatArray[V]
actually wraps
  av$x: Array[X]
  av$y: Array[Y]
instead of being a single array of Vs.

You still get into trouble if you have to return values (you have to create an object, but if you made it mutable you could cleverly push it outside of loops so you didn't have to pay the creation tax every iteration) or put them into a generic collection (you have to box, but you would have had to with a primitive anyway).  But with a huge amount of work, and attention to many corner cases, and with abandoning easy Java interoperability in this case, you could get something that had near-JVM-supported performance and was almost transparent.

Personally I don't think it's worth the effort, but I do think it's plausible.  These are just the changes that one makes by hand in order to achieve top performance when it really matters.

  --Rex

Ismael Juma

unread,
Feb 17, 2012, 11:11:46 AM2/17/12
to scala...@googlegroups.com
On Fri, Feb 17, 2012 at 4:02 PM, Rex Kerr <ich...@gmail.com> wrote:
That's not _quite_ true.  It just requires a lot of extra compiler work and wouldn't perform as well as a JVM-supported version.

I guess one can argue about the definition of plausible. Let's sidestep that, and simply agree that it would not be worth it (as you state below).
 
Personally I don't think it's worth the effort, but I do think it's plausible.  These are just the changes that one makes by hand in order to achieve top performance when it really matters.

Sure, I do that more times than I would like. But parallel arrays of primitives instead of a single array of structs still doesn't give top performance due to the higher number of cache misses (often the main performance bottleneck in situations where these things matter). It is, as you say, the best one can do in the JVM though.

Best,
Ismael

Jeff Olson

unread,
Feb 17, 2012, 11:53:31 AM2/17/12
to scala...@googlegroups.com
That's great. Where can we see the FlatArray implementation?
-Jeff

Ismael Juma

unread,
Feb 17, 2012, 12:04:44 PM2/17/12
to scala...@googlegroups.com
On Fri, Feb 17, 2012 at 4:11 PM, Ismael Juma <ism...@juma.me.uk> wrote:
It is, as you say, the best one can do in the JVM though.

Well, in some cases, one can do better and use a single array at the cost of being able to fit less elements in the array (e.g. for a struct with two ints, pack the struct fields one after the other). 

Best,
Ismael

Simon Ochsenreither

unread,
Feb 17, 2012, 12:40:49 PM2/17/12
to scala...@googlegroups.com
Any chance to separate the semantic bits of the proposal from the implementation specific ones?

I imagine that value classes could very cleanly be implemented as structs on .NET for example ...

David Hall

unread,
Feb 17, 2012, 1:04:29 PM2/17/12
to scala...@googlegroups.com

I'd been thinking about this some. How slow are the reinterpret-cast
type operations? doubleToRawLongBits etc? One crazy idea is to
actually back everything by Array[Byte] or Array[Long] and do
everything c-style. It solves the cache problem, but it's probably
hard to get all the subtleties right.

-- David

>
> Best,
> Ismael

martin odersky

unread,
Feb 17, 2012, 1:10:57 PM2/17/12
to scala...@googlegroups.com
On Fri, Feb 17, 2012 at 4:45 PM, Daniel Sobral <dcso...@gmail.com> wrote:
> Is the SIP updated? I see that the change history has stuff all the
> way to today, but the date at the beginning still says February 7.
>
I forgot to update the date. -- Martin

> On Fri, Feb 17, 2012 at 13:16, martin odersky <martin....@epfl.ch> wrote:
>> I have now a proposal I am quite happy with. I changed the array
>> handling scheme to FlatArrays that take implicit parameters
>> representing box/unbox conversions. This went well. I have a version
>> of FlatArray which is fully integrated in Scala collectionns.
>>
>> What needs to be done short-term: Auto-generate BoxingConversion
>> objects. Enforce the restrictions laid down in the SIP. More testing.
>> Converting selective library classes to be value classes.
>>
>> Longer term: Try to get specialization to a point where common
>> FlatArray operations need lead to boxing anymore. Right now, every
>> time you select an element in a FlatArray it is boxed, because
>> FlatArray's interface is generic. The boxed object is typically
>> short-lived because we often store it in unboxed form afterwards.
>> Specialization is something that should be doable here. It will
>> require effort, so it might arrive after 2.10. But I think the basic
>> value classes scheme is validated and usable now.
>>
>> Cheers
>>
>>  -- Martin
>
>
>
> --
> Daniel C. Sobral
>
> I travel to the future all the time.

--
Martin Odersky
Prof., EPFL and Chairman, Typesafe
PSED, 1015 Lausanne, Switzerland
Tel. EPFL: +41 21 693 6863
Tel. Typesafe: +41 21 691 4967

martin odersky

unread,
Feb 17, 2012, 1:15:02 PM2/17/12
to scala...@googlegroups.com
On Fri, Feb 17, 2012 at 4:33 PM, Jason Zaugg <jza...@gmail.com> wrote:
> On Fri, Feb 17, 2012 at 4:16 PM, martin odersky <martin....@epfl.ch> wrote:
>> I have now a proposal I am quite happy with. I changed the array
>> handling scheme to FlatArrays that take implicit parameters
>> representing box/unbox conversions. This went well. I have a version
>> of FlatArray which is fully integrated in Scala collectionns.
>>
>> What needs to be done short-term: Auto-generate BoxingConversion
>> objects. Enforce the restrictions laid down in the SIP. More testing.
>> Converting selective library classes to be value classes.
>>
>> Longer term: Try to get specialization to a point where common
>> FlatArray operations need lead to boxing anymore. Right now, every
>> time you select an element in a FlatArray it is boxed, because
>> FlatArray's interface is generic. The boxed object is typically
>> short-lived because we often store it in unboxed form afterwards.
>> Specialization is something that should be doable here. It will
>> require effort, so it might arrive after 2.10. But I think the basic
>> value classes scheme is validated and usable now.
>
> Is the proposal limited to value classes with a single constructor
> parameter? If so, how would it interact with future work to model
> structs, e.g. Complex(r: Double, i: Double).
>
The current proposal is limited to single parameter value classes. But
of course I have been thinking on and off about how to generalize
this. It seems to me that the most promising course of action is
actually to make tuples to be value classes with flat implementations,
and to interprete functions taking multiple parameters as unary
functions taking a tuple type, the way it is done in SML. But it will
take a long and arduous road to get there, and I do not want to
derail the current proposal with it.

Cheers

-- Martin


n-arr parameter

> These are supported on .NET, and might be added to the JVM one day. I
> suppose a JVM compiler could encode them as groups of
> fields/parameters, too.
>
> -jason

--

Jesper Nordenberg

unread,
Feb 18, 2012, 4:35:22 AM2/18/12
to scala...@googlegroups.com, Rex Kerr
Rex Kerr skrev 2012-02-17 17:02:
> The basic idea is that if you have a value class V with fields x, y,
> every time you see
> v: V
> you actually write
> v$x: X
> v$y: Y
> if you can, and box only if you cannot. You can extend this to flat
> arrays (better stay clear of real arrays except in boxed form), so
> av: FlatArray[V]
> actually wraps
> av$x: Array[X]
> av$y: Array[Y]
> instead of being a single array of Vs.

Yes, this is the easy part.

> You still get into trouble if you have to return values (you have to
> create an object, but if you made it mutable you could cleverly push it
> outside of loops so you didn't have to pay the creation tax every
> iteration) or put them into a generic collection (you have to box, but
> you would have had to with a primitive anyway).

This won't work in the general case. What about calling a method in a
loop that calls another method that return value types? The only way I
see that can remove object creation totally is either inline everything,
or pass a singleton, mutable object containing lots of primitive fields
of all types that are use for return values. Neither solution is very
practical.

If only the JVM added multiple return values you could quite easily
emulate .NET value types in the JVM similar to the way Martin has done
for single value types. Unfortunately this is not very high on Oracle's
priority list as they are reluctant towards JVM spec changes.

/Jesper Nordenberg

Ismael Juma

unread,
Feb 18, 2012, 6:04:22 AM2/18/12
to scala...@googlegroups.com
On Sat, Feb 18, 2012 at 9:35 AM, Jesper Nordenberg <mega...@yahoo.com> wrote:
Unfortunately this is not very high on Oracle's priority list as they are reluctant towards JVM spec changes.

I don't think that is the reason why it's not very high on Oracle's priority list. I think it's simply because there have many other items of higher priority in their list, like merging JRockit and HotSpot, tiered compilation, removal of PermGen, Mac OS X support and so on.

Best,
Ismael

martin odersky

unread,
Feb 19, 2012, 12:29:01 PM2/19/12
to scala...@googlegroups.com
After working some more on the compilation scheme I came to do two
more changes on the value class proposal.

First, the restriction that value classes may not have super accesses
can be dropped. This was fairly easy to implement.

Second, I also has to drop the idea that we could auto-generate the
implicit BoxingConversion terms. The reason is pretty technical but it
comes down to this: We need to implement these implicits very early in
the compilation scheme, so that any potential calls will see the
implicits. But finding out whether to generate these implicits in that
early phase would have triggered more type exploration than previously
with the consequence that some reasonable programs would be rejected
with "illegal cyclic reference" errors. The only way we could avoid
the errors would be if there was a syntactic rule that described value
classes unambiguously without resorting to name and type explorations.
Note that the "extends AnyVal" in

class Foo(x) extends AnyVal

is not unambiguous. AnyVal might be imported to mean something else,
so sometimes extending something named "AnyVal" does not imply having
a value class. Or else we might have a type alias

type AV = scala.AnyVal
class Bar(x) extends AV

This shows that some value classes do not extend AnyVal literally.

I toyed with the idea of finding new syntax for value classes. But in
the end I came down with the opinion that instead of micro-optimizing
now we should try in the long run to find a more general scheme where
classes could derive stuff automatically. So, it seemed best to keep
the minimalistic syntax.

Cheers

-- Martin

Ismael Juma

unread,
Feb 23, 2012, 5:56:04 PM2/23/12
to scala...@googlegroups.com
On Fri, Feb 17, 2012 at 6:04 PM, David Hall <dl...@cs.berkeley.edu> wrote:
I'd been thinking about this some. How slow are the reinterpret-cast
type operations?  doubleToRawLongBits etc? One crazy idea is to
actually back everything by Array[Byte] or Array[Long] and do
everything c-style. It solves the cache problem, but it's probably
hard to get all the subtleties right.

I would be interested in the results, personally.

Best,
Ismael

Erik Osheim

unread,
Mar 26, 2012, 2:09:21 PM3/26/12
to scala...@googlegroups.com
Hi,

I just wanted to follow up on my earlier email about value classes (SIP-15)

When replying to Simon's email in that thread Martin says that
"flatArray is the best anyone can do." But I think we must try to do
better.

My basic concern is that value classes as specified are a bit too
unpredictable. Specifically, I expect a programmer to use a value type
for performance reasons when she wants to ensure that the underlying
value is never boxed.

Allowing value classes extend traits (via the universal trait
mechanism) is nice, but the price (complicated rules around Arrays and
boxing) is not worth it. I think that programmers who use value types
would be willing to give up inheritance and reflection in order to gain
assurances about unboxed representation. (At least, I would.) Even
without this, the extension methods, rerouting, and peephole
optimizations still make using value classes worthwhile.

Type classes give us a way to abstract across the AnyVal types, and it
seems totally natural to me that other value classes would require the
same mechanism (rather than being able to extend Ordered[T] or
Printable or whatnot). While allowing value classes to extend universal
traits is nice, it's not worth the pain of boxing (even if we hope that
specialization might be able to solve that in the future)... especially
since types like Int and Double will still need typeclasses.

If we didn't permit value classes to extend methods, I think we *could*
do a lot better than FlatArray, right? The example in SIP-15
(illustrating why arrays must do boxing) would not be legal (since a
value class T could not be a subtype of Printable).

If there is some reason why arrays *still* must box which I haven't
thought of, I think we should move to a FlatArray that is parameterized
on both Boxed and Unboxed. At least then, users would have some way to
get and set unboxed values directly without intermediate boxing.
Without this, I'm not sure FlatArray is much better than Array (you
save on storage space a bit but pay even more costs on object
creation).

I realize that such a FlatArray would not be very compatible with
collections, but when I have to reach for FlatArray it's because I
*really* don't want boxing... so building boxing into it seems pretty
wrong. I can provide an alternate FlatArray implementation if people
would like to compare/contrast.

Sorry to be so negative--I really am excited about value classes, which
is why I'm hoping to make the spec as nice as possible. My opinion is
that it is close, but not quite there

Thanks,

-- Erik

Rex Kerr

unread,
Mar 26, 2012, 2:28:25 PM3/26/12
to scala...@googlegroups.com
On Mon, Mar 26, 2012 at 2:09 PM, Erik Osheim <er...@plastic-idolatry.com> wrote:
Hi,

I just wanted to follow up on my earlier email about value classes (SIP-15)

When replying to Simon's email in that thread Martin says that
"flatArray is the best anyone can do." But I think we must try to do
better.

My basic concern is that value classes as specified are a bit too
unpredictable. Specifically, I expect a programmer to use a value type
for performance reasons when she wants to ensure that the underlying
value is never boxed.

I agree.  I am unconvinced right now that the utility of value classes exceeds the burden of extra complexity that they impose, _especially_ because of the complexity around boxing.
 
Allowing value classes extend traits (via the universal trait
mechanism) is nice, but the price (complicated rules around Arrays and
boxing) is not worth it. I think that programmers who use value types
would be willing to give up inheritance and reflection in order to gain
assurances about unboxed representation. (At least, I would.) Even
without this, the extension methods, rerouting, and peephole
optimizations still make using value classes worthwhile.

Type classes give us a way to abstract across the AnyVal types, and it
seems totally natural to me that other value classes would require the
same mechanism (rather than being able to extend Ordered[T] or
Printable or whatnot). While allowing value classes to extend universal
traits is nice, it's not worth the pain of boxing (even if we hope that
specialization might be able to solve that in the future)... especially
since types like Int and Double will still need typeclasses.

I am inclined to agree, but it is hard to form a solid opinion without good examples of what would and wouldn't work.

  --Rex

martin odersky

unread,
Mar 26, 2012, 2:29:51 PM3/26/12
to scala...@googlegroups.com
On Mon, Mar 26, 2012 at 8:09 PM, Erik Osheim <er...@plastic-idolatry.com> wrote:
> Hi,
>
> I just wanted to follow up on my earlier email about value classes (SIP-15)
>
> When replying to Simon's email in that thread Martin says that
> "flatArray is the best anyone can do." But I think we must try to do
> better.
>
> My basic concern is that value classes as specified are a bit too
> unpredictable. Specifically, I expect a programmer to use a value type
> for performance reasons when she wants to ensure that the underlying
> value is never boxed.
>
> Allowing value classes extend traits (via the universal trait
> mechanism) is nice, but the price (complicated rules around Arrays and
> boxing) is not worth it. I think that programmers who use value types
> would be willing to give up inheritance and reflection in order to gain
> assurances about unboxed representation. (At least, I would.) Even
> without this, the extension methods, rerouting, and peephole
> optimizations still make using value classes worthwhile.
>
There's more than that. If you go down that route,

- members of value classes must print like their underlying type. I.e
you could not get 10.0m as a toString from a Meter quantity.

- members of value classes would be equal to members of the
underlying type. So 10 meter would equal 10 would equal 10 feet. The
last one, for me, is the killer.

- Martin

martin odersky

unread,
Mar 26, 2012, 2:34:11 PM3/26/12
to scala...@googlegroups.com
Philosophically, we have to realize that Array on the JVM is
fundamentally broken. Realizing that, we have to content ourselves to
do a best effort. But I would not let that best effort ruin the
coherence of the underlying model. If something has to give it must
always be arrays.

Cheers

- Martin

--

√iktor Ҡlang

unread,
Mar 26, 2012, 2:37:55 PM3/26/12
to scala...@googlegroups.com
On Mon, Mar 26, 2012 at 8:34 PM, martin odersky <martin....@epfl.ch> wrote:
Philosophically, we have to realize that Array on the JVM is
fundamentally broken.

And also a horrible implementation detail (contiguous memory).



--
Viktor Klang

Akka Tech Lead
Typesafe - The software stack for applications that scale

Twitter: @viktorklang

Erik Osheim

unread,
Mar 26, 2012, 2:43:40 PM3/26/12
to scala...@googlegroups.com
On Mon, Mar 26, 2012 at 08:29:51PM +0200, martin odersky wrote:
> There's more than that. If you go down that route,
>
> - members of value classes must print like their underlying type. I.e
> you could not get 10.0m as a toString from a Meter quantity.

I have seen this already.

I agree that this would happen when the type of the paramter isn't
known. I could imagine being able to create an "extension" of toString
that would work around it in some cases, but you're right that in many
cases it would happen. To me it's acceptable, even if it's a bit ugly.



> - members of value classes would be equal to members of the
> underlying type. So 10 meter would equal 10 would equal 10 feet. The
> last one, for me, is the killer.

This is a big problem, for sure, a natural outcome of the "equals
situation" we inherit from Java.

I am on the fence about how bad this is, compared to the boxing issues
I raised. In some cases (like units) it's clearly not great. Unsigned
integers are another place that is a bit strange. I'm not sure that
Complex(0.0F, 0.0F) == 0L is wrong per se though.

I think for my purposes I would rather have value classes that are
guaranteed to be fast (unboxed) but have some gotchas: use something
besides toString to print them out, and something else (e.g. ===) to
test for equality instead of ==.

What are other people's thoughts? I'm sure there are many perspectives
on this.

-- Erik

martin odersky

unread,
Mar 26, 2012, 2:51:39 PM3/26/12
to scala...@googlegroups.com

I am also interested in people's opinions on this. Personally, I
believe it is wrong to give up semantic integrity for speed.

- Martin

Daniel Sobral

unread,
Mar 26, 2012, 3:05:49 PM3/26/12
to scala...@googlegroups.com

Trunk currently has this:

final class StringOps(override val repr: String) extends AnyVal with
StringLike[String] {
final class Ensuring[A](val __resultOfEnsuring: A) extends AnyVal {
final class ArrowAssoc[A](val __leftOfArrow: A) extends AnyVal {

I haven't measured performance changes, but the bytecode changes
looked promising to me. Now, the first one would be made illegal by
the change proposed, and I can't think of any case where the other two
would be affected.

I'm not sure about the issues surrounding array. It seems to me that
trying to abstract anything about them is always so full or corner
cases as to make them too dangerous to use. Of course, I'd love to be
proven wrong, but if the choice is between having to use unabstracted
arrays vs having to tread warily whenever I use abstracted arrays, I'd
pick the former (ie, keep the current SIP).

Josh Suereth

unread,
Mar 26, 2012, 3:13:30 PM3/26/12
to scala...@googlegroups.com
So, Value classes are solving a few different problems (in Scala).  One is that of extension methods and implicit views.   We can get the same performance (or bytecode) as extension methods on implicit views using value classes.  That's pretty spiffy.

The remaining additions are gravy.   I'd prefer to not loose the above optimisation in anything else we do.  I think it's ok for us to err on the side of correctness rather than efficiency and hope the JVM eventually corrects itself.

Roland Kuhn

unread,
Mar 26, 2012, 3:15:00 PM3/26/12
to scala...@googlegroups.com

On Mar 26, 2012, at 20:43 , Erik Osheim wrote:

> On Mon, Mar 26, 2012 at 08:29:51PM +0200, martin odersky wrote:
>> There's more than that. If you go down that route,
>>
>> - members of value classes must print like their underlying type. I.e
>> you could not get 10.0m as a toString from a Meter quantity.
>
> I have seen this already.
>
> I agree that this would happen when the type of the paramter isn't
> known. I could imagine being able to create an "extension" of toString
> that would work around it in some cases, but you're right that in many
> cases it would happen. To me it's acceptable, even if it's a bit ugly.
>
>> - members of value classes would be equal to members of the
>> underlying type. So 10 meter would equal 10 would equal 10 feet. The
>> last one, for me, is the killer.
>
> This is a big problem, for sure, a natural outcome of the "equals
> situation" we inherit from Java.
>
> I am on the fence about how bad this is, compared to the boxing issues
> I raised. In some cases (like units) it's clearly not great. Unsigned
> integers are another place that is a bit strange. I'm not sure that
> Complex(0.0F, 0.0F) == 0L is wrong per se though.
>

You picked exactly the one value for which this is okay. Would you say the same for Complex(1f, 1f)==4575657222473777152L? (my own concocted encoding, don’t know if this matches what you do)

> I think for my purposes I would rather have value classes that are
> guaranteed to be fast (unboxed) but have some gotchas: use something
> besides toString to print them out, and something else (e.g. ===) to
> test for equality instead of ==.
>

Consistency is rather important when discussing a programming language feature, I think. If you want raw arrays, then you obviously care so much that you should probably just use raw arrays, I guess.

> What are other people's thoughts? I'm sure there are many perspectives
> on this.
>

Take this with a pinch of salt, as I have never actually implemented something close to what you want to have on the JVM. But I’m still worried about the equals thingy.

Regards,

Roland

David Hall

unread,
Mar 26, 2012, 3:15:59 PM3/26/12
to scala...@googlegroups.com
On Mon, Mar 26, 2012 at 11:43 AM, Erik Osheim <er...@plastic-idolatry.com> wrote:
>
> What are other people's thoughts? I'm sure there are many perspectives
> on this.

Yeah, I'm not honestly sure how useful these are going to be if arrays
are slow. I'd bet that the vast majority of the use cases surrounding
value types will want arrays. It's hard for me to think of any non-toy
numeric application of value classes that won't use arrays. And, as
has been pointed out, we're going to need typeclasses to do any actual
generic operations with these things, anyway, since we'll want fast
Double/Float/Int ops still.

I do a lot of AI/ML work, and I'd love to have floats with more
exponent and less mantissa, or being able to represent doubles in log
space without overhead. (I'd especially love being able to have a
double and a long in a value class. Maybe one day.) As it currently
stands, I don't think we could really get any benefit out of using
these in Scalala, and I don't think I could use them in my inner
loops. (Basic example inner loop: CKY for weighted context free
grammars.)

Maybe it'll be possible to write a macro class version of FlatArray
one day? I have no faith in specialization...

-- David

Andreas Flierl

unread,
Mar 26, 2012, 3:19:28 PM3/26/12
to scala...@googlegroups.com
Hi,

martin odersky wrote:

FWIW, I agree that giving up semantic integrity for speed would be wrong. But Object#equals is already pretty broken (in my book) and I see toString abused more often than not. Personally, I could live with having to use a "Show" type class instead of "toString" and === resp. an "Equal" type class instead of == resp. equals.

But then... toString and equals are probably in too widespread use already, making value classes incompatible with libraries that are already out there.

All in all, I suspect it would bring more trouble than it's worth. :(

Kind regards
Andreas

Erik Osheim

unread,
Mar 26, 2012, 3:39:24 PM3/26/12
to scala...@googlegroups.com
On Mon, Mar 26, 2012 at 09:15:00PM +0200, Roland Kuhn wrote:
> > integers are another place that is a bit strange. I'm not sure that
> > Complex(0.0F, 0.0F) == 0L is wrong per se though.
> >
> You picked exactly the one value for which this is okay. Would you
> say the same for Complex(1f, 1f)==4575657222473777152L? (my own
> concocted encoding, don’t know if this matches what you do)

Sorry if that seemed flippant. I guess my opinion is that if you're
comparing Complex to Long you should know what you're doing. Especially
if we don't get improved array support I expect I will be doing a lot
of Complex#u == Long tests, so this result would be OK.

Really, in my own work I would probably be using an Eq[A] typeclass
with === so I would only use == precisely when I was willing to have
something "interesting" like this happen.



> Consistency is rather important when discussing a programming
> language feature, I think. If you want raw arrays, then you obviously
> care so much that you should probably just use raw arrays, I guess.

Of course. I accept that weirdos who care about performance of large
arrays of data are not usually the main constituency for these things.
:) That said, for a moment it seemed like value classes would permit a
lot of interesting uses in this area.

Thanks for your feedback.

-- Erik

Erik Osheim

unread,
Mar 26, 2012, 3:41:16 PM3/26/12
to scala...@googlegroups.com
On Mon, Mar 26, 2012 at 03:13:30PM -0400, Josh Suereth wrote:
> The remaining additions are gravy. I'd prefer to not loose the above
> optimisation in anything else we do. I think it's ok for us to err on the
> side of correctness rather than efficiency and hope the JVM eventually
> corrects itself.

That's a good point. Just because value classes aren't solving all my
problems doesn't mean they aren't solving any of them. :)

If we can (eventually) get these things playing nicely with specialized
Ops[A] classes then that by itself will be a gigantic win.

-- Erik

Jori Jovanovich

unread,
Mar 26, 2012, 3:49:08 PM3/26/12
to scala...@googlegroups.com

On Mar 26, 2012, at 2:13 PM, Josh Suereth wrote:

> So, Value classes are solving a few different problems (in Scala). One is that of extension methods and implicit views. We can get the same performance (or bytecode) as extension methods on implicit views using value classes. That's pretty spiffy.
>
> The remaining additions are gravy. I'd prefer to not loose the above optimisation in anything else we do. I think it's ok for us to err on the side of correctness rather than efficiency and hope the JVM eventually corrects itself.

+1. Our primary interest in value classes for my company's code base are for the optimization of implicits. The other stuff is merely a nice-to-have for us.

I've been getting nervous when I see people talk about how value classes might be more trouble than they are worth based on arrays or whatnot. I couldn't disagree more!

Andreas Flierl

unread,
Mar 26, 2012, 3:58:41 PM3/26/12
to scala...@googlegroups.com

Jori Jovanovich wrote:

>
> I've been getting nervous when I see people talk about how value classes might be more trouble than they are worth based on arrays or whatnot. I couldn't disagree more!

Just to be clear, I meant if value classes give up semantic consistency (toString, equals) for speed, then they might be more trouble than they are worth. The proposal in its current form doesn't have that problem, as far as I understand, and I'm all for it. Sorry if I wasn't clear about that. :(

Kind regards
Andreas

Simon Ochsenreither

unread,
Mar 26, 2012, 5:09:13 PM3/26/12
to scala...@googlegroups.com
I think getting in touch with the JVM/OpenJDK people would be the sensible thing to do. The compromises necessary are just not worth all the trouble.
Imho not shipping a feature where people are not 100% happy about it, is a feature, too.

Having read John Rose's article I think he would be glad if he could get some people behind his ideas. :-)
Last time dynamic languages got their way (Java 7), this time Java will get some much needed updates (Java 8), maybe it is Scala's turn now?


Lieven Lemiengre

unread,
Mar 26, 2012, 5:58:28 PM3/26/12
to scala...@googlegroups.com
I'd just like to point out that the current FlatArray may perform better than expected: http://www.stefankrause.net/wp/?p=64 , escape analysis seems to do a fantastic job in this example.

sreque

unread,
Mar 27, 2012, 11:42:47 AM3/27/12
to scala-sips




On Mar 26, 2:41 pm, Erik Osheim <e...@plastic-idolatry.com> wrote:
> On Mon, Mar 26, 2012 at 03:13:30PM -0400, Josh Suereth wrote:
> > The remaining additions are gravy.   I'd prefer to not loose the above
> > optimisation in anything else we do.  I think it's ok for us to err on the
> > side of correctness rather than efficiency and hope the JVM eventually
> > corrects itself.

Correctness is definitely more important than efficiency, but if a
particular feature is meant specifically to improve performance, than
correctness is not enough. We already have correctness. Value classes
have no other purpose than to improve performance! They aren't adding
any new features or capabilities to the language. It's also wishful
thinking at best to hope that the JVM swoops in and saves the day
here. Value types are nowhere on the JVM roadmap right now for the
next 5-10 years.

Also, I don't like the idea of relying on JVM escape analysis to
ensure FlatArray performance. I'm no expert in the area, but I get the
impression that you're playing Russian roulette if you are counting on
escape analysis to make your JVM code high-performance. Each minor
code change and re-compile is just another spin on the revolver
cylinder! All the fun that came from optimizing Range.foreach seems to
be a good example of this.

> That's a good point. Just because value classes aren't solving all my
> problems doesn't mean they aren't solving any of them. :)
>
> If we can (eventually) get these things playing nicely with specialized
> Ops[A] classes then that by itself will be a gigantic win.

If value classes are primarily meant to solve the implicit conversions
use case for the next release, which is a wonderful thing, IMO, why
implement FlatArray at all right now? It seems to me it would be
better to hold off on it until a real working solution for arrays of
value classes is implemented.

I think specialization is a good analogy. It's great that this feature
enabled optimizations for Function2's, but I feel like advertising it
as a general feature lead to more harm and frustration than it was
worth as library writers hit all the limitations and found out it
couldn't really do what they thought it could. Would an implementation
of FlatArray that still causes a lot of boxing not do the same by
advertising to users a feature that doesn't work very well in
practice? This can be more damaging than not promising the feature at
all! I already saw one comment on this thread where someone said they
had no faith in specialization being able to optimize their numeric-
intensive library routines. Do we want more features that so un-
inspire?

Finally, I am worried, reading all the debates in this mailing list
right now, that Scala is risking moving too quickly for the next few
releases. I am glad there is a lot of pushback for some of the more
controversial recent proposals. I hope it leads to a more correct
evolution of Scala, even if that evolution takes longer.

Scala is solving hard problems on the JVM with proposals like value
classes and specialization. It might be worth it to take more time
getting these things right before offering them as a language feature
for general consumption when they may not yet have general
applicability.

> -- Erik
-- Sean

Paul Phillips

unread,
Mar 27, 2012, 11:52:58 AM3/27/12
to scala...@googlegroups.com
On Tue, Mar 27, 2012 at 8:42 AM, sreque <sean...@yahoo.com> wrote:
> Correctness is definitely more important than efficiency, but if a
> particular feature is meant specifically to improve performance, than
> correctness is not enough. We already have correctness. Value classes
> have no other purpose than to improve performance!

I strongly agree with this sentiment. There are clearly places to
favor performance over correctness, and if (generic) you disagree you
had better at minimum be using BigInt everywhere.

The complexity burden that specialization has placed on the
implementation has been very very high. We must avoid the further
imposition of complexity on the noble implementors where the upside of
the complexity fails to carry its weight.

Jeff Olson

unread,
Mar 27, 2012, 12:00:50 PM3/27/12
to scala...@googlegroups.com
Just to be clear, what are the issues with FlatArray in the current implementation? It certainly seems possible that a correct implementation will have no boxing issues whatsoever (expecting of course the trivial boxing of the array itself). Is Array specialization standing in the way of achieving this ideal?

-Jeff

martin odersky

unread,
Mar 27, 2012, 12:16:59 PM3/27/12
to scala...@googlegroups.com
On Tue, Mar 27, 2012 at 6:00 PM, Jeff Olson <jeff.d...@gmail.com> wrote:
> Just to be clear, what are the issues with FlatArray in the current
> implementation? It certainly seems possible that a correct implementation
> will have no boxing issues whatsoever (expecting of course the trivial
> boxing of the array itself). Is Array specialization standing in the way of
> achieving this ideal?

I believe it is that FlatArray[Meter] needs to take Meters as the
elements that go in and out of a FlatArray, including any constructor
arguments. But FlatArray is a generic class, so any elements have to
be boxed and unboxed when they go in or out of a FlatArray. They would
still be stored as unboxed. But to take an element out of a FlatArray,
say, you'd have to box it for the generic interface, then immediately
unbox it at the monomorphic use site. One hopes that escape analysis
will find and eliminate the short-lived object, but that depends on
the code being inlined by Hotspot.

In the SIP we intentionally did not want to include specialization.
But to make FlatArray go well we need specialization to value class
type parameters. This will be rather hairy I am afraid, maybe not even
possible without a fundamental rethinking of the specialization
architecture.

The first problem here is one of phases. Value classes need to be
expanded during erasure. Specialization happens before that. So
Specialization is not able to treat a value class as its underlying
type. To be able to do that is the whole point of the transform in
erasure and postErasure.

So it seems for the mid term our only choices are:

- keep FlatArray and rely on escape analysis.
- don't have a solution for arrays at all.

In fact, for large arrays, FlatArray should win over non-flat arrays
even if boxing occurs at the interface because of the better locality
and smaller memory footprint. So there might be reasons enough to keep
FlatArray.

Cheers

- Martin

sreque

unread,
Mar 27, 2012, 12:41:36 PM3/27/12
to scala-sips


On Mar 27, 11:16 am, martin odersky <martin.oder...@epfl.ch> wrote:
> On Tue, Mar 27, 2012 at 6:00 PM, Jeff Olson <jeff.d.ol...@gmail.com> wrote:
> > Just to be clear, what are the issues with FlatArray in the current
> > implementation? It certainly seems possible that a correct implementation
> > will have no boxing issues whatsoever (expecting of course the trivial
> > boxing of the array itself). Is Array specialization standing in the way of
> > achieving this ideal?
>
> I believe it is that FlatArray[Meter] needs to take Meters as the
> elements that go in and out of a FlatArray, including any constructor
> arguments. But FlatArray is a generic class, so any elements have to
> be boxed and unboxed when they go in or out of a FlatArray. They would
> still be stored as unboxed. But to take an element out of a FlatArray,
> say, you'd have to box it for the generic interface, then immediately
> unbox it at the monomorphic use site. One hopes that escape analysis
> will find and eliminate the short-lived object, but that depends on
> the code being inlined by Hotspot.

There is some precedence for this. PLT-Racket, for instance, has
native float arrays with their own set of performance tradeoffs .

http://docs.racket-lang.org/reference/flonums.html?q=flvector#(def._((lib._racket/flonum..rkt)._flvector))

http://groups.google.com/group/plt-scheme/browse_thread/thread/620676828d44b746

It will be interesting to see the actual performance tradeoffs in
Scala when run on the different VMs.

Anyways, I think you and all the other Scala contributors are doing
amazing things with the language right now. I believe that macros
alone, if implemented well, have enormous potential behind them. On
top of that, we have reflection, extension methods, a better pattern
matcher, and so many other things, all in one release!

-- Sean

martin odersky

unread,
Mar 27, 2012, 12:46:39 PM3/27/12
to scala...@googlegroups.com
On Tue, Mar 27, 2012 at 6:41 PM, sreque <sean...@yahoo.com> wrote:
>
>
> On Mar 27, 11:16 am, martin odersky <martin.oder...@epfl.ch> wrote:
>> On Tue, Mar 27, 2012 at 6:00 PM, Jeff Olson <jeff.d.ol...@gmail.com> wrote:
>> > Just to be clear, what are the issues with FlatArray in the current
>> > implementation? It certainly seems possible that a correct implementation
>> > will have no boxing issues whatsoever (expecting of course the trivial
>> > boxing of the array itself). Is Array specialization standing in the way of
>> > achieving this ideal?
>>
>> I believe it is that FlatArray[Meter] needs to take Meters as the
>> elements that go in and out of a FlatArray, including any constructor
>> arguments. But FlatArray is a generic class, so any elements have to
>> be boxed and unboxed when they go in or out of a FlatArray. They would
>> still be stored as unboxed. But to take an element out of a FlatArray,
>> say, you'd have to box it for the generic interface, then immediately
>> unbox it at the monomorphic use site. One hopes that escape analysis
>> will find and eliminate the short-lived object, but that depends on
>> the code being inlined by Hotspot.
>
> There is some precedence for this. PLT-Racket, for instance, has
> native float arrays with their own set of performance tradeoffs .
>
> http://docs.racket-lang.org/reference/flonums.html?q=flvector#(def._((lib._racket/flonum..rkt)._flvector))
>
> http://groups.google.com/group/plt-scheme/browse_thread/thread/620676828d44b746
>
Yes, that seems to be the same idea. Interesting discussion of
performance tradeoffs.

-- Martin


> It will be interesting to see the actual performance tradeoffs in
> Scala when run on the different VMs.
>
> Anyways, I think you and all the other Scala contributors are doing
> amazing things with the language right now. I believe that macros
> alone, if implemented well, have enormous potential behind them. On
> top of that, we have reflection, extension methods, a better pattern
> matcher, and so many other things, all in one release!
>
> -- Sean

--

Erik Osheim

unread,
Mar 27, 2012, 1:12:23 PM3/27/12
to scala...@googlegroups.com
On Tue, Mar 27, 2012 at 06:16:59PM +0200, martin odersky wrote:
> So it seems for the mid term our only choices are:
>
> - keep FlatArray and rely on escape analysis.
> - don't have a solution for arrays at all.

If the use-case for value classes is mostly for things like implicit
conversions (rather than for creating new number types which are
totally unboxed), then I would support removing FlatArray to simplify
the SIP and to avoid creating expectations which we can't fulfill.

> In fact, for large arrays, FlatArray should win over non-flat arrays
> even if boxing occurs at the interface because of the better locality
> and smaller memory footprint. So there might be reasons enough to keep
> FlatArray.

This is true, but you can always allocate the Array[Unboxed] yourself
and get/set manually to get the same space savings. This is a bit more
verbose but at least it is clear how it works (Array[Foo] is boxed,
Array[Double] is not), and not very error prone.

-- Erik

martin odersky

unread,
Mar 27, 2012, 1:24:08 PM3/27/12
to scala...@googlegroups.com
On Tue, Mar 27, 2012 at 7:12 PM, Erik Osheim <er...@plastic-idolatry.com> wrote:
> On Tue, Mar 27, 2012 at 06:16:59PM +0200, martin odersky wrote:
>> So it seems for the mid term our only choices are:
>>
>>  - keep FlatArray and rely on escape analysis.
>>  - don't have a solution for arrays at all.
>
> If the use-case for value classes is mostly for things like implicit
> conversions (rather than for creating new number types which are
> totally unboxed), then I would support removing FlatArray to simplify
> the SIP and to avoid creating expectations which we can't fulfill.
>

I think both are use cases. And, I also think that FlatArray is the
only thing we will ever be able to do for arrays. No other scheme will
work.
The choice is: Introduce it now, and hope for escape analysis and
future improvements to specialization to remove the bottlenecks. Or
introduce it later when these improvements have materialized but then
face the problem that people will have used other solutions in their
code (ie boxed arrays or arrays of primitive values with manual
packing/unpacking).

Cheers

- Martin

Paul Phillips

unread,
Mar 27, 2012, 1:30:05 PM3/27/12
to scala...@googlegroups.com
On Tue, Mar 27, 2012 at 10:24 AM, martin odersky <martin....@epfl.ch> wrote:
> The choice is: Introduce it now, and hope for escape analysis and
> future improvements to specialization to remove the bottlenecks. Or
> introduce it later when these improvements have materialized but then
> face the problem that people will have used other solutions in their
> code (ie boxed arrays or arrays of primitive values with manual
> packing/unpacking).

That's not dissimilar from the choice which was faced with
specialization. And I thought then and still think that "introduce it
now" was not the way to go.

martin odersky

unread,
Mar 27, 2012, 1:36:15 PM3/27/12
to scala...@googlegroups.com

But there is a crucial difference. Specialization is a huge and hairy beast
FlatArray is a simple class with 150 lines of code total, fully
integrated into collections. And it's the canonical class, it will not
be any different if we introduce it in 2.11 or 2.10.

I would still also hesitate if there was a chance that there would be
a better way to deal with arrays in the future. But that won't happen.

Cheers

- Martin

Pavel Pavlov

unread,
Mar 27, 2012, 1:57:27 PM3/27/12
to scala...@googlegroups.com


понедельник, 20 февраля 2012 г. 0:29:01 UTC+7 пользователь Martin написал:
After working some more on the compilation scheme I came to do two
more changes on the value class proposal.

First, the restriction that value classes may not have super accesses
can be dropped. This was fairly easy to implement.

Second, I also has to drop the idea that we could auto-generate the
implicit BoxingConversion terms. The reason is pretty technical but it
comes down to this: We need to implement these implicits very early in
the compilation scheme, so that any potential calls will see the
implicits. But finding out whether to generate these implicits in that
early phase would have triggered more type exploration than previously
with the consequence that some reasonable programs would be rejected
with "illegal cyclic reference" errors. The only way we could avoid
the errors would be if there was a syntactic rule that described value
classes unambiguously without resorting to name and type explorations.


Maybe `val class Meter(x: Double)` ?


Note that the "extends AnyVal" in

   class Foo(x) extends AnyVal

is not unambiguous. AnyVal might be imported to mean something else,
so sometimes extending something named "AnyVal" does not imply having
a value class. Or else we might have a type alias

   type AV = scala.AnyVal
   class Bar(x) extends AV

This shows that some value classes do not extend AnyVal literally.

I toyed with the idea of finding new syntax for value classes. But in
the end I came down with the opinion that instead of micro-optimizing
now we should try in the long run to find a more general scheme where
classes could derive stuff automatically. So, it seemed best to keep
the minimalistic syntax.

Cheers

 -- Martin


понедельник, 20 февраля 2012 г. 0:29:01 UTC+7 пользователь Martin написал:
After working some more on the compilation scheme I came to do two
more changes on the value class proposal.

First, the restriction that value classes may not have super accesses
can be dropped. This was fairly easy to implement.

Second, I also has to drop the idea that we could auto-generate the
implicit BoxingConversion terms. The reason is pretty technical but it
comes down to this: We need to implement these implicits very early in
the compilation scheme, so that any potential calls will see the
implicits. But finding out whether to generate these implicits in that
early phase would have triggered more type exploration than previously
with the consequence that some reasonable programs would be rejected
with "illegal cyclic reference" errors. The only way we could avoid
the errors would be if there was a syntactic rule that described value
classes unambiguously without resorting to name and type explorations.
Note that the "extends AnyVal" in

   class Foo(x) extends AnyVal

is not unambiguous. AnyVal might be imported to mean something else,
so sometimes extending something named "AnyVal" does not imply having
a value class. Or else we might have a type alias

   type AV = scala.AnyVal
   class Bar(x) extends AV

This shows that some value classes do not extend AnyVal literally.

I toyed with the idea of finding new syntax for value classes. But in
the end I came down with the opinion that instead of micro-optimizing
now we should try in the long run to find a more general scheme where
classes could derive stuff automatically. So, it seemed best to keep
the minimalistic syntax.

Cheers

 -- Martin

martin odersky

unread,
Mar 27, 2012, 3:30:55 PM3/27/12
to scala...@googlegroups.com
On Tue, Mar 27, 2012 at 7:57 PM, Pavel Pavlov <pavel.e...@gmail.com> wrote:
>
>
> понедельник, 20 февраля 2012 г. 0:29:01 UTC+7 пользователь Martin написал:
>>
>> After working some more on the compilation scheme I came to do two
>> more changes on the value class proposal.
>>
>> First, the restriction that value classes may not have super accesses
>> can be dropped. This was fairly easy to implement.
>>
>> Second, I also has to drop the idea that we could auto-generate the
>> implicit BoxingConversion terms. The reason is pretty technical but it
>> comes down to this: We need to implement these implicits very early in
>> the compilation scheme, so that any potential calls will see the
>> implicits. But finding out whether to generate these implicits in that
>> early phase would have triggered more type exploration than previously
>> with the consequence that some reasonable programs would be rejected
>> with "illegal cyclic reference" errors. The only way we could avoid
>> the errors would be if there was a syntactic rule that described value
>> classes unambiguously without resorting to name and type explorations.
>
>
> Maybe `val class Meter(x: Double)` ?
>
>
Yes, that might indeed be a possibility. When I first thought of it id
did not look appealing but now that I see it written out, it looks not
so bad.

-- Martin

--

Pavel Pavlov

unread,
Mar 27, 2012, 4:03:14 PM3/27/12
to scala...@googlegroups.com


среда, 28 марта 2012 г. 2:30:55 UTC+7 пользователь Martin написал:
On Tue, Mar 27, 2012 at 7:57 PM, Pavel Pavlov <pavel.e...@gmail.com> wrote:
>
> Maybe `val class Meter(x: Double)` ?
>
>
Yes, that might indeed be a possibility. When I first thought of it id
did not look appealing but now that I see it written out, it looks not
so bad.

What I really like about this is that this way the compiler can extend any traits it wants, add any number of members (e.g. `type Underlying = Double`), define companion object of any shape etc. And further extend any of these in the future (post-2.10) Scala versions, improving the functionality of user's code without touching the sources. Exactly the same way as it's now for case classes.

Rex Kerr

unread,
Mar 27, 2012, 4:18:10 PM3/27/12
to scala...@googlegroups.com
On Tue, Mar 27, 2012 at 1:24 PM, martin odersky <martin....@epfl.ch> wrote:
On Tue, Mar 27, 2012 at 7:12 PM, Erik Osheim <er...@plastic-idolatry.com> wrote:
> On Tue, Mar 27, 2012 at 06:16:59PM +0200, martin odersky wrote:
>> So it seems for the mid term our only choices are:
>>
>>  - keep FlatArray and rely on escape analysis.
>>  - don't have a solution for arrays at all.
>
> If the use-case for value classes is mostly for things like implicit
> conversions (rather than for creating new number types which are
> totally unboxed), then I would support removing FlatArray to simplify
> the SIP and to avoid creating expectations which we can't fulfill.
>

I think both are use cases. And, I also think that FlatArray is the
only thing we will ever be able to do for arrays. No other scheme will
work.

Do you mean no other scheme will work _period_, or no other scheme will work without JVM support?  If Java gains intrinsic support for value classes, then arrays would be e.g. [KMeter and everything would be fine, no?

  --Rex

Alex Repain

unread,
Mar 27, 2012, 4:47:52 PM3/27/12
to scala...@googlegroups.com


2012/3/27 Rex Kerr <ich...@gmail.com>

Probably, but as stated earlier in the thread, it is a very weak development plan for Scala to rely on hypothetic, likely ages ahead JVM improvements. I mean, it's not like Sun andThen Oracle had proved their will to fasten the pace of adding new features to the VM.
 
  --Rex


martin odersky

unread,
Mar 27, 2012, 4:49:35 PM3/27/12
to scala...@googlegroups.com

I'm very sceptical that will happen, and certainly not in the
timeframes we want to consider. Look at the treatments of arrays today
in Java - you can't even define an Array[List[String]]. - Martin

Rex Kerr

unread,
Mar 27, 2012, 4:54:52 PM3/27/12
to scala...@googlegroups.com
Well, I guess we can have a confusing-to-optimize FlatArray for now, and then see if Oracle does something useful, and deprecate/change if so.  I'd hope that people with possible influence would try to encourage Oracle to make positive developments in that regard.

Anyway, in JVM bytecode you can't even define a List[String].  It's just List.  How is Array[List[String]] erasing to Array[List] any different than that?

  --Rex

Ismael Juma

unread,
Mar 27, 2012, 5:00:05 PM3/27/12
to scala...@googlegroups.com
On Tue, Mar 27, 2012 at 9:49 PM, martin odersky <martin....@epfl.ch> wrote:
I'm very sceptical that will happen, and certainly not in the
timeframes we want to consider.

Yes, Java 9 would be the earliest. That is still 3+ years away.

Best,
Ismael

nafg

unread,
Mar 27, 2012, 5:07:03 PM3/27/12
to scala...@googlegroups.com


On Tuesday, March 27, 2012 12:16:59 PM UTC-4, Martin wrote:

In the SIP we intentionally did not want to include specialization.
But to make FlatArray go well we need specialization to value class
type parameters. This will be rather hairy I am afraid, maybe not even
possible without a fundamental rethinking of the specialization
architecture.

The first problem here is one of phases. Value classes need to be
expanded during erasure. Specialization happens before that. So
Specialization is not able to treat a value class as its underlying
type. To be able to do that is the whole point of the transform in
erasure and postErasure.

So it seems for the mid term our only choices are:

 - keep FlatArray and rely on escape analysis.
 - don't have a solution for arrays at all.


Maybe what's needed is a separate, "special" specialization for value classes?
 

nafg

unread,
Mar 27, 2012, 5:08:45 PM3/27/12
to scala...@googlegroups.com
On Monday, March 26, 2012 2:29:51 PM UTC-4, Martin wrote:

 - members of value classes would be equal to members of the
underlying type. So 10 meter would equal 10 would equal 10 feet. The
last one, for me, is the killer.


Not sure if I'm missing context, but maybe the solution is for value classes to wait until scala has a typesafe equals (is there still hope for that)?
 

Alex Repain

unread,
Mar 27, 2012, 5:23:37 PM3/27/12
to scala...@googlegroups.com


2012/3/27 nafg <nafto...@gmail.com>

That's one out of many other problems, which lead me to the following thought :

Scala concepts, Scala richness simply deserve a better environment than what the JVM currently is.

Problem is, it is not available per se, so it's a DIY (see you in a while then) or wait until Oracle fixes for us. But Java accomodates of the broken things of JVM because it was built with them taken as inherent axioms for Java. So Oracle has no absolute interest to fix these things for the sake of Java itself, which evolution pace is also based on this of the JVM. And if I'm just thinking business, I have no interest in paying people to work on something that will mostly benefit to concurrent languages on the platform, and need rework on our own language too to accomodate the changes. There may be some influential authorities in the Scala ecosystem who would deserve to be listened to, but I doubt making changes happen for the sake of Scala would be easy. At best, it would just make the things happen eventually, but not accelerate the JVM evolution...


Rex Kerr

unread,
Mar 27, 2012, 5:24:23 PM3/27/12
to scala...@googlegroups.com
I'm not sure this is such a killer in principle.

If you had extension methods that took precedence over inherited methods and could be overloaded, then

    def (m: Meter)==(n: Meter) = (m: Int) == (n: Int)
    def (m: Meter)==(a: All) = false

would get the meter-based value equals right (with a rule that something typed as a value class only is equal to another thing typed as the same value class, and with rewriting of a==b as b==a when the rhs is typed as a value class and the left is not).

  --Rex

martin odersky

unread,
Mar 28, 2012, 4:39:38 AM3/28/12
to scala...@googlegroups.com
I believe we have two different abstractions at play here.

1. Value classes as presented in the SIP: Can extend traits, need
FlatArray for unboxed array representation.

What some people here are after is this:

2. Newtypes over primitive value types. These could neither extend
traits nor reimplement an Object method (equals, toString, hashCode).
Since == maps to equals, == can also not be redefined. The latter is a
point that may or may not change in the future. Such val newtypes
could be stored in plain arrays without being boxed.

It turns out that (2) is not only compatible with (1), but it needs
(1) to work well. The only way to attach new behavior to a val newtype
is with an implicit decorator. And the only reliable way to make
implicit decorators work without overhead is (1).

So I believe that (1) can very well stand on its own. I would also
give FlatArray a shot and see how far we can get with it with
optimizations on the Scala side and escape analysis on the JVM (which
is also getting better btw). The worst that can happen is that we
conclude that we need (2) for Scala 2.11, and that then FlatArray
would be less useful (I claim it would likely still be useful). If
nobody uses it in 2.11, we can deprecate it and get rid of it later.
But I do not expect that to happen.

Cheers

- Martin

martin odersky

unread,
Mar 28, 2012, 4:41:25 AM3/28/12
to scala...@googlegroups.com
That's currently unknown.

But the most dangerous usages of equals are the ones you do not see:
Java collections, for instance.
It would be very inconvenient if you stored meters and feet in a
collection and they got confused with each other.

- Martin

Reply all
Reply to author
Forward
0 new messages