Failing in a companion object's apply mehod
scala
Solution
This is a bit subjective, but I don't think you should do either.
Suppose you allow `apply` to fail, i.e. throw an exception or return an empty option. Then doing `val url = Url(someString)` might fail, despite looking awfully like a constructor. That's the whole problem: the `apply` method of a companion object should reliably construct new instances for you, and you simply cannot reliably construct `Url` instances from arbitrary Strings. So don't do that.
`unapply` should generally be used to take a valid `Url` object and return another representation with which you could create a `Url` again. As an example of this, look at the generated `unapply` method for case classes, which simply returns a tuple containing the arguments with which it was constructed. So the signature should actually be `def unapply(url: Url): String`.
So my conclusion is that neither should be used for the construction of a `Url`. I think it would be the most idiomatic to have a method `def parse(str: String): Option[Url]` to make explicit what you're actually doing (parsing the string) and that it might fail. You can then do `Url.parse(someString).map(url => ...)` to use your `Url` instance.
Problem
It's common for Scala classes to have `apply` and `unapply` methods in their companion object. The behaviour of `unapply` is unambiguous: if its parameter is or can be transformed into a valid instance of the class, return a `Some` of it. Otherwise, return `None`. To take a concrete example, let's imagine a `Url` case class: ``` object Url { def apply(str: String): Url = ??? def unapply(str: String): Option[Url] = ??? } case class Url(protocol: String, host: String, path: String) ``` If `str` is a valid URL, then `unapply` will return a `Some[Url]`, otherwise `None`. `apply` is a bit less clear to me, however: how should it react to `str` not being a valid URL? Coming from the Java world, my first instinct is to throw an `IllegalArgumentException`, which would allow us to implement the companion object as: ``` object Url { def apply(str: String): Url = ... // some function that parses a URI and throws if it fails. def unapply(str: String): Option[Url] = Try(apply(str)).toOption } ``` I understand that this is not considered terribly good practice in the functional world (as explained, for example, in this answer). The alternative would be to have `apply` return an `Option[Url]`, in which case it'd be a simple clone of `unapply` and better left unimplemented. Is that the correct conclusion to reach? Should this type of potentially failing `apply` methods simply not be implemented? Is throwing, in this case, considered to be ok? Is there a third option that I'm not seeing?