what is '???' in Scala? - scala

I'm learning Scala using IntelliJ IDE.
When I subs class Element and override contents method, IDE provided default implementation for contents method with definition ???
Below code from the book Programming in Scala, 3rd edition
Element
abstract class Element {
def contents: Array[String]
def height = contents.length
def width = if (height == 0) 0 else contents(0).length
}
ArrayElement
class ArrayElement(cont: Array[String]) extends Element {
override def contents: Array[String] = ??? // impl provided by IDE
}
I don't see any issues in running the program but when I access the method I get below exception
Exception in thread "main" scala.NotImplementedError: an implementation is missing
at scala.Predef$.$qmark$qmark$qmark(Predef.scala:284)
at org.saravana.scala.ArrayElement.contents(ScalaTest.scala:65)
Can someone explain what is ??? and use of it?

??? is designed as a placeholder and is a method defined in Predef (which is automatically imported by default)
It's definition is
def ??? : Nothing = throw new NotImplementedError
So it has return type Nothing and all it does is throw NotImplementedError. This definition allows it to used as a placeholder implementation for methods you defined but haven't implemented yet but still want to be able to compile your program.
Nothing is a subtype of every type, which makes ??? a valid implementation no matter what type is expected.

Related

Option and null in Scala

If I have the following function:
def getOrNull[T >: Null](f: => T): T = {
try { f } catch { case _: NullPointerException => null }
}
And I want to use it with Option like so:
val r = Option(getOrNull(someString.split("/")(0)))
I get:
Error:(25, 19) Option.type does not take parameters
What is going on, and how can I overcome this?
You might wonder what Option you are referring to.
From sbt console, use //print<tab>:
scala> Option //print
scala.Option // : Option.type
For better context:
package nooption
class Option(arg: String) // some other option on class path
object Option
object Test {
import scala.reflect.internal.util.ScalaClassLoader
def main(args: Array[String]): Unit = println {
//Option(null)
//ScalaClassLoader.originOfClass(classOf[Option])
ScalaClassLoader.originOfClass(classOf[Option$])
}
}
The class name for the companion object has a dollar at the end.
Your IDE might "go to definition."
If you started a REPL at the command line, class files in the current directory are on its class path. If you previously compiled an Option in the default or "empty" package, it will hide scala.Option.
As noted in the comments, this code does compile OK, but you really shouldn't use null in Scala unless you are interfacing with Java.
This is a better way of implementing your code:
val r = Try{ someString.split("/")(0) }.toOption
Try is widely used in Scala so this code is clear to anyone experienced with the language, so there is no need for a separate function.

Strange Scala compiler error when removing a call to a function that has Unit return type, how is this even possible?

Here is a strange situation:
If I comment out the call to feed_usingExplicitTypeClassInstance below, then I get a compiler error.
Very puzzling. Any explanation ?
I mean, I comment out a function call (which returns no value) and then the code does not compile anymore ?
Should this be even possible at all in theory ? In any programming language ?
I mean I comment out something like println("hello") and then the code does not compile anymore ?
Of course it would be understandable if I would comment out a declaration or something, but a call to a function that does not return anything ?
object AnimalFeeder extends App {
def feed_usingExplicitTypeClassInstance[AnimalInstance]
(animalTypeClass: AnimalTypeClass[AnimalInstance])
(food: animalTypeClass.FoodThatAnimalLikes) =
{
animalTypeClass.feed(food)
}
def feed_usingImplicitTypeClassInstance[AnimalInstance, Food]
(food: Food)
(implicit animalTypeClass: AnimalTypeClass.Aux[Food,AnimalInstance]) =
{
animalTypeClass.feed(food)
}
// If I comment out this line, THEN !, I get an error !!!! How ???
feed_usingExplicitTypeClassInstance(AnimalTypeClass.CatInstance)(new CatFood())
feed_usingImplicitTypeClassInstance(new CatFood)
}
trait Food {
def eat(): Unit
}
trait AnimalTypeClass[AnimalInstance] {
type FoodThatAnimalLikes <: Food
def feed(f: FoodThatAnimalLikes) = f.eat()
}
object AnimalTypeClass {
type Aux[Food, Animal] = AnimalTypeClass[Animal] {
type FoodThatAnimalLikes = Food
}
implicit object CatInstance extends AnimalTypeClass[Cat] {
override type FoodThatAnimalLikes = CatFood
}
}
trait Cat
class CatFood extends Food {
override def eat(): Unit = println("meow")
}
This is the error:
Error:(23, 38) could not find implicit value for parameter animalTypeClass: AnimalTypeClass.Aux[CatFood,AnimalInstance]
feed_usingImplicitTypeClassInstance(new CatFood)
Error:(23, 38) not enough arguments for method feed_usingImplicitTypeClassInstance: (implicit animalTypeClass: AnimalTypeClass.Aux[CatFood,AnimalInstance])Unit.
Unspecified value parameter animalTypeClass.
feed_usingImplicitTypeClassInstance(new CatFood)
EDIT:
If I insert the line:
AnimalTypeClass.CatInstance
before:
feed_usingImplicitTypeClassInstance(new CatFood)
then the code compiles again, even if the line
feed_usingExplicitTypeClassInstance(AnimalTypeClass.CatInstance)(new CatFood())
is commented out.
This is a pretty well known issue, where implicits which appear after their usage in the same file and without an explicit type annotation are not found. For that reason it is strongly advised (and this will eventually be enforced) to give all non-local implicits an explicit type annotation. Unfortunately implicit objects are a bit tricky here, because they always act like implicit definitions without type annotation, and it is impossible to give them an explicit type... However last I checked this seemed to be fixed in Dotty for implicit objects.
See also, among others https://github.com/scala/bug/issues/8697
The reason that it does work when you uncomment a call to AnimalTypeClass.CatInstance in your code is that that reference will force the implicit object to be type checked earlier, so its type will be known before its implicit usage.
You have the definition of the implicit value in the same file after the usage of this value. It is not initialized when the compiler looks for an implicit value when you call feed_usingImplicitTypeClassInstance. Calling feed_usingExplicitTypeClassInstance with an explicit reference to this implicit value forces the implicit to initialize, and the compiler can use it in the implicit call.
Possible solutions:
Move the definition of the implicit value to another file.
If the implicit value is in the same file, move its definition above the place where you use it implicitly.

