So i have this Enumeration:
object MyEnum extends Enumeration {
val a = Value(0, "Valid")
val b = Value(1, "Valid")
val c = Value(2, "Not Valid")
val d = Value(3, "Not Valid")
}
This Enumeration contains 2 types: Valid and Not valid.
Is it possible to select random MyEnum by value ?
For example i want to select a random MyEnum that is Valid.
Even when Yuval answer is correct and the solution will work, using Enumeration for encoding additional property is not recommended. By using name field for encoding the type as "Valid" or "Not Valid" (or any other classification) of your Values you are loosing build in ability of Enumeration class to reconstruct the enum value instances from String via .withName method:
// result will be always `a` for "Valid" and `b` for "Not Valid"
// it will throw an NoSuchElementException for any other string
MyEnum.withName(someString)
To put it simple when you are simply misusing name field for classification of your enum value instances. If this is not a problem in your code you're a lucky guy, but anyway document the misuse very precisely.
Enumeration was intended to express simple values, which have an index and can have nice human readable name. That's it, no more, no less.
Rule of thumb is, that when you have an enum which needs another fields it is better to model that using sealed hierarchy of case objects or case classes. Something like that (just an example for your particular case):
// Hierarchy is sealed, thus you will get can pattern match with check for exhaustiveness
sealed trait MyEnum {
def id: Int
def name: String
def valid: Boolean
}
// Helper case class, which allows to not define
private case class Value(id: Int, name: String, valid: Boolean) extends MyEnum
object MyEnum {
// Your values
val A: MyEnum = Value(0, "My A", true)
val B: MyEnum = Value(1, "My B", true)
val C: MyEnum = Value(0, "My A", false)
val D: MyEnum = Value(1, "My B", false)
// Re-implementation of methods contained in Enumeration, pick what you need
val values: Seq[MyEnum] = Seq(A, B, C, D)
// You can implement your own semantics, e.g. no Exception rather Option
def withName(name: String): Option[MyEnum] = values.find( _.name == name )
// Methods already for your example
val valids: Seq[MyEnum] = values.filter( _.valid )
// Or with randomization build in to enum
def randomValid: MyEnum = valids(util.Random.nextInt(valids.length))
}
In addition you will get more type safety:
// More type safety, fn simple does not compile
def fn(value: MyEnum) = value match {
case MyEnum.A => true
}
<console>:14: warning: match may not be exhaustive.
It would fail on the following input: Value(_, _, _)
def fn(value: MyEnum) = value match {
^
fn: (value: MyEnum)Boolean
Your milage may vary, because possibilities for writing an enum in Scala are almost endless :) In my example I'm showing only one of many possible implementations. If you have many values above mentioned approach can be impractical.
To know more about drawbacks of using Enumeration see "Scala Enumerations" blog post. Beware that solution in the end of article is not silver bullet and has problems with pattern matching exhaustiveness checking as Enumeration does.
Enjoy
This should do what you need:
val valids = MyEnum.values.filter { _.toString.equalsIgnoreCase("Valid") }.toSeq
val selected = valids(util.Random.nextInt(valids.length))
println(s"Selected $selected with id: ${selected.id}")
You can use scala Random:
scala.util.Random.shuffle(MyEnum.values.toList).find(_.toString.equalsIgnoreCase("Valid"))
and it will return an Option
Related
I want to be able to create a class/trait that behaves somewhat like an enumeration (HEnum in the first snippet below). I can't use a plain enumeration because each enum value could have a different type (though the container class will be the same): Key[A]. I'd like to be able to construct the enum roughly like this:
class Key[A](val name: String)
object A extends HEnum {
val a = new Key[String]("a")
val b = new Key[Int]("b")
val c = new Key[Float]("c")
}
And then I'd like to be able to perform more or less basic HList operations like:
A.find[String] // returns the first element with type Key[String]
A.find("b") // returns the first element with name "b", type should (hopefully) be Key[Int]
So far I've been playing with an HList as the underlying data structure, but constructing one with the proper type has proven difficult. My most successful attempt looks like this:
class Key[A](val name: String)
object Key {
def apply[A, L <: HList](name: String, l: L): (Key[A], Key[A] :: L) = {
val key = new Key[A](name)
(key, key :: l)
}
}
object A {
val (a, akeys) = Key[String, HNil]("a", HNil)
val (b, bkeys) = Key[Int, Key[String] :: HList]("b", akeys)
val (c, ckeys) = Key[Float, Key[Int] :: HList]("c", bkeys)
val values = ckeys // use this for lookups, etc
def find[A]: Key[A] = values.select[A]
def find[A](name: String): Key[A] = ...
}
The problem here is that the interface is clunky. Adding a new value anywhere besides the end of the list of values is error prone and no matter what, you have to manually update values any time a new value is introduced. My solution without HList involved a List[Key[_]] and error prone/unsafe casting to the proper type when needed.
EDIT
I should also mention that the enum example found here is not particularly helpful to me (although, if that can be adapted, then great). The added compiler checks for exhaustive pattern matches are nice (and I would ultimately want that) but this enum still only allows a homogeneous collection of enum values.
I'm wondering the best way to achieve type-safety with my code when various values might all be Strings or Doubles, but are still incompatible. For example, I might have units in pounds and kilograms, but I should be forbidden to assign one to the other. Likewise, I might have a person ID as a String and a lookup table of animal IDs as a Map[String,Int], but I should be forbidden to look a person up in the animals table.
Conceptually I'm looking for something like this:
class PersonId extends String
class AnimalId extends String
var p : PersonId = "1234"
var tab : Map[AnimalId,Int] = Map("foo" -> 5, "bar" -> 6)
tab.get(p) // Want this to cause a compile error
But there are several problems making that not work. Suggestions for something that fits the spirit?
I'd use value classes for this. It behaves pretty much the same as a regular case class but the compiler places some restrictions on it, and generally it never has to actually waste time/memory creating the wrapper object - it can usually use the underlying value directly.
case class Person(value: String) extends AnyVal
case class Animal(value: String) extends AnyVal
You cannot extend String for obvious reasons. I suggest using case classes for that:
case class PersonId(id:String)
case class AnimalId(id:String)
Syntax gets a little bit more complicated, but not that much. And you can use case classes easily when pattern matching!
var p: PersonId = PersonId("1234")
var tab: Map[AnimalId,Int] = Map(AnimalId("foo") -> 5, AnimalId("bar") -> 6)
One simple solution is just use
case class PersonId(id:String)
case class AnimalId(id:String)
This solution is usually good enough.
If you want to play a bit with Scala's type system you can do something like that -
trait Person
trait Animal
case class IdOf[T](s: String) extends AnyVal
implicit def string2idOf[T](s: String): IdOf[T] = IdOf(s)
var p: IdOf[Person] = "1234"
var tab: Map[IdOf[Animal], Int] = Map(("foo": IdOf[Animal]) -> 5, ("bar": IdOf[Animal]) -> 6)
tab.get(p)
// Error:(25, 11) type mismatch;
// found : com.novak.Program.IdOf[com.novak.Program.Person]
// required: com.novak.Program.IdOf[com.novak.Program.Animal]
// tab.get(p)
^
Just another option is Scalaz's tagged type. Might be useful in some cases as it alows you to combine your type with some other type without creating new instance of this other type (value classes do simmilar for primitive types); however new Scalaz requires to explicitly unbox it (with Tag.unwrap), so not much useful as one can expect.
Example:
trait Person
val Person = Tag.of[Person]
val person = Prsn("Me")
Person.unwrap(person)
trait Animal
val Animal = Tag.of[Animal]
val animal = Anml("Me")
Animal.unwrap(person) //error
Animal.unwrap(animal)
Just quotes:
Suppose we want a way to express mass using kilogram, because kg is
the international standard of unit. Normally we would pass in Double
and call it a day, but we can’t distinguish that from other Double
values. Can we use case class for this?
case class KiloGram(value: Double)
Although it does adds type safety,
it’s not fun to use because we have to call x.value every time we need
to extract the value out of it. Tagged type to the rescue.
scala> sealed trait KiloGram defined trait KiloGram
scala> def KiloGram[A](a: A): A ## KiloGram = Tag[A, KiloGram](a)
KiloGram: [A](a: A)scalaz.##[A,KiloGram]
scala> val mass = KiloGram(20.0) mass: scalaz.##[Double,KiloGram] =
20.0
scala> sealed trait JoulePerKiloGram
defined trait JoulePerKiloGram
scala> def JoulePerKiloGram[A](a: A): A ## JoulePerKiloGram = Tag[A, JoulePerKiloGram](a)
JoulePerKiloGram: [A](a: A)scalaz.##[A,JoulePerKiloGram]
scala> def energyR(m: Double ## KiloGram): Double ## JoulePerKiloGram =
JoulePerKiloGram(299792458.0 * 299792458.0 * Tag.unsubst[Double, Id, KiloGram](m))
energyR: (m: scalaz.##[Double,KiloGram])scalaz.##[Double,JoulePerKiloGram]
scala> energyR(mass)
res4: scalaz.##[Double,JoulePerKiloGram] = 1.79751035747363533E18
scala> energyR(10.0)
<console>:18: error: type mismatch;
found : Double(10.0)
required: scalaz.##[Double,KiloGram]
(which expands to) AnyRef{type Tag = KiloGram; type Self = Double}
energyR(10.0)
^
I have a list of simple scala case class instances and I want to print them in predictable, lexicographical order using list.sorted, but receive "No implicit Ordering defined for ...".
Is there exist an implicit that provides lexicographical ordering for case classes?
Is there simple idiomatic way to mix-in lexicographical ordering into case class?
scala> case class A(tag:String, load:Int)
scala> val l = List(A("words",50),A("article",2),A("lines",7))
scala> l.sorted.foreach(println)
<console>:11: error: No implicit Ordering defined for A.
l.sorted.foreach(println)
^
I am not happy with a 'hack':
scala> l.map(_.toString).sorted.foreach(println)
A(article,2)
A(lines,7)
A(words,50)
My personal favorite method is to make use of the provided implicit ordering for Tuples, as it is clear, concise, and correct:
case class A(tag: String, load: Int) extends Ordered[A] {
// Required as of Scala 2.11 for reasons unknown - the companion to Ordered
// should already be in implicit scope
import scala.math.Ordered.orderingToOrdered
def compare(that: A): Int = (this.tag, this.load) compare (that.tag, that.load)
}
This works because the companion to Ordered defines an implicit conversion from Ordering[T] to Ordered[T] which is in scope for any class implementing Ordered. The existence of implicit Orderings for Tuples enables a conversion from TupleN[...] to Ordered[TupleN[...]] provided an implicit Ordering[TN] exists for all elements T1, ..., TN of the tuple, which should always be the case because it makes no sense to sort on a data type with no Ordering.
The implicit ordering for Tuples is your go-to for any sorting scenario involving a composite sort key:
as.sortBy(a => (a.tag, a.load))
As this answer has proven popular I would like to expand on it, noting that a solution resembling the following could under some circumstances be considered enterprise-grade™:
case class Employee(id: Int, firstName: String, lastName: String)
object Employee {
// Note that because `Ordering[A]` is not contravariant, the declaration
// must be type-parametrized in the event that you want the implicit
// ordering to apply to subclasses of `Employee`.
implicit def orderingByName[A <: Employee]: Ordering[A] =
Ordering.by(e => (e.lastName, e.firstName))
val orderingById: Ordering[Employee] = Ordering.by(e => e.id)
}
Given es: SeqLike[Employee], es.sorted() will sort by name, and es.sorted(Employee.orderingById) will sort by id. This has a few benefits:
The sorts are defined in a single location as visible code artifacts. This is useful if you have complex sorts on many fields.
Most sorting functionality implemented in the scala library operates using instances of Ordering, so providing an ordering directly eliminates an implicit conversion in most cases.
object A {
implicit val ord = Ordering.by(unapply)
}
This has the benefit that it is updated automatically whenever A changes. But, A's fields need to be placed in the order by which the ordering will use them.
To summarize, there are three ways to do this:
For one-off sorting use .sortBy method, as #Shadowlands have showed
For reusing of sorting extend case class with Ordered trait, as #Keith said.
Define a custom ordering. The benefit of this solution is that you can reuse orderings and have multiple ways to sort instances of the same class:
case class A(tag:String, load:Int)
object A {
val lexicographicalOrdering = Ordering.by { foo: A =>
foo.tag
}
val loadOrdering = Ordering.by { foo: A =>
foo.load
}
}
implicit val ord = A.lexicographicalOrdering
val l = List(A("words",1), A("article",2), A("lines",3)).sorted
// List(A(article,2), A(lines,3), A(words,1))
// now in some other scope
implicit val ord = A.loadOrdering
val l = List(A("words",1), A("article",2), A("lines",3)).sorted
// List(A(words,1), A(article,2), A(lines,3))
Answering your question Is there any standard function included into the Scala that can do magic like List((2,1),(1,2)).sorted
There is a set of predefined orderings, e.g. for String, tuples up to 9 arity and so on.
No such thing exists for case classes, since it is not easy thing to roll off, given that field names are not known a-priori (at least without macros magic) and you can't access case class fields in a way other than by name/using product iterator.
The unapply method of the companion object provides a conversion from your case class to an Option[Tuple], where the Tuple is the tuple corresponding to the first argument list of the case class. In other words:
case class Person(name : String, age : Int, email : String)
def sortPeople(people : List[Person]) =
people.sortBy(Person.unapply)
The sortBy method would be one typical way of doing this, eg (sort on tag field):
scala> l.sortBy(_.tag)foreach(println)
A(article,2)
A(lines,7)
A(words,50)
Since you used a case class you could extend with Ordered like such:
case class A(tag:String, load:Int) extends Ordered[A] {
def compare( a:A ) = tag.compareTo(a.tag)
}
val ls = List( A("words",50), A("article",2), A("lines",7) )
ls.sorted
My personal favorite method is using the SAM(Single abstraction method) with 2.12 as mentioned over the below example:
case class Team(city:String, mascot:String)
//Create two choices to sort by, city and mascot
object MyPredef3 {
// Below used in 2.11
implicit val teamsSortedByCity: Ordering[Team] = new Ordering[Team] {
override def compare(x: Team, y: Team) = x.city compare y.city
}
implicit val teamsSortedByMascot: Ordering[Team] = new Ordering[Team] {
override def compare(x: Team, y: Team) = x.mascot compare y.mascot
}
/*
Below used in 2.12
implicit val teamsSortedByCity: Ordering[Team] =
(x: Team, y: Team) => x.city compare y.city
implicit val teamsSortedByMascot: Ordering[Team] =
(x: Team, y: Team) => x.mascot compare y.mascot
*/
}
object _6OrderingAList extends App {
//Create some sports teams
val teams = List(Team("Cincinnati", "Bengals"),
Team("Madrid", "Real Madrid"),
Team("Las Vegas", "Golden Knights"),
Team("Houston", "Astros"),
Team("Cleveland", "Cavaliers"),
Team("Arizona", "Diamondbacks"))
//import the implicit rule we want, in this case city
import MyPredef3.teamsSortedByCity
//min finds the minimum, since we are sorting
//by city, Arizona wins.
println(teams.min.city)
}
I'm trying to get a better understanding of the correct usage of apply and unapply methods.
Considering an object that we want to serialize and deserialize, is this a correct usage (i.e. the Scala way) of using apply and unapply?
case class Foo
object Foo {
apply(json: JValue): Foo = json.extract[Foo]
unapply(f: Foo): JValue = //process to json
}
Firstly, apply and unapply are not necessarily opposites of each other. Indeed, if you define one on a class/object, you don't have to define the other.
apply
apply is probably the easier to explain. Essentially, when you treat your object like a function, apply is the method that is called, so, Scala turns:
obj(a, b, c) to obj.apply(a, b, c).
unapply
unapply is a bit more complicated. It is used in Scala's pattern matching mechanism and its most common use I've seen is in Extractor Objects.
For example, here's a toy extractor object:
object Foo {
def unapply(x : Int) : Option[String] =
if(x == 0) Some("Hello, World") else None
}
So now, if you use this is in a pattern match like so:
myInt match {
case Foo(str) => println(str)
}
Let's suppose myInt = 0. Then what happens? In this case Foo.unapply(0) gets called, and as you can see, will return Some("Hello, World"). The contents of the Option will get assigned to str so in the end, the above pattern match will print out "Hello, world".
But what if myInt = 1? Then Foo.unapply(1) returns None so the corresponding expression for that pattern does not get called.
In the case of assignments, like val Foo(str) = x this is syntactic sugar for:
val str : String = Foo.unapply(x) match {
case Some(s) => s
case None => throw new scala.MatchError(x)
}
The apply method is like a constructor which takes arguments and creates an object, whereas the unapply takes an object and tries to give back the arguments.
A simple example:
object Foo {
def apply(name: String, suffix: String) = name + "." + suffix
def unapply(name: String): Option[(String, String)] = {
//simple argument extractor
val parts = name.split("\\.")
if (parts.length == 2) Some(parts(0), parts(1)) else None
}
}
when you call
val file = Foo("test", "txt")
It actually calls Foo.apply("test", "txt") and returns test.txt
If you want to deconstruct, call
val Foo(name) = file
This essentially invokes val name = Foo.unapply(file).get and returns (test, txt) (normally use pattern matching instead)
You can also directly unpack the tuple with 2 variables, i.e.
scala> val Foo(name, suffix) = file
val name: String = test
val suffix: String = txt
BTW, the return type of unapply is Option by convention.
So apply and unapply are just defs that have extra syntax support.
Apply takes arguments and by convention will return a value related to the object's name. If we take Scala's case classes as "correct" usage then the object Foo's apply will construct a Foo instance without needing to add "new". You are free of course to make apply do whatever you wish (key to value in Map, set contains value in Set, and indexing in Seq come to mind).
Unapply, if returning an Option or Boolean can be used in match{} and pattern matching. Like apply it's just a def so can do whatever you dream up but the common usage is to extract value(s) from instances of the object's companion class.
From the libraries I've worked with serialization/deserialization defs tend to get named explicitly. E.g., write/read, show/read, toX/fromX, etc.
If you want to use apply/unapply for this purpose the only thing I'd suggest is changing to
def unapply(f: Foo): Option[JValue]
Then you could do something like:
val myFoo = Foo("""{name: "Whiskers", age: 7}""".asJson)
// use myFoo
val Foo(jval) = myFoo
// use jval
I have an enumeration in scala mapped to strings in JPA. For more comfortable coding, I defined implicit conversions between them. So I now can define value val person.role = "User", - person.role is the enumeration type "User" a String so there's the conversion. But when I try to compare these two, I always get false, because the def equals (arg0: Any) : Boolean takes Any so there's not any conversion triggered. I need some explicit conversion, but my plan was to be able to omit that, what do you think is the best practice | neatest solution here?
Expanding on Thomas's answer, if you're using the comparison to branch, using pattern matching may be more appropriate:
object Role extends Enumeration {
val User = MyValue("User")
val Admin = MyValue("Admin")
def MyValue(name: String): Value with Matching =
new Val(nextId, name) with Matching
// enables matching against all Role.Values
def unapply(s: String): Option[Value] =
values.find(s == _.toString)
trait Matching {
// enables matching against a particular Role.Value
def unapply(s: String): Boolean =
(s == toString)
}
}
You can then use this as follows:
def allowAccess(role: String): Boolean = role match {
case Role.Admin() => true
case Role.User() => false
case _ => throw ...
}
or
// str is a String
str match {
case Role(role) => // role is a Role.Value
case Realm(realm) => // realm is a Realm.Value
...
}
The Value("User") in your Enumeration is of type Val. And I believe it's implementation of equals does not compare the string name of the value. I think one heavy handed way of doing this is creating your own Enumeration and Val so that it returns true if the name match.
But in my code uses, not with JPA, I always convert the string into the MyEnumeration.Value. This is easy with things like:
object E extends Enumeration { val User = Value("User") }
scala> val a = E.withName("User")
a: E.Value = User
Note that when using withName, if the string does not match any name in the enumeration you get an exception.
Then always use the enumeration fields in your comparisons:
scala> a == E.User
res9: Boolean = true
If JPA only returns a string, and there is no way around it. Then I think the best option is to either convert the value to string and match string to string, or upgrade the string to a Val and compare Val. Mixing these types will not work for comparison, unless you you implement some kind of extension to the equals method, and that is tricky.