Scala function to change attribute of class - scala

I created a class Door and want to write a function that changes the open status to whatever is the argument.
The below does not work. What would be the best way of doing that? (Sorry for the beginner question.)
class Door(var name: String,
var open: Boolean){
def open_door(newDoorState: Boolean): Unit = new Door(name, newDoorState)
override def toString(): String =
"(" + name + ", " + newDoorState + ")"
}
var door = new Door("MyDoor",true)
door.name // "MyDoor"
door.open // true
door.open_door(false)
door.name // "MyDoor"
door.open // still true. I would like this to be false

As Łukasz and Venkat Sudheer Reddy Aedama mentioned in their comments, the recommended way to mutate values in Scala is to use immutable objects.
This means that every change of object state you will be creating a new object with updated values. It's necessary for achieving referential transparency allowing programs to be free of side effects, which is considered a desirable property that makes code significantly easier to maintain.
In Scala there is a convenient mechanism called case classes. Let's look at how Door could be defined as a case class:
case class Door(name: String, open: Boolean) {
def opened(open: Boolean) = copy(open = open)
}
As you may have noticed there are is no var or val before class arguments. This is because in case class every argument is assumed to be a val, making case classes immutable by default.
Another difference is that instead of creating a new instance with new operator, it uses a copy method, which allows to change the values of specified fields. It may be hard to see the benefit of doing it this way now, but it becomes very convenient when you are dealing with case classes with lot more fields.
Now you can instantiate Door and update it in the following way:
val door = Door("MyDoor", false)
door.name // "MyDoor"
door.open // false
val door2 = door.opened(true)
door2.name // "MyDoor"
door2.open // true
Another convenience provided by case classes is that you can instantiate them without using new keyword, which is a syntactic sugar for calling Door.apply("MyDoor", false).
So far we have seen how to declare and use a case class for immutable data objects. But does it mean that we should always declare our classes this way?
The important property of case classes is that they are transparent. Which is imposed by the fact that all their fields are exposed as public vals. This is useful when you want to read object's properties the same way as they were stored.
On the other hand, if you don't want to expose the internals of your objects (so your class can be called opaque), for example to enforce some invariants, it might be a better idea to use standard Scala classes.
For general rules and tradeoffs associated with transparency vs opacity I recommend reading Li Haoyi's article Strategic Scala Style: Designing Datatypes.
In some cases, for example if you want to improve performance or reduce memory footprint of your program, you may decide to use mutable class instead:
class Door(var name: String,
var open: Boolean) {
def openDoor(newDoorState: Boolean): Unit =
open = newDoorState
}
val door = new Door("MyDoor",true)
door.name // "MyDoor"
door.open // true
door.openDoor(false)
door.name // "MyDoor"
door.open // false
Just keep in mind that immutable object are generally preferred way of passing the data around, and you should design your programs to be referentially transparent by default, and when it becomes really necessary, then consider such micro-optimizations like changing your data structures to be mutable.
Also I'll add that in Scala there is a convention (that originates from Java) to use camel case for class fields and methods, so instead of naming your method open_door like in the original example, you should name it openDoor.

Your open_door function returns a new door. Instead, it should set the open attribute:
class Door(var name: String, var open: Boolean) {
def openDoor(newDoorState: Boolean) {
open = newDoorState
}
override def toString(): String = "(" + name + ", " + newDoorState + ")"
}

Your current open_door method creates new instance of Door, where open is set to newDoorState.
To achieve what you want, you have to do:
def open_door(newDoorState: Boolean): Unit {
open = newDoorState
}
(Note the absense of equal sign before the function body. Also, you can drop ":Unit" part - it will be inferred.)

Thanks, so far the answers were all object oriented.
I'm adding a more functional answer, i.e. not changing the original Door class:
class Door{
var name="MyDoor"
var open_status=true
def this(name:String, open_status:Boolean){
this()
this.open_status = open_status
}
override def toString = {
"%s is open is %s.".format(name, open_status)
}
}
println(new Door)
println(new Door("MyDoor",false))

Related

How to write efficient type bounded code if the types are unrelated in Scala

