Change scala Enumeration id - scala

I want to create enum type with value that can be changed.
Consider the following:
object Type extends Enumeration
{
var a = Value(0, "some string1")
val b = Value(1, "some string2")
val c = Value(2, "some string3")
}
I gave every enum field a value but i want to have the option to change this value.
And another is that i am reading this values from some table so enum with same value its a option.
Is it possible ?

In common parlance, an enum is not something that is mutable. The elements are enumerated at compile time, as typesafe constants.
Also, Enumeration is relatively fragile.
scala> object X extends Enumeration { var x = Value(0, "a") ; def f() = x = Value(1, "b") }
defined object X
scala> X.x
res1: X.Value = a
scala> X.f()
scala> X.x
res3: X.Value = b
scala> X.values
res4: X.ValueSet = X.ValueSet(a, b)

Related

Scala Either : simplest way to get a property that exists on right and left

I have a template using a valueObject that might be one of two flavours depending on where it is used in our app. So I am importing it as an Either:
valueObject: Either[ ObjectA, ObjectB ]
Both objects have an identically named property on them so I would like to retrieve it just by calling
valueObject.propertyA
Which doesn't work.
What is the most concise/ best way of doing this?
Assuming the two objects have the same type (or a supertype / trait) that defines that property - you can use merge which returns left if it exists and right otherwise, with the lowest common type of both:
scala> class MyClass {
| def propertyA = 1
| }
defined class MyClass
scala> val e1: Either[MyClass, MyClass] = Left(new MyClass)
e1: Either[MyClass,MyClass] = Left(MyClass#1e51abf)
scala> val e2: Either[MyClass, MyClass] = Right(new MyClass)
e2: Either[MyClass,MyClass] = Right(MyClass#b4c6d0)
scala> e1.merge.propertyA
res0: Int = 1
scala> e2.merge.propertyA
res1: Int = 1
Using fold
Assuming the two objects do not share a common supertype that holds the property/method, then you have to resort to fold:
scala> case class A(a: Int)
defined class A
scala> case class B(a: Int)
defined class B
scala> def foldAB(eab: Either[A,B]): Int = eab.fold(_.a,_.a)
foldAB: (eab: Either[A,B])Int
scala> foldAB(Left(A(1)))
res1: Int = 1
scala> foldAB(Right(B(1)))
res2: Int = 1
Pattern matching
Another possibility is to use pattern matching:
scala> def matchAB(eab: Either[A,B]): Int = eab match { case Left(A(i)) => i; case Right(B(i)) => i}
matchAB: (eab: Either[A,B])Int
scala> matchAB(Left(A(1)))
res3: Int = 1
scala> matchAB(Right(B(1)))
res4: Int = 1

Unexpected Result when Overriding 'val'

In Scala 2.10.4, Given the following class:
scala> class Foo {
| val x = true
| val f = if (x) 100 else 200
| }
defined class Foo
The following two examples make sense to me:
scala> new Foo {}.f
res0: Int = 100
scala> new Foo { override val x = false}.f
res1: Int = 200
But, why doesn't this call return 100?
scala> new Foo { override val x = true }.f
res2: Int = 200
Because vals aren't initialized more than once, x is actually null (or false for a default Boolean) during the initialization of Foo, and then initialized in the anonymous class that is extending Foo in your example.
We can test it more easily with an AnyRef:
class Foo {
val x = ""
val f = if (x == null) "x is null" else "not null"
}
scala> new Foo { override val x = "a" }.f
res10: String = x is null
scala> new Foo {}.f
res11: String = not null
There's a full explanation in the Scala FAQ. Excerpt:
Naturally when a val is overridden, it is not initialized more than once. So though x2 in the above example is seemingly defined at every point, this is not the case: an overridden val will appear to be null during the construction of superclasses, as will an abstract val.
A simple way to avoid this would be to use a lazy val or def, if the val being referenced may be overridden.
Additionally, you can use the -Xcheckinit compiler flag to warn you about potential initialization errors like this.

Dynamically create extensible record in shapeless 2.0

I need to produce an extensible record given an HList of keys and a map of values, here's a MWE of what I'm trying to achieve (you can copy/paste this in any REPL with shapeless 2.0 available, in order to reproduce the issue)
import shapeless._; import syntax.singleton._; import record._
case class Foo[T](column: Symbol)
val cols = Foo[String]('column1) :: HNil
val values = Map("column1" -> "value1")
object toRecord extends Poly1 {
implicit def Foo[T] = at[Foo[T]] { foo =>
val k = foo.column.name
val v = values.get(k)
(k ->> v)
}
}
val r = cols.map(toRecord)
// r: shapeless.::[Option[String] with shapeless.record.KeyTag[k.type,Option[String]] forSome { val k: String },shapeless.HNil] = Some(value1) :: HNil
val value = r("column1")
// error: No field String("column1") in record shapeless.::[Option[String] with shapeless.record.KeyTag[k.type,Option[String]] forSome { val k: String },shapeless.HNil]
val value = r("column1")
If I try defining the record manually everything works as expected
val q = ("column1" ->> Some("value1")) :: HNil
// q: shapeless.::[Some[String] with shapeless.record.KeyTag[String("column1"),Some[String]],shapeless.HNil] = Some(value1) :: HNil
q("column1")
// Some[String] = Some(value1)
Clearly the difference is that in one case the KeyTag has type
KeyTag[String("column1"), Some[String]]
and in the (non-working) other
KeyTag[k.type,Option[String]] forSome { val k: String }
I sense the issue is with the string k not being statically known, but I have no clue on how to fix this.
Generally speaking, is there a way of dynamically generating an extensible record from a list of keys?
I fear the answer is to use a macro, but I'd be glad if another solution existed.
This isn't too bad if you can change your Foo definition a bit to allow it to keep track of the singleton type of the column key (note that I've removed the unused T type parameter):
import shapeless._; import syntax.singleton._; import record._
case class Foo[K <: Symbol](column: Witness.Aux[K])
val cols = Foo('column1) :: HNil
val values = Map("column1" -> "value1")
object toRecord extends Poly1 {
implicit def atFoo[K <: Symbol] = at[Foo[K]] { foo =>
field[K](values.get(foo.column.value.name))
}
}
val r = cols.map(toRecord)
And then:
scala> val value = r('column1)
value: Option[String] = Some(value1)
Note that I've changed your string key ("column1") to a symbol, since that's what we've put into the record.

Different types in Map Scala

I need a Map where I put different types of values (Double, String, Int,...) in it, key can be String.
Is there a way to do this, so that I get the correct type with map.apply(k) like
val map: Map[String, SomeType] = Map()
val d: Double = map.apply("double")
val str: String = map.apply("string")
I already tried it with a generic type
class Container[T](element: T) {
def get: T = element
}
val d: Container[Double] = new Container(4.0)
val str: Container[String] = new Container("string")
val m: Map[String, Container] = Map("double" -> d, "string" -> str)
but it's not possible since Container takes an parameter. Is there any solution to this?
This is not straightforward.
The type of the value depends on the key. So the key has to carry the information about what type its value is. This is a common pattern. It is used for example in SBT (see for example SettingsKey[T]) and Shapeless Records (Example). However, in SBT the keys are a huge, complex class hierarchy of its own, and the HList in shapeless is pretty complex and also does more than you want.
So here is a small example of how you could implement this. The key knows the type, and the only way to create a Record or to get a value out of a Record is the key. We use a Map[Key, Any] internally as storage, but the casts are hidden and guaranteed to succeed. There is an operator to create records from keys, and an operator to merge records. I chose the operators so you can concatenate Records without having to use brackets.
sealed trait Record {
def apply[T](key:Key[T]) : T
def get[T](key:Key[T]) : Option[T]
def ++ (that:Record) : Record
}
private class RecordImpl(private val inner:Map[Key[_], Any]) extends Record {
def apply[T](key:Key[T]) : T = inner.apply(key).asInstanceOf[T]
def get[T](key:Key[T]) : Option[T] = inner.get(key).asInstanceOf[Option[T]]
def ++ (that:Record) = that match {
case that:RecordImpl => new RecordImpl(this.inner ++ that.inner)
}
}
final class Key[T] {
def ~>(value:T) : Record = new RecordImpl(Map(this -> value))
}
object Key {
def apply[T] = new Key[T]
}
Here is how you would use this. First define some keys:
val a = Key[Int]
val b = Key[String]
val c = Key[Float]
Then use them to create a record
val record = a ~> 1 ++ b ~> "abc" ++ c ~> 1.0f
When accessing the record using the keys, you will get a value of the right type back
scala> record(a)
res0: Int = 1
scala> record(b)
res1: String = abc
scala> record(c)
res2: Float = 1.0
I find this sort of data structure very useful. Sometimes you need more flexibility than a case class provides, but you don't want to resort to something completely type-unsafe like a Map[String,Any]. This is a good middle ground.
Edit: another option would be to have a map that uses a (name, type) pair as the real key internally. You have to provide both the name and the type when getting a value. If you choose the wrong type there is no entry. However this has a big potential for errors, like when you put in a byte and try to get out an int. So I think this is not a good idea.
import reflect.runtime.universe.TypeTag
class TypedMap[K](val inner:Map[(K, TypeTag[_]), Any]) extends AnyVal {
def updated[V](key:K, value:V)(implicit tag:TypeTag[V]) = new TypedMap[K](inner + ((key, tag) -> value))
def apply[V](key:K)(implicit tag:TypeTag[V]) = inner.apply((key, tag)).asInstanceOf[V]
def get[V](key:K)(implicit tag:TypeTag[V]) = inner.get((key, tag)).asInstanceOf[Option[V]]
}
object TypedMap {
def empty[K] = new TypedMap[K](Map.empty)
}
Usage:
scala> val x = TypedMap.empty[String].updated("a", 1).updated("b", "a string")
x: TypedMap[String] = TypedMap#30e1a76d
scala> x.apply[Int]("a")
res0: Int = 1
scala> x.apply[String]("b")
res1: String = a string
// this is what happens when you try to get something out with the wrong type.
scala> x.apply[Int]("b")
java.util.NoSuchElementException: key not found: (b,Int)
This is now very straightforward in shapeless,
scala> import shapeless._ ; import syntax.singleton._ ; import record._
import shapeless._
import syntax.singleton._
import record._
scala> val map = ("double" ->> 4.0) :: ("string" ->> "foo") :: HNil
map: ... <complex type elided> ... = 4.0 :: foo :: HNil
scala> map("double")
res0: Double with shapeless.record.KeyTag[String("double")] = 4.0
scala> map("string")
res1: String with shapeless.record.KeyTag[String("string")] = foo
scala> map("double")+1.0
res2: Double = 5.0
scala> val map2 = map.updateWith("double")(_+1.0)
map2: ... <complex type elided> ... = 5.0 :: foo :: HNil
scala> map2("double")
res3: Double = 5.0
This is with shapeless 2.0.0-SNAPSHOT as of the date of this answer.
I finally found my own solution, which worked best in my case:
case class Container[+T](element: T) {
def get[T]: T = {
element.asInstanceOf[T]
}
}
val map: Map[String, Container[Any]] = Map("a" -> Container[Double](4.0), "b" -> Container[String]("test"))
val double: Double = map.apply("a").get[Double]
val string: String = map.apply("b").get[String]
(a) Scala containers don't track type information for what's placed inside them, and
(b) the return "type" for an apply/get method with a simple String parameter/key is going to be static for a given instance of the object the method is to be applied to.
This feels very much like a design decision that needs to be rethought.
I don't think there's a way to get bare map.apply() to do what you'd want. As the other answers suggest, some sort of container class will be necessary. Here's an example that restricts the values to be only certain types (String, Double, Int, in this case):
sealed trait MapVal
case class StringMapVal(value: String) extends MapVal
case class DoubleMapVal(value: Double) extends MapVal
case class IntMapVal(value: Int) extends MapVal
val myMap: Map[String, MapVal] =
Map("key1" -> StringMapVal("value1"),
"key2" -> DoubleMapVal(3.14),
"key3" -> IntMapVal(42))
myMap.keys.foreach { k =>
val message =
myMap(k) match { // map.apply() in your example code
case StringMapVal(x) => "string: %s".format(x)
case DoubleMapVal(x) => "double: %.2f".format(x)
case IntMapVal(x) => "int: %d".format(x)
}
println(message)
}
The main benefit of the sealted trait is compile-time checking for non-exhaustive matches in pattern matching.
I also like this approach because it's relatively simple by Scala standards. You can go off into the weeds for something more robust, but in my opinion you're into diminishing returns pretty quickly.
If you want to do this you'd have to specify the type of Container to be Any, because Any is a supertype of both Double and String.
val d: Container[Any] = new Container(4.0)
val str: Container[Any] = new Container("string")
val m: Map[String, Container[Any]] = Map("double" -> d, "string" -> str)
Or to make things easier, you can change the definition of Container so that it's no longer type invariant:
class Container[+T](element: T) {
def get: T = element
override def toString = s"Container($element)"
}
val d: Container[Double] = new Container(4.0)
val str: Container[String] = new Container("string")
val m: Map[String, Container[Any]] = Map("double" -> d, "string" -> str)
There is a way but it's complicated. See Unboxed union types in Scala. Essentially you'll have to type the Map to some type Int |v| Double to be able to hold both Int and Double. You'll also pay a high price in compile times.

Scala: Filtering based on type

I'm learning Scala as it fits my needs well but I am finding it hard to structure code elegantly. I'm in a situation where I have a List x and want to create two Lists: one containing all the elements of SomeClass and one containing all the elements that aren't of SomeClass.
val a = x collect {case y:SomeClass => y}
val b = x filterNot {_.isInstanceOf[SomeClass]}
Right now my code looks like that. However, it's not very efficient as it iterates x twice and the code somehow seems a bit hackish. Is there a better (more elegant) way of doing things?
It can be assumed that SomeClass has no subclasses.
EDITED
While using plain partition is possible, it loses the type information retained by collect in the question.
One could define a variant of the partition method that accepts a function returning a value of one of two types using Either:
import collection.mutable.ListBuffer
def partition[X,A,B](xs: List[X])(f: X=>Either[A,B]): (List[A],List[B]) = {
val as = new ListBuffer[A]
val bs = new ListBuffer[B]
for (x <- xs) {
f(x) match {
case Left(a) => as += a
case Right(b) => bs += b
}
}
(as.toList, bs.toList)
}
Then the types are retained:
scala> partition(List(1,"two", 3)) {
case i: Int => Left(i)
case x => Right(x)
}
res5: (List[Int], List[Any]) = (List(1, 3),List(two))
Of course the solution could be improved using builders and all the improved collection stuff :) .
For completeness my old answer using plain partition:
val (a,b) = x partition { _.isInstanceOf[SomeClass] }
For example:
scala> val x = List(1,2, "three")
x: List[Any] = List(1, 2, three)
scala> val (a,b) = x partition { _.isInstanceOf[Int] }
a: List[Any] = List(1, 2)
b: List[Any] = List(three)
Just wanted to expand on mkneissl's answer with a "more generic" version that should work on many different collections in the library:
scala> import collection._
import collection._
scala> import generic.CanBuildFrom
import generic.CanBuildFrom
scala> def partition[X,A,B,CC[X] <: Traversable[X], To, To2](xs : CC[X])(f : X => Either[A,B])(
| implicit cbf1 : CanBuildFrom[CC[X],A,To], cbf2 : CanBuildFrom[CC[X],B,To2]) : (To, To2) = {
| val left = cbf1()
| val right = cbf2()
| xs.foreach(f(_).fold(left +=, right +=))
| (left.result(), right.result())
| }
partition: [X,A,B,CC[X] <: Traversable[X],To,To2](xs: CC[X])(f: (X) => Either[A,B])(implicit cbf1: scala.collection.generic.CanBuildFrom[CC[X],A,To],implicit cbf2: scala.collection.generic.CanBuildFrom[CC[X],B,To2])(To, To2)
scala> partition(List(1,"two", 3)) {
| case i: Int => Left(i)
| case x => Right(x)
| }
res5: (List[Int], List[Any]) = (List(1, 3),List(two))
scala> partition(Vector(1,"two", 3)) {
| case i: Int => Left(i)
| case x => Right(x)
| }
res6: (scala.collection.immutable.Vector[Int], scala.collection.immutable.Vector[Any]) = (Vector(1, 3),Vector(two))
Just one note: The partition method is similar, but we need to capture a few types:
X -> The original type for items in the collection.
A -> The type of items in the left partition
B -> The type of items in the right partition
CC -> The "specific" type of the collection (Vector, List, Seq etc.) This must be higher-kinded. We could probably work around some type-inference issues (see Adrian's response here: http://suereth.blogspot.com/2010/06/preserving-types-and-differing-subclass.html ), but I was feeling lazy ;)
To -> The complete type of collection on the left hand side
To2 -> The complete type of the collection on the right hand side
Finally, the funny "CanBuildFrom" implicit paramters are what allow us to construct specific types, like List or Vector, generically. They are built into to all the core library collections.
Ironically, the entire reason for the CanBuildFrom magic is to handle BitSets correctly. Because I require CC to be higher kinded, we get this fun error message when using partition:
scala> partition(BitSet(1,2, 3)) {
| case i if i % 2 == 0 => Left(i)
| case i if i % 2 == 1 => Right("ODD")
| }
<console>:11: error: type mismatch;
found : scala.collection.BitSet
required: ?CC[ ?X ]
Note that implicit conversions are not applicable because they are ambiguous:
both method any2ArrowAssoc in object Predef of type [A](x: A)ArrowAssoc[A]
and method any2Ensuring in object Predef of type [A](x: A)Ensuring[A]
are possible conversion functions from scala.collection.BitSet to ?CC[ ?X ]
partition(BitSet(1,2, 3)) {
I'm leaving this open for someone to fix if needed! I'll see if I can give you a solution that works with BitSet after some more play.
Use list.partition:
scala> val l = List(1, 2, 3)
l: List[Int] = List(1, 2, 3)
scala> val (even, odd) = l partition { _ % 2 == 0 }
even: List[Int] = List(2)
odd: List[Int] = List(1, 3)
EDIT
For partitioning by type, use this method:
def partitionByType[X, A <: X](list: List[X], typ: Class[A]):
Pair[List[A], List[X]] = {
val as = new ListBuffer[A]
val notAs = new ListBuffer[X]
list foreach {x =>
if (typ.isAssignableFrom(x.asInstanceOf[AnyRef].getClass)) {
as += typ cast x
} else {
notAs += x
}
}
(as.toList, notAs.toList)
}
Usage:
scala> val (a, b) = partitionByType(List(1, 2, "three"), classOf[java.lang.Integer])
a: List[java.lang.Integer] = List(1, 2)
b: List[Any] = List(three)
If the list only contains subclasses of AnyRef, becaus of the method getClass. You can do this:
scala> case class Person(name: String)
defined class Person
scala> case class Pet(name: String)
defined class Pet
scala> val l: List[AnyRef] = List(Person("Walt"), Pet("Donald"), Person("Disney"), Pet("Mickey"))
l: List[AnyRef] = List(Person(Walt), Pet(Donald), Person(Disney), Pet(Mickey))
scala> val groupedByClass = l.groupBy(e => e.getClass)
groupedByClass: scala.collection.immutable.Map[java.lang.Class[_],List[AnyRef]] = Map((class Person,List(Person(Walt), Person(Disney))), (class Pet,List(Pet(Donald), Pet(Mickey))))
scala> groupedByClass(classOf[Pet])(0).asInstanceOf[Pet]
res19: Pet = Pet(Donald)
Starting in Scala 2.13, most collections are now provided with a partitionMap method which partitions elements based on a function returning either Right or Left.
That allows us to pattern match a given type (here Person) that we transform as a Right in order to place it in the right List of the resulting partition tuple. And other types can be transformed as Lefts to be partitioned in the left part:
// case class Person(name: String)
// case class Pet(name: String)
val (pets, persons) =
List(Person("Walt"), Pet("Donald"), Person("Disney")).partitionMap {
case person: Person => Right(person)
case pet: Pet => Left(pet)
}
// persons: List[Person] = List(Person(Walt), Person(Disney))
// pets: List[Pet] = List(Pet(Donald))