[SIP-E] scala.Enum for Scala 2.11

1999 views
Skip to first unread message

Simon Ochsenreither

unread,
Aug 8, 2013, 8:31:10 AM8/8/13
to scala...@googlegroups.com
Hi everyone,

while I'm far from finished, I'd like to propose a SIP, whose goal is to provide better support for enums in Scala and improve compatibility with the runtime.
The goal is the inclusion in the upcoming version of Scala (and the deprecation of scala.Enumeration).

Short syntax primer:

@Enum
class Day {
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
}


Usage (from Java(!)):

        Day mon = Day.Monday();
        int ord = mon.ordinal();
        assert Day.class.getClass().isEnum();


The document is here: https://docs.google.com/document/d/1mIKml4sJzezL_-iDJMmcAKmavHb9axjYJos_7UMlWJ8/edit#

I would be happy about feedback, criticisms and suggestions!
Please let me know what you think!

Thanks,

Simon

Related mailing list threads:
    https://groups.google.com/d/topic/scala-internals/8RWkccSRBxQ/discussion
    https://groups.google.com/d/topic/scala-language/C7Pm6ab1sPs/discussion

Jason Zaugg

unread,
Aug 8, 2013, 8:33:47 AM8/8/13
to scala...@googlegroups.com
On Thursday, August 8, 2013 2:31:10 PM UTC+2, Simon Ochsenreither wrote:
Hi everyone,

while I'm far from finished, I'd like to propose a SIP, whose goal is to provide better support for enums in Scala and improve compatibility with the runtime.
The goal is the inclusion in the upcoming version of Scala (and the deprecation of scala.Enumeration).

Short syntax primer:

@Enum
class Day {
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
}


Usage (from Java(!)):

        Day mon = Day.Monday();
        int ord = mon.ordinal();
        assert Day.class.getClass().isEnum();


The document is here: https://docs.google.com/document/d/1mIKml4sJzezL_-iDJMmcAKmavHb9axjYJos_7UMlWJ8/edit#

I would be happy about feedback, criticisms and suggestions!
Please let me know what you think!

Enums are a great use case for macro annotations. But macro annotations themselves must be accepted into mainstream scala, and then stabilized, before we can consider shipping new features on top of them.

-jason

Kfir Bloch

unread,
Aug 8, 2013, 9:51:33 AM8/8/13
to scala...@googlegroups.com
I would like to see how this will marshal to json. Current Scala Enumeration requires to save in the json the class name. Because of that i am still using Java enums in my Scala project.
Can you explain how it will be mapped to json inside complex objects?

Som Snytt

unread,
Aug 8, 2013, 9:54:08 AM8/8/13
to scala...@googlegroups.com

Also, I believe it's necessary to deprecate Saturday and Sunday for a complete release cycle before removing them from the days of the week.

/humor

--
You received this message because you are subscribed to the Google Groups "scala-sips" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-sips+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Simon Ochsenreither

unread,
Aug 8, 2013, 9:54:42 AM8/8/13
to scala...@googlegroups.com
Hi Jason,

as you mentioned, the current proposal depends on the inclusion of macro annotations in 2.11.

I think it is reasonable to ship functionality based on an experimental feature (macro annotations) as long as the "magic" is not exposed to the user. That's the case with enums.
Imho, there is a huge difference between exposing an experimental API to a developer and exposing some functionality (enums) to the user, where the macro annotation usage is just an implementation detail.

Even if the macro annotation API would change considerably between versions, it's nothing which would effect the user of the enum in any way.

It would be nice if macro annotations were a stable feature, but I can only work with what I got and waiting for another 2 years looks like an extremely terrible alternative.

Thanks and bye,

Simon

Simon Ochsenreither

unread,
Aug 8, 2013, 9:58:32 AM8/8/13
to scala...@googlegroups.com
Hi Kfir!


I would like to see how this will marshal to json. Current Scala Enumeration requires to save in the json the class name. Because of that i am still using Java enums in my Scala project.
Can you explain how it will be mapped to json inside complex objects?

The big improvement is that Scala enums are Java enums. In that sense, the only change with this SIP is that you can now define your good old "Java enums" in Scala.

Bye,

Simon

Kfir Bloch

unread,
Aug 8, 2013, 10:00:42 AM8/8/13
to scala...@googlegroups.com
Thanks a lot :)


--
You received this message because you are subscribed to a topic in the Google Groups "scala-sips" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/scala-sips/Bf82LxK02Kk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to scala-sips+...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Kfir Bloch
Server


054-5685848

Andrés Testi

unread,
Aug 8, 2013, 10:50:59 AM8/8/13
to scala...@googlegroups.com
Great!

Andrés Testi

unread,
Aug 8, 2013, 11:22:43 AM8/8/13
to scala...@googlegroups.com
Hi Simon, your work looks very cool! Believe it or not, lack of proper java compatible enums, was stopping me from choice scala for many works. I don't know where is the right place to discuss this, but I have some points to share:

1- @enum uncapitalized is more scala-ish than @Enum

