Efficient map with case class as a key in Scala? - scala

A following C code uses enum and array as efficient "map" from enum to anything:
enum Color { ColorRed, ColorGreen, ColorBlue, ColorSize};
void f() {
int x[ColorSize];
x[ColorRed] = 12;
x[ColorGreen] = 33;
x[ColorBlue] = 4;
return x[ColorGreen];
}
Is this possible with Scala?
I.e. to have a "map" from case class to something, implemented as efficient array and not as tree or as hashmap. Yet I would like to be able to index only with a paricular type not with Int.
Update: In short I would like to have Scala Array indexed by some kind of enum (case class or Enumeration).

For small enumerations you can "simulate" the C behavior:
abstract sealed class Color(val index: Int)
object Color {
implicit def col2int(color:Color) = color.index
}
case object ColorRed extends Color(0)
case object ColorGreen extends Color(1)
case object ColorBlue extends Color(2)
...
import Color._
val array = Array(1,2,3)
array(ColorRed) = 12
However, I doubt this would be considered good style, especially because it's unsafe. Using a map is a better approach, or you could wrap an array in a specialized data structure which deals with Color indizes:
class ColorArray[T:ClassManifest] {
val array = new Array[T] (3)
def apply(color: Color) = array(color.index)
def update(color: Color, value: T) = array(color.index) = value
}
...
val cArray = new ColorArray[Int]()
cArray(ColorRed) = 12
println(cArray(ColorRed))

object Color extends Enumeration{
val ColorRed, ColorGreen, ColorBlue = Value
}
import Color._
def f:Map[Color.Value,Int] =
Map(ColorRed -> 12 , ColorGreen -> 33, ColorBlue -> 4)

If you want the full C performance you could do this:
trait CEnum {
private var size = 0;
def value = { size += 1; size-1 }
}
object Color extends CEnum {
val colorRed = value
val colorGreen = value
val colorBlue = value
val colorSize = 3
}
import Color._
def f() = {
val x = Array[Int](colorSize)
x(colorRed) = 12
x(colorGreen) = 33
x(colorBlue) = 4
x(colorGreen)
}
It's equally unsafe as the method in C & just as performant. It is however very unsafe.

Related

How to dynamically create an Enum type in Scala?

I have a basic enum type Currency that will include all major currencies traded e.g. EUR, USD, JPY, etc. This code I can write or generate one time. However, I'd also like to have strong enum type for all currency pair combinations e.g. EURCHF, USDCHF, etc. Is there any provision in Scala that would allow me to build such a derived enum type dynamically? I could also do it with some script generator from outside ... but I wonder whether it would be possible.
object Ccy extends Enumeration {
type Type = Value
val USD = Value("USD")
val CHF = Value("CHF")
val EUR = Value("EUR")
val GBP = Value("GBP")
val JPY = Value("JPY")
}
object CcyPair extends Enumeration {
type Type = Value
// ??? Ccy.values.toSeq.combinations(2) ...
}
UPDATE using the accepted answer as reference this was my solution implementation:
import scala.language.dynamics
object CcyPair extends Enumeration with Dynamic {
type Type = Value
/*
* contains all currency combinations including the symmetric AB and BA
*/
private val byCcy: Map[(Ccy.Value, Ccy.Value), Value] =
Ccy.values.toSeq.combinations(2).map { case Seq(c1, c2) =>
Seq(
(c1, c2) -> Value(c1.toString + c2.toString),
(c2, c1) -> Value(c2.toString + c1.toString)
)
}.flatten.toMap
/**
* reverse lookup to find currencies by currency pair, needed to find
* the base and risk components.
*/
private val revByCcy = byCcy.toSeq.map { case (((ccyRisk, ccyBase), ccyPair)) =>
ccyPair -> (ccyRisk, ccyBase)
}.toMap
def apply(ccy1: Ccy.Value, ccy2: Ccy.Value): Value = {
assert(ccy1 != ccy2, "currencies should be different")
byCcy((ccy1, ccy2))
}
implicit class DecoratedCcyPair(ccyPair: CcyPair.Type) {
def base: Ccy.Type = {
revByCcy(ccyPair)._1
}
def risk: Ccy.Type = {
revByCcy(ccyPair)._2
}
def name: String = ccyPair.toString()
}
def selectDynamic(ccyPair: String): Value = withName(ccyPair)
}
and then I can do things like:
val ccyPair = CcyPair.EURUSD
// or
val ccyPair = CcyPair(Ccy.EUR, Ccy.USD)
// and then do
println(ccyPair.name)
// and extract their parts like:
// print the base currency of the pair i.e. EUR
println(CcyPair.EURUSD.base)
// print the risk currency of the pair i.e. USD
println(CcyPair.EURUSD.risk)
There is no magic in Scala's Enumeration. The call to the Value function inside simply does some modifications to Enumeration's internal mutable structures. So you just have to call Value for each pair of currencies. The following code will work:
object CcyPair1 extends Enumeration {
Ccy.values.toSeq.combinations(2).foreach {
case Seq(c1, c2) =>
Value(c1.toString + c2.toString)
}
}
It's not very comfortable to work with though. You can access the values only through withName or values functions.
scala> CcyPair1.withName("USDEUR")
res20: CcyPair1.Value = USDEUR
But it's possible to extend this definition, for example, to allow retrieving CcyPair.Value by a pair of Ccy.Values, or to allow access by object fields with Dynamic, or to provide other facilities you may need:
import scala.language.dynamics
object CcyPair2 extends Enumeration with Dynamic {
val byCcy: Map[(Ccy.Value, Ccy.Value), Value] =
Ccy.values.toSeq.combinations(2).map {
case Seq(c1, c2) =>
(c1, c2) -> Value(c1.toString + c2.toString)
}.toMap
def forCcy(ccy1: Ccy.Value, ccy2: Ccy.Value): Value = {
assert(ccy1 != ccy2, "currencies should be different")
if (ccy1 < ccy2) byCcy((ccy1, ccy2))
else byCcy((ccy2, ccy1))
}
def selectDynamic(pairName: String): Value =
withName(pairName)
}
This definition is a bit more useful:
scala> CcyPair2.forCcy(Ccy.USD, Ccy.EUR)
res2: CcyPair2.Value = USDEUR
scala> CcyPair2.forCcy(Ccy.EUR, Ccy.USD)
res3: CcyPair2.Value = USDEUR
scala> CcyPair2.USDCHF
res4: CcyPair2.Value = USDCHF

