I want to get a list of inner objects of a scala object. Sample code:
object Outer {
val v = "-"
def d = "-"
object O1
object O2
}
object Main {
def main(args: Array[String]) {
Outer.getClass.getDeclaredMethods.map(_.getName) foreach println // prints d and v
// Outer.getClass.get ... Objects???
}
}
I can find v and d, but how can I find O1 and O2 ?
With the new reflection library in Scala 2.10 (since Milestone 4) it is possible to get the inner objects:
scala> import scala.reflect.runtime.{universe => u}
import scala.reflect.runtime.{universe=>u}
scala> val outer = u.typeOf[Outer.type]
outer: reflect.runtime.universe.Type = Outer.type
scala> val objects = outer.declarations.filter(_.isModule).toList
objects: List[reflect.runtime.universe.Symbol] = List(object O1, object O2)
Object O1 and O2 are nested classes and are not a part of Outer Object.
println(Outer.O1.getClass.getName) //Outer$O1$
println(Outer.getClass.getName) //Outer$
println(Outer.O2.getClass.getName) //Outer$O2$
Related
I've created three classes A,B,C and in each class contains a list of elements , each class also contains a method that prints the elements , I've made a function outside the classes which has a pattern matching to choose which class to Print which takes a parameter of a list of the objects of the classes , my code is working well and can choose which class to print , but my question is what if the order of the objects of the classes in the list is not a,b,c but let's say c,a,b , how can someone then choose to print class A without knowing the order but just typing a ?
object printClass {
class A{
val a:List[Int] = List(1,2,3,4)
def printA(): Unit ={
println("Class A")
println(a)
}
}
class B{
val b:List[String] = List("Adam","Ali","Sara","Yara")
def printB(): Unit ={
println("Class B")
println(b)
}
}
class C{
val c:List[Char] = List('A','S','C','E')
def printC(): Unit ={
println("Class C")
println(c)
}
}
def prtClass(ch:Any): Unit ={
val a = new A()
val b = new B()
val c = new C()
ch match {
case a: A => a.printA()
case b: B => b.printB()
case c: C => c.printC()
case _ => print("Class not found")
}
}
def main(args: Array[String]): Unit = {
val a = new A()
val b = new B()
val c = new C()
val listOfObjects = List(a,b,c)
println("Choose the class to print (A,B,C) : ")
val choice:Int = scala.io.StdIn.readInt()
val ch = listOfObjects(choice)
prtClass(ch)
}
}
TLDR;
Use Map
Instead of using List to store a, b, c objects you could use Map. Keys as letters 'a' , 'b' , 'c' and values as objects a, b, c
val objects: Map[Char, Any] = Map('a' -> a, 'b' -> b, 'c' -> c)
And parse user input as Char
val choice = scala.io.StdIn.readChar()
Now now rest should fall in place. Objects will be fetched based on their association and same will be passed to prtClass function.
You could also define a parent class or trait to your A,B,C classes, so that Map value type can be confined to those types.
I have a simple inner class variable, how do i access it in scala?
class Outer {
class Inner {
var x = 1
}}
object Main {
def main(args: Array[String]): Unit = {
val o = new Outer
val i = new o.Inner
println(i.x)
}
}
The problem is that IntelliJ complains that it cannot resolve x, but when i run the program it works fine.
you can simply use .member_name to access variables in scala.
scala> class Outer {
class Inner {
var x = 1 //it can be val which is immutable
}}
defined class Outer
scala> val o = new Outer
o: Outer = Outer#358b0b42
scala> val i = new o.Inner
i: o.Inner = Outer$Inner#512f2c7d
scala> i.x
res13: Int = 1
since your example has x defined as mutable, you can change the value of x,
scala> i.x = 100
i.x: Int = 100
scala> i.x
res14: Int = 100
See working example - https://scastie.scala-lang.org/prayagupd/C9k9an4ASdaISnohbYQBmA
If you don't really need Outer to be a class, you can define it as singleton,
scala> object Outer {
| class Inner {
| var x = 1 //it can be val which is immutable
| }}
defined object Outer
then, simple instantiate Inner and access variables,
scala> val inner = new Outer.Inner
inner: Outer.Inner = Outer$Inner#4bcdd11
scala> inner.x
res2: Int = 1
Regarding not working on intellij, File | Invalidate Caches/Restart... should work
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.
I'd like to dynamically execute the methods that start with removeAt of the object X at runtime.
How can I do that with the scala.reflect.runtime.universe API described in REFLECTION Environment, Universes, and Mirrors
Here is solution for your problem:
object X {
def aa = 1
def ab = 2
def removeAtX = 3
def bb = 4
def removeAtY = 5
}
val ru = scala.reflect.runtime.universe
val m = ru.runtimeMirror(getClass.getClassLoader)
val im = m.reflect(X)
val l = X.getClass.getMethods.map(_.getName).filter(_ startsWith "removeAt")
val r = l.map(y => ru.typeOf[X.type].declaration(ru.newTermName(y)).asMethod).map(im.reflectMethod(_).apply())
Result:
r: scala.collection.mutable.ArraySeq[Any] = ArraySeq(3, 5)
I'd like to link 2 columns of unique identifiers and be able to get a first column value by a second column value as well as a second column value by a first column value. Something like
Map(1 <-> "one", 2 <-> "two", 3 <-> "three")
Is there such a facility in Scala?
Actually I need even more: 3 columns to select any in a triplet by another in a triplet (individual values will never be met more than once in the entire map). But a 2-column bidirectional map can help too.
Guava has a bimap that you can use along with
import scala.collection.JavaConversions._
My BiMap approach:
object BiMap {
private[BiMap] trait MethodDistinctor
implicit object MethodDistinctor extends MethodDistinctor
}
case class BiMap[X, Y](map: Map[X, Y]) {
def this(tuples: (X,Y)*) = this(tuples.toMap)
private val reverseMap = map map (_.swap)
require(map.size == reverseMap.size, "no 1 to 1 relation")
def apply(x: X): Y = map(x)
def apply(y: Y)(implicit d: BiMap.MethodDistinctor): X = reverseMap(y)
val domain = map.keys
val codomain = reverseMap.keys
}
val biMap = new BiMap(1 -> "A", 2 -> "B")
println(biMap(1)) // A
println(biMap("B")) // 2
Of course one can add syntax for <-> instead of ->.
Here's a quick Scala wrapper for Guava's BiMap.
import com.google.common.{collect => guava}
import scala.collection.JavaConversions._
import scala.collection.mutable
import scala.languageFeature.implicitConversions
class MutableBiMap[A, B] private (
private val g: guava.BiMap[A, B] = new guava.HashBiMap[A, B]()) {
def inverse: MutableBiMap[B, A] = new MutableBiMap[B, A](g.inverse)
}
object MutableBiMap {
def empty[A, B]: MutableBiMap[A, B] = new MutableBiMap()
implicit def toMap[A, B] (x: MutableBiMap[A, B]): mutable.Map[A,B] = x.g
}
I have a really simple BiMap in Scala:
case class BiMap[A, B](elems: (A, B)*) {
def groupBy[X, Y](pairs: Seq[(X, Y)]) = pairs groupBy {_._1} mapValues {_ map {_._2} toSet}
val (left, right) = (groupBy(elems), groupBy(elems map {_.swap}))
def apply(key: A) = left(key)
def apply[C: ClassTag](key: B) = right(key)
}
Usage:
val biMap = BiMap(1 -> "x", 2 -> "y", 3 -> "x", 1 -> "y")
assert(biMap(1) == Set("x", "y"))
assert(biMap("x") == Set(1, 3))
I don't think it exists out of the box, because the generic behavior is not easy to extract
How to handle values matching several keys in a clean api?
However for specific cases here is a good exercise that might help. It must be updated because no hash is used and getting a key or value is O(n).
But the idea is to let you write something similar to what you propose, but using Seq instead of Map...
With the help of implicit and trait, plus find, you could emulate what you need with a kind of clean api (fromKey, fromValue).
The specificities is that a value is not supposed to appear in several places... In this implementation at least.
trait BiMapEntry[K, V] {
def key:K
def value:V
}
trait Sem[K] {
def k:K
def <->[V](v:V):BiMapEntry[K, V] = new BiMapEntry[K, V]() { val key = k; val value = v}
}
trait BiMap[K, V] {
def fromKey(k:K):Option[V]
def fromValue(v:V):Option[K]
}
object BiMap {
implicit def fromInt(i:Int):Sem[Int] = new Sem[Int] {
def k = i
}
implicit def fromSeq[K, V](s:Seq[BiMapEntry[K, V]]) = new BiMap[K, V] {
def fromKey(k:K):Option[V] = s.find(_.key == k).map(_.value)
def fromValue(v:V):Option[K] = s.find(_.value == v).map(_.key)
}
}
object test extends App {
import BiMap._
val a = 1 <-> "a"
val s = Seq(1 <-> "a", 2 <-> "b")
println(s.fromKey(2))
println(s.fromValue("a"))
}
Scala is immutable and values are assigned as reference not copy, so memory footprint will for reference/pointer storage only, which it's better to use to two maps, with type A being key for first and type being B being key for second mapped to B and A respectively, than tun time swapping of maps. And the swapping implementation also has it's own memory footprint and the newly swapped hash-map will also be there in memory till the execution of parent call back and the garbage collector call. And if the the swapping of map is required frequently than virtually your are using equally or more memory than the naive two maps implementation at starting.
One more approach you can try with single map is this(will work only for getting key using mapped value):
def getKeyByValue[A,B](map: Map[A,B], value: B):Option[A] = hashMap.find((a:A,b:B) => b == value)
Code for Scala implementation of find by key:
/** Find entry with given key in table, null if not found.
*/
#deprecatedOverriding("No sensible way to override findEntry as private findEntry0 is used in multiple places internally.", "2.11.0")
protected def findEntry(key: A): Entry =
findEntry0(key, index(elemHashCode(key)))
private[this] def findEntry0(key: A, h: Int): Entry = {
var e = table(h).asInstanceOf[Entry]
while (e != null && !elemEquals(e.key, key)) e = e.next
e
}