When should I use "new" in scala? - scala

When I use ArrayBuffer, I should use:
val arr = new ArrayBuffer[Int]
but when I use Map, I should use:
val map = Map[Int, Int]()

To understand why you need to use Map[T, T]() and not new Map[T, T](...), you need to understand the how the apply method on a companion object works.
A companion object is an object that has the same name as a class along with it. This object contains, generally, contains factory methods and other methods that you need to create (easily) the objects of the class.
To make sure that one doesn't have to go through a lot of verbose code, Scala makes use of the apply method which is executed directly when you call the object as you would call a function.
So, the companion object of Map must look something like this:
object Map {
def apply[K, V](...) = new Map[K,V](...) // Or something like this
}
While the class would be something like
protected class Map[K, V](...) {
...
}
Now calling Map[String, String](...) you are actually calling the apply method of the Map companion object.
ArrayBuffer, here, does not have a companion object though. Thus, you need to create a new instance of the class yourself by directly using the constructor.

Related

scala: Any default apply method in a class?

Does scala provide a default apply method for a class?
I have a class:
class Player(tea: String, sal: Int = 0) {
val team = tea
private val salary = sal
}
So no apply method here, and I haven't defined any companion object for it, so no apply method from there too.
But I am able to do:
val player = Player("AAAA", 1000)
With no 'new' operator used, I understand that this line of code must invoke some apply method. But there is none defined by me. So how does it work?
Yes, since Scala 3, as described in the docs:
Scala case classes generate apply methods, so that values of case classes can be created using simple function application, without needing to write new.
Scala 3 generalizes this scheme to all concrete classes. Example:
class StringBuilder(s: String):
def this() = this("")
StringBuilder("abc") // old: new StringBuilder("abc")
StringBuilder() // old: new StringBuilder()
This works since a companion object with two apply methods is generated together with the class. The object looks like this:
object StringBuilder:
inline def apply(s: String): StringBuilder = new StringBuilder(s)
inline def apply(): StringBuilder = new StringBuilder()
The synthetic object StringBuilder and its apply methods are called constructor proxies. Constructor proxies are generated even for Java classes and classes coming from Scala 2. The precise rules are as follows:
A constructor proxy companion object object C is created for a concrete class C, provided the class does not have already a companion, and there is also no other value or method named C defined or inherited in the scope where C is defined.
Constructor proxy apply methods are generated for a concrete class provided
the class has a companion object (which might have been generated in step 1), and
that companion object does not already define a member named apply.
Each generated apply method forwards to one constructor of the class. It has the same type and value parameters as the constructor.

Understanding companion object in scala