2- Is it possible to emit enum fields as static field members instead of static methods? With the current approach, it will be not possible to use scala enums on Java annotation fields, i.e. @MyAnnotation(value = Day.Monday()) is forbidden in Java.

3- Retrieving a mutable array of values() is Java compatible, but from scala perspective, inmutable is preferred. May be there is not a good solution for this issue.

4- ¿Will pattern matching be supported?

Thanks!

- Andrés

El jueves, 8 de agosto de 2013 09:31:10 UTC-3, Simon Ochsenreither escribió:

Simon Ochsenreither

unread,
Aug 8, 2013, 11:58:28 AM8/8/13
to scala...@googlegroups.com
Hi Andrés!


1- @enum uncapitalized is more scala-ish than @Enum

Agreed.
 

2- Is it possible to emit enum fields as static field members instead of static methods? With the current approach, it will be not possible to use scala enums on Java annotation fields, i.e. @MyAnnotation(value = Day.Monday()) is forbidden in Java.

This is imo the largest remaining issue and I'm not sure if something can be done about it, because this is what scalac does when one creates companion objects. We are more or less two or three levels of abstraction/indirection away from being able to influence what ends up in the bytecode.


3- Retrieving a mutable array of values() is Java compatible, but from scala perspective, inmutable is preferred. May be there is not a good solution for this issue.

It's possible to add more idomatic methods to the enum, but we can't change the existing method.

4- ¿Will pattern matching be supported?

Yes, it already is! (Although I'm thinking about generating additional unapply methods to make it a bit nicer.)

Thanks a lot for your input!

Bye,

Simon

Jason Zaugg

unread,
Aug 8, 2013, 12:03:02 PM8/8/13
to scala...@googlegroups.com
On Thu, Aug 8, 2013 at 5:22 PM, Andrés Testi <andres....@gmail.com> wrote:
Hi Simon, your work looks very cool! Believe it or not, lack of proper java compatible enums, was stopping me from choice scala for many works.

Just curious: is the imposition of dropping into a .java file to write Java-compatible enums enough to stop you from choosing Scala?

-jason

Alex Boisvert

unread,
Aug 8, 2013, 12:09:20 PM8/8/13
to scala...@googlegroups.com
Just my $0.02 ... and this is probably in bike-shed territory already ... but I'd much prefer for the annotation to be named something like @javaEnum since the goal here is to produce an enum that's compatible with Java.

I personally find the sealed-trait + case object enum a better solution for Scala since it provides exhaustiveness checking -- though I understand it sacrifices Java interop.   

I'm not sure the two approaches are reconcilable and would be happy to see a similar macro + SIP to produce the more idiomatic Scala enum (I'm referring to the sealed trait pattern) with less boilerplate.



--
You received this message because you are subscribed to the Google Groups "scala-sips" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-sips+...@googlegroups.com.

Simon Ochsenreither

unread,
Aug 8, 2013, 12:27:14 PM8/8/13
to scala...@googlegroups.com

I personally find the sealed-trait + case object enum a better solution for Scala since it provides exhaustiveness checking -- though I understand it sacrifices Java interop.  

Java enums provide exhaustiveness checking, too.

I think the large and important distinction between the sealed trait pattern an enums is that enums are by definition flat, while the sealed trait pattern allows nesting and recursion.
This way, if you only need a flat structure use enums and enjoy additional compatibility benefits, but if you require a nested/recursive structure use the sealed trait pattern.

The main idea of my proposal is to cut down the way we can write similar things.

Before:
  • Sealed trait pattern
  • scala.Enumeration
  • "Real" enum
After:
  • Sealed trait pattern
  • "Real" enum
Whether this can be further reduced remains to be seen imho.

Thanks and bye,

Simon

Andrés Testi

unread,
Aug 8, 2013, 12:39:44 PM8/8/13
to scala...@googlegroups.com
Thanks Simon!
Thanks Simon! :-) 

Jason:

Sometimes it's hard to convince a customer with a deep Java background, whose domain models make heavy use of enums, to migrate to a language you propose as the successor of Java, if to define one of the most common constructs of Java, as is the case of enums, you must back to Java and write .java files because your hallowed and higher new language does not support it. IT industry is full of conservative minds :-)

Regards.

- Andrés 

Simon Ochsenreither

unread,
Aug 8, 2013, 2:04:27 PM8/8/13
to scala...@googlegroups.com
I came up with an idea of how to get the static members while keeping the complexity low.
It's not great, because it involves a minimal bit of a special-cased check for enums, but better than nothing.

Fernando Racca

unread,
Aug 8, 2013, 4:41:40 PM8/8/13
to scala...@googlegroups.com
It looks very promising so far. Thanks a lot Simon and Eugene for the great work.

These "Real enums" would be a big advantage over the many handcrafted solutions out there.

Do you see any possible issues with user defined constructors and overrides? (as described in the SIP)

Fernando

Simon Ochsenreither

unread,
Aug 8, 2013, 4:46:46 PM8/8/13
to scala...@googlegroups.com

Do you see any possible issues with user defined constructors and overrides? (as described in the SIP)

Compared to the static stuff, this should be easy.
I think the time-consuming part will be the testing and guarding against invalid input.

