getting Value from scala enumeration - scala

say i have enumeration like this
object SimpleEnum extends Enumeration{
val ONE = Value(1)
val TWO = Value(2)
val THREE = Value(3)
etc...
}
also i've a class which i want to be extending Ordered[SimpleEnum]
class SimpleClass(se: SimpleEnum) extends Ordered[SimpleEnum] {
override def compare(that: SimpleEnum): Int = this.se.[here i want to get instance of SimpleEnum, just like i used to do in java, but unfortunately it's not possible]
}
So in SimpleClass i just need to get the Value attached to corresponding SimpleEnum val.
In java i'm able to declare a variable on enum and access an actual value corresponding to it by this var, in scala i'm looking for a way to get an instance of enum and reach out for its value.

It is possible, use id method.
scala> object E extends Enumeration {
val A = Value(1)
val B = Value(7)
val C = Value(2)
}
defined object E
scala> E.A.id
res7: Int = 1
scala> E.B.id
res8: Int = 7
scala> E.C.id
res9: Int = 2
Enumeration values can also be easly compared
scala> E.A < E.B
res10: Boolean = true
scala> E.C < E.B
res11: Boolean = true
scala> E.B < E.A
res12: Boolean = false
Refer to documentation for more
Edit
Your code in the picture is wrong. Firstly, as in your original code (that is not in the picture), SimpleEnum should be an object, not a class. As soon as you make that change your code won't compile and that should ring a bell.
You want SimpleClass to be able to wrap your enum values. Type of those values (i.e. ONE, TWO, THREE) is not SimpleEnum, it is SimpleEnum.Value. Objects of this type have id method.
class SimpleClass(se: SimpleEnum.Value) extends Ordered[SimpleEnum.Value] {
override def compare(that: SimpleEnum.Value): Int = se.id
}
A common thing to do is to declare a type alias for Value with exact same name as the enum object. Then you can import this type and use it
object SimpleEnum extends Enumeration {
type SimpleEnum = Value
val ONE = Value(1)
val TWO = Value(2)
val THREE = Value(3)
}
import SimpleEnum.SimpleEnum
class SimpleClass(se: SimpleEnum) extends Ordered[SimpleEnum] {
override def compare(that: SimpleEnum): Int = se.id
}
Note that Enumeration#Value already implements Ordered[Value]. You can verify it in the docs that I linked earlier.
There is no classic java enum in scala, but because the language is so cool, it was possible to create a regular class called Enumeration that with some tricks allows for similar behavior.

The question is already answered but my approach is the following:
object SimpleEnum extends Enumeration{
type SimpleEnum = Value
val ONE = Value(1)
val TWO = Value(2)
val THREE = Value(3)
etc...
}
class SimpleClass(val i : Int){
def getNumber() {
import SimpleEnum._
SimpleEnum(i)
}
}

Related

Extending from trait where each instance's singleton type is type parameter

Suppose I want every instance of an Item to be a SourceOf that Item, and every SourceOf a subtype of Item to be a SourceOf all instances of that subtype. This seems like a natural way to do it:
object Demo {
trait Item extends SourceOf[this.type]
trait SourceOf[+A <: Item]
}
Obviously this won't work, since this refers to the Demo object, not to each Item instance. (I've tested it.)
How can I tell the Scala compiler that every Item is a source of itself? It should be possible to get the compiler to deduce stuff like:
"Every source of (all) farming implements is a source of the specific farming implement you're looking for."
"If you're looking for the source of a farming implement, and you already have the farming implement, then you need look no further."
Here's an example (written to ignore type erasure for brevity):
trait FarmingImplement extends Item
object TheRototiller extends FarmingImplement
def findSource(item: Item, seq: Seq[SourceOf[_]]): Option[SourceOf[item.type]] =
seq.collectFirst {
case src: SourceOf[item.type] => src
}
val sources = Seq( // example: possible sources of TheRototiller
new SourceOf[Nothing] { override def toString = "Wrong source" },
new SourceOf[FarmingImplement] { override def toString = "Right" },
TheRototiller /* also right */ )
val got = findSource(TheRototiller, sources).get
println(got) // Should print "Right", since the second source in `sources`
// is the first match.
I want the type of got be SourceOf[TheRototiller.type], not SourceOf[Item]. But mainly I want Scala's type system to do the work of determining whether a SourceOf matches a given Item or category of Items.
At least, this gonna solve your problem with passing this:
object Demo {
trait C[+A]
trait Item extends SourceOf {
type T = C[this.type]
}
trait SourceOf {
type T <: C[Item]
}
}
Example (you'll have to compare Ts instead of SourceOfs here):
scala> val i = new Item{}
i: Demo.Item = $anon$1#c70cb4c
scala> implicitly[i.T =:= i.T] //compile-time type equality check
res4: =:=[i.T,i.T] = <function1>
scala> val i2 = new Item{}
i2: Demo.Item = $anon$1#1f26ac06
scala> implicitly[i.T =:= i2.T]
<console>:18: error: Cannot prove that i.T =:= i2.T.
implicitly[i.T =:= i2.T]
If you need to check types in runtime (as you've shown in example with pattern matching) - I would recomend to use TypeTag:
import scala.reflect.runtime.universe._
object Demo {
abstract class C[+A: TypeTag]
trait Item extends SourceOf {
type T = C[this.type]
}
trait SourceOf {
val tag = typeTag[this.type] //just to access
}
}
Usage:
scala> val i = new Item{}
i: Demo.Item = $anon$1#3b2111b0
scala> val i2 = new Item{}
i2: Demo.Item = $anon$1#4e7bb48a
scala> typeTag[i.T].tpe =:= typeTag[i2.T].tpe //runtime type-equality check
res9: Boolean = false
scala> typeTag[i.T].tpe =:= typeTag[i.T].tpe
res10: Boolean = true
Finally, implementation of findSource:
import scala.reflect.runtime.universe._
object Demo {
trait Item extends SourceOf
trait SourceOf {
type I = this.type
val tag = typeTag[I]
}
def findSource(item: Item, seq: Seq[SourceOf]): Option[item.I] =
seq.find(_.tag.tpe =:= item.tag.tpe).asInstanceOf[Option[item.I]]
}
Examples:
scala> val i = new Item{}
i: Demo.Item = $anon$1#1fc2899d
scala> val i2 = new Item{}
i2: Demo.Item = $anon$1#5f308abb
scala> val ri = findSource(i, Seq(i, i2)).get
ri: i.I = $anon$1#1fc2899d
scala> implicitly[ri.I =:= i.I]
res2: =:=[ri.I,i.I] = <function1>
asInstanceOf is used (it's safe to do here) because Seq looses path-dependent type in compile-time and we used runtime-check to match types, so no way to find it for compiler. However, Shapeless2's HList + Selector based implementation might be more pure.

Dynamic instantiation of Scala Enumeration

Is there any way to dynamically instantiate an Enumeration#Value in Scala?
So far I have:
object Letter extends Enumeration {
val A,B,C = Value
}
// fieldType is of type Universe.Type for the field in my case class, which happens to
// be of type Letter.Value
val ftype = fieldType.typeSymbol.name.toString
val enumVal = "B" // a valid Enumeration.Value
val erasedEnumType = fieldType.asInstanceOf[TypeRef] // Letter
Now what? I'm trying to arrive at an object of value Letter.B in this case.
I saw this clip on another posting:
def create[T <: Enum[T]](clazz: Class[T], input: String): T = Enum.valueOf(clazz, input)
I couldn't make this work because I don't have "T" at compile-time (I'm parsing this value from input strings at runtime).
You mean retrieve instead of instantiate?
scala> object Letter extends Enumeration {
| val A,B,C = Value
| }
defined module Letter
scala> Letter withName "B"
res0: Letter.Value = B
as opposed to creating another value.
Updated:
package reflectenum
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{currentMirror=>cm}
import scala.reflect.NameTransformer._
object Letters extends Enumeration {
val A,B,C = Value
}
object Test extends App {
val claas = cm.classLoader loadClass "reflectenum.Letters$"
Console println s"$claas"
val enum = claas.getField(MODULE_INSTANCE_NAME).get(null).asInstanceOf[Enumeration]
Console println s"$enum"
Console println s"${enum withName "B"}"
// given some element of the enumeration
val v = enum withName "B"
val im = cm reflect v
val outerName = newTermName("scala$Enumeration$$outerEnum")
val outer = typeOf[enum.Value] member outerName
val f = im reflectField outer.asTerm.accessed.asTerm
assert(enum == f.get)
}
This works:
val foo = Class.forName("reflectnum.Letter$") //← note extra $
val anObj = foo.getField("MODULE$").get(foo)
val meth = anObj.getClass.getMethod("withName",classOf[String])
val z = meth.invoke(anObj,"B")

How do I create an enum in scala that has an extra field

In Java I have something like this
public enum FlatFileHeaderMapping {
HEADER_EL(1),
HEADER_RESERVED1(5),
HEADER_RESERVED2(2),
HEADER_MESSAGE_TYPE(4)
public final int fieldSize;
private FlatFileHeaderMapping(int fieldSize) {
this.fieldSize = fieldSize;
}
}
which I can then use it place each line into a map and later access the keys in the map via this enum (like symbols)
Enumeration does not have this quality as far as I can see, and case classes are not ordered like the enum declarations - so cannot be used to match a record layout as shown above. At least not without the support of an ordered collection.
I could be missing something obvious, hence the question!
Thanks
Ray
overthink is right, but there's a less verbose way of declaring the case objects:
sealed abstract class FlatFileHeaderMapping(val fieldSize: Int)
case object HEADER_EL extends FlatFileHeaderMapping(1)
case object HEADER_RESERVED1 extends FlatFileHeaderMapping(5)
case object HEADER_RESERVED2 extends FlatFileHeaderMapping(2)
case object HEADER_MESSAGE_TYPE extends FlatFileHeaderMapping(4)
You could try using case objects:
sealed trait FlatFileHeaderMapping { val fieldSize: Int }
case object HEADER_EL extends FlatFileHeaderMapping { val fieldSize = 1 }
case object HEADER_RESERVED1 extends FlatFileHeaderMapping { val fieldSize = 5 }
case object HEADER_RESERVED2 extends FlatFileHeaderMapping { val fieldSize = 2 }
case object HEADER_MESSAGE_TYPE extends FlatFileHeaderMapping { val fieldSize = 4 }
You can then use the enum like so:
object Test {
def foo(x: FlatFileHeaderMapping) {
val result =
x match {
case HEADER_EL => "it's a HEADER_EL!"
case other => "its field size is: " + other.fieldSize
}
println(result)
}
def main(args: Array[String]) {
foo(HEADER_EL)
foo(HEADER_MESSAGE_TYPE)
}
}
The main nicety you get here is compile-time checking that all enum values are handled. i.e in the x match { ... } code above you'd get a compile error if you didn't have the 'case other => ...` clause in there.
I'm pretty much just restating this answer, which lists pros and cons of this approach.
object Direction extends Enumeration {
val North = Value("North")
val East = Value("East")
val South = Value("South")
val West = Value("West")
}
scala> import Direction._
scala> values foreach println
scala> val map = HashMap(North -> 1, South -> 2)
This is answered in Enumeration with constructor and lookup table
A simpler solution exist for integer value:
object FlatFileHeaderMapping extends Enumeration {
type FlatFileHeaderMapping = Value
val HEADER_EL = Value(1, "HEADER_EL")
val HEADER_RESERVED1 = Value(5, "HEADER_RESERVED1")
val HEADER_RESERVED2 = Value(2, "HEADER_RESERVED2")
val HEADER_MESSAGE_TYPE = Value(4, "HEADER_MESSAGE_TYPE")
}
Reproducing the contents of the accepted answer, as it's hidden behind a broken Tumblr link (that I accessed via Archive.org), which in turn points to this page.
trait Enum { //DIY enum type
import java.util.concurrent.atomic.AtomicReference //Concurrency paranoia
type EnumVal <: Value //This is a type that needs to be found in the implementing class
private val _values = new AtomicReference(Vector[EnumVal]()) //Stores our enum values
//Adds an EnumVal to our storage, uses CCAS to make sure it's thread safe, returns the ordinal
private final def addEnumVal(newVal: EnumVal): Int = { import _values.{get, compareAndSet => CAS}
val oldVec = get
val newVec = oldVec :+ newVal
if((get eq oldVec) && CAS(oldVec, newVec)) newVec.indexWhere(_ eq newVal) else addEnumVal(newVal)
}
def values: Vector[EnumVal] = _values.get //Here you can get all the enums that exist for this type
//This is the trait that we need to extend our EnumVal type with, it does the book-keeping for us
protected trait Value { self: EnumVal => //Enforce that no one mixes in Value in a non-EnumVal type
final val ordinal = addEnumVal(this) //Adds the EnumVal and returns the ordinal
def name: String //All enum values should have a name
override def toString = name //And that name is used for the toString operation
override def equals(other: Any) = this eq other.asInstanceOf[AnyRef]
override def hashCode = 31 * (this.getClass.## + name.## + ordinal)
}
}
//And here's how to use it, if you want compiler exhaustiveness checking
object Foos extends Enum {
sealed trait EnumVal extends Value /*{ you can define your own methods etc here }*/
val F = new EnumVal { val name = "F" }
val X = new EnumVal { val name = "X" }
}
/**
scala> Foos.values.find(_.name == "F")
res3: Option[Foos.EnumVal] = Some(F)
scala> Foos.X.ordinal
res4: Int = 1
scala> def doSmth(foo: Foos.EnumVal) = foo match {
case Foos.X => println("pigdog")
}
<console>:10: warning: match is not exhaustive!
missing combination $anon$1
missing combination $anon$2
scala> def doSmth(foo: Foos.EnumVal) = foo match {
case Foos.X => println("pigdog")
case Foos.F => println("dogpig")
}
doSmth: (foo: Foos.EnumVal)Unit
**/
//But if you don't care about getting exhaustiveness warnings, you can do:
object Foos extends Enum {
case class EnumVal private[Foos](name: String) extends Value /* { you can define your own methods and stuff here } */
val F = EnumVal("F")
val X = EnumVal("X")
}
/**
Which is a bit less boilerplatey.
Cheers,
√
**/

Overriding Scala Enumeration Value

As far as I can tell, Scala has definitions for the Enumeration Value class for Value(Int), Value(String), and Value(Int, String).
Does anyone know of an example for creating a new Value subclass to support a different constructor?
For example, If I want to create an Enumeration with Value(Int, String, String) objects, how would I do it? I would like all of the other benefits of using the Enumeration class.
Thanks.
The Enumeration values are instance of the Val class. This class can be extended and a factory method can be added.
object My extends Enumeration {
val A = Value("name", "x")
val B = Value("other", "y")
class MyVal(name: String, val x : String) extends Val(nextId, name)
protected final def Value(name: String, x : String): MyVal = new MyVal(name, x)
}
scala> My.B.id
res0: Int = 1
scala> My.B.x
res1: String = y
Actually in Scala Enumeration has a much simpler meaning than in Java. For your purpose you don't have to subclass Enumeration nor its Value in any way, you just need to instantiate your own type in its companion object as a val. This way you'll get the familiar access model of val value:MyEnum = MyEnum.Value as you had in Java which is not possible in the example provided by Thomas Jung. There you'll have def value:My.MyVal = MyEnum.Value which is kinda confusing as it seems to me besides all the hackiness of the solution. Here's an example of what I propose:
class MyEnum(myParam:String)
object MyEnum {
val Value1 = new MyEnum("any parameters you want")
val Value2 = new MyEnum("")
object Value3 extends MyEnum("A different approach to instantialization which also lets you extend the type in place")
}
Here you'll find a more complicated example: Scala Best Practices: Trait Inheritance vs Enumeration
I would prefer doing it by extending the Enumeration.Val class.
For your requirement, I would post a sample below:
object FileType extends Enumeration {
val csv = Val(1,"csv", ",")
val tsv = Val(2,"tsv", "\t")
protected case class Val(num: Int, fileType: String, delimiter: String) extends super.Val
implicit def valueToFileType(x: Value): Val = x.asInstanceOf[Val]
}
Accessing values is as below:
scala> FileType.csv
res0: FileType.Val = csv
scala> FileType.csv.delimiter
res29: String = ,
Here is another simpler approach:
scala> :paste
// Entering paste mode (ctrl-D to finish)
object Colors extends Enumeration {
sealed case class Color private[Colors](hexCode: String, name: String) extends Val(name)
val Black = Color("#000000", "black")
val White = Color("#FFFFFF", "white")
}
// Exiting paste mode, now interpreting.
defined object Colors
scala> Colors.Black.hexCode
res0: String = #000000
scala> Colors.Black.name
res1: String = black
scala> Colors.values
res2: Colors.ValueSet = Colors.ValueSet(black, white)
scala>

Scala: How can I implement a clone method on a superclass, and use it in a subclass?

I might be approaching this the wrong way, but I'd like to have an object like this:
class MyDataStructure {
def myClone = {
val clone = new MyDataStructure
// do stuff to make clone the same as this
...
clone
}
}
class MyDataStructureExtended(val foo: String) extends MyDataStructure
Then:
val data = MyDataStructureExtended
val dataClone = data.clone
println(dataClone.foo)
So, the problem is that dataClone is of type MyDataStructure, not MyDataStructureExtended as I'd hoped.
I thought about adding a type T to the super class, that the subclass can specify (e.g. itself), but that didn't seem very promising.
As you have suggested, abstract types, or generic parameters, are what you need. Do you require that MyDataStructure not be a trait or abstract class? The following defines MyDataStructure to be an abstract class, but you can make it a trait as well.
abstract class MyDataStructure {
type T
def myClone: T
}
class MyDataStructureExtended(foo: String) extends MyDataStructure {
type T = MyDataStructureExtended
def myClone = new MyDataStructureExtended(foo)
}
The results from the Scala interpreter show that the myClone method defined in MyDataStructureExtended is the correct type.
scala> val mde = new MyDataStructureExtended("foo")
val mde = new MyDataStructureExtended("foo")
mde: MyDataStructureExtended = MyDataStructureExtended#3ff5d699
scala> val cloned = mde.myClone
val cloned = mde.myClone
cloned: MyDataStructureExtended = MyDataStructureExtended#2e1ed620
You might want to restrict T so that its type can only be that of MyDataStructure subclasses
abstract class MyDataStructure {
type T <: MyDataStructure
def myClone: T
}
I don't know your requirements, but I believe that Scala 2.8 will have some nice functionality with case classes and named arguments that allow one to clone case classes with a copy method.
Assuming you want to minimize amount of ceremony in the subclasses, here is my suggestion:
class A extends Cloneable {
protected[this] def myCloneImpl[T] = {
val justLikeMe = this.clone
// copy values and such.
// Note that the Object.clone method already made a shallow copy, but you may want
// to deepen the copy or do other operations.
justLikeMe.asInstanceOf[T]
}
def myClone = myCloneImpl[A]
}
class B extends A {
override def myClone = myCloneImpl[B]
}
By extending java.lang.Cloneable and calling the Object.clone method, you ensure that your runtime type is the same as the object being cloned. The static type is coerced with a type-cast (asInstanceOf[T]). You will need to override the myClone method in each subclass and specify the type, but it should be a one-liner.
Hard to say whether you're doing it right with such a vague problem description, but it's actually pretty straightforward to do this. You can simply override myclone in MyDataStructureExtended such that it returns the more specific type. When you have a variable of the more specific type, you'll be able to use the more specific clone method as well.
Example code in case that description was unclear:
class A {
def getMe = this
}
class B extends A {
override def getMe = this
def isAnInstanceOfB = true
}
And a corresponding REPL session:
scala> val a = new A
a: A = A#1a6eeab
scala> val b = new B
b: B = B#a36771
scala> a.getMe
res0: A = A#1a6eeab
scala> a.getMe.isAnInstanceOfB
<console>:7: error: value isAnInstanceOfB is not a member of A
a.getMe.isAnInstanceOfB
^
scala> b.isAnInstanceOfB
res2: Boolean = true
scala> b.getMe.isAnInstanceOfB
res3: Boolean = true
I think this could be the solution. This is not inherited and you can do some modification to achieve your thing. Good Luck.
class CloneableClass extends scala.Cloneable {
def myMethod: Unit = println("Inside "+this.getClass)
override def clone(): CloneableClass =super.clone().asInstanceOf[this.type]
}
class CloneableDemo {
val cc = new CloneableClass
val cc1 = cc.clone()
cc1.myMethod
}
object CloneObject extends App {
val cd = new CloneableDemo
}