I have an enum like this:
object Animals extends Enumeration {
type Animals = Value
val Monkey = Value("Monkey")
val Lion = Value("Lion")
val Dog = Value("Dog")
val Cat = Value("Cat")
}
and I need to pick at random an element from this enumeration. How can i efficiently do this in scala?
Less than a minute with the documentation shows
final def maxId: Int
The one higher than the highest integer amongst those used to identify values in this enumeration.
and
final def apply(x: Int): Value
The value of this enumeration with given id x
So
Animals(scala.util.Random.nextInt(Animals.maxId))
//> res0: recursion.recursion.Animals.Value = Monkey
(assuming all values are used, and you didn't pass in an initial value to the constructor)
Or you could enumerate the values with Animals.values and then refer to this question
Related
I'm trying to access variables of an object by using strings whose values are determined at run time.
Basically the object is used as a dictionary, and now I want to dynamically poll values from that dictionary
A simplified example:
object Something extends scala.AnyRef {
final val zero = 0
final val one = 1
final val two = 2
}
I would then principally like to do the following
Somthing."zero"
and get 0 in return.
Ideally I would like to use scala reflection for this
WARNING: Please heed Jörg W Mittag's advice before following my answer:
Scala heavily prefers type-safe compile-time reflection. So, using
reflection in this way is not the Scala way. The Scala way would
probably be to use compile-time reflection to generate all those
pattern match cases
Using reflection Something.getClass.getDeclaredMethods.foreach(println) gives:
public final int example.Something$.zero()
public final int example.Something$.one()
public final int example.Something$.two()
so to get the names we can do
Something.getClass.getDeclaredMethods.map(_.getName) // Array(zero,one,two)
and to get the value
Something.getClass.getMethod("zero").invoke(Something) // 0
Defining the following implicit class
implicit class AccessMembersByReflectionName(something: Something.type) {
def get(name: String): AnyRef = {
Something.getClass.getMethod(name).invoke(Something)
}
}
cleans up the call site
Something.get("zero") // 0
As #n.m. already pointed, if you only want to retrieve values of the same type given an string key, you should use a Dictionary.
However, if for some reason you still need an object, you could accomplish something similar of what you want with this method.
Object Something {
val Zero: Int = 0
val One: Int = 1
val Three: Int = 3
def getValueByString(valName: String): Int = valName.toLowerCase match {
case "zero" => Zero
case "one" => One
case "three" => Three
}
}
EDIT
I just read that you can modify the object, you still can make a function that will receive the object and the valName as a string.
Supposedly I have the following
case class test {
a:string
b: string
c: Int
d: Int }
var temp = List(test("lol","lel",1,2))
var total = List(test)
total = total:::temp //this doesn't work because temp is of type [test] while total is of type [test.type]
I do not understand the difference.
The reason I want to use this is that I want to have a running list where elements will be conditionally added in a loop.
So in this instance, total should initially an empty list which takes test objects. How do I do this?
Any feedback is appreciated!
Let me begin by explaining few basics about Scala.
In Scala, you define a class like following,
scala> class Demo(a: String, b: Int) {
| def stringify: String = a + " :: " + b
| }
// defined class Demo
You can think of a class as a blueprint given to Scala which will be used to create instances of that class. Here, every instance of class Demo will have two properties - a which will be a String and b which will be an Int and one method - stringify which will return a String.
scala> val demo1 = new Demo("demo1", 1)
// demo1: Demo = Demo#21eee94f
scala> demo1.getClass
// res0: Class[_ <: Demo] = class Demo
Here demo1 is an instance of class Demo and has type Demo.
Scala also has a concept of object which are instances of specially generated inner classes.
scala> object OtherDemo {
| val a: Int = 10
| }
// defined object OtherDemo
scala> DemoObject.getClass
// res2: Class[_ <: OtherDemo.type] = class OtherDemo$
Here OtherDemo will be the only instance of that specially generated class OtherDemo$ and has type OtherDemo.type.
And then there are case class in Scala
scala> case class AnotherDemo(a: Int)
// defined class AnotherDemo
This will create not only a class AnotherDemo but also an object AnotherDemo which we call a companion object. Which is equivalent to,
class AnotherDemo(a: Int)
object AnotherDemo {
def apply(a: Int): AnotherDemo = new AnotherDemo(a)
def unapply(anotherDemo: AnotherDemo): Option[Int] = Some(anotherDemo.a)
// And many more utility functions
}
We call this object AnotherDemo as companion object of class AnotherDemo.
We can create instances of AnotherDemo in two ways,
// By using new keyword, as we can do for any class
scala> val anotherDemo1 = new AnotherDemo(1)
// anotherDemo1: AnotherDemo = AnotherDemo(1)
// Or we can use `apply` method provided by companion object
scala> val anotherDemo2 = AnotherDemo(2)
// anotherDemo2: AnotherDemo = AnotherDemo(2)
scala> anotherDemo1.getClass
// res6: Class[_ <: AnotherDemo] = class AnotherDemo
scala> anotherDemo2.getClass
// res7: Class[_ <: AnotherDemo] = class AnotherDemo
scala> AnotherDemo.getClass
// res8: Class[_ <: AnotherDemo.type] = class AnotherDemo$
Also, In Scala your class names should start with Capital Letter. This enables you to easily distinguish them from instance variable which should start with small letters. This helps you in avoiding confusion.
Now, it is supposed to be a: String and not a: string.
scala> case class Test(
| a: String,
| b: String,
| c: Int,
| d: Int
| )
// defined class Test
Now, when you write,
scala> var temp = List(Test("lol","lel",1,2))
// temp: List[Test] = List(Test(lol,lel,1,2))
It is actually equivalent to,
var temp = List.apply(Test.apply("lol","lel",1,2))
Or,
val test1 = Test.apply("lol","lel",1,2)
var temp = List.apply(test1)
The Test in Test.apply is not your class Test but the companion object Test. And calling Test.apply returns an instance of class Test which is being passed to List.apply to finally get a List of type List[Test] containing this instance of Test.
But when you write this,
scala> var total = List(Test)
// total: List[Test.type] = List(Test)
You are creating a List of type List[Test.type] containing that companion object of Test.
Focus on total: List[Test.type] part... this means that total is a variable of type List[Test.type] which means that it will want to point to a value/instance of type List[Test.type], and will refuse to point to anything else.
Now... you are trying to do this,
total = total ::: temp
Which is equivalent to,
val x = total ::: temp
total = x
which is actually,
val x = temp.:::(total)
total = x
Now look at this val x = total ::: temp,
scala> val x = total ::: temp
// x: List[Serializable] = List(Test, Test(lol,lel,1,2))
You see... this x is of type List[Serializable]. So when you try total = x, you will get following error,
scala> total = x
// <console>:13: error: type mismatch;
// found : List[Serializable]
// required: List[Test.type]
// total = x
// ^
Which means that total required a List[Test.type] but you are giving it a List[Serializable].
You are looking for total = List.empty[test] rather than List(test).
The former creates an empty list of type List[test], the latter is a one-element list of type List[test.type] (test.type is not the same as test - it is its own object, representing the type of instances of test).
Also, do not use var. They are evil, and not really needed in scala in 99% of uses-cases. Just pretend that keyword does not exist at all, until you get enough of a grip at the language to be able to confidently distinguish the other 1%.
When you do this:
var total = List(test)
You are not initializing the object test, that's why the type of the list is Test.type, you are only creating a list of a template for an object.
When you do this instead:
var temp = List(test("lol","lel",1,2))
Yo have the object instantiated from a template (a class, in this case, Test) so the type of temp is List[Temp].
So, if you do something like:
val template = Test
Then the type of t is Test.type
And you can instantiate an object Test from template like this:
val instantiated = template("lol","lel",1,2)
As you see in your example, the total variable is just a list of templates from where you can instantiate objects while the temp variable is a list of objects of type Test.
To create an empty list of objects of type Test you just have to do:
val t: List[Test] = List.empty
Then you can add any object (of type Test) to this list
Based on your description ('I want to have a running list where elements will be conditionally added in a loop'), my understanding is that you are getting Test objects from some source and want to put them in a list but only if they meet certain criteria. We can express this requirement as a method. For convenience, we'll put the method in the Test companion object. Companion objects are a place to put things that should be available without having to instantiate any objects.
case class Test(a: String, b: String, c: Int, d: Int)
object Test {
/**
Returns a list of `Test` objects that pass the given criteria.
#param tests some source of tests that we can loop over one at a
time.
#param condition checks whether a `Test` object should go into our
output list.
*/
def runningList(
tests: Iterable[Test])(condition: Test => Boolean): List[Test] =
tests.filter(condition).toList
}
You can use it like (e.g.):
Test.runningList(testsSource) { test => test.c > 0 && test.d < 100 }
As you can see here, I've used a few Scala features, like iterables and their list conversion method, multi-parameter-list methods, first-class functions, function-as-last-argument DSL, and so on. If you have more questions on these topics I'd recommend a Scala tutorial.
I have been playing lately with compound types and I recently was trying the following code:
import scala.reflect._
object Main {
def main(args: Array[String]) {
val a1 = classTag[Int with String with Double].newArray(3)
println(a1.mkString(" "))
val a2 = classTag[String with Int with Double].newArray(3)
println(a2.mkString(" "))
val a3 = classTag[Double with Int with String].newArray(3)
println(a3.mkString(" "))
}
}
With the following output:
0 0 0
null null null
0.0 0.0 0.0
It results a bit strange to me. Each of the array elements has access to the methods of the three types: Int, String and Double. What is happening exactly behind scene here? The compound types are actually instances of the first type? Can a compound type being instanced explicitly? Their use case is only for when the types composing the compound are related through inheritance and so on? Thanks.
P.S.: I'm using Scala 2.11.4
What is happening exactly behind scene here? The compound types are actually instances of the first type?
Looking at the newArray method as defined for ClassTag:
override def newArray(len: Int): Array[T] =
runtimeClass match {
case java.lang.Byte.TYPE => new Array[Byte](len).asInstanceOf[Array[T]]
case java.lang.Integer.TYPE => new Array[Int](len).asInstanceOf[Array[T]]
/* snip */
case _ => java.lang.reflect.Array.newInstance(runtimeClass, len).asInstanceOf[Array[T]]
}
And then your type:
scala> classTag[Int with String with Double].runtimeClass
res4: Class[_] = int
It seems pretty clear how it's arriving at the conclusion to use the first type. The runtimeClass of Int with String with Double is Int, and the newArray method uses the runtimeClass to construct the new Array. So the Array is filled with default Int values. Likewise for the other order combinations.
Why is the runtime class Int? Well, Int with String with Double isn't an actual class, but Int is. The compiler's choice of which class to use can't just be arbitrary, so why not the first?
Can a compound type be instanced explicitly?
I'm not sure what you mean by this. If you think about it, the compiler kind of has to favor one type in this composition. What would an explicit Int with String with Double look like? What about Int with String with Double with Product with Process ? I don't know, either.
Each of the array elements has access to the methods of the three types: Int, String and Double
They do, and yet they don't.
scala> val arr = classTag[Int with Process].newArray(3)
arr: Array[Int with Process] = Array(0, 0, 0)
scala> arr(0).exitValue()
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Process
You're really just tricking the compiler into believing you have an Array of these types, when in fact you don't (and can't, because nothing can be a sub-type of both Int and Process).
Their use case is only for when the types composing the compound are related through inheritance and so on?
Pretty much, yes. I can't think if any situation in which you'd ever want to try to build these types directly. Their main use case is to guarantee that a type inherits from other specific types.
For example, a method that requires that a parameter inherit methods from two traits:
trait Hello { def hello = println("Hello") }
trait Bye { def bye = println("Bye") }
def greet(hb: Hello with Bye): Unit = { hb.hello; hb.bye }
class A extends Hello
class B extends Hello with Bye
scala> greet(new A)
<console>:15: error: type mismatch;
found : A
required: Hello with Bye
greet(new A)
^
scala> greet(new B)
Hello
Bye
Is there a way to call a function with arguments from a list? The equivalent in Python is sum(*args).
// Scala
def sum(x: Int, y: Int) = x + y
val args = List(1, 4)
sum.???(args) // equivalent to sum(1, 4)
sum(args: _*) wouldn't work here.
Don't offer change the declaration of the function anyhow. I'm acquainted with a function with repeated parameters def sum(args: Int*).
Well, you can write
sum(args(0), args(1))
But I assume you want this to work for any list length? Then you would go for fold or reduce:
args.reduce(sum) // args must be non empty!
(0 /: args)(sum) // aka args.foldLeft(0)(sum)
These methods assume a pair-wise reduction of the list. For example, foldLeft[B](init: B)(fun: (B, A) => B): B reduces a list of elements of type A to a single element of type B. In this example, A = B = Int. It starts with the initial value init. Since you want to sum, the sum of an empty list would be zero. It then calls the function with the current accumulator (the running sum) and each successive element of the list.
So it's like
var result = 0
result = sum(result, 1)
result = sum(result, 4)
...
The reduce method assumes that the list is non-empty and requires that the element type doesn't change (the function must map from two Ints to an Int).
I wouldn't recommend it for most uses since it's a bit complicated and hard to read, bypasses compile-time checks, etc., but if you know what you're doing and need to do this, you can use reflection. This should work with any arbitary parameter types. For example, here's how you might call a constructor with arguments from a list:
import scala.reflect.runtime.universe
class MyClass(
val field1: String,
val field2: Int,
val field3: Double)
// Get our runtime mirror
val runtimeMirror = universe.runtimeMirror(getClass.getClassLoader)
// Get the MyClass class symbol
val classSymbol = universe.typeOf[MyClass].typeSymbol.asClass
// Get a class mirror for the MyClass class
val myClassMirror = runtimeMirror.reflectClass(classSymbol)
// Get a MyClass constructor representation
val myClassCtor = universe.typeOf[MyClass].decl(universe.termNames.CONSTRUCTOR).asMethod
// Get an invokable version of the constructor
val myClassInvokableCtor = myClassMirror.reflectConstructor(myClassCtor)
val myArgs: List[Any] = List("one", 2, 3.0)
val myInstance = myClassInvokableCtor(myArgs: _*).asInstanceOf[MyClass]
I have an enum Fruit defined as:
object Fruit extends Enumeration {
val Apple, Banana, Cherry = Value
}
Now printing values of this enum, on Scala 2.7.x gives:
scala> Fruit foreach println
line1$object$$iw$$iw$Fruit(0)
line1$object$$iw$$iw$Fruit(1)
line1$object$$iw$$iw$Fruit(2)
However the same operation on Scala 2.8 gives:
scala> Fruit foreach println
warning: there were deprecation warnings; re-run with -deprecation for details
Apple
Banana
Cherry
My question is:
How is the method toString in Enumeration in Scala 2.8 implemented? I tried looking into the source of Enumeration but couldn't understand anything.
The implementation is based on the Java reflection API.
If you define val for the enum values:
object Fruit extends Enumeration {
val Apple, Banana, Cherry = Value
}
There are methods for the val in the class Fruit:
scala> Fruit.getClass.getMethods filter (_.getName.contains("Apple")) foreach println
public scala.Enumeration$Value line10$object$$iw$$iw$Fruit$.Apple()
toString calls Enumeration.this.nameOf(i) if the name is not explicitly set. This method will try to find all methods in the enumeration class returning Value instances.
val methods = getClass.getMethods
for (m <- methods
if (classOf[Value].isAssignableFrom(m.getReturnType) &&
!java.lang.reflect.Modifier.isFinal(m.getModifiers) &&
m.getParameterTypes.isEmpty &&
isValDef(m)))
These are the methods of the Fruit class.
It then takes the name of the methods and the ids of enum values to build a map id -> name and retrieves the name from the map with the id of enum value.
val name = m.getName
// invoke method to obtain actual `Value` instance
val value = m.invoke(this)
// invoke `id` method
val idMeth = classOf[Val].getMethod("id")
val id: Int = idMeth.invoke(value).asInstanceOf[java.lang.Integer].intValue()
This implementation can be easily broken if you define a enum like this:
object X extends Enumeration {
val Y = Value
}
object Fruit extends Enumeration {
val x = X.Y
val A,B,C = Value
}
This Fruit.value returns object$Fruit.ValueSet(x, B, C) not object$Fruit.ValueSet(A, B, C).
In Scala 2.8.0.RC2 you can find the implementation of toString in the inner class Val in line 273 of Enumeration.scala. The instances of Val are instantiated through the Value method in line 192. Currently I don't understand how the names (Apple, Banana, ...) are extracted. May somebody can help out?