David Barri

unread,
Aug 8, 2013, 9:16:19 PM8/8/13
to scala...@googlegroups.com
This is very welcome news indeed!! Nice work!

Two thoughts after reading the SIP:

1) I understand that the macro will generate enum fields like this: new Day("Monday", 1);
What is to prevent users doing the same thing and creating new instances? Should the class be sealed?

2) values() defensively clones the value array on each invocation. Bad luck for Java interop but for the Scala-side, what do you think about adding another method that returns the values, say, as an immutable list? That should yield a little performance saving, arguably not worth the effort or the divergence with java enums but there you go.

Cheers,

Simon Ochsenreither

unread,
Aug 9, 2013, 3:59:33 AM8/9/13
to scala...@googlegroups.com
Hi David,


1) I understand that the macro will generate enum fields like this: new Day("Monday", 1);
What is to prevent users doing the same thing and creating new instances? Should the class be sealed?

Depending on whether enum items define/override methods, the constructor needs to be private or protected and the class can either be final (final in Java) or sealed (nothing in Java).
 
2) values() defensively clones the value array on each invocation. Bad luck for Java interop but for the Scala-side, what do you think about adding another method that returns the values, say, as an immutable list? That should yield a little performance saving, arguably not worth the effort or the divergence with java enums but there you go.

Yes, sure, as mentioned, methods can be added via traits/extension methods. I prefer not adding methods myself and which can easily added using the usual mechanisms in Scala.

Bye,

Simon

Ken Scambler

unread,
Aug 9, 2013, 10:09:09 AM8/9/13
to scala...@googlegroups.com
I feel very uneasy about this proposal.

scala.Enumeration, for all its villainous flaws, is at least halfway orthogonal to case classes, in that it is a lightweight int-based alternative.  Not that I'd be sorry to see it go.   If the new structure is to mirror Java enums, then it would have to support a fully-fledged class definition, which is a much bigger overlap.

For pure Scala usage, again, I can't see the new enums being very useful -- case classes are not that hard to write. 

For Java interop, which I gather is the major motivating factor -- surely people concerned with interop can't be that concerned with defining enums in Java.

And then there's the syntax; it horrifies me.  I realise this is a Macro Annotations thing rather than an Enum thing, but how am I to parse a bunch of floating identifiers?  The answer for me, and perhaps others, is that I would accrete a mental special case, where a @Enum + floating identifiers = a Java enum.  And then the per-value definition block?  Another mental special case.  And if you have an equivalent of Java's semicolon that ends the enum cases and begins the regularish class bit, that's another special case.  How do you Scaladoc it?

It's not just going to be enums, either.  The next clever library that comes along with some arrangement of floating syntax fragments -- more mental special cases, accreted after I have read the documentation, or more likely, some AST-munging source code.  You can call it a library-only implementation, but I don't see how it can be mentally parsed without special prior knowledge.

TL;DR it doesn't smell like Scala - not very orthogonal, special snowflake syntax.

Cheers,
Ken

Simon Ochsenreither

unread,
Aug 9, 2013, 6:19:36 PM8/9/13
to scala...@googlegroups.com
I'm always open to a better syntax proposal. As mentioned, I certainly liked the one using type macros and untyped macros, but that option is gone.


And then there's the syntax; it horrifies me.

Sure, it's not ideal, but at least it is better than scala.Enumeration: The declaration of enums with scala.Enumeration is completely unintuitive and error-prone even without using special syntax.

I don't think scala.Enumeration is more lightweight, either. Both @enum and scala.Enumeration have one instance per enum item, they are certainly not int-based. Every scala.Enumeration enum declaration involves two HashMaps, an Iterator and reflection. @enum doesn't.

Tomer Gabel

unread,
Aug 12, 2013, 7:43:08 PM8/12/13
to scala...@googlegroups.com

+1 on all of Ken's points, but especially these two:


For Java interop, which I gather is the major motivating factor -- surely people concerned with interop can't be that concerned with defining enums in Java.

Hallelujah. Interop code is allowed to be a little messy so long as it's simple and easy to reason about. I don't see a need for a new Scala language construct just for this use case. And I honestly don't get how the new enum construct (or lack thereof) can be a meaningful factor in deciding whether or not to use Scala when you can always very easily fall back on Java enums, but it's certainly possible I'm missing something.

TL;DR it doesn't smell like Scala - not very orthogonal, special snowflake syntax.

Couldn't agree more. I actually don't find Scala's Enumeration construct all that bad -- it's messy behind the scenes, but that's precisely the point, I don't really care about what goes on behind the scenes. The current Enumerations are fairly easy to use and extend and the few times I had to dig into the code-behind weren't very scary either. In short, I don't see a single use case necessitating this change. 

Rex Kerr

unread,
Aug 12, 2013, 8:12:29 PM8/12/13
to scala...@googlegroups.com
On Mon, Aug 12, 2013 at 7:43 PM, Tomer Gabel <to...@tomergabel.com> wrote:

+1 on all of Ken's points, but especially these two:


