Case class Members not accessible via Companion Object - scala

Lets start off with a story
I am in contact with a fictious club namd Foo where people have registered for a party. The manager has asked me to maintain separate list of member names and member ids. The manager came to me one day and told about the problem. I as a developer playing around with scala gave him a solution like the aforementioned.
I wanted to maintain a class which will contain the name of the members and their ids. The code was very crude in nature and I absolutely had performed no validations
STEP 1: I created a class called NonEmptyFoo
case class NonEmptyFoo(bar1:String,bar2:String)
while drinking beer in the club, I found few people registering
STEP 2: Adding users (username,userid) both are String objects
val member1=NonEmptyFoo("member1","Foo_member1")
val member2=NonEmptyFoo("member2","Foo_member2")
val member3=NonEmptyFoo("member3","Foo_member3")
many people registered later, which was really good for the manager
STEP 3: Creating separate lists for username and userid
val (memName,memId)=clubMembers map(x=>(x.bar1,x.bar2)) unzip
Whoooah! my solution seemed to work unless one day the manager came and told me;
"Man! people are so excited, that at times, they are registering without even entering the data; I am not able to get the correct list of member names and their ids as the list have many empty fields. This got on my nerves.
I assured the manager of the club to provide him with a robust solution the next day.
Two things came to my mind
1. If I write the code from scratch I need to remove the old code and the new code may not be readable
2. I need to keep the code readable and make it in a way such that the new developer can find it easy to maintain the new code and add/remove features from it
At night I thought to add abstractions to it. I added the following code
STEP 1 Created a trait Foo with NonEmptyFoo for users with valid entry and EmptyFoo for people with invalid entries
trait Foo
case class EmptyFoo() extends Foo
case class NonEmptyFoo(bar1:String,bar2:String) extends Foo
object Foo{
def apply(bar1:String,bar2:String)= (bar1,bar2) match{
case (x,y)=>if(x.isEmpty||y.isEmpty) EmptyFoo() else NonEmptyFoo(x,y)
case _=> EmptyFoo()
}
}
The above code has benefits. First off I am able to validate users with valid entry and users with invalid entry. Secondly I am abstracting out the empty and non empty Foo to only Foo such that the new methods can easily be added into Foo and implemented thereby in the child classes which as a result hides the inner implementation.
As the user enters a valid data as under
val mamber1=Foo("member1","Foo_member1")
The output on the worksheet is being shown as
member1: Product with Serializable with Foo = NonEmptyFoo(member1,Foo_member1)
and, when someone misses to enter one of the fields as given below
val member2=Foo("member2","")
The output on the worksheet is being shown as
member2: Product with Serializable with Foo = EmptyFoo()
Interesting!! it works...
Please be little patient;
I am able to perform an abstraction and able to come out with a minimal yet good solution. But, I was facing real problem when I wrote the code as follows
val member1=Foo("member1","Foo_member1")
val member2=Foo("member2","Foo_member2")
val member3=Foo("member3","Foo_member3")
val clubMembers=List(member1,member2,member3)
//heres where the problem occurs
val (memName,memId)=clubMembers map(x=>(x.bar1,x.bar2)) unzip
Whooah! I got stuck here, because the compiler, in the lambda expression given below
x=>(x.bar1,x.bar2)
was not able to recognize bar1 and bar2.
But, this solution worked well;
val member1=NonEmptyFoo("member1","Foo_member1")
val member2=NonEmptyFoo("member2","Foo_member2")
val member3=NonEmptyFoo("member3","Foo_member3")
val clubMembers=List(member1,member2,member3)
//heres where the problem occurs
val (memName,memId)=clubMembers map(x=>(x.bar1,x.bar2)) unzip
Apparently, the solution violates abstraction since I am explicitly using the inner class names whereas I should have made use of the name of the trait from where based upon the validation, the compiler shall infer the need for instatiation of the objects as per the inner classes.
Could you please suggest what could be wrong with the new solution.
The reasons due to which the compiler did not recognize bar1 and bar2 will be highly appreciated. Yes alternate solutions do exist yet I would love to be suggested with the problems existing solution and that may be followed by an alternate solution which completely upon your discretion.
Thanks in advance for help!

Inferred type of clubMembers is List[Foo] (even though concrete elements are instances of NonEmptyFoo) and since Foo doesn't have bar1 and bar2 fields, you can't access them in your map invocation. One possible solution would be to add bar1 and bar2 to the Foo:
sealed abstract class Foo(val bar1: String, val bar2: String)
case object EmptyFoo extends Foo("", "")
case class NonEmptyFoo(override val bar1: String, override val bar2: String) extends Foo(bar1, bar2)
object Foo {
def apply(bar1: String, bar2: String): Foo = {
if (bar1.isEmpty || bar2.isEmpty) EmptyFoo else NonEmptyFoo(bar1, bar2)
}
}

Related

Case class with Id with reactivemongo, should be optional or required

