Why "case class" doesn't need "new" to create a new object - class

In Scala what is the reason that you don't need to use "new" to create a new "case class"?
I tried searching for awhile now without answers.

Do you want the how or the why? As the other answer notes, the how is just the apply method on the automatically generated companion object.
For the why: case classes are often used to implement algebraic data types in Scala, and the new-less constructor allows code that is more elegant (creating a value looks more like deconstructing it via pattern matching, for example) and that more closely resembles ADT syntax in other languages.

Case class has prebuilt companion object with apply() implemented. Someone even complains about this: How to override apply in a case class companion :)

Case classes provide you with an automatically generated apply function on their companion object that you can use like a constructor.
In Scala decompiled byte code you will find apply function created as the following :
object Person {
def apply(name: String, age: Integer): Person = new Person(name,age)
}
Example :
case class Person(name: String, age: Integer)
The following three all do the same thing.
val p0 = new Person("Frank", 23) // normal constructor
val p1 = Person("Frank", 23) // this uses apply
val p2 = Person.apply("Frank", 23) // using apply manually
So if you use val p1 = Person("Frank", 23) it is not a constructor, this a method that call apply method.
Please read scala-object-apply-functions for more info.

Related

Is it possible to create a secondary constructor without a macro annotation in Scala?

I would like to create a macro that generates a secondary constructor{'s body). Is it possible to do this without resorting to macro annotations? (i.e. macro-paradise plugin)
For example:
Something like this:
class A(a : String, b : String) {
def this(s : List[Any]) = macro fromlist
}
Should be equivalent to something like this:
class A(a : String, b : String) {
def this(s : List[Any]) = this(s.head.toString, s.tail.head.toString)
}
Simply using the "macro" keyword does not seem to help. Is this completely disallowed in plain Scala? Thanks.
The problem is, that a constructor is not a method returning a new instance, but a method initializing an already created one. (So the = in your constructor definition does not make sense, the parent constructor does not return anything).
The next problem is, that an alternative constructor in Scala has to call an other constructor as the first step, you cannot call something else, not even a macro.
You could however call a macro to generate the parameters to this, like
this(fromList(s): _*)
But why would you even want to do that? It is very uncommon in Scala to have multiple constructors. The common way is to have an overloaded apply method in the companion object. You don't have any restrictions there.

Trouble with constructors in Scala

It's been a while since I've used constructors at all- so naturally when I have to use one in Scala I'm having trouble.
I want to do the following: When I create a new class without passing through anything- it creates an empty vector.
Otherwise if it passes through a vector- we use that vector and define it to be used with the class.
How do I do this? I previously had
Class example{
val a: Vector[int] = Vector();
Then I'm lost. I was thinking of doing something like
Class example{
val a: Vector[Int] = Vector()
def this(vector: Vector[Int]){
this{
a = vector
}
}
But I'm getting tons of errors. Can anyone help? I'm trying to find my scala book but I can't find it- I know it had a good section on constructors.
Sounds like you want a constructor with a default argument:
class example(val a : Vector[Int] = Vector())
If you really want to do this by constructor overloading, it looks like this:
class Example(val a: Vector[Int]) {
def this() = this(Vector())
}
Personal-opinion addendum: Overloading and default arguments are often good to avoid. I'd recommend just making a different function that calls the constructor:
class Example(val a: Vector[Int])
object Example {
def empty = new Example(Vector())
}
case class Example(a: Vector[Int] = Vector())
No need to put the val keyword.
Also, using the case keywork you get:
a compact initialisation syntax: Example(Vector(1,2)), instead of new Example(Vector(1,2))
pattern matching for you class
equality comparisons implicitly defined and pretty toString
Reference

Pre-process parameters of a case class constructor without repeating the argument list

I have this case class with a lot of parameters:
case class Document(id:String, title:String, ...12 more params.. , keywords: Seq[String])
For certain parameters, I need to do some string cleanup (trim, etc) before creating the object.
I know I could add a companion object with an apply function, but the LAST thing I want is to write the list of parameters TWICE in my code (case class constructor and companion object's apply).
Does Scala provide anything to help me on this?
My general recommendations would be:
Your goal (data preprocessing) is the perfect use case of a companion object -- so it is maybe the most idiomatic solution despite the boilerplate.
If the number of case class parameters is high the builder pattern definitely helps, since you do not have to remember the order of the parameters and your IDE can help you with calling the builder member functions. Using named arguments for the case class constructor allows you to use a random argument order as well but, to my knowledge, there is not IDE autocompletion for named arguments => makes a builder class slightly more convenient. However using a builder class raises the question of how to deal with enforcing the specification of certain arguments -- the simple solution may cause runtime errors; the type-safe solution is a bit more verbose. In this regard a case class with default arguments is more elegant.
There is also this solution: Introduce an additional flag preprocessed with a default argument of false. Whenever you want to use an instance val d: Document, you call d.preprocess() implemented via the case class copy method (to avoid ever typing all your arguments again):
case class Document(id: String, title: String, keywords: Seq[String], preprocessed: Boolean = false) {
def preprocess() = if (preprocessed) this else {
this.copy(title = title.trim, preprocessed = true) // or whatever you want to do
}
}
But: You cannot prevent a client to initialize preprocessed set to true.
Another option would be to make some of your parameters a private val and expose the corresponding getter for the preprocessed data:
case class Document(id: String, title: String, private val _keywords: Seq[String]) {
val keywords = _keywords.map(kw => kw.trim)
}
But: Pattern matching and the default toString implementation will not give you quite what you want...
After changing context for half an hour, I looked at this problem with fresh eyes and came up with this:
case class Document(id: String, title: String, var keywords: Seq[String]) {
keywords = keywords.map(kw => kw.trim)
}
I simply make the argument mutable adding var and cleanup data in the class body.
Ok I know, my data is not immutable anymore and Martin Odersky will probably kill a kitten after seeing this, but hey.. I managed to do what I want adding 3 characters. I call this a win :)

Scala: validating arguments in overloaded constructors

Is it possible to validate arguments in an overloaded constructor before calling the default one? E.g. assume that my class has a default constructor
Clazz(foo: String, bar: String)
And I would like to provide another constructor
def this(fooBar: String) {
//validate if fooBar is of form FOO-BAR, if not, throw some custom exception, else invoke
this(fooBar.split("-")(0), fooBar.split("-")(1))
}
Is it possible to somehow perform the validation?
Auxiliary constructors in Scala have to invoke another constructor as the first thing they do, see the Scala Language Reference, Section 5.3.1, p. 74 or Scala constructor overload? So, validation of arguments in the way suggested is not possible.
See also Why can auxiliary constructors in Scala only consist of a single call to another constructor? The book "Programming in Scala" by Odersky, Spoon, and Venners sates the following on this topic (Section 6.7, p. 147):
If you’re familiar with Java, you may wonder why Scala’s rules for
constructors are a bit more restrictive than Java’s. In Java, a
constructor must either invoke another constructor of the same class,
or directly invoke a constructor of the superclass, as its first
action. In a Scala class, only the primary constructor can invoke a
superclass constructor. The increased restriction in Scala is really a
design trade-off that needed to be paid in exchange for the greater
conciseness and simplicity of Scala’s constructors compared to Java’s.
Superclasses and the details of how constructor invocation and
inheritance interact will be explained in Chapter 10.
As a solution to your question, you might want to consider factory objects, see, e.g., http://fupeg.blogspot.in/2008/11/scala-constructors.html or http://alvinalexander.com/scala/factory-pattern-in-scala-design-patterns This would lead to something like the following (with a more sophisticated validation, probably):
case class Clazz(foo : String, bar : String)
case class FooBarException(msg: String) extends RuntimeException(msg)
object Clazz {
def apply(fooBar : String) : Clazz =
if (fooBar.count(_ == '-') == 1)
new Clazz(fooBar.split("-")(0), fooBar.split("-")(1))
else
throw new FooBarException("not valid: " + fooBar)
}
object Test extends App {
val c1 = Clazz("foo", "bar")
println(c1)
val c2 = Clazz("foo-bar")
println(c2)
try {
val c3 = Clazz("will throw error")
} catch {
case FooBarException(msg) => println(msg)
}
}

What is the apply function in Scala?

I never understood it from the contrived unmarshalling and verbing nouns ( an AddTwo class has an apply that adds two!) examples.
I understand that it's syntactic sugar, so (I deduced from context) it must have been designed to make some code more intuitive.
What meaning does a class with an apply function give? What is it used for, and what purposes does it make code better (unmarshalling, verbing nouns etc)?
how does it help when used in a companion object?
Mathematicians have their own little funny ways, so instead of saying "then we call function f passing it x as a parameter" as we programmers would say, they talk about "applying function f to its argument x".
In mathematics and computer science, Apply is a function that applies
functions to arguments.
Wikipedia
apply serves the purpose of closing the gap between Object-Oriented and Functional paradigms in Scala. Every function in Scala can be represented as an object. Every function also has an OO type: for instance, a function that takes an Int parameter and returns an Int will have OO type of Function1[Int,Int].
// define a function in scala
(x:Int) => x + 1
// assign an object representing the function to a variable
val f = (x:Int) => x + 1
Since everything is an object in Scala f can now be treated as a reference to Function1[Int,Int] object. For example, we can call toString method inherited from Any, that would have been impossible for a pure function, because functions don't have methods:
f.toString
Or we could define another Function1[Int,Int] object by calling compose method on f and chaining two different functions together:
val f2 = f.compose((x:Int) => x - 1)
Now if we want to actually execute the function, or as mathematician say "apply a function to its arguments" we would call the apply method on the Function1[Int,Int] object:
f2.apply(2)
Writing f.apply(args) every time you want to execute a function represented as an object is the Object-Oriented way, but would add a lot of clutter to the code without adding much additional information and it would be nice to be able to use more standard notation, such as f(args). That's where Scala compiler steps in and whenever we have a reference f to a function object and write f (args) to apply arguments to the represented function the compiler silently expands f (args) to the object method call f.apply (args).
Every function in Scala can be treated as an object and it works the other way too - every object can be treated as a function, provided it has the apply method. Such objects can be used in the function notation:
// we will be able to use this object as a function, as well as an object
object Foo {
var y = 5
def apply (x: Int) = x + y
}
Foo (1) // using Foo object in function notation
There are many usage cases when we would want to treat an object as a function. The most common scenario is a factory pattern. Instead of adding clutter to the code using a factory method we can apply object to a set of arguments to create a new instance of an associated class:
List(1,2,3) // same as List.apply(1,2,3) but less clutter, functional notation
// the way the factory method invocation would have looked
// in other languages with OO notation - needless clutter
List.instanceOf(1,2,3)
So apply method is just a handy way of closing the gap between functions and objects in Scala.
It comes from the idea that you often want to apply something to an object. The more accurate example is the one of factories. When you have a factory, you want to apply parameter to it to create an object.
Scala guys thought that, as it occurs in many situation, it could be nice to have a shortcut to call apply. Thus when you give parameters directly to an object, it's desugared as if you pass these parameters to the apply function of that object:
class MyAdder(x: Int) {
def apply(y: Int) = x + y
}
val adder = new MyAdder(2)
val result = adder(4) // equivalent to x.apply(4)
It's often use in companion object, to provide a nice factory method for a class or a trait, here is an example:
trait A {
val x: Int
def myComplexStrategy: Int
}
object A {
def apply(x: Int): A = new MyA(x)
private class MyA(val x: Int) extends A {
val myComplexStrategy = 42
}
}
From the scala standard library, you might look at how scala.collection.Seq is implemented: Seq is a trait, thus new Seq(1, 2) won't compile but thanks to companion object and apply, you can call Seq(1, 2) and the implementation is chosen by the companion object.
Here is a small example for those who want to peruse quickly
object ApplyExample01 extends App {
class Greeter1(var message: String) {
println("A greeter-1 is being instantiated with message " + message)
}
class Greeter2 {
def apply(message: String) = {
println("A greeter-2 is being instantiated with message " + message)
}
}
val g1: Greeter1 = new Greeter1("hello")
val g2: Greeter2 = new Greeter2()
g2("world")
}
output
A greeter-1 is being instantiated with message hello
A greeter-2 is being instantiated with message world
TLDR for people comming from c++
It's just overloaded operator of ( ) parentheses
So in scala:
class X {
def apply(param1: Int, param2: Int, param3: Int) : Int = {
// Do something
}
}
Is same as this in c++:
class X {
int operator()(int param1, int param2, int param3) {
// do something
}
};
1 - Treat functions as objects.
2 - The apply method is similar to __call __ in Python, which allows you to use an instance of a given class as a function.
The apply method is what turns an object into a function. The desire is to be able to use function syntax, such as:
f(args)
But Scala has both functional and object oriented syntax. One or the other needs to be the base of the language. Scala (for a variety of reasons) chooses object oriented as the base form of the language. That means that any function syntax has to be translated into object oriented syntax.
That is where apply comes in. Any object that has the apply method can be used with the syntax:
f(args)
The scala infrastructure then translates that into
f.apply(args)
f.apply(args) has correct object oriented syntax. Doing this translation would not be possible if the object had no apply method!
In short, having the apply method in an object is what allows Scala to turn the syntax: object(args) into the syntax: object.apply(args). And object.apply(args) is in the form that can then execute.
FYI, this implies that all functions in scala are objects. And it also implies that having the apply method is what makes an object a function!
See the accepted answer for more insight into just how a function is an object, and the tricks that can be played as a result.
To put it crudely,
You can just see it as custom ()operator. If a class X has an apply() method, whenever you call X() you will be calling the apply() method.