For Java interop, which I gather is the major motivating factor -- surely people concerned with interop can't be that concerned with defining enums in Java.

Hallelujah. Interop code is allowed to be a little messy so long as it's simple and easy to reason about.

What about not having your code defined in the place where it makes sense (not even in the same file, not even the same namespace you naturally would use)?

Interop that hurts isn't very good interop, especially if you might be doing lots of it.  (Maybe you'd like to write half your code in C and half in Java and use JNI as glue?  Interop is allowed to be a little messy, right?)
 

TL;DR it doesn't smell like Scala - not very orthogonal, special snowflake syntax.

Couldn't agree more. I actually don't find Scala's Enumeration construct all that bad -- it's messy behind the scenes, but that's precisely the point, I don't really care about what goes on behind the scenes.

Welllll maybe you haven't run into any bugs related to it.  It works well until it mysteriously falls on its face, e.g. where you think you have type-safety and actually don't:

  https://issues.scala-lang.org/browse/SI-3815

I would like things to work behind the scenes to not require me to keep track of a variety of ways in which these hidden details will cause my code to fail.  It's really hard to reason about correct code then.

  --Rex

Fernando Racca

unread,
Aug 13, 2013, 3:41:58 AM8/13/13
to scala...@googlegroups.com
Java enums are one of the few features that people actually like in Java.

Scala enums are ugly and messy.

Using Java enums in Scala, as Rex correctly points out, is a very poor patch.

This new SIP brings a much more instantly recognizable construct. Less friction, easier to adopt.

Fernando

Ittay Dror

unread,
Aug 13, 2013, 4:08:23 AM8/13/13
to scala...@googlegroups.com

My vote, FWIW, is to create enums and annotations that are better than java, like the rest of scala, and maybe allow an easier way of writing java enums and annotarions if there's a need. For example, a java{...} similar to c's assembly dowgrade. I don't think anyone will mind...

--
Message has been deleted

Tomer Gabel

unread,
Aug 13, 2013, 7:15:27 AM8/13/13
to scala...@googlegroups.com
To clarify my arguments against the original proposition, there are really two major criticisms:
  • Specialized syntax: the enum declaration above looks nothing like any other Scala class declaration. If you're going to go with new syntax, at least call it what it is and add an "enum" keyword to Scala. I'm against this, by the way, because I believe this goes against the Scala orthogonality/language simplicity guiding principle, whereas the current Scala enum construct is actually a library feature that builds on top of the language instead of adding to it.

  • This doesn't solve a fundamental interop problem because, as mentioned earlier, the generated underlying class does not actually provide stable identifiers, which means it cannot be used in annotations. This makes it a no-win solution in my opinion.

martin odersky

unread,
Aug 13, 2013, 9:57:43 AM8/13/13
to scala...@googlegroups.com
I believe SI-3815 is much more a failure of overloading than a failure of Enums. I sure would like to be able to write:

  def handler(f: Int => Int) = ...
  def handler(f: String => Int) = ...

But I get the same erasure conflict as for enums. So you might wish for enums to map to different erased types the same way you might wish different function types to map to different erased types. Unfortunately, the JVM gives you neither.

For me the conclusion is: Overloading in Scala is not a first-class feature but a "best-effort" feature. If it was not for Java interop we probably would not have it. Consequently I see no motivation to complicate the language just to make overloading work better in some cases.

That said, I am happy to have the proposal be a SIP when you are ready, Simon, so that we can discuss it more formally.

Cheers

 - Martin 

--
You received this message because you are subscribed to the Google Groups "scala-sips" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-sips+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



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

Simon Ochsenreither

unread,
Aug 13, 2013, 10:11:43 AM8/13/13
to scala...@googlegroups.com
Hi,


My vote, FWIW, is to create enums and annotations that are better than java, like the rest of scala,

I think this is entirely possible in the design I'm proposing, I just wanted to keep the SIP as small as possible. Enum functionality can of course be enhanced by adding traits just as usual. Additionally, I have been thinking about generating unapply methods to make pattern matching of Enums with values a bit nicer.
But all of this can be done later, I just want to get the basic things right, first.

 

and maybe allow an easier way of writing java enums and annotarions if there's a need. For example, a java{...} similar to c's assembly dowgrade. I don't think anyone will mind...

Every change has an associated cost and I think adding some enum functionality which doesn't solve one of the major pain points and then adding yet another construct to finally do what many people are asking for is not good enough when one looks at the cost/benefit ratio.

I'm especially concerned about people learning the language. We already have three different ways of building “enums”. With my proposal, we would have only two, which would actually work.

Bye,

Simon

Simon Ochsenreither

unread,
Aug 13, 2013, 10:26:27 AM8/13/13
to scala...@googlegroups.com
Hi Tomer,



To clarify my arguments against the original proposition, there are really two major criticisms:
  • Specialized syntax: the enum declaration above looks nothing like any other Scala class declaration. If you're going to go with new syntax, at least call it what it is and add an "enum" keyword to Scala. I'm against this, by the way, because I believe this goes against the Scala orthogonality/language simplicity guiding principle, whereas the current Scala enum construct is actually a library feature that builds on top of the language instead of adding to it.
