I have an enum like this:
object Ops extends Enumeration {
val one = Value(0x01)
val two = Value(0x02)
val three = Value(0x03)
val four = Value(0x04)
}
I want to say
Byte someByte = functionThatReturnsAByte
val op = Ops.valueOf(someByte)
The only method close is withName which only takes a String.
Ops(someByte)
will do the trick.
Related
I've come across an issue where using the this keyword in Scala multiple times within the same method will actually fail.
I cannot replicate the problem here because the codebase is too large, but I will do my best to show the problem.
I have a class, Foo, with an override-able method fooMethod. Inside fooMethod, three property values are generated, and the current class instance is updated with these properties separately, using this. However, only the last this call actually sets any of the properties, the two preceding this calls have no effect on the object.
case class Foo(prop1: prop, prop2: prop2, prop3:prop3) extends FooParent {
override def fooMethod(){
val propA = gen()
val propB = gen()
val propC = gen()
this.withPropA(propA)
this.withPropB(propB)
this.withPropC(propC)
}
def withPropA(:propA): Foo = this.copy(prop1 = propA)
def withPropB(:propB): Foo = this.copy(prop2 = propB)
def withPropC(:propC): Foo = this.copy(prop3 = propC)
}
The above code will only apply the final this.withPropC call, and therefore only prop3 is updated.
However, if I do the following
case class Foo(prop1: prop, prop2: prop2, prop3:prop3) extends FooParent {
override def fooMethod(){
val propA = gen()
val propB = gen()
val propC = gen()
// here
val one = this.withPropA(propA)
val two = one.withPropB(propB)
two.withPropC(propC)
}
def withPropA(:propA): Foo = this.copy(prop1 = propA)
def withPropB(:propB): Foo = this.copy(prop2 = propB)
def withPropC(:propC): Foo = this.copy(prop3 = propC)
}
then all of the properties are updated. Why is this?
Case class are immutable, so copy based functions (like those withProp*) never mutate this.
Moreover, in case of sequential property changes, each update must be applied on the result of previous one (chain); Not on (orginal) this, what would create separate instances corresponding to each unrelated update.
If you really intend to use such functions, it should be
withPropA(propA). // chain update
withPropB(propB). // chain
withPropC(propC)
What can be written:
copy(prop1 = propA, prop2 = propB, prop3 = propC)
I have a use-case where I need to define a new enum type LongShort but I need it in a way to also carry the sign so it can be directly used in mathematical expressions e.g.
object LongShortType extends Enumeration {
type Type = Value
val Long = Value(+1)
val Short = Value(-1)
}
I'd then like to use it like this:
val longShort = LongShortType.Short
val numberOfContracts: Int = 10
val vanillaOptionNotional: Double = longShort*numberOfContracts
but this leads to compiler error cannot resolve symbol * ... is there a way to extract the value of the enum? Or am I not understanding how enum types work?
The type of LongShortType.Short isn't Int, it's Value. You can either extract the underlying id of the value:
val longShort = LongShortType.Short.id
Which is a little ugly. Or you could not use an enum type at all:
object LongShortType {
val Long = 1
val Short = -1
}
And then your equation would work as is.
OK I worked out a solution to accomplish what I wanted without any compromisse and by that I mean that this solution has all the advantages of using Scala enum e.g. the withName and still allows me to define extra features on it:
object LongShortType extends Enumeration {
type Type = LongShortVal
val Long = Value("Long", +1)
val Short = Value("Short", -1)
case class LongShortVal(name: String, sign: Int) extends Val(nextId, name)
protected final def Value(name: String, sign: Int) = new LongShortVal(name, sign)
}
and now can do:
val longShort = LongShortType.Short
val numberOfContracts: Int = 10
val vanillaOptionNotional: Double = longShort.sign*numberOfContracts
and can also do:
val longShort = LongShort.withName("Long") // returns LongShort.Long
I'd like a container class that I can extend with some number of traits to contain groups of default vals that can later be changed in an immutable way. The traits will hold certain simple pieces of data that go together so that creating the class with a couple of traits will create an object with several collections of default values.
Then I'd like to be able to modify any of the vals immutably by copying the object while changing one new value at a time.
The class might have something like the following:
class Defaults(val string: String = "string", val int: Int = "int")
Then other traits like this
trait MoreDefaults{
val long: Long = 1l
}
Then I'd like to mix them when instantiated to build my the particular needed set of defaults
var d = new Defaults with MoreDefaults
and later to something like:
if (someFlag) d = d.copy( long = 1412341234l )
You can do something like this with a single case class but I run out of params at 22. But I'll have a bunch of groupings of defaults I'd like to mixin depending on the need, then allow changes to any of them (class defined or trait defined) in an immutable way.
I can stick a copy method in the Defaults class like this:
def copy(
string: String = string,
int: Int = int): Defaults = {
new Defaults(string, int)
}
then do something like
var d = new Defaults
if (someFlag) d = d.copy(int = 234234)
Question ====> This works for values in the base class but I can't figure how to extend this to the mixin traits. Ideally the d.copy would work on all vals defined by all of the class + traits. Overloading is trouble too since the vals are mainly Strings but all of the val names will be unique in any mix of class and traits or it is an error.
Using only classes I can get some of this functionality by having a base Defaults class then extending it with another class that has it's own non-overloaded copyMoreDefault function. This is really ugly and I hope a Scala expert will see it and have a good laugh before setting me straight--it does work though.
class Defaults(
val string: String = "one",
val boolean: Boolean = true,
val int: Int = 1,
val double: Double = 1.0d,
val long: Long = 1l) {
def copy(
string: String = string,
boolean: Boolean = boolean,
int: Int = int,
double: Double = double,
long: Long = long): Defaults = {
new Defaults(string, boolean, int, double, long)
}
}
class MoreDefaults(
string: String = "one",
boolean: Boolean = true,
int: Int = 1,
double: Double = 1.0d,
long: Long = 1l,
val string2: String = "string2") extends Defaults (
string,
boolean,
int,
double,
long) {
def copyMoreDefaults(
string: String = string,
boolean: Boolean = boolean,
int: Int = int,
double: Double = double,
long: Long = long,
string2: String = string2): MoreDefaults = {
new MoreDefaults(string, boolean, int, double, long, string2)
}
}
Then the following works:
var d = new MoreDefualts
if (someFlag) d = d.copyMoreDefaults(string2 = "new string2")
This method will be a mess if Defaults get's changed parameters! All the derived classes will have to be updated--ugh. There must be a better way.
I don't think I'm strictly speaking answering your question, rather suggesting an alternative solution. So your having problems with large case classes, e.g.
case class Fred(a: Int = 1, b: Int = 2, ... too many params ... )
What I would do is organize the params into more case classes:
case class Bar(a: Int = 1, b: Int = 2)
case class Foo(c: Int = 99, d: Int = 200)
// etc
case class Fred(bar: Bar = Bar(), foo: Foo = Foo(), ... etc)
Then when you want to do a copy and change, say one of the values of Foo you do:
val myFred: Fred = Fred()
val fredCopy: Fred = myFred.copy(foo = myFred.foo.copy(d = 300))
and you need not even define the copy functions, you get them for free.
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.
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.