While learning Scala, I came across interesting concept of companion object. Companion object can used to define static methods in Scala. Need few clarifications in the below Spark Scala code in regard of companion object.
class BballStatCounter extends Serializable {
val stats: StatCounter = new StatCounter()
var missing: Long = 0
def add(x: Double): BballStatCounter = {
if (x.isNaN) {
missing += 1
} else {
stats.merge(x)
}
this
}
}
object BballStatCounter extends Serializable {
def apply(x: Double) = new BballStatCounter().add(x)
}
Above code is invoked using val stat3 = stats1.map(b=>BballStatCounter(b)).
What is nature of variables stats and missing declared in the
class? Is it similar to class attributes of Python?
What is the significance of apply method in here?
Here stats and missing are class attributes and each instance of BballStatCounter will have their own copy of them just like in Python.
In Scala the method apply serves a special purpose, if any object has a method apply and if that object is used as function calling notation like Obj() then the compiler replaces that with its apply method calling, like Obj.apply() .
The apply method is generally used as a constructor in a Class Companion object.
All the collection Classes in Scala has a Companion Object with apply method, thus you are able to create a list like : List(1,2,3,4)
Thus in your above code BballStatCounter(b) will get compiled to BballStatCounter.apply(b)
stats and missing are members of the class BcStatCounter. stats is a val so it cannot be changed once it has been defined. missing is a var so it is more like a traditional variable and can be updated, as it is in the add method. Every instance of BcStatCounter will have these members. (Unlike Python, you can't add or remove members from a Scala object)
The apply method is a shortcut that makes objects look like functions. If you have an object x with an apply method, you write x(...) and the compiler will automatically convert this to x.apply(...). In this case it means that you can call BballStatCounter(1.0) and this will call the apply method on the BballStatCounter object.
Neither of these questions is really about companion objects, this is just the normal Scala class framework.
Please note the remarks in the comments about asking multiple questions.

Scala - how to access an object from a class?

I want to create a Map with information about sales in one class (object) and that use it in another class ProcessSales - iterate over the Map keys and use values. I have already written logic creating a Map in an object SalesData.
However since I've started learning Scala not long ago I'm not sure if it is a good approach to implement the logic in an object.
What will be the correct way to access the Map from another class?
Should the Map be created in an object or in a separate class? Or maybe it's better to create an object in the ProcessSales class that will be using it?
Could you share best practices and examples?
object SalesData {
val stream : InputStream = getClass.getResourceAsStream("/sales.csv")
val salesIterator: Iterator[String] = scala.io.Source.fromInputStream(stream).getLines
def getSales(salesData: Iterator[String]): Map[Int, String] = {
salesData
.map(_.split(","))
.map(line => (line(0).toInt, line(1)))
.toMap
}
val salesMap: Map[Int, String] = getSales(salesIterator)
}
If you wanted flexibility to "mix in" this map you could put the map and getSales() into a new trait.
If, on the other hand, you wanted to insure one and only one factory method existed to create the map, you could put getSales() into a companion object, which has to have the same name as your class and defined in the same source file. For example,
object ProcessSales {
def getSales():Map[Int,String] = {...}
}
Remember that methods in a companion object are analogous to static methods in Java.
It is also possible to put the map instance itself into the companion object, if you want the map to be a singleton--one map instance per many instances of ProcessSales.
Or, if you want 1 such map per each instance of ProcessSales, you would make it a field within the ProcessSales class.
Or, if you wanted the map to be available to all members of a class hierarchy under ProcessSales, you could make ProcessSales an abstract class. But regarding use of an abstract class, remember that use of a trait affords greater flexibility in case you are not certain that all subclasses in the hierarchy will need the map.
It all depends on how you want to use it. Scala is more functional oriented. So for the best practice, you could define getSalesData in an object and in another object you could pass the parameters and call the def getSalesData.
For example,
import packaganame.SalesData._;
Object Check {
val stream : InputStream = getClass.getResourceAsStream("/sales.csv");
val salesIterator: Iterator[String] = scala.io.Source.fromInputStream(stream).getLines;
val salesMap = getSales(salesIterator);
}

Scala Apply Method in companion object

I have created a companion object for my Scala class with an apply method in it so that I can create an instance of my class without using 'new'.
object StanfordTokenizer{
def apply() = new StanfordTokenizer()
}
class StanfordTokenizer() extends Tokenizer{
def tokenizeFile(docFile: java.io.File) = new PTBTokenizer(new FileReader(docFile), new CoreLabelTokenFactory(), "").tokenize.map(x => x.word().toLowerCase).toList
def tokenizeString(str: String) = new PTBTokenizer(new StringReader(str), new CoreLabelTokenFactory(), "").tokenize.map(x => x.word.toLowerCase()).toList
}
However when I try to instantiate the StanfordTokenizer class without 'new' e.g. StandfordTokenizer.tokenizeString(str).
I get the error
value tokenizeString is not a member of object StanfordTokenizer
However, if I explicitly include the apply method like StandfordTokenizer.apply().tokenizeString(str) it does work.
I feel like I am missing something fundamental about companion objects. Can someone shed some light on this for me?
^
It's exactly as the compiler message says. tokenizeString is a member of the class StandfordTokenizer, but not its companion object. The companion object does not inherit any methods from the class. Therefore, in order to use tokenizeString, you need an instance of StandfordTokenizer in order to call it.
StandfordTokenizer.apply creates an instance of the class StandfordTokenizer, which has the method tokenizeString. It seems as though the class StandfordTokenizer holds no real information, and won't have more than one instance. If that is true, you should probably just make it an object, and you'll be able to acquire the behavior you're looking for.
object StanfordTokenizer extends Tokenizer {
def tokenizeFile(docFile: java.io.File) = ...
def tokenizeString(str: String) = ...
}
This should work as well (as a class):
StandfordTokenizer().tokenizeString(str)
StandfordTokenizer without parenthesis does not call apply, it references the object. StandfordTokenizer() does call apply, and creates a new instance of the class. This is probably the source of your confusion.

Using .tupled method when companion object is in class

I am in the process of migrating from Slick to Slick 2, and in Slick 2 you are meant to use the tupled method when projecting onto a case class (as shown here http://slick.typesafe.com/doc/2.0.0-RC1/migration.html)
The problem is when the case class has a companion object, i.e. if you have something like this
case class Person(firstName:String, lastName:String) {
}
Along with a companion object
object Person {
def something = "rawr"
}
In the same scope, the tupled method no longer works, because its trying to run tupled on the object, instead of the case class.
Is there a way to retrieve the case class of Person rather than the object, so you can call tupled properly?
You can also write
(Person.apply _).tupled
to avoid repeating the types.
This is very similar to what Alexey Romanov said, but in order to avoid lifting apply whenever you need tupled, we just add it to our companion objects.
object Person {
def something = "rawr"
def tupled = (Person.apply _).tupled
}
Now you can call Person.tupled just like you would have if it didn't have a companion object.
One workaround is define a companion object as follows:
object Person extends((String,String) => Person) {
...
}
See. https://groups.google.com/d/msg/scala-user/jyWBMz5Qslw/Bryv4ftzRLgJ
To build on some of the other comments you could do the following as well since tuple is calling the generated default apply method for the case class.
object Person {
...
def tupled = (this.apply _).tupled
}