I'm really open to any better syntax proposals. I would prefer a nicer way to, but I can only work with code which is valid Scala syntax. Macro annotations don't allow me to make up new syntax. So please, please, please if you have a nicer syntax proposal, please step forward.
Adding an enum construct would of course be a bit easier, but it won't fly. Martin said no and that's it. Initially, I wasn't happy about it, but seeing that we might finally end up with a workable solution using macro annotations, I think he was right all the time.
  • This doesn't solve a fundamental interop problem because, as mentioned earlier, the generated underlying class does not actually provide stable identifiers, which means it cannot be used in annotations. This makes it a no-win solution in my opinion.
I consider this nothing more than a bug, which needs to be solved.

Thanks,

Simon

Ryan Hendrickson

unread,
Aug 13, 2013, 11:30:50 AM8/13/13
to scala...@googlegroups.com
> I'm really open to any better syntax proposals. I would prefer a nicer
> way to, but I can only work with code which is valid Scala syntax. Macro
> annotations don't allow me to make up new syntax. So please, please,
> please if you have a nicer syntax proposal, please step forward.
> Adding an enum construct would of course be a bit easier, but it won't
> fly. Martin said no and that's it. Initially, I wasn't happy about it,
> but seeing that we might finally end up with a workable solution using
> macro annotations, I think he was right all the time.

At the cost of slightly more syntax, could this be an acceptable compromise?

@enum object DayOfWeek {
val Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday: DayOfWeek
}

