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

Enums in scala

9 replies
ounos
Joined: 2008-12-29,
User offline. Last seen 3 years 44 weeks ago.

Hi all,

I'm trying to accomplish something very simple: simulate java enums.

I came up with:

sealed case class MyEnum {
}
object MyEnum {
val values = X1 :: X2 :: X3 :: Nil
case object X1 extends MyEnum
case object X2 extends MyEnum
case object X3 extends MyEnum
}

//Java
enum MyEnum {
X1, X2, X3;
}

This has all benefits of enums: singletons, equals, hashCode, toString,
serializable, but I had to explicitly create a "values" list. Can
someone factor this out, perhaps to an Enum superclass? Or is there a
better way to define enums? (Though I don't mind Java version being
simpler, since the benefits I get from javac only apply to enums while
in scala case classes is a more general facility)

Thanks,
Dimitris Andreou

Derek Chen-Becker
Joined: 2008-12-16,
User offline. Last seen 42 years 45 weeks ago.
Re: Enums in scala

Andreou Dimitris wrote:
> Hi all,
>
> I'm trying to accomplish something very simple: simulate java enums.>

See scala.Enumeration:

http://www.scala-lang.org/docu/files/api/scala/Enumeration.html

I think it has everything you want already.

Derek

ounos
Joined: 2008-12-29,
User offline. Last seen 3 years 44 weeks ago.
Re: Enums in scala

O/H Derek Chen-Becker έγραψε:
> Andreou Dimitris wrote:
>
>> Hi all,
>>
>> I'm trying to accomplish something very simple: simulate java enums.>
>>
>
> See scala.Enumeration:
>
> http://www.scala-lang.org/docu/files/api/scala/Enumeration.html
>
> I think it has everything you want already.
>
> Derek
>
Thanks for the pointer, it seems fine. Though I have to duplicate the
name of the constant in order to have a nice toString method:

object WeekDay extends Enumeration {
type WeekDay = Value
val Mon = Value("Mon") //so it won't print out as "WeekDay(0)"
...
}

Can someone explain what the semantics of "type WeekDay = Value" is? Is
it needed at all? (Seems to work without it)
Dimitris

ounos
Joined: 2008-12-29,
User offline. Last seen 3 years 44 weeks ago.
Re: Enums in scala