I want to improve the following Cassandra related Scala code. I have two unrelated user defined types which are actually in Java source files (leaving out the details).
public class Blob { .. }
public class Meta { .. }
So here is how I use them currently from Scala:
private val blobMapper: Mapper[Blob] = mappingManager.mapper(classOf[Blob])
private val metaMapper: Mapper[Meta] = mappingManager.mapper(classOf[Meta])
def save(entity: Object) = {
entity match {
case blob: Blob => blobMapper.saveAsync(blob)
case meta: Meta => metaMapper.saveAsync(meta)
case _ => // exception
}
}
While this works, how can you avoid the following problems
repetition when adding new user defined type classes like Blob or Meta
pattern matching repetition when adding new methods like save
having Object as parameter type
You can definitely use Mapper as a typeclass, doing:
def save[A](entity: A)(implicit mapper: Mapper[A]) = mapper.saveAsync(entity)
Now you have a generic method able to perform a save operation on every type A for which a Mapper[A] is in scope.
Also, the mappingManager.mapper implementation could be probably improved to avoid classOf, but it's hard to tell from the question in the current state.
A few questions:
Is mappingManager.mapper(cls) expensive?
How much do you care about handling subclasses of Blob or Meta?
Can something like this work for you?
def save[T: Manifest](entity: T) = {
mappingManager.mapper(manifest[T].runtimeClass).saveAsync(entity)
}
If you do care about making sure that subclasses of Meta grab the proper mapper then you may find isAssignableFrom helpful in your .mapper (and store found sub-classes in a HashMap so you only have to look once).
EDIT: Then maybe you want something like this (ignoring threading concerns):
private[this] val mapperMap = mutable.HashMap[Class[_], Mapper[_]]()
def save[T: Manifest](entity: T) = {
val cls = manifest[T].runtimeClass
mapperMap.getOrElseUpdate(cls, mappingManager.mapper(cls))
.asInstanceOf[Mapper[T]]
.saveAsync(entity)
}

Simple example of extending a Scala collection