Disadvantages: the extra text 'val' and ': DayOfWeek'
Advantages:
* No longer implies that something is being executed, merely declared
* Slightly less magic (to my eyes) about what will be treated as an enum value and what is object initialization code (the heuristic would be: any declared but undefined members in an @enum object which are typed with the object's companion class (regardless of whether the companion is declared in code) are enum values)
* The surface syntax coincides with the signature of the generated object--from Scala's perspective, these values will end up as vals on the object with the appropriate type

Thoughts?






(please forgive me my corporate legal disclaimer)

----------------------------------------

This message is intended exclusively for the individual(s) or entity to
which it is addressed. It may contain information that is proprietary,
privileged or confidential or otherwise legally exempt from disclosure.
If you are not the named addressee, you are not authorized to read,
print, retain, copy or disseminate this message or any part of it.
If you have received this message in error, please notify the sender
immediately by e-mail and delete all copies of the message.

Simon Ochsenreither

unread,
Aug 14, 2013, 8:59:57 AM8/14/13
to scala...@googlegroups.com, ryan.hen...@bwater.com
Hi Ryan,


At the cost of slightly more syntax, could this be an acceptable compromise?

@enum object DayOfWeek {
  val Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday: DayOfWeek
}

Disadvantages: the extra text 'val' and ': DayOfWeek'
Advantages:
  * No longer implies that something is being executed, merely declared
  • How would enums with constructors work?
  • How would overridden methods work?
 
  * Slightly less magic (to my eyes) about what will be treated as an enum value and what is object initialization code (the heuristic would be: any declared but undefined members in an @enum object which are typed with the object's companion class (regardless of whether the companion is declared in code) are enum values)

I think that's nice idea!
 
  * The surface syntax coincides with the signature of the generated object--from Scala's perspective, these values will end up as vals on the object with the appropriate type

As far as I know this won't work: an annotation of an object won't give me control of the companion class.

Thanks any bye,

Simon

Olivier Chafik

unread,
Aug 14, 2013, 11:31:15 AM8/14/13
to scala...@googlegroups.com, simon.och...@gmail.com
Hi Simon, all,

It's great that you tackle this issue!

I have an alternative syntax proposal, which works under the current version of Scala (with simple def macros):

  object Fruits extends enum {
    val Banana, Lemon, Apple, Orange = enum values
  }

  def takeFruit(f: Fruits.Type) = println(f)
  takeFruit(Fruits.Banana)
  println(Fruits.values)
  println(Fruits.valueOf("Banana"))

The idea here is to decouple the naming of the stable object (which is a bag of items, plural form) from the actual enum class: the class `enum` contains an inner / dependent class `Type`, which is the actual enum class. Deserialization and valueOf should work as expected, as do equality tests (Java seems to manage to capture the correct declaring class for different enum types).

I've attached the dirty but functional code that can be tried out with:

  scala -i enums.scala

  object Fruits extends enum { val Banana, Lemon, Apple, Orange = enum values }

It looks a bit weird, but it's still plain old Scala syntax... Any thoughts?

Cheers

--
enums.scala

Simon Ochsenreither

unread,
Aug 14, 2013, 11:55:02 AM8/14/13
to scala...@googlegroups.com, simon.och...@gmail.com, olivier...@gmail.com
Hi Olivier,

Any thoughts?

same as above:


  • How would enums with constructors work?
  • How would overridden methods work?

Thanks,

Simon

 

Olivier Chafik

unread,
Aug 14, 2013, 12:02:48 PM8/14/13
to Simon Ochsenreither, scala-sips
2013/8/14 Simon Ochsenreither <simon.och...@gmail.com>
same as above:
  • How would enums with constructors work?
  • How would overridden methods work?
Hehe, none of that would work, of course (that's just poor man's enums for 2.10.x, no type generation voodoo)

Keep up the good work :-)
--
Olivier

Ryan Hendrickson

unread,
Aug 14, 2013, 12:41:33 PM8/14/13
to Simon Ochsenreither, scala...@googlegroups.com
> * How would enums with constructors work?
> * How would overridden methods work?

Very explicitly:

@enum class Coin(value: Int) extends Whatever {
def color: String = "Silver"
}

@enum object Coin {
val Penny = new Coin(1) { override def color = "Copper" }
val Nickel = new Coin(5)
val Dime = new Coin(10)
val Quarter = new Coin(25)
}

I'm not terribly confident that this is the best tradeoff to make; it is obviously more verbose than the Java equivalent. But it is much less snowflakey than the Java equivalent, and I would expect there to be very little confusion to someone who knows the rest of Scala about what this means and what other orthogonal Scala features would be permitted in this design.

An @enum macro can deliver value on multiple fronts: being compatible with Java libraries that expect enums; providing name, ordinal, values, valueOf methods without requiring reflection or error-prone redundancy; reducing boilerplate. In the case of enums with constructors and overridden methods, you'd be giving up most of the reducing boilerplate value but you'd still get the other two. In the simple case, you get all three. In my mind at least, the tradeoff has to be how much clever engineering is merited in order to get that third value in the case of constructors and overridden methods at the cost of introducing syntax-interpretation semantics unique to enums.

That said:

> * The surface syntax coincides with the signature of the
> generated object--from Scala's perspective, these values will end up as
> vals on the object with the appropriate type
>
>
>
> As far as I know this won't work: an annotation of an object won't give
> me control of the companion class.

Well, oof. If that's not possible, then my whole suggestion is moot. I kind of thought from this message <https://groups.google.com/d/msg/scala-language/C7Pm6ab1sPs/dxASvhN3olwJ> that Eugene had a mechanism for introducing a companion if one didn't exist. And if you're going to explicitly declare both class and object, I'd expect them both to be annotated with @enum since they'll both have their signatures implicitly extended (the class will get name and ordinal, the object will get values and valueOf). But I haven't actually tried this, or tried using macro annotations for anything actually, so if it's not possible, then I'm sorry for wasting your time.

Eugene Burmako

unread,
Aug 14, 2013, 12:50:34 PM8/14/13
to scala...@googlegroups.com
It might be possible to give control over companion classes as well. We just need a compelling use case. If you guys agree that the design you presented works, I can add the required capability to macro annotations.

Paul Phillips

unread,
Aug 14, 2013, 1:02:27 PM8/14/13
to scala...@googlegroups.com

On Wed, Aug 14, 2013 at 9:50 AM, Eugene Burmako <eugene....@epfl.ch> wrote:
It might be possible to give control over companion classes as well. We just need a compelling use case. If you guys agree that the design you presented works, I can add the required capability to macro annotations.

I don't find this use case particularly compelling, but there will be an endless parade of use cases which require being able to control both class and object. You can pick and choose the compelling ones.

Eugene Burmako

unread,
Aug 14, 2013, 1:04:31 PM8/14/13
to scala...@googlegroups.com
It's currently possible for a macro annotation on a class to control a companion object. I just never actually thought that it might need to work the other way around.

Are there any such cases in scalac?

Paul Phillips

unread,
Aug 14, 2013, 1:22:05 PM8/14/13
to scala...@googlegroups.com
On Wed, Aug 14, 2013 at 10:04 AM, Eugene Burmako <eugene....@epfl.ch> wrote:
Are there any such cases in scalac?

Nothing I can think of, but I'm not the guy to think of them anymore. 

Simon Ochsenreither

unread,
Aug 14, 2013, 1:55:45 PM8/14/13
to scala...@googlegroups.com, Simon Ochsenreither, ryan.hen...@bwater.com


But it is much less snowflakey than the Java equivalent, and I would expect there to be very little confusion to someone who knows the rest of Scala about what this means and what other orthogonal Scala features would be permitted in this design.

I don't see what's particularly snowflakey about Java. It's pretty much the same in many other languages.

Imho, the code shown above exhibits similar issues as scala.Enumeration. Hard to define correctly and cumbersome to understand what's actually happening because of the ceremony around it.
 

Simon Ochsenreither

unread,
Aug 14, 2013, 2:08:19 PM8/14/13
to scala...@googlegroups.com, Simon Ochsenreither, ryan.hen...@bwater.com


Well, oof. If that's not possible, then my whole suggestion is moot. I kind of thought from this message <https://groups.google.com/d/msg/scala-language/C7Pm6ab1sPs/dxASvhN3olwJ> that Eugene had a mechanism for introducing a companion if one didn't exist.

Currently, that only works one way. If you annotate the class you can control class + companion object, but if you annotate theobject, you only get the object, not the companion class.

That's part of the reason why I'm using a class instead of an object, the other is that we don't have to add excessive amounts of code if we go from “plain” enums to “enums with fields, constructors end overriding”.

Simon Ochsenreither

unread,
Aug 21, 2013, 8:18:29 PM8/21/13
to scala...@googlegroups.com

  • This doesn't solve a fundamental interop problem because, as mentioned earlier, the generated underlying class does not actually provide stable identifiers, which means it cannot be used in annotations. This makes it a no-win solution in my opinion.
I consider this nothing more than a bug, which needs to be solved.

We are getting closer ...

public class JavaDayConsumer {
    public static void main(String[] args) {
    System.out.println(Day.Monday);
    }
}


:-)

