Puzzle

96 views
Skip to first unread message

Bruce Eckel

unread,
Oct 20, 2012, 7:59:58 PM10/20/12
to scala...@googlegroups.com
I got this from the second answer at:

First, the example. This runs:

trait Enum[A] {
  trait Value { self: A =>
    _values :+= this
  }
  private var _values = List.empty[A]
  def values = _values
}

sealed trait Currency extends Currency.Value
object Currency extends Enum[Currency] {
  case object EUR extends Currency
  case object GBP extends Currency
}

println(Currency.values)  

My first problem is trying to figure out the syntax of:

  trait Value { self: A =>
    _values :+= this
  }

From the context, I'm guessing that the code after the => somehow runs for every object that's created. But how do you read/mentally parse "self: A=>"? 

My second problem is that the code in Value doesn't seem to execute; the output of the println is List(). What's the correct way to do this?

Thanks...



Som Snytt

unread,
Oct 20, 2012, 9:48:00 PM10/20/12
to Bruce Eckel, scala...@googlegroups.com
On Sat, Oct 20, 2012 at 4:59 PM, Bruce Eckel <bruce...@gmail.com> wrote:
 But how do you read/mentally parse "self: A=>"? 

Self-type is A, just constrains what the trait may be mixed-in with.  This is an A.
 

My second problem is that the code in Value doesn't seem to execute; the output of the println is List(). What's the correct way to do this?



Objects aren't pre-loaded.

println(Currency.values) 

// Exiting paste mode, now interpreting.

List()
defined trait Enum
defined trait Currency
defined module Currency

scala> Currency.EUR
res1: Currency.EUR.type = EUR

scala> Currency.GBP
res2: Currency.GBP.type = GBP

scala> println(Currency.values)
List(EUR, GBP)
 

Daniel Sobral

unread,
Oct 21, 2012, 7:59:11 AM10/21/12
to Bruce Eckel, scala...@googlegroups.com
On Sat, Oct 20, 2012 at 9:59 PM, Bruce Eckel <bruce...@gmail.com> wrote:
> I got this from the second answer at:
> http://stackoverflow.com/questions/1898932/case-classes-vs-enumerations-in-scala
>
> First, the example. This runs:
>
> trait Enum[A] {
> trait Value { self: A =>
> _values :+= this
> }
> private var _values = List.empty[A]
> def values = _values
> }
>
> sealed trait Currency extends Currency.Value
> object Currency extends Enum[Currency] {
> case object EUR extends Currency
> case object GBP extends Currency
> }
>
> println(Currency.values)
>
> My first problem is trying to figure out the syntax of:
>
> trait Value { self: A =>
> _values :+= this
> }
>
> From the context, I'm guessing that the code after the => somehow runs for
> every object that's created. But how do you read/mentally parse "self: A=>"?

That's not related, really. "self: A =>" is a self type, which is just
a way of creating an alias for "this" and/or adding a requirement to
the concrete implementations of the trait (that is, they must extend
"A", directly or indirectly).

What comes after that is just your regular primary constructor.

> My second problem is that the code in Value doesn't seem to execute; the
> output of the println is List(). What's the correct way to do this?

An object is lazily initialized, pretty much like a lazy val. A
declaration like "case object EUR extends Currency" is a lot like
"lazy val EUR = new Currency with Singleton".

Since you have not used any of those objects, they have not been
initialized. As to how to do that correctly, that is, imho, one of
Scala's unsolved hurdles.

--
Daniel C. Sobral

I travel to the future all the time.

mar

unread,
Oct 22, 2012, 1:20:08 AM10/22/12
to scala...@googlegroups.com
One thing to take note of is the misconception that the word "self" in this example is some sort of keyword -- it is not; self is a named alias for the this-reference. I mention this because I have seen this incorrectly described as such before and it seems important to get right.

Where an alias isn't required, use 'this' such as

trait Squishy { this: A =>

Bruce Eckel

unread,
Oct 22, 2012, 1:59:56 AM10/22/12
to mar, scala...@googlegroups.com
Thanks for all the pointers.

-- Bruce Eckel

Alec Zorab

unread,
Oct 22, 2012, 2:17:05 AM10/22/12
to Bruce Eckel, scala-user, mar

Martin made a wonderfully offhand comment during a talk once (possibly one about the compiler design for 2.10?) when he said something along the lines of "scala lets us rename and add type constraints to our 'this' reference". I've found that to be a very simple and easy way to explain what's going on.

Reply all
Reply to author
Forward
0 new messages