I'm building the following api for Users in play scala:
case class User(_id: BSONObjectId, username: String)
The issue is that when the client sends a request in order to store/create a new user the _id is not present.
One viable solution seemed to be:
case class User(_id: Option[BSONObjectId], username: String)
However, it seemed a bit annoying to check for the option field not only for inserting the user, but for the other CRUD operations.
One suggestions that I got was to have two types:
case class User(name: String) ; type UserWithId = (Id, User)
or
case class User[A](id: A, name: String); type UserWithId = User[BSONObjectId]
type UserWithoutId = User[Unit]
I chose the latter implementation as it seemed appropiate.
I created the proper Json Formats to deal with both cases insertion and the other operations:
object User {
lazy val userWithIdFormat: OFormat[UserWithId] = Json.format[UserWithId]
lazy val userWithoutIdFormat: OFormat[UserWithoutId] = Json.format[UserWithoutId]
}
However, now I faced an issue when Inserting, how to convert elegantly from UserWithoutId => UserwithId after the Id has been generated
So the next step was to create this method:
case class User[A](_id: A, username: String)
{
def map[B](f: A => B): User[B] = ???
}
Is this some type of Monad that I need to implement? (Just learning category theory now)
I guess the easiest way is to just add an "initialized/empty" state where the case Class is required to always have an Id, and only when it's persisted it will have username.
Something like val initalizedUser = User(BSONObjectId.generate(), "")
What is the best approach here?
Are using Types would improve performance wise and make the domain more rich, or just adding a state will make it more approachable for future colleagues
What would be the implementation for map, is this something I should extract and have my own Monad implementation to be applied for all future collections?
Is it better to reach for a functional library to solve this issue or not yet?
In my opinion using complex types seems unnecessary here: it won't improve performance and may confuse some colleagues who are not familiar with the concepts.
My favorite approach here is to have two case classes, one for user creation and one to represent the created entity:
case class CreateUser(username: String)
case class User(id: BSONObjectId, username: String)
This has several advantages:
expresses the user intents
you can have different fields in both entities and more complex validation on the CreateUser case class
will be more future proof
The downsize is that it requires to write one more case class, but it's quite easy in scala

Scala immutability in persistent storage with Squeryl