O/H Dimitris Andreou έγραψε:
> O/H Derek Chen-Becker έγραψε:
>> Andreou Dimitris wrote:
>>
>>> Hi all,
>>>
>>> I'm trying to accomplish something very simple: simulate java
>>> enums.>
>>
>> See scala.Enumeration:
>>
>> http://www.scala-lang.org/docu/files/api/scala/Enumeration.html
>>
>> I think it has everything you want already.
>>
>> Derek
>>
> Thanks for the pointer, it seems fine. Though I have to duplicate the
> name of the constant in order to have a nice toString method:
>
> object WeekDay extends Enumeration {
> type WeekDay = Value
> val Mon = Value("Mon") //so it won't print out as "WeekDay(0)"
> ...
> }
>
> Can someone explain what the semantics of "type WeekDay = Value" is?
> Is it needed at all? (Seems to work without it)
> Dimitris
Oh, nevermind, got it. The example in the Enumeration scaladoc is this:
object WeekDay extends Enumeration {
type WeekDay = Value
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
But it is a typo, it just meant to write this:
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = WeekDay

>
>

Jorge Ortiz
Joined: 2008-12-16,
User offline. Last seen 29 weeks 3 days ago.
Re: Enums in scala
IMO sealed abstract classes and case objects are usually a better way of doing enumerations than the Enumeration trait.

--j

On Sun, Jan 18, 2009 at 9:15 AM, Andreou Dimitris <jim.andreou@gmail.com> wrote:
O/H Dimitris Andreou έγραψε:
O/H Derek Chen-Becker έγραψε:
Andreou Dimitris wrote:
 
Hi all,

I'm trying to accomplish something very simple: simulate java enums.>    

See scala.Enumeration:

http://www.scala-lang.org/docu/files/api/scala/Enumeration.html

I think it has everything you want already.

Derek
 
Thanks for the pointer, it seems fine. Though I have to duplicate the name of the constant in order to have a nice toString method:

object WeekDay extends Enumeration {
 type WeekDay = Value
 val Mon = Value("Mon") //so it won't print out as "WeekDay(0)"
 ...
}

Can someone explain what the semantics of "type WeekDay = Value" is? Is it needed at all? (Seems to work without it)
Dimitris
Oh, nevermind, got it. The example in the Enumeration scaladoc is this:
  object WeekDay extends Enumeration {
    type WeekDay = Value
    val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
  }
But it is a typo, it just meant to write this:
    val Mon, Tue, Wed, Thu, Fri, Sat, Sun = WeekDay





ounos
Joined: 2008-12-29,
User offline. Last seen 3 years 44 weeks ago.
Re: Enums in scala

That was in fact my initial attempt, if you read the previous messages.
After playing a bit with Enumeration, I also share this opinion. I find
it inconvenient that constants don't have the same type as the enclosing
class, so instead of adding functionality, in a oo style, as abstract
methods to the common super type, I ended up writing functions that took
a constant as an argument and performed a match on it. Which makes it
fragile to add or remove constants.

But this idiom, even it is more friendly to adding data/methods to
constants, is not perfect either:

abstract sealed case class MyEnum {
}
object MyEnum {
val values = C1 :: C2 :: Nil

case object C1 extends MyEnum
case object C2 extends MyEnum
}

Is there (I guess not) any way that C1 and C2 objects to be created
eagerly? Apart from using them in the "values" list, which creates a
somewhat ugly code duplication and small maintainance issue. If yes,
then it would be possible to factor out the boilerplate code "val values
= C1 :: C2 :: Nil", in a superclass of the enumeration, which would
track the created instances and automatically create the list (without
eager loading, it would only know about the constants that were already
used), and this idiom would be a drop-in replacement for java enums...

O/H Jorge Ortiz έγραψε:
> IMO sealed abstract classes and case objects are usually a better way
> of doing enumerations than the Enumeration trait.
>
> --j
>
> On Sun, Jan 18, 2009 at 9:15 AM, Andreou Dimitris
> > wrote:
>
> O/H Dimitris Andreou έγραψε:
>
> O/H Derek Chen-Becker έγραψε:
>
> Andreou Dimitris wrote:
>
>
> Hi all,
>
> I'm trying to accomplish something very simple:
> simulate java enums.>
>
>
> See scala.Enumeration:
>
> http://www.scala-lang.org/docu/files/api/scala/Enumeration.html
>
> I think it has everything you want already.
>
> Derek
>
>
> Thanks for the pointer, it seems fine. Though I have to
> duplicate the name of the constant in order to have a nice
> toString method:
>
> object WeekDay extends Enumeration {
> type WeekDay = Value
> val Mon = Value("Mon") //so it won't print out as "WeekDay(0)"
> ...
> }
>
> Can someone explain what the semantics of "type WeekDay =
> Value" is? Is it needed at all? (Seems to work without it)
> Dimitris
>
> Oh, nevermind, got it. The example in the Enumeration scaladoc is
> this:
>
> object WeekDay extends Enumeration {
> type WeekDay = Value
> val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
> }
> But it is a typo, it just meant to write this:
> val Mon, Tue, Wed, Thu, Fri, Sat, Sun = WeekDay
>
>
>
>
>

John Nilsson
Joined: 2008-12-20,
User offline. Last seen 42 years 45 weeks ago.
Re: Enums in scala
On Sun, Jan 18, 2009 at 10:54 PM, Dimitris Andreou <jim.andreou@gmail.com> wrote:
Is there (I guess not) any way that C1 and C2 objects to be created eagerly? Apart from using them in the "values" list, which creates a somewhat ugly code duplication and small maintainance issue. If yes, then it would be possible to factor out the boilerplate code "val values = C1 :: C2 :: Nil", in a superclass of the enumeration, which would track the created instances and automatically create the list (without eager loading, it would only know about the constants that were already used), and this idiom would be a drop-in replacement for java enums...

Why not do it via reflection?

BR,
John

Samuel Robert Reid
Joined: 2008-12-17,
User offline. Last seen 1 year 22 weeks ago.
Re: Enums in scala

How about managing the list of values in the constructor to avoid
duplication and maintenance issue:

import scala.collection.mutable.ArrayBuffer

object TestEnum {
object Day {
val values = new ArrayBuffer[Day]
case class Day(name:String) {
values += this
}

val MONDAY = new Day("monday")
val TUESDAY = new Day("tuesday")
}
def main(args: Array[String]) = {
println(Day.MONDAY)
println(Day.values)
}
}

Sam Reid

Dimitris Andreou wrote:
> That was in fact my initial attempt, if you read the previous
> messages. After playing a bit with Enumeration, I also share this
> opinion. I find it inconvenient that constants don't have the same
> type as the enclosing class, so instead of adding functionality, in a
> oo style, as abstract methods to the common super type, I ended up
> writing functions that took a constant as an argument and performed a
> match on it. Which makes it fragile to add or remove constants.
>
> But this idiom, even it is more friendly to adding data/methods to
> constants, is not perfect either:
>
> abstract sealed case class MyEnum {
> }
> object MyEnum {
> val values = C1 :: C2 :: Nil
>
> case object C1 extends MyEnum
> case object C2 extends MyEnum
> }
>
> Is there (I guess not) any way that C1 and C2 objects to be created
> eagerly? Apart from using them in the "values" list, which creates a
> somewhat ugly code duplication and small maintainance issue. If yes,
> then it would be possible to factor out the boilerplate code "val
> values = C1 :: C2 :: Nil", in a superclass of the enumeration, which
> would track the created instances and automatically create the list
> (without eager loading, it would only know about the constants that
> were already used), and this idiom would be a drop-in replacement for
> java enums...
>
> O/H Jorge Ortiz έγραψε:
>> IMO sealed abstract classes and case objects are usually a better way
>> of doing enumerations than the Enumeration trait.
>>
>> --j
>>
>> On Sun, Jan 18, 2009 at 9:15 AM, Andreou Dimitris
>> > wrote:
>>
>> O/H Dimitris Andreou έγραψε:
>>
>> O/H Derek Chen-Becker έγραψε:
>>
>> Andreou Dimitris wrote:
>>
>> Hi all,
>>
>> I'm trying to accomplish something very simple:
>> simulate java enums.>
>>
>> See scala.Enumeration:
>>
>>
>> http://www.scala-lang.org/docu/files/api/scala/Enumeration.html
>>
>> I think it has everything you want already.
>>
>> Derek
>>
>> Thanks for the pointer, it seems fine. Though I have to
>> duplicate the name of the constant in order to have a nice
>> toString method:
>>
>> object WeekDay extends Enumeration {
>> type WeekDay = Value
>> val Mon = Value("Mon") //so it won't print out as "WeekDay(0)"
>> ...
>> }
>>
>> Can someone explain what the semantics of "type WeekDay =
>> Value" is? Is it needed at all? (Seems to work without it)
>> Dimitris
>>
>> Oh, nevermind, got it. The example in the Enumeration scaladoc is
>> this:
>>
>> object WeekDay extends Enumeration {
>> type WeekDay = Value
>> val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
>> }
>> But it is a typo, it just meant to write this:
>> val Mon, Tue, Wed, Thu, Fri, Sat, Sun = WeekDay
>>
>>
>>
>>
>>
>

Samuel Robert Reid
Joined: 2008-12-17,
User offline. Last seen 1 year 22 weeks ago.
Re: Enums in scala

Here's an enum implementation that differs from my last post in the
following respects:

1. the values list is now of a val of type List[Day]
2. equality is handled properly for enum values even when enum value
args are not specified
3. worse toString behavior (perhaps this could be easily resolved with
reflection)

import scala.collection.mutable.ArrayBuffer

object TestEnum {
object Day {
private var list = new ArrayBuffer[Day] //temporary list
class Day() {list += this}

val MONDAY, TUESDAY, WEDNESDAY = new Day
val values = list.toList
}
def main(args: Array[String]) = {
println(Day.MONDAY)
println(Day.values)
println("monday==tuesday = " + (Day.MONDAY == Day.TUESDAY))
println("monday==monday= " + (Day.MONDAY == Day.MONDAY))
}
}

Samuel Robert Reid wrote:
> How about managing the list of values in the constructor to avoid
> duplication and maintenance issue:
>
> import scala.collection.mutable.ArrayBuffer
>
> object TestEnum {
> object Day {
> val values = new ArrayBuffer[Day]
> case class Day(name:String) {
> values += this
> }
>
> val MONDAY = new Day("monday")
> val TUESDAY = new Day("tuesday")
> }
> def main(args: Array[String]) = {
> println(Day.MONDAY)
> println(Day.values)
> }
> }
>
> Sam Reid
>
> Dimitris Andreou wrote:
>> That was in fact my initial attempt, if you read the previous
>> messages. After playing a bit with Enumeration, I also share this
>> opinion. I find it inconvenient that constants don't have the same
>> type as the enclosing class, so instead of adding functionality, in a
>> oo style, as abstract methods to the common super type, I ended up
>> writing functions that took a constant as an argument and performed a
>> match on it. Which makes it fragile to add or remove constants.
>>
>> But this idiom, even it is more friendly to adding data/methods to
>> constants, is not perfect either:
>>
>> abstract sealed case class MyEnum {
>> }
>> object MyEnum {
>> val values = C1 :: C2 :: Nil
>>
>> case object C1 extends MyEnum
>> case object C2 extends MyEnum
>> }
>>
>> Is there (I guess not) any way that C1 and C2 objects to be created
>> eagerly? Apart from using them in the "values" list, which creates a
>> somewhat ugly code duplication and small maintainance issue. If yes,
>> then it would be possible to factor out the boilerplate code "val
>> values = C1 :: C2 :: Nil", in a superclass of the enumeration, which
>> would track the created instances and automatically create the list
>> (without eager loading, it would only know about the constants that
>> were already used), and this idiom would be a drop-in replacement for
>> java enums...
>>
>> O/H Jorge Ortiz έγραψε:
>>> IMO sealed abstract classes and case objects are usually a better
>>> way of doing enumerations than the Enumeration trait.
>>>
>>> --j
>>>
>>> On Sun, Jan 18, 2009 at 9:15 AM, Andreou Dimitris
>>> > wrote:
>>>
>>> O/H Dimitris Andreou έγραψε:
>>>
>>> O/H Derek Chen-Becker έγραψε:
>>>
>>> Andreou Dimitris wrote:
>>> Hi all,
>>>
>>> I'm trying to accomplish something very simple:
>>> simulate java enums.>
>>> See scala.Enumeration:
>>>
>>>
>>> http://www.scala-lang.org/docu/files/api/scala/Enumeration.html
>>>
>>> I think it has everything you want already.
>>>
>>> Derek
>>> Thanks for the pointer, it seems fine. Though I
>>> have to
>>> duplicate the name of the constant in order to have a nice
>>> toString method:
>>>
>>> object WeekDay extends Enumeration {
>>> type WeekDay = Value
>>> val Mon = Value("Mon") //so it won't print out as "WeekDay(0)"
>>> ...
>>> }
>>>
>>> Can someone explain what the semantics of "type WeekDay =
>>> Value" is? Is it needed at all? (Seems to work without it)
>>> Dimitris
>>>
>>> Oh, nevermind, got it. The example in the Enumeration scaladoc is
>>> this:
>>>
>>> object WeekDay extends Enumeration {
>>> type WeekDay = Value
>>> val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
>>> }
>>> But it is a typo, it just meant to write this:
>>> val Mon, Tue, Wed, Thu, Fri, Sat, Sun = WeekDay
>>>
>>>
>>>
>>>
>>>
>>

Samuel Robert Reid
Joined: 2008-12-17,
User offline. Last seen 1 year 22 weeks ago.
Re: Enums in scala
Here's an implementation of toString that uses reflection:

override def toString = (DayEnum.getClass.getDeclaredMethods.find((a: Method) => {Modifier.isPublic(a.getModifiers) && a.invoke(DayEnum.this) == this})).get.getName

Here's the full example:

import java.lang.reflect.{Field, Method, Modifier}
import scala.collection.mutable.ArrayBuffer

object TestEnum {
    object DayEnum {
        private var list = new ArrayBuffer[Day] //temporary list
        class Day() {
            list += this
            override def toString = (DayEnum.getClass.getDeclaredMethods.find((a: Method) => {Modifier.isPublic(a.getModifiers) && a.invoke(DayEnum.this) == this})).get.getName
        }

        val MONDAY, TUESDAY, WEDNESDAY = new Day
        val values = list.toList
    }
    def main(args: Array[String]) = {
        println(DayEnum.MONDAY)
        println(DayEnum.values)
    }
}

The output is:

MONDAY
List(MONDAY, TUESDAY, WEDNESDAY)

Sam Reid

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