can we have methods as arguments in a class definition?

Following is the snippet of code I was going thru a scala book.
One of the parameter of the Car class is "def color: String"
I didn't understand. "def" is a keyword to define a method. how can that be used in paramenters?
scala> abstract class Car {
| val year: Int
| val automatic: Boolean = true
| def color: String
| }
A function that takes other functions are arguments is known as a higher-order function, here is an example of that:
// A function that takes a list of Ints, and a function that takes an Int and returns a boolean.
def filterList(list: List[Int], filter: (Int) => Boolean) = { /* implementation */ }
// You might call it like this
def filter(i: Int) = i > 0
val list = List(-5, 0, 5, 10)
filterList(list, filter)
// Or shorthand like this
val list = List(-5, 0, 5, 10)
filterList(list, _ > 0)
However that is not what is happening in your example. In your example the Car class has three class members, two of them are variables, and one of them is a function. If you were to extend your abstract class, you could test the values out:
abstract class Car {
val year: Int
val automatic: Boolean = true
def color: String
}
case class Sedan(year: Int) extends Car {
def color = "red"
}
val volkswagen = Sedan(2012)
volkswagen.year // 2012
volkswagen.automatic // true
volkswagen.color // red
Here, having color as a function (using def) doesn't make too much sense, because with my implementation, the color is always going to be "red".
A better example for using a function for a class member would be for some value that is going to change:
class BrokenClock {
val currentTime = DateTime.now()
}
class Clock {
def currentTime = DateTime.now()
}
// This would always print the same time, because it is a value that was computed once when you create a new instance of BrokenClock
val brokenClock = BrokenClock()
brokenClock.currentTime // 2017-03-31 22:51:00
brokenClock.currentTime // 2017-03-31 22:51:00
brokenClock.currentTime // 2017-03-31 22:51:00
// This will be a different value every time, because each time we are calling a function that is computing a new value for us
val clock = Clock()
clock.currentTime // 2017-03-31 22:51:00
clock.currentTime // 2017-03-31 22:52:00
clock.currentTime // 2017-03-31 22:53:00

Getting previous and next element of a value in a Scala enumeration