Suminda Dharmasena

unread,
Oct 5, 2013, 3:21:59 AM10/5/13
to scala...@googlegroups.com
One area that might be interesting to consider is an extension mechanism to add new enums. In Java one you define an enum you cannot create a larger enum list from already available enums. So extension and production mechanisms (union, intersection and negation) can help. E.g. I have weekday, weekend, and day. Day will have both weekday and weekend.

Also another area to think is enum ranges.

Looking forward to see the SIP you would submit.

Simon Ochsenreither

unread,
Jan 18, 2014, 3:49:52 PM1/18/14
to scala...@googlegroups.com
Constructors, methods, traits and pattern matching is now supported as of today:

// Declaration

trait Bar {
  def bar = "bar"
}

@enum
class Day(val abbreviation: String, val isWeekend: Boolean) extends Bar {
  Monday("Mon", false)
  Tuesday("Tue", false)
  Wednesday("Wed", false)
  Thursday("Thu", false)
  Friday("Fri", false)
  Saturday("Sat", true)
  Sunday("Sun", true)

  def foo = "foo"
}

// Usage

public class DayConsumer {

    public static void main(String[] args) {
        System.out.println("Day.Monday");
        System.out.println(Day.Monday);
        System.out.println("Day.values()");
        for (Day day : Day.values()) {
            System.out.println(day);
        }
        System.out.println("Day.valueOf(\"Monday\")");
        Day monday = Day.valueOf("Monday");
        System.out.println(monday);
        System.out.println("Day.Monday.abbreviation()");
        System.out.println(monday.abbreviation());
        System.out.println("Call method foo defined in Day");
        System.out.println(monday.foo());
        System.out.println("Call method bar defined in Bar and mixed into Day");
        System.out.println(monday.bar());
    }
}

// Output

Day.Monday
Monday
Day.values()

Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
Day.valueOf("Monday")
Monday
Day.Monday.abbreviation()
Mon
Call method foo defined in Day
foo
Call method bar defined in Bar and mixed into Day
bar


:-)

Simon Ochsenreither

unread,
Jan 18, 2014, 3:52:12 PM1/18/14
to scala...@googlegroups.com
I forgot to show the pattern matching:

object ScalaDayUnapplyConsumer extends App {
  // Temporary workaround due to scalac not looking for static members in Scala classes
  val monday: Day = classOf[Day].getField("Monday").get(null).asInstanceOf[Day]

  val Day(abbr, weekend) = monday
  println(abbr)
  println(weekend)
}

Fernando Racca

unread,
Jan 19, 2014, 5:59:23 PM1/19/14
to scala...@googlegroups.com
That looks really cool. I'd love to be able to use this ASAP.
This bit is is not particularly pleasant, and not exactly the most typesafe. Any other alternative?

Simon Ochsenreither

unread,
Jan 19, 2014, 6:23:10 PM1/19/14
to scala...@googlegroups.com

This bit is is not particularly pleasant, and not exactly the most typesafe. Any other alternative?

Mh, could you be more specific about that? It's just standard pattern matching, with the implementation supplied by the macro. What's missing?

Thanks,

Simon

Eric Pederson

unread,
Mar 20, 2014, 1:10:14 PM3/20/14
to scala...@googlegroups.com
Hi Simon - 

Were you able to get this done for 2.11?  I haven't seen much discussion about it since January.  It's probably my most anticipated new feature.

Thanks,

Simon Ochsenreither

unread,
Mar 20, 2014, 3:25:35 PM3/20/14
to scala...@googlegroups.com

Were you able to get this done for 2.11?  I haven't seen much discussion about it since January.  It's probably my most anticipated new feature.

No, macro annotations won't ship with 2.11. There is a minor issue that Scala doesn't look for static members in Scala classes. Apart from that, things look fine.

Rich Oliver

unread,
Mar 21, 2014, 7:56:43 AM3/21/14
to scala...@googlegroups.com
I realised recently that it would be really useful if Scala could use enums from c /c++ header files.

On Thursday, 8 August 2013 13:31:10 UTC+1, Simon Ochsenreither wrote:
Hi everyone,

while I'm far from finished, I'd like to propose a SIP, whose goal is to provide better support for enums in Scala and improve compatibility with the runtime.
The goal is the inclusion in the upcoming version of Scala (and the deprecation of scala.Enumeration).

Short syntax primer:

@Enum
class Day {

    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
}


Usage (from Java(!)):

        Day mon = Day.Monday();
        int ord = mon.ordinal();
        assert Day.class.getClass().isEnum();


