10

I am reading this example from their docs:

class Email(val username: String, val domainName: String)

object Email {
  def fromString(emailString: String): Option[Email] = {
    emailString.split('@') match {
      case Array(a, b) => Some(new Email(a, b))
      case _ => None
    }
  }
}

println(Email.fromString("scala.center@epfl.ch"))
val scalaCenterEmail = Email.fromString("scala.center@epfl.ch")
scalaCenterEmail match {
  case Some(email) => println(
    s"""Registered an email
       |Username: ${email.username}
       |Domain name: ${email.domainName}
     """)
  case None => println("Error: could not parse email")
}

My questions:

  1. What is Some and Option?

  2. What is a factory method (just some function that creates a new object and returns it?)

  3. What is the point of companion objects? Is it just to contain functions that are available to all instances of class? Are they like class methods in Ruby?

Jwan622
  • 11,015
  • 21
  • 88
  • 181
  • Factory is a design pattern and is not specific to Scala. Regarding the rest of the questions, there are a few good books and tutorials on scala, just search: https://stackoverflow.com/questions/609744/what-is-the-rationale-behind-having-companion-objects-in-scala http://danielwestheide.com/blog/2012/12/19/the-neophytes-guide-to-scala-part-5-the-option-type.html – nmat Apr 20 '18 at 15:33
  • Option is an [Algebraic Data Type](https://en.wikipedia.org/wiki/Algebraic_data_type), in functional programming functions are designed to not break the function into an error, instead safely/consistent return the same type of data so you can process it later, more on [side-effects](https://en.wikipedia.org/wiki/Side_effect_(computer_science)). Like in Int you could return the values ...-2323,...,1,2,3... in Option you could return Some if it succeeded and None if it fails. – Jader Martins Apr 20 '18 at 15:48
  • 2
    If you have multiple questions, please ask multiple questions. In particular, every single one of our three questions has already been asked and answered multiple times already on [so], but it is *impossible* to point to those questions using the built-in duplicate system because your question mashes them up into one. One of the important features of [so] is that knowledge is accessible via multiple different questions, but your questions breaks that system. – Jörg W Mittag Apr 20 '18 at 20:59
  • 2
    Shouldn't you be reading a good introduction/tutorial instead of reading documentation you don't understand and running to SO with questions that any Scala beginner can answer? – jwvh Apr 20 '18 at 21:50

2 Answers2

31

What is Some and Option?

Option is a data structure that represents optionality, as the name suggests. Whenever a computation may not return a value, you can return an Option. Option has two cases (represented as two subclasses): Some or None.

In the example above, the method Email.fromString can fail and not return a value. This is represented with Option. In order to know whether the computation yielded a value or not, you can use match and check whether it was a Some or a None:

Email.fromString("scala.center@epfl.ch") match {
  case Some(email) => // do something if it's a Some
  case None => // do something it it's a None
}

This is much better than returning null because now whoever calls the method can't possibly forget to check the return value.

For example compare this:

def willReturnNull(s: String): String = null

willReturnNull("foo").length() // NullPointerException!

with this

def willReturnNone(s: String): Option[String] = None

willReturnNone("foo").length() // doesn't compile, because 'length' is not a member of `Option`

Also, note that using match is just a way of working with Option. Further discussion would involve using map, flatMap, getOrElse or similar methods defined on Option, but I feel it would be off-topic here.

What is a factory method (just some function that creates a new object and returns it?)

This is nothing specific to Scala. A "factory method" is usually a static method that constructs the value of some type, possibly hiding the details of the type itself. In this case fromString is a factory method because it allows you create an Email without calling the Email constructor with new Email(...)

What is the point of companion objects? Is it just to contain functions that are available to all instances of class? Are they like class methods in Ruby?

As a first approximation, yes. Scala doesn't have static members of a class. Instead, you can have an object associated with that class where you define everything that is static.

E.g. in Java you would have:

public class Email {
   public String username;
   public String domain;
   public static Optional<Email> fromString(String: s) {
      // ...
   }
}

Where as in Scala you would define the same class as roughly:

class Email(val username: String, val domain: String)
object Email {
  def fromString(s: String): Option[Email] = {
    // ...
  }
}
Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
  • 5
    _This is much better than returning null because now whoever calls the method can't possibly forget to check the return value._ Thank you. That's what I needed. – sennett Oct 07 '21 at 15:15
0

I would like to add some examples/information to the third question.

If you use akka in companion object you can put every message that you use in case method (it should proceed and use by actor). Moreover, you can add some val for a name of actors or other constant values.

If you work with JSON you should create a format for it (sometimes custom reads and writes). This format you should put inside companion object. Methods to create instances too.

If you go deeper to Scala you can find case classes. So a possibility to create an object of this class without new is because there is a method apply in "default" companion object.

But in general, it's a place where you can put every "static" method etc.

About Option, it provides you a possibility to avoid some exception and make something when you don't have any values. Gabriele put an example with email, so I'll add another one. You have a method that sends email, but you take email from User class. The user can have this field empty, so if we have something like it val maybeEmail: Option[String] = user.email you can use for example map to send an email maybeEmail.map(email => sendEmail(email))

So if you use it, during writing methods like above you don't need to think that user specify his email or not :)

Patryk Rudnicki
  • 755
  • 1
  • 8
  • 21