I would like to add two new operations to a Scala Enumeration to get the previous and the next value given a certain value if it exists. For example, I would like to write something like:
object Nums extends MyNewEnumerationType {
type Nums = Value
val One,Two,Three = Value
}
Nums.nextOf(One) // Some(Two)
Nums.prevOf(One) // None
My idea was to create a new class and add the methods in this way:
class PrevNextEnum extends Enumeration {
val prevOf = values.zip(None +: values.map{_.some}.toSeq).toMap
val nextOf = {
if (values.isEmpty) Map.empty
else values.zip(values.tail.map{_.some}.toSeq :+ None).toMap
}
}
The problem is that this doesn't work because when prevOf and nextOf are initialized, values is empty.
First question: why values is empty and when it is filled with the values?
Second question: how can I implement prevOf and nextOf?
Third question: is it possible to add the methods prevOf and nextOf to the value type instead of the enumeration? Writing One.next feels more natural than writing Num.nextOf(One)
try the following codes:
class PrevNextEnum extends Enumeration {
lazy val prevOf = {
val list = values.toList
val map = list.tail.zip(list.map(Some(_))).toMap + (list.head -> None)
map
}
lazy val nextOf = {
val list = values.toList
val map = (list.zip(list.tail.map(Some(_)) :+ None).toMap)
map
}
}
object Nums extends PrevNextEnum {
type Nums = Value
val One, Two, Three = Value
}
object App extends App {
println(Nums.prevOf(Nums.Two))
println(Nums.nextOf(Nums.One))
println(Nums.nextOf(Nums.Three))
println(Nums.prevOf(Nums.One))
}
Building on the answer of user1484819 :
class PrevNextEnum extends Enumeration {
lazy val prevOf = {
val list = values.toList
val map = list.tail.zip(list).toMap
v:Value => map.get(v)
}
lazy val nextOf = {
val list = values.toList
val map = list.zip(list.tail).toMap
v:Value => map.get(v)
}
}
object Nums extends PrevNextEnum {
type Nums = Value
val One, Two, Three = Value
}
This has basically the same structure, but uses the fact that Map can return Options itself when using get instead of apply.

Converting List of lists to Stream - Functional Programming

I am working on Scala to convert list of lists to list of customized object "Point"
class Point(val x: Int, val y: Int) {
var cX: Int = x
var cY: Int = y
}
Should I use Foreach or should I use Map or foreach in this case
def list_To_Point(_listOfPoints :List[List[String]]) : List[Point] = {
var elem =
lazy val _list: List[Point] = _listOfPoints.map(p=> new Point(p[0],p[1])
_list
}
I couldn't figure out where the problem exactly ?
def listToPoint(l:List[List[String]]):List[Point] =
l.collect({case x::y::Nil => new Point(x.toInt,y.toInt)})
But you really shouldn't use a List[String] to represent what is basically (Int,Int) …
ugly as hell and untested but it should work (pls consider making your structures immutable) :
case class Point(x:Int,y:Int)
object Point {
def listToPoint(listOfPoints:List[List[String]]):List[Point] =
listOfPoints.map(p => new Point(p(0).toInt,p(1).toInt))
}

Problem with Scala's getter/setters

I'm currently learning Scala, and just discovered the way to create custom field getters/setters. I have a simple example working:
class Thing(private val a:Int){
override def toString = "Thing[" + a + "]"
private var _value = a
def value = _value
def value_= (newVal:Int) = _value = newVal
}
On the console I can do:
scala> var t = new Thing(2)
t: dylan.code.Thing = Thing[2]
scala> t.value
res1: Int = 2
scala> t.value = 3
scala> t.value
res2: Int = 3
Now I'm trying to bring this concept to a slightly more complicated example; I'll try to whittle the code down to what's relevant:
abstract class CellExpression[Type] extends Publisher[CellUpdateEvent[Type]] with Subscriber[CellUpdateEvent[Type], CellExpression[Type]]{
protected var cachedValue: Type = recalculateValue()
protected def recalculateValue(): Type
protected def changeValue(newValue: Type):Unit = {
val oldValue = value()
if(newValue != oldValue){
cachedValue = newValue
publish(new CellUpdateEvent(this, oldValue, newValue))
}
}
def value() = cachedValue
def notify(pub: CellExpression[Type], event: CellUpdateEvent[Type]) = changeValue(recalculateValue())
}
//....
class CellVariable[Type](private val initialValue:Type) extends CellExpression[Type]{
cachedValue = initialValue
protected def recalculateValue() = { cachedValue }
override def toString = "CellVariable[" + value + "]"
def value_= (newValue:Type) = {changeValue(newValue)}
}
As far as I can tell, I've done what I need to in order to be able to treate value as a field via its getter and setter. But when I try it out in the console, I get:
scala> var i = new CellVariable(2)
i: dylan.code.CellVariable[Int] = CellVariable[2]
scala> i.value = 3
<console>:11: error: reassignment to val
i.value = 3
^
What have I done wrong, and how can I fix it?
I actually stumbled onto the solution.
The line where I declare my value function: def value() = cachedValue is the culprit.
If I remove the parentheses to make the line def value = cachedValue everything seems to work as I expected.
You cannot change values in Scala. A value is assigned once and only once. If you want to do this then you need to use variables instead of values. In other words, change the declaration from val to var.
The problem is inside one of your class definitions and may be on a line without val because I believe that if you neglect to declare a name, then Scala assumes that it is a value and therefore immutable.
Not sure what you want getters and setters for though. Scala enables you to ignore all of that Java overhead.
It is probably the line that says cachedValue = initialValue because it is not declared with var anywhere in that class. The definition in the other class is a different name because it is in a different scope. You would have to say something like class.varname to change a variable defined in another class.