I’m having trouble understanding why I can’t reference a scala enum type.
The problem is that sometimes I can reference enums:
enum(UserStatus)
and sometimes it complains about not being able to find the enum
not found: type UserStatus
How come I sometimes cannot reference the Enumeration class?
The generated source for the enum seems to be ok, and it works great with another enum that I have which lives in the same place, same usage…
Any Suggestions?
More info
The generated source for the enum is:
public final class models.UserStatus extends java.lang.Object{
public static final scala.Enumeration$Value Busy();
public static final scala.Enumeration$Value Free();
public static final scala.Enumeration$ValueSet$ ValueSet();
public static final scala.Enumeration$Value withName(java.lang.String);
public static final scala.Enumeration$Value apply(int);
public static final int maxId();
public static final scala.Enumeration$ValueSet values();
public static final java.lang.String toString();
}
I’m trying to implement an enum mapper for play framework 2.0
def enumFormat[E <: Enumeration](enum: E): Formatter[E#Value] = new Formatter[E#Value] {
def bind(key: String, data: Map[String, String]) = {
Formats.stringFormat.bind(key, data).right.flatMap { s =>
scala.util.control.Exception.allCatch[E#Value]
.either(enum.withName(s))
.left.map(e => Seq(FormError(key, "error.enum", Nil)))
}
}
def unbind(key: String, value: E#Value) = Map(key -> value.toString)
}
And this method that calls the mapper
def enum[E <: Enumeration](enum: E): Mapping[E#Value] = of(enumFormat(enum))
This means that the mapper automatically converts between a enum when using the form binding
Pseudo code of usage.
package models {
object UserStatus extends Enumeration {
val Free = Value("free")
val Busy = Value("busy")
}
case class User(
status: UserStatus.Value = UserStatus.Free
)
}
package controllers {
imports models._
val userForm = Form(
mapping(
"status" -> enum(UserStatus)
)(User.apply)(User.unapply)
)
}
Your problem may come from the fact that in Scala you can use the same identifier for a type and for a value.
When you write the following:
You define a
Fooobject, but you don’t define aFootype. If you come from a Java background you may not find this behavior intuitive.So what’s the type of the
Fooenumeration values? Their type isFoo.Value(that’s called a path dependent type).If you want to define a
Footype corresponding to the enumeration values type, you can alias theFoo.Valuetype:Now you can refer to the enumeration type by writing
Foo.Foo. You can import the fields of theFooobject to reduce the syntactic overhead:In the above code, the first line refers to the
Fooobject, and the second line refers to theFootype.