I'm looking for a very simple example of subclassing a Scala collection. I'm not so much interested in full explanations of how and why it all works; plenty of those are available here and elsewhere on the Internet. I'd like to know the simple way to do it.
The class below might be as simple an example as possible. The idea is, make a subclass of Set[Int] which has one additional method:
class SlightlyCustomizedSet extends Set[Int] {
def findOdd: Option[Int] = find(_ % 2 == 1)
}
Obviously this is wrong. One problem is that there's no constructor to put things into the Set. A CanBuildFrom object must be built, preferably by calling some already-existing library code that knows how to build it. I've seen examples that implement several additional methods in the companion object, but they're showing how it all works or how to do something more complicated. I'd like to see how to leverage what's already in the libraries to knock this out in a couple lines of code. What's the smallest, simplest way to implement this?
If you just want to add a single method to a class, then subclassing may not be the way to go. Scala's collections library is somewhat complicated, and leaf classes aren't always amenable to subclassing (one might start by subclassing HashSet, but this would start you on a journey down a deep rabbit hole).
Perhaps a simpler way to achieve your goal would be something like:
implicit class SetPimper(val s: Set[Int]) extends AnyVal {
def findOdd: Option[Int] = s.find(_ % 2 == 1)
}
This doesn't actually subclass Set, but creates an implicit conversion that allows you to do things like:
Set(1,2,3).findOdd // Some(1)
Down the Rabbit Hole
If you've come from a Java background, it might be surprising that it's so difficult to extend standard collections - after all the Java standard library's peppered with j.u.ArrayList subclasses, for pretty much anything that can contain other things. However, Scala has one key difference: its first-choice collections are all immutable.
This means that they don't have add methods that modify them in-place. Instead, they have + methods that construct a new instance, with all the original items, plus the new item. If they'd implemented this naïvely, it'd be very inefficient, so they use various class-specific tricks to allow the new instances to share data with the original one. The + method may even return an object of a different type to the original - some of the collections classes use a different representation for small or empty collections.
However, this also means that if you want to subclass one of the immutable collections, then you need to understand the guts of the class you're subclassing, to ensure that your instances of your subclass are constructed in the same way as the base class.
By the way, none of this applies to you if you want to subclass the mutable collections. They're seen as second class citizens in the scala world, but they do have add methods, and rarely need to construct new instances. The following code:
class ListOfUsers(users: Int*) extends scala.collection.mutable.HashSet[Int] {
this ++= users
def findOdd: Option[Int] = find(_ % 2 == 1)
}
Will probably do more-or-less what you expect in most cases (map and friends might not do quite what you expect, because of the the CanBuildFrom stuff that I'll get to in a minute, but bear with me).
The Nuclear Option
If inheritance fails us, we always have a nuclear option to fall back on: composition. We can create our own Set subclass that delegates its responsibilities to a delegate, as such:
import scala.collection.SetLike
import scala.collection.mutable.Builder
import scala.collection.generic.CanBuildFrom
class UserSet(delegate: Set[Int]) extends Set[Int] with SetLike[Int, UserSet] {
override def contains(key: Int) = delegate.contains(key)
override def iterator = delegate.iterator
override def +(elem: Int) = new UserSet(delegate + elem)
override def -(elem: Int) = new UserSet(delegate - elem)
override def empty = new UserSet(Set.empty)
override def newBuilder = UserSet.newBuilder
override def foreach[U](f: Int => U) = delegate.foreach(f) // Optional
override def size = delegate.size // Optional
}
object UserSet {
def apply(users: Int*) = (newBuilder ++= users).result()
def newBuilder = new Builder[Int, UserSet] {
private var delegateBuilder = Set.newBuilder[Int]
override def +=(elem: Int) = {
delegateBuilder += elem
this
}
override def clear() = delegateBuilder.clear()
override def result() = new UserSet(delegateBuilder.result())
}
implicit object UserSetCanBuildFrom extends CanBuildFrom[UserSet, Int, UserSet] {
override def apply() = newBuilder
override def apply(from: UserSet) = newBuilder
}
}
This is arguably both too complicated and too simple at the same time. It's far more lines of code than we meant to write, and yet, it's still pretty naïve.
It'll work without the companion class, but without CanBuildFrom, map will return a plain Set, which may not be what you expect. We've also overridden the optional methods that the documentation for Set recommends we implement.
If we were being thorough, we'd have created a CanBuildFrom, and implemented empty for our mutable class, as this ensures that the handful of methods that create new instances will work as we expect.
But that sounds like a lot of work...
If that sounds like too much work, consider something like the following:
case class UserSet(users: Set[Int])
Sure, you have to type a few more letters to get at the set of users, but I think it separates concerns better than subclassing.

Scala "update" immutable object best practices

With a mutable object I can write something like
var user = DAO.getUser(id)
user.name = "John"
user.email ="john#doe.com"
// logic on user
If user is immutable then I need to clone\copy it on every change operation.
I know a few ways to perform this
case class copy
method (like changeName) that creates a new object with the new property
What is the best practice?
And one more question. Is there any existing technique to get "changes" relative to the original object(for example to generate update statement)?
Both ways you've mentioned belongs to functional and OO paradigms respectively. If you prefer functional decomposition with abstract data type, which, in Scala, is represented by case classes, then choose copy method. Using mutators is not a good practice in my option, cause that will pull you back to Java/C#/C++ way of life.
On the other hand making ADT case class like
case class Person(name: String, age: String)
is more consise then:
class Person(_name: String, _age: String) {
var name = _name
var age = _a
def changeName(newName: String): Unit = { name = newName }
// ... and so on
}
(not the best imperative code, can be shorter, but clear).
Of cause there is another way with mutators, just to return a new object on each call:
class Person(val name: String,
val age: String) {
def changeName(newName: String): Unit = new Person(newName, age)
// ... and so on
}
But still case class way is more consise.
And if you go futher, to concurrent/parallel programming, you'll see that functional consept with immutable value are much better, then tring to guess in what state your object currently are.
Update
Thanks to the senia, forgot to mention two things.
Lenses
At the most basic level, lenses are sort of getters and setters for immutable data and looks like this:
case class Lens[A,B](get: A => B, set: (A,B) => A) {
def apply(a: A) = get(a)
// ...
}
That is it. A lens is a an object that contains two functions: get and set. get takes an A and returns a B. set takes an A and B and returns a new A. It’s easy to see that the type B is a value contained in A. When we pass an instance to get we return that value. When we pass an A and a B to set we update the value B in A and return a new A reflecting the change. For convenience the get is aliased to apply. There is a good intro to Scalaz Lens case class
Records
This one, ofcause, comes from the shapeless library and called Records. An implementation of extensible records modelled as HLists of associations. Keys are encoded using singleton types and fully determine the types of their corresponding values (ex from github):
object author extends Field[String]
object title extends Field[String]
object price extends Field[Double]
object inPrint extends Field[Boolean]
val book =
(author -> "Benjamin Pierce") ::
(title -> "Types and Programming Languages") ::
(price -> 44.11) ::
HNil
// Read price field
val currentPrice = book.get(price) // Inferred type is Double
currentPrice == 44.11
// Update price field, relying on static type of currentPrice
val updated = book + (price -> (currentPrice+2.0))
// Add a new field
val extended = updated + (inPrint -> true)

Scala - handling initialization of objects (_ vs Option[T])

I know there are multiple questions addressing related problems, but I'm not sure it does attack exactly what I'm looking for. I'm still new to Scala, after several years of Java development. I'm looking for the best way to test if an object has been initialized, and if not, initialize it then. For example, in Java:
private MyObject myObj = null;
and at some point in the future:
public void initMyObj(){
if (myObj == null){
myObj = new MyObj();
}
// do something with myObj
}
After this, I might reassign myObj to a different object, but it is unlikely. In Scala, I have this:
class Test {
var myObj: MyObj = _
}
I've read that I could use Option instead, something like:
var myObj = None : Option[MyObj]
and then my check:
myObj match {
case None => ...
case Some(value) => ...
}
but it feels ackward to use this pattern when I might not make this kind of check anywhere else at any other time - though being so new to Scala, I might be wrong. Is this the best way to achieve what I want or is there any other option not involving Option?
It is not generally ideal practice in Scala to leave partially-constructed objects lying around. You would normally rethink how your objects were getting instantiated to see if you can't use a different pattern that is less fragile. For example, instead of setting uninitialized variables in methods:
class Foo { var a: String = null; var b: String = null }
def initFooA(s: String, f: Foo) { if (f.a == null) f.a = s }
def initFooB(s: String, f: Foo) { if (f.b == null) f.b = s }
f
initFooA("salmon", f)
// Do stuff
initFooB("herring", f)
you would attempt to restructure your code to generate the values you need on demand, and delay the instantiation of foo until then:
case class Bar(a: String, b: String) {}
def initBarA(s: String) = s
def initBarB(s: String) = s
val iba = initBarA("halibut")
// Do stuff
val ibb = initBarB("cod")
Bar(iba, ibb)
Because Scala has easy access to tuples (and type inference), this can be a lot less painful than in Java.
Another thing you can do is defer the late initialization to someone else.
case class Baz(a: String)(bMaker: => String) {
lazy val b = bMaker
}
Now you pass in something that will make parameter b, and arrange for it to handle any late initialization stuff that needs to be handled. This doesn't always avoid needing to set vars, but it can help push it out of your class code into your initialization logic (which is usually a better place for it).
Doing this with vars is a little less straightforward. Realistically, you're probably best off just devoting a class to it e.g. by:
class LazyVar[A](initial: => A) {
private[this] var loaded = false
private[this] var variable: A = _
def apply() = { if (!loaded) { loaded = true; variable = initial }; variable }
def update(a: A) { loaded = true; variable = a }
}
where you then (sadly) have to use () on every read and write.
scala> val lv = new LazyVar({ println("Hi!"); 5 })
lv: LazyVar[Int] = LazyVar#2626ea08
scala> lv()
Hi!
res2: Int = 5
scala> lv() = 7
scala> lv()
res4: Int = 7
Then you use an instance of this class instead of the actual var and pass through the lazy initializer. (lazy val is very much like this under the hood; the compiler just protects you from noticing.)
Finally, if you want to have a fully-functional object that is occasionally missing a value, var x: Option[X] is the construct you want to use; if you can't find a way around the standard Java creation patterns (and you don't want to try something more exotic like objects that create each other with more and more information, either because performance is critical and you can't afford it, or you dislike writing that much boilerplate to allow type-checking to verify that your object is properly created) but you otherwise want to use it, var x: X = null is what I'd choose, not _. If X is a primitive, you probably need to choose the correct value wisely anyway (for example, Double.NaN instead of 0.0, -1 rather than 0 for Int) to indicate I-am-not-initialized. If it's generic code and you want Any instead of AnyRef, asInstanceOf-ing back and forth between Any and AnyRef is probably the best way out of poorly typechecked situation (assuming you really, really can't use Option, which at that point is much clearer).
Maybe a lazy variable is what you need.
lazy val myObj: MyObj = //here you put the object creation code
In this way the object creation is postponed to the first time the code tries to access it.

