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?
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:
object Foo extends Enumeration {
val A, B, C = Value
}
You define a Foo
object, but you don’t define a Foo
type. If you come from a Java background you may not find this behavior intuitive.
So what’s the type of the Foo
enumeration values? Their type is Foo.Value
(that’s called a path dependent type).
If you want to define a Foo
type corresponding to the enumeration values type, you can alias the Foo.Value
type:
object Foo extends Enumeration {
type Foo = Value // Type alias
val A, B, C = Value
}
Now you can refer to the enumeration type by writing Foo.Foo
. You can import the fields of the Foo
object to reduce the syntactic overhead:
import Foo._
def bar(foo: Foo): String = foo match {
case A => "value A"
case B => "value B"
case C => "value C"
}
In the above code, the first line refers to the Foo
object, and the second line refers to the Foo
type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With