Need held with scala compile time error when defining a lagom service implementation

I've been using lagom with Java for some time without problems, but am struggling to get it to work with scala (disclosure - since I am
fairly new to scala, I am probably doing something daft).
I have defined a (very) minimal lagom service (below) which should not cause
any problems, but I am getting the scala compile-time error "missing parameter type" for the underscore parameter in the implementation
code and I do not understand why.... I thought that the scala implicit typing
should do the necessary but obviously I am wrong.
Can anybody help? I am probably doing something stupid, but for the life of me I cannot see what.
Regards,
Rick
This is my service interface (API) definition (in the file MyService-api/MyTestService.scala):
trait MyTestService extends Service {
def myTest2(cmd: String) : ServiceCall[NotUsed, String] // (abstract) method definition
override final def descriptor = { // Service Descriptor
import Service._
named("myTest2") // service name
.withCalls {
pathCall("myTest/:cmd", myTest2 _) // will become the REST URI
}
.withAutoAcl(true)
}
}
and this is the implementation definition (in the file MyService-impl/MyTestServiceImpl.scala) that is causing the compiler error:
class MyTestServiceImpl extends MyTestService {
// this is where the error happens....
override def myTest2() = ServiceCall { _ => Future.successful("Hi MyTest2 user") }
^
^
(here)
}
It would be good if you pasted the exact error output, but the problem is that you defined myTest2 to be a method that takes a String, ie def myTest2(cmd: String), but then you've implemented it as a method that takes no parameters, ie override def myTest2(). Change it to override def myTest2(cmd: String) and that will fix your problem.
The reason for the specific error you're getting is that because you're not actually overriding the myTest2 method as defined, the Scala compiler can't infer the type of ServiceCall that you're meant to be returning, and hence can't infer the type of the parameter in the lambda that you're passing to ServiceCall.

Why does an implicit conversion on the constructor require 'this'?

Consider the following typical Scala 'pimp' code:
class PimpedA(a:A){
def pimp() = "hi"
}
implicit def pimpA(a:A) = new PimpedA(a)
new A(){
pimp() //<--- does not compile
}
However, changing it to:
new A(){
this.pimp()
}
Makes it work.
Shouldn't it be the same to the Scala compiler?
EDIT : Is there any solution that can make it work without having to add the this.?
Not at all. For it to work, pimp needs to be either an object or an imported member of a value, and it is neither. A class has an "implicit" import this._. It has not a mechanism that auto-prepends this to stuff to see if it compiles.
In this case you should give compiler a hint that pimp() is not a random function. When you write
this.pimp()
compiler know there isn't pimp function on class A so it's an error and before giving up it searches implicit conversion in scope and finds it.
pimpA(this).pimp()
And when you just call pimp() compiler doesn't know what object to pass to the pimpA(a: A) implicit function.
UPDATE
It is hard to understand what is your goal. I can only suggest to make PimpedA a typeclass (Pimp[T] in this example).
trait Pimp[T] {
def action(p: T): String
}
implicit object PimpA extends Pimp[A] {
override def action(p: A) = "some actions related to A"
}
def pimp[T: Pimp](p: T) = implicitly[Pimp[T]].action(p)
class A {
val foo = pimp(this)
}
scala> new A foo
res2: String = some actions related to A

How do you define implicit conversion in modern way?

Stupid question, but none of the examples works for me; classic article "Pimp my Library" is buggy and even the simplest code has problems.
Btw. I assume you have to put conversion method in the object (a lot of snippets omit that part). According to PiS book it seems hanging implicit def is OK, but this gives me error as well.
object Minutes
{
implicit def toMinutes(x : Int) = new Minutes(x)
}
class Minutes(private val x : Int)
{
def minutes = x.toString+"m"
}
object MainApp {
def main(args : Array[String])
{
println(5.minutes)
...
The error -- "value minutes is not a member of Int".
Question
What am I missing? Scala 2.9.1.
All you need you to do is bring your implicit conversion into scope where you want to use it, so the compiler can find it...
def main(args : Array[String]) {
import Minutes._
println(5.minutes)
}
The implicit conversion must be in scope, e.g.
def main(args : Array[String]) {
import Minutes._
println(5.minutes)
...
}
There are other ways, too, e.g. using package objects.
You can get the example in the Pimp my library article to work as follows:
class RichArray[T: Manifest](value: Array[T]) {
def append(other: Array[T]): Array[T] = {
val result = new Array[T](value.length + other.length)
Array.copy(value, 0, result, 0, value.length)
Array.copy(other, 0, result, value.length, other.length)
result
}
}
implicit def enrichArray[T: Manifest](xs: Array[T]) = new RichArray[T](xs)
You need a context bound for T: [T: Manifest] is short for [T](implicit m: Manifest[T]). A Manifest is a way of passing the value of T to the method at runtime, when T is known. Normally the parameterized type information is used by the compiler to ensure type safety at compile time, but is not incorporated into the bytecode because the JVM can't handle it (type erasure). Scala collections changed in version 2.8 so that for performance reasons, Arrays are now not automatically wrapped by compiler magic, hence supplying a manifest for generic operations became necessary.
The other change is the (xs) argument for new RichArray[T]. I think that one's a typo.