Option and null in Scala - 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.

Related

In scala macro, is it possible to execute code after the macro context has aborted?

I'm solving a macro bug that may affects shapeless & singleton-ops for scala 2, both contains the following code to override the implicitNotFound annotation of a particular type symbol:
def setAnnotation(msg: String, annotatedSym : TypeSymbol): Unit = {
import c.internal._
import decorators._
val tree0 =
c.typecheck(
q"""
new _root_.scala.annotation.implicitNotFound("dummy")
""",
silent = false
)
class SubstMessage extends Transformer {
val global = c.universe.asInstanceOf[scala.tools.nsc.Global]
override def transform(tree: Tree): Tree = {
super.transform {
tree match {
case Literal(Constant("dummy")) => Literal(Constant(msg))
case t => t
}
}
}
}
val tree = new SubstMessage().transform(tree0)
annotatedSym.setAnnotations(Annotation(tree))
()
}
The above code will override the error reporting when c.abort() is called, after which this stateful change should be regard as useless, and the change should be reverted ASAP. In fact, since the TypeSymbol is unique within each compiler invocation, failing to do so will cause the remainder of the compilation to behave erratically (see
https://github.com/fthomas/singleton-ops/issues/234 for detail)
To my best knowledge, what I"m asking for seems to be beyond the capability of the macro system. I need to add the clean up code into a thunk which can be called by The context AFTER the top-level implicit not found error has been reported. How should I do this?

Scala 3 Macro - Retain a generic type in runtime

I'm looking for an option to retain a generic type in runtime in Scala3. In Scala2 there was a TypeTag for this, however, now it is removed and the suggested option is to use macros (https://contributors.scala-lang.org/t/scala-3-and-reflection/3627).
The documentation, however, is somewhat cryptic...
This is what I'm trying to do:
Here's a macro implementation:
object TestMacroImpl {
def getClassImpl[T](using Quotes)(using t: Type[T]): Expr[Class[T]] = '{
classOf[${t}]
}
}
Here's a macro:
import macros.TestMacro.getClassMacro
class TypedBox[T] {
val staticClass: Class[T] = TypedBox.getStaticClass[T]
}
object TypedBox {
inline def getStaticClass[T] = ${ getClassMacro[T] }
}
Test:
object Test {
def main(args: Array[String]): Unit = {
val stringBox = TypedBox[String]()
println(stringBox.staticClass)
}
}
I would envision this to be resolved as val staticClass = classOf[String]
But this does not compile, I'm getting:
/workspace/macros-test/src/main/scala/macros/TestMacro.scala:7:13
t.Underlying is not a class type
classOf[${t}]
What am I missing?
Not really sure why but I don't think you can reliably get an Expr[Class[T]] out of macros (from what I understood, it could be that the Class does not yet exist at the time of macro execution).
Plus, a Class[T] does not retain the parameterized types: classOf[Map [String, String]] = classOf[Map[Int, Int]] for instance.
If you don't care about them, I'd use a ClassTag instead of TypeTag which is still available in Scala 3. And no need for macros.
By the way, in macros, you can write something like the following to get a Expr[ClassTag[T]]:
private def getClassTag[T](using Type[T], Quotes): Expr[ClassTag[T]] = {
import quotes.reflect._
Expr.summon[ClassTag[T]] match {
case Some(ct) =>
ct
case None =>
report.error(
s"Unable to find a ClassTag for type ${Type.show[T]}",
Position.ofMacroExpansion
)
throw new Exception("Error when applying macro")
}
}
Finally, you might find some useful things at https://github.com/gaeljw/typetrees/blob/main/src/main/scala/io/github/gaeljw/typetrees/TypeTreeTagMacros.scala#L8 (disclaimer: I wrote it for personal projects).

Is there anyway to create a new Scala object from a Java Class

I have a number of use cases for this, all around the idea of interop between existing Java libraries and new Scala Code. The use case I've selected is the easiest I think.
Use Case:
I working on providing a JUnit Runner for some scala tests (so that I can get my lovely red / green bar in Eclipse)
The runner needs to have a constructor with a java class as a parameter. So in Scala I can do the following:
class MyRunner(val clazz: Class[Any]) extends Runner {
def getDescription(): Description
def run(notifier: RunNotifier)
}
When I use either
#RunWith(MyRunner)
object MyTestObject
or
#RunWith(MyRunner)
class MyTestClass
then the runner is indeed instantiated correctly, and is passed a suitable class object
Unfortunately what i want to do now is to "get hold of" the object MyTestObject, or create a MyTestClass, which are both Scala entities. I would prefer to use Scala Reflection, but I also want to use the standard Junit jar.
What I have done
The following Stackover flow questions were educational, but not the same problem. There were the nearest questions I could find
How to create a TypeTag manually?
Any way to obtain a Java class from a Scala (2.10) type tag or symbol?
Using Scala reflection with Java reflection
The discussion on Environments, Universes and Mirrors in http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html was good, and the similar documents on other scala reflection also helped. Mostly through it is about the Scala reflection.
I browsed the Scaladocs, but my knowledge of Scala reflection wasn't enough (yet) to let me get what I wanted out of them.
Edit:
As asked here is the code of the class that is being created by reflection
#RunWith(classOf[MyRunner])
object Hello2 extends App {
println("starting")
val x= "xxx"
}
So the interesting thing is that the solution proposed below using the field called MODULE$ doesn't print anything and the value of x is null
This solution works fine if you want to use plan old java reflection. Not sure if you can use scala reflection given all you will have is a Class[_] to work with:
object ReflectTest {
import collection.JavaConversions._
def main(args: Array[String]) {
val fooObj = instantiate(MyTestObject.getClass())
println(fooObj.foo)
val fooClass = instantiate(classOf[MyTestClass])
println(fooClass.foo)
}
def instantiate(clazz:Class[_]):Foo = {
val rm = ru.runtimeMirror(clazz.getClassLoader())
val declaredFields = clazz.getDeclaredFields().toList
val obj = declaredFields.find(field => field.getName() == "MODULE$") match{
case Some(modField) => modField.get(clazz)
case None => clazz.newInstance()
}
obj.asInstanceOf[Foo]
}
}
trait Foo{
def foo:String
}
object MyTestObject extends Foo{
def foo = "bar"
}
class MyTestClass extends Foo{
def foo = "baz"
}

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

Is it possible to define companion classes/modules in the Scala interpreter?

It's often convenient to test things out in the Scala interpreter. However, one issue I run into is that I have to restructure code that uses implicit conversions because defining an object with the same name as an existing class does not make it a companion module in the REPL. As a result, I can't be confident my code will still work when I translate back to "real source".
Is there a way to define companions in the REPL? Maybe something along the lines of
bigblock {
class A
object A {
implicit def strToA(s: String): A = // ...
}
}
such that
val v: A = "apple"
will compile.
That's close:
object ABlock {
class A
object A {
implicit def strToA(s: String): A = // ...
}
}
import ABlock._
Or, the following, if you put everything on one line:
class A; object A { implicit def strToA(s: String): A = // ... } }
...though either way you'll still need to import the implicit conversion to make the following work as you requested:
import ABlock.A.strToA // for the form with the enclosing object
import A.strToA // for the one-line form without an enclosing object
val v: A = "apple"
The reason you need to do this is that every line you enter at the REPL is enclosed in an object and each subsequent one is nested within the immediately preceding one. This is done so you can do things like the following without getting redefinition errors:
val a = 5
val a = "five"
(Effectively, the second definition of a here shadows the first.)
With more recent versions use can use the :paste command.