The document is here: https://docs.google.com/document/d/1mIKml4sJzezL_-iDJMmcAKmavHb9axjYJos_7UMlWJ8/edit#

I would be happy about feedback, criticisms and suggestions!
Please let me know what you think!

Thanks,

Simon

Related mailing list threads:
    https://groups.google.com/d/topic/scala-internals/8RWkccSRBxQ/discussion
    https://groups.google.com/d/topic/scala-language/C7Pm6ab1sPs/discussion

Thorpe, Michael

unread,
Mar 21, 2014, 8:09:26 AM3/21/14
to <scala-sips@googlegroups.com>, scala...@googlegroups.com
This is one of the most terrifying sentences I've ever read. 

Why do you want this?
--
You received this message because you are subscribed to the Google Groups "scala-sips" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-sips+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Lieven Lemiengre

unread,
Mar 21, 2014, 9:08:49 AM3/21/14
to scala...@googlegroups.com
native interop

Rich Oliver

unread,
Mar 21, 2014, 10:58:54 AM3/21/14
to scala...@googlegroups.com
On Friday, 21 March 2014 12:09:26 UTC, Michael Thorpe wrote:
This is one of the most terrifying sentences I've ever read. 

Why do you want this?

On 21 Mar 2014, at 11:56, "Rich Oliver" <rzi...@gmail.com> wrote:
Well, I've been playing around with an X11 client using JNI. X11 is horrible and so is Xlib, but I'm interested in writing a Scala Wayland client as soon as a fully functional Linux Wayland desktop distro is released. I'm also interested in other Scala Linux-System integration. Wayland will use EGL for OpenGl so a lot of the code could easily be reused on other platforms. No one else in the world seems interested but I believe JEP 178 made into in Java 8 which means static JNI. This could provide interesting opportunities for Scala.  I'm not sure but it might be possible to get rid of the JNI layer altogether and communicate directly with the System, Wayland compositor and other applications from Scala code using direct buffers and off heap memory, but either way it will necessary to interpret C /C++ defined enums.

Simon Ochsenreither

unread,
Mar 21, 2014, 11:51:21 AM3/21/14
to scala...@googlegroups.com
Until the JVM supports
  • painless interop with C
  • value types
  • generics

it's just not a viable platform for doing such kinds of projects.

If we had some non-braindead interop with native libraries, one could write a typeprovider for it.

Suminda Dharmasena

unread,
Mar 23, 2014, 12:52:15 AM3/23/14
to scala...@googlegroups.com
This group might be of interest to you. https://groups.google.com/forum/?hl=en-GB#!forum/jep-off-heap

Simon Ochsenreither

unread,
Mar 23, 2014, 4:42:37 AM3/23/14
to scala...@googlegroups.com

This group might be of interest to you. https://groups.google.com/forum/?hl=en-GB#!forum/jep-off-heap

Done by the people who brought us Generics and Lambdas. What makes you assume that they finally decided, given their track record, to get something right this time?

Nils Kilden-Pedersen

unread,
Mar 24, 2014, 12:12:14 PM3/24/14
to scala...@googlegroups.com
On Sun, Mar 23, 2014 at 3:42 AM, Simon Ochsenreither <simon.och...@gmail.com> wrote:

This group might be of interest to you. https://groups.google.com/forum/?hl=en-GB#!forum/jep-off-heap

Done by the people who brought us Generics and Lambdas. What makes you assume that they finally decided, given their track record, to get something right this time?

It's getting increasingly tiresome to read about your disrespectful comments and personal attacks on people in the community. Please stop.

Thorpe, Michael

unread,
Mar 24, 2014, 12:47:09 PM3/24/14
to <scala-sips@googlegroups.com>, scala...@googlegroups.com
Given that Martin was one of the people who designed Generics, why do you even use Scala?

On 23 Mar 2014, at 08:42, "Simon Ochsenreither" <simon.och...@gmail.com> wrote:


This group might be of interest to you. https://groups.google.com/forum/?hl=en-GB#!forum/jep-off-heap

Done by the people who brought us Generics and Lambdas. What makes you assume that they finally decided, given their track record, to get something right this time?

--

Francois

unread,
Mar 24, 2014, 1:04:53 PM3/24/14
to scala...@googlegroups.com
On 24/03/2014 17:47, Thorpe, Michael wrote:
Given that Martin was one of the people who designed Generics, why do you even use Scala?

Well, one can argue that the Generics Martin designed and the one which ended in Java are quite differents, and that is one of the reason Scala exists :)




On 23 Mar 2014, at 08:42, "Simon Ochsenreither" <simon.och...@gmail.com> wrote:


This group might be of interest to you. https://groups.google.com/forum/?hl=en-GB#!forum/jep-off-heap

Done by the people who brought us Generics and Lambdas. What makes you assume that they finally decided, given their track record, to get something right this time?
--
You received this message because you are subscribed to the Google Groups "scala-sips" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-sips+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "scala-sips" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-sips+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Adriaan Moors

unread,
Mar 24, 2014, 1:06:30 PM3/24/14