So as I am reading the Play for Scala book, I came across something odd that was explained in the book. This is the relevant snippet:
There's something strange going on, though. If you're using immutable
classes—which vanilla case classes are—you might be worried when you
discover that Squeryl updates your object's supposedly immutable id
field when you insert the object. That means that if you execute the
following code,
val myImmutableObject = Product(0, 5010255079763,
"plastic coated blue", "standard paperclip, coated with blue plastic")
Database.productsTable.insert(myImmutableObject)
println(myImmutableObject)
the output will unexpectedly be something like: Product(13,
5010255079763, "plastic coated blue", "standard paperclip, coated with
blue plastic"). This can lead to bad situations if the rest of your
code expects an instance of one of your model classes to never change.
In order to protect yourself from this sort of stuff, we recommend you
change the insert methods we showed you earlier into this:
def insert(product: Product): Product = inTransaction {
val defensiveCopy = product.copy
productsTable.insert(defensiveCopy)
}
My question is, given that the product class is defined like this:
import org.squeryl.KeyedEntity
case class Product(
id: Long,
ean: Long,
name: String,
description: String) extends KeyedEntity[Long]
Database object is defined like this:
import org.squeryl.Schema
import org.squeryl.PrimitiveTypeMode._
object Database extends Schema {
val productsTable = table[Product]("products")
...
on(productsTable) { p => declare {
p.id is(autoIncremented)
}}
}
How then is it possible that a case class declared as val can have one of its fields changed? Is Squeryl using reflection of some sort to change the field or is the book mistaken somehow?
I am not able to run the examples to verify what the case might be, but someone who has used Squeryl can perhaps give an answer?
You can check the definition of table method for yourself:
https://github.com/squeryl/squeryl/blob/master/src/main/scala/org/squeryl/Schema.scala#L345
It's a generic function which does use reflection to instantiate the Table object bound to the given case class. Functions are first-class citizens in Scala, so they can be assigned to a val just like anything else.
The last fragment is also an asynchronous function, which maps a given argument to some modification defined for it.

Why I need that field like that

case class AlertWindowDto(id: String)
protected val InitialWindowPeriodOneOnPeak = AlertWindowDto(ValidId)
protected val ValidId = "someSite"
I saw these there lines in different different classes. just I put together for understanding.
In general, If i am creating an dummy or some object of Class, then I give some value or null or empty string. What is the need of creating another field ValidId and assign some value and assign that field to final object.
is there any benefit, or anything help in test cases.
could you please help me.
Imagine this:
protected val InitialWindowPeriodOneOnPeak = AlertWindowDto("someSite")
Does it convey the information that "someSite" is a valid id for an alert window?
This is a trivial example, but the general idea is that sometimes breaking down expressions and assigning names to them is great for expressing meaning.
I would also add that the more this naming information is in the types, the better. For instance, here's another way of achieving the same result, without using a variable name.
case class ValidId(value: String) extends AnyVal
case class AlertWindowDto(id: ValidId)
protected val InitialWindowPeriodOneOnPeak = AlertWindowDto(ValidId("someSite"))
Same information, but the "valid id" information is now stored in the type system.

Dealing with nested classes in Scala

I am unable to understand how to work with nested classes in Scala esp when I encountered the error below:
class Action {
val entityModelVar = new EntityModel
}
class EntityModel {
class EntityLabel {
....
}
}
The above code-snippet gives an idea about my class structure. Here's two code blocks that puzzle me on how they work.
val actionList=Array[Action](Action1,Action2)
..
val newLabels=actionList(i).test(doc)
actionList(i).retrain(newLabels) //error pointed here
**Error: type mismatch:
found : Seq[a.entityModelVar.EntityLabel]
required : Seq[_13.entityModelVar.EntityLabel] where _13:Action**
However, the following code compiles without any error:
//This works fine
val a=actionList(i)
val newLabels=a.test(doc2)
a.retrain(newLabels)
Also, here is the definition of the retrain function:
def retrain(labels:Seq[entityModelVar.EntityLabel])={
entityModelVar.retrain(labels)
}
and the signature of EntityModel.retrain function:
def retrain(testLabels:Seq[EntityLabel]):Unit
The problem is that the inner class has got to belong to the same instance of the outer class. But is actionList(i) guaranteed to be the same instance between two calls? The compiler doesn't know for certain (maybe another thread fiddles with it? who knows what apply does anyway?), so it complains. The _13 is its name for a temporary variable that it wishes were there to assure that it is the same instance.
Your next one works because the compiler can see that you call actionList(i) once, store that instance, get an inner class from it and then apply it.
So, moral of the story is: you need to make it abundantly obvious to the compiler that your inner class instances match up to their proper outer class, and the best way to do that is to store that outer class in a val where it can't change without you (or the compiler) noticing.
(You can also specify types of individual variables if you break up parameter blocks. So, for instance: def foo(m: EntityModel)(l: m.EntityLabel) would be a way to write a function that takes an outer class an an inner one corresponding to it.)

Why people define class, trait, object inside another object in Scala?

Ok, I'll explain why I ask this question. I begin to read Lift 2.2 source code these days.
It's good if you happened to read lift source code before.
In Lift, I found that, define inner class and inner trait are very heavily used.
object Menu has 2 inner traits and 4 inner classes. object Loc has 18 inner classes, 5 inner traits, 7 inner objects.
There're tons of codes write like this. I wanna to know why the author write like this.
Is it because it's the author's
personal taste or a powerful use of
language feature?
Is there any trade-off for this kind
of usage?
Before 2.8, you had to choose between packages and objects. The problem with packages is that they cannot contain methods or vals on their own. So you have to put all those inside another object, which can get awkward. Observe:
object Encrypt {
private val magicConstant = 0x12345678
def encryptInt(i: Int) = i ^ magicConstant
class EncryptIterator(ii: Iterator[Int]) extends Iterator[Int] {
def hasNext = ii.hasNext
def next = encryptInt(ii.next)
}
}
Now you can import Encrypt._ and gain access to the method encryptInt as well as the class EncryptIterator. Handy!
In contrast,
package encrypt {
object Encrypt {
private[encrypt] val magicConstant = 0x12345678
def encryptInt(i: Int) = i ^ magicConstant
}
class EncryptIterator(ii: Iterator[Int]) extends Iterator[Int] {
def hasNext = ii.hasNext
def next = Encrypt.encryptInt(ii.next)
}
}
It's not a huge difference, but it makes the user import both encrypt._ and encrypt.Encrypt._ or have to keep writing Encrypt.encryptInt over and over. Why not just use an object instead, as in the first pattern? (There's really no performance penalty, since nested classes aren't actually Java inner classes under the hood; they're just regular classes as far as the JVM knows, but with fancy names that tell you that they're nested.)
In 2.8, you can have your cake and eat it too: call the thing a package object, and the compiler will rewrite the code for you so it actually looks like the second example under the hood (except the object Encrypt is actually called package internally), but behaves like the first example in terms of namespace--the vals and defs are right there without needing an extra import.
Thus, projects that were started pre-2.8 often use objects to enclose lots of stuff as if they were a package. Post-2.8, one of the main motivations has been removed. (But just to be clear, using an object still doesn't hurt; it's more that it's conceptually misleading than that it has a negative impact on performance or whatnot.)
(P.S. Please, please don't try to actually encrypt anything that way except as an example or a joke!)
Putting classes, traits and objects in an object is sometimes required when you want to use abstract type variables, see e.g. http://programming-scala.labs.oreilly.com/ch12.html#_parameterized_types_vs_abstract_types
It can be both. Among other things, an instance of an inner class/trait has access to the variables of its parent. Inner classes have to be created with a parent instance, which is an instance of the outer type.
In other cases, it's probably just a way of grouping closely related things, as in your object example. Note that the trait LocParam is sealed, which means that all subclasses have to be in the same compile unit/file.
sblundy has a decent answer. One thing to add is that only with Scala 2.8 do you have package objects which let you group similar things in a package namespace without making a completely separate object. For that reason I will be updating my Lift Modules proposal to use a package object instead of a simple object.