scala using a class argument a placeholder (or input variable) - scala

Lets say i have a data structure that holds a parameterised type of data:
case class Terminal[A](value: A, name: String ="")
I can easily create a Terminal[Double] if i pass it a materialised constant:
val terminal = Terminal(2.0)
However, i want it to also be able to receive a (not materialised) input so that i can evaluate the terminal multiple times with different contexts. I can achieve a simple solution by calling value by name, i.e.
class Terminal[A](value: => A, name: String ="") {
def getValue = this.value
}
var x = 1.0
val terminal = new Terminal(x)
terminal.getValue // 1.0
x = 100.0
terminal.getValue // 100.0
However the user of this program would have to initialise the input with something like var input_x = None, which is not nice, and then change its state, which in turn would have to make me turn value into a Option[A]
Is this the best way to deal with this situation? Isn't any design pattern or scala feature that i could use?
i can also create a class Input to represent these context-dependent inputs, but then i would need to change a lot of things.

You can use immutable objects as below:
scala> case class Terminal[A](value: A, name: String ="") {
| def update(newValue: A): Terminal[A] = this.copy(value = newValue)
| def getValue: A = this.value
| }
defined class Terminal
scala> val terminal = Terminal(1.0)
terminal: Terminal[Double] = Terminal(1.0,)
scala> val updatedTerminal = terminal.update(100.0)
updatedTerminal: Terminal[Double] = Terminal(100.0,)
scala> val oldValue = terminal.getValue
oldValue: Double = 1.0
scala> val newValue = updatedTerminal.getValue
newValue: Double = 100.0
The getValue method is actually redundant here because getters come free with case classes. I just had it in there to demonstrate the example.
scala> oldValue == terminal.value
res0: Boolean = true
scala> newValue == updatedTerminal.value
res1: Boolean = true
In general, prefer case-classes if you want to create objects that don't have mutable state (For example, all singleton components are better-off as non-case classes).

Related

Scala - Using 'this' keyword multiple times one after the other will fail

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)

Scala: recursive value listHuman needs type

Why is this function giving me the following error:
recursive value listHuman needs type
def setHumanResources(physicalResources: List[Physical], totalHumanResources: List[Human]): List[Human] = {
val listHuman = physicalResources.map{pr => totalHumanResources.find(_.handles.contains(pr.post)).filterNot(a=>listHuman.contains(a))}
return listHuman
}
I tried to do this, but it gives me another error:
val listHuman: List[Human] = physicalResources.map{pr => totalHumanResources.find(_.handles.contains(pr.post)).get}.filterNot(human=>listHuman.contains(human))
forward reference extends over definition of value listHuman
This error means that constant value or variable is used before its declaration. For example
val y = x + 2
val x = 5
What wrong with your code is you try to define constant value with itself. It's impossible by definition of constant. To build recursion use def.
It seems like you want to do a foldLeft, does this work?
def setHumanResources(physicalResources: List[Physical], totalHumanResources: List[Human]): List[Human] = {
physicalResources.foldLeft(Set.empty[Human]) { (l, pr) =>
val applicableHuman = totalHumanResources.find(_.handles.contains(pr.post))
l ++ applicableHuman
}.toList
}
The premises here is to have setHumanResourcesreturn a unique/distint list of Human objects. The code tries this by doing filterNot(a=>listHuman.contains(a)) in definition of listHuman and thus recursively referring to listHuman while defining listHuman in semantically illegal way. This de-duping can be achieved properly by the following ways.
convert the List to Set and convert it back to List to remove duplicates like listHuman.toSet.ToList. for this method to work the Human object have property identity defined by overriding equals method. so the code will now look like
def setHumanResources(physicalResources: List[Physical], totalHumanResources: List[Human]): List[Human] = {
val listHuman = physicalResources.map{pr => totalHumanResources.find(_.handles.contains(pr.post))
listHuman.toSet.toList
}
A Demo for a sample class of Human is shown below.
scala> class Human(val firstName: String, val lastName: String) {
| override def toString = this.firstName
| override def equals(that: Any): Boolean = that match {
| case that: Human if that.firstName == this.firstName => true
| case _ => false
| }
| }
defined class Human
scala> List(new Human("Peter", "Parker"), new Human("Peter", "Quill")).toSet.toList
res14: List[Human] = List(Peter)
If the class Human cannot have object equality defined in it by overriding equals method then follow this approach. considering each Human can be uniquely identified by say two properties property1 and property2. the listHuman can be deduped by the following expression. For our previously defined Human class if we want to de-dupe on both firstName and lastName properties, the code would be like below.
listHuman.groupBy(x => (x.firstName, x.lastName)).map(_._2.head)
so the new method definition becomes
def setHumanResources(physicalResources: List[Physical], totalHumanResources: List[Human]): List[Human] = {
val listHuman = physicalResources.map{pr =>
totalHumanResources.find(_.handles.contains(pr.post))
listHuman.groupBy(x => (x.property1, x.property2) ).map(_._2.head)
}

Scala: How to define an enum with extra attributes?

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

How to get the type of a field using reflection?

Is there a way to get the Type of a field with scala reflection?
Let's see the standard reflection example:
scala> class C { val x = 2; var y = 3 }
defined class C
scala> val m = ru.runtimeMirror(getClass.getClassLoader)
m: scala.reflect.runtime.universe.Mirror = JavaMirror ...
scala> val im = m.reflect(new C)
im: scala.reflect.runtime.universe.InstanceMirror = instance mirror for C#5f0c8ac1
scala> val fieldX = ru.typeOf[C].declaration(ru.newTermName("x")).asTerm.accessed.asTerm
fieldX: scala.reflect.runtime.universe.TermSymbol = value x
scala> val fmX = im.reflectField(fieldX)
fmX: scala.reflect.runtime.universe.FieldMirror = field mirror for C.x (bound to C#5f0c8ac1)
scala> fmX.get
res0: Any = 2
Is there a way to do something like
val test: Int = fmX.get
That means can I "cast" the result of a reflection get to the actual type of the field? And otherwise: is it possible to do a reflection set from a string? In the example something like
fmx.set("10")
Thanks for hints!
Here's the deal... the type is not known at compile time, so, basically, you have to tell the compiler what the type it's supposed to be. You can do it safely or not, like this:
val test: Int = fmX.get.asInstanceOf[Int]
val test: Int = fmX.get match {
case n: Int => n
case _ => 0 // or however you want to handle the exception
}
Note that, since you declared test to be Int, you have to assign an Int to it. And even if you kept test as Any, at some point you have to pick a type for it, and it is always going to be something static -- as in, in the source code.
The second case just uses pattern matching to ensure you have the right type.
I'm not sure I understand what you mean by the second case.

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.