scala programming without vars

val and var in scala, the concept is understandable enough, I think.
I wanted to do something like this (java like):
trait PersonInfo {
var name: Option[String] = None
var address: Option[String] = None
// plus another 30 var, for example
}
case class Person() extends PersonInfo
object TestObject {
def main(args: Array[String]): Unit = {
val p = new Person()
p.name = Some("someName")
p.address = Some("someAddress")
}
}
so I can change the name, address, etc...
This works well enough, but the thing is, in my program I end up with everything as vars.
As I understand val are "preferred" in scala. How can val work in this
type of example without having to rewrite all 30+ arguments every time one of them is changed?
That is, I could have
trait PersonInfo {
val name: Option[String]
val address: Option[String]
// plus another 30 val, for example
}
case class Person(name: Option[String]=None, address: Option[String]=None, ...plus another 30.. ) extends PersonInfo
object TestObject {
def main(args: Array[String]): Unit = {
val p = new Person("someName", "someAddress", .....)
// and if I want to change one thing, the address for example
val p2 = new Person("someName", "someOtherAddress", .....)
}
}
Is this the "normal" scala way of doing thing (not withstanding the 22 parameters limit)?
As can be seen, I'm very new to all this.
At first the basic option of Tony K.:
def withName(n : String) = Person(n, address)
looked promising, but I have quite a few classes that extends PersonInfo.
That means in each one I would have to re-implement the defs, lots of typing and cutting and pasting,
just to do something simple.
If I convert the trait PersonInfo to a normal class and put all the defs in it, then
I have the problem of how can I return a Person, not a PersonInfo?
Is there a clever scala thing to somehow implement in the trait or super class and have
all subclasses really extend?
As far as I can see all works very well in scala when the examples are very simple,
2 or 3 parameters, but when you have dozens it becomes very tedious and unworkable.
PersonContext of weirdcanada is I think similar, still thinking about this one. I guess if
I have 43 parameters I would need to breakup into multiple temp classes just to pump
the parameters into Person.
The copy option is also interesting, cryptic but a lot less typing.
Coming from java I was hoping for some clever tricks from scala.
Case classes have a pre-defined copy method which you should use for this.
case class Person(name: String, age: Int)
val mike = Person("Mike", 42)
val newMike = mike.copy(age = 43)
How does this work? copy is just one of the methods (besides equals, hashCode etc) that the compiler writes for you. In this example it is:
def copy(name: String = name, age: Int = age): Person = new Person(name, age)
The values name and age in this method shadow the values in the outer scope. As you can see, default values are provided, so you only need to specify the ones that you want to change. The others default to what there are in the current instance.
The reason for the existence of var in scala is to support mutable state. In some cases, mutable state is truly what you want (e.g. for performance or clarity reasons).
You are correct, though, that there is much evidence and experience behind the encouragement to use immutable state. Things work better on many fronts (concurrency, clarity of reason, etc).
One answer to your question is to provide mutator methods to the class in question that don't actually mutate the state, but instead return a new object with a modified entry:
case class Person(val name : String, val address : String) {
def withName(n : String) = Person(n, address)
...
}
This particular solution does involve coding potentially long parameter lists, but only within the class itself. Users of it get off easy:
val p = Person("Joe", "N St")
val p2 = p.withName("Sam")
...
If you consider the reasons you'd want to mutate state, then thing become clearer. If you are reading data from a database, you could have many reasons for mutating an object:
The database itself changed, and you want to auto-refresh the state of the object in memory
You want to make an update to the database itself
You want to pass an object around and have it mutated by methods all over the place
In the first case, immutable state is easy:
val updatedObj = oldObj.refresh
The second is much more complex, and there are many ways to handle it (including mutable state with dirty field tracking). It pays to look at libraries like Squery, where you can write things in a nice DSL (see http://squeryl.org/inserts-updates-delete.html) and avoid using the direct object mutation altogether.
The final one is the one you generally want to avoid for reasons of complexity. Such things are hard to parallelize, hard to reason about, and lead to all sorts of bugs where one class has a reference to another, but no guarantees about the stability of it. This kind of usage is the one that screams for immutable state of the form we are talking about.
Scala has adopted many paradigms from Functional Programming, one of them being a focus on using objects with immutable state. This means moving away from getters and setters within your classes and instead opting to to do what #Tony K. above has suggested: when you need to change the "state" of an inner object, define a function that will return a new Person object.
Trying to use immutable objects is likely the preferred Scala way.
In regards to the 22 parameter issue, you could create a context class that is passed to the constructor of Person:
case class PersonContext(all: String, of: String, your: String, parameters: Int)
class Person(context: PersonContext) extends PersonInfo { ... }
If you find yourself changing an address often and don't want to have to go through the PersonContext rigamarole, you can define a method:
def addressChanger(person: Person, address: String): Person = {
val contextWithNewAddress = ...
Person(contextWithNewAddress)
}
You could take this even further, and define a method on Person:
class Person(context: PersonContext) extends PersonInfo {
...
def newAddress(address: String): Person = {
addressChanger(this, address)
}
}
In your code, you just need to make remember that when you are updating your objects that you're often getting new objects in return. Once you get used to that concept, it becomes very natural.