abandon calling `get` on Option and generate compile error - scala

If I want to generate compile time error when calling .get on any Option value, how to go about doing this?
Haven't written any custom macros but guess it's about time for it? Any pointers?

There is a compiler plugin called wartremover, that provides what you want.
https://github.com/typelevel/wartremover
It has error messages and warning for some scala functions, that should be avoided for safety.
This is the description of the OptionPartial wart from the github readme page:
scala.Option has a get method which will throw if the value is
None. The program should be refactored to use scala.Option#fold to
explicitly handle both the Some and None cases.
compiler plugin
To add wartremover, as a plugin, to scalac, you need to add this to your project/plugins.sbt:
resolvers += Resolver.sonatypeRepo("releases")
addSbtPlugin("org.brianmckenna" % "sbt-wartremover" % "0.11")
And activate it in your build.sbt:
wartremoverErrors ++= Warts.unsafe
macro
https://github.com/typelevel/wartremover/blob/master/OTHER-WAYS.md descripes other ways how you can use the plugin, one of them is using it as a macro, as mentioned in the question.
Add wart remover as library to your build.sbt:
resolvers += Resolver.sonatypeRepo("releases")
libraryDependencies += "org.brianmckenna" %% "wartremover" % "0.11"
You can make any wart into a macro, like so:
scala> import language.experimental.macros
import language.experimental.macros
scala> import org.brianmckenna.wartremover.warts.Unsafe
import org.brianmckenna.wartremover.warts.Unsafe
scala> def safe(expr: Any):Any = macro Unsafe.asMacro
safe: (expr: Any)Any
scala> safe { 1.some.get }
<console>:10: error: Option#get is disabled - use Option#fold instead
safe { 1.some.get }
The example is adapted from the wartremover github page.

Not strictly an answer to your question, but you might prefer to use Scalaz's Maybe type, which avoids this problem by not having a .get method.

Related

Implicit ParameterBinderFactory[org.joda.time.LocalDateTime] for the parameter type

I brought up the scalikejdbc version and got an error like this:
[error] Implicit ParameterBinderFactory[org.joda.time.LocalDateTime]
for the parameter type org.joda.time.LocalDateTime is missing. [error]
You need to define ParameterBinderFactory for the type or use
AsIsParameterBinder.
def toUpdaters: Seq[(SQLSyntax, ParameterBinder)] = {
val ses = SeasonProjection.column
Seq(
start.map(ses.start -> _) //<- here
How can I solve the problem?
I have not found any examples
You can check out the documentation at http://scalikejdbc.org/documentation/operations.html, section Using joda-time library.
You need to add a library to allow scalikejdbc to work with Joda:
libraryDependencies += "org.scalikejdbc" %% "scalikejdbc-joda-time" % "3.5.0"
Then use appropriate imports in your code like:
// If you need ParameterBinderFactory for joda-time classes
import scalikejdbc.jodatime.JodaParameterBinderFactory._
// If you need TypeBinder for joda-time classes
import scalikejdbc.jodatime.JodaTypeBinder._
That being said, you might want to get rid of Joda in favour of java.time which is nowadays standard for date/time representations and is most of the time supported out-of-the-box by libraries.

Can't get the banana-rdf to work with scalajs

From my understanding I should be able to use the banana-rdf library in my scalajs code? I followed the instructions on the website and added the following to my build.sbt:
val banana = (name: String) => "org.w3" %% name % "0.8.4" excludeAll (ExclusionRule(organization = "org.scala-stm"))
and added the following to my common settings:
resolvers += "bblfish-snapshots" at "http://bblfish.net/work/repo/releases"
libraryDependencies ++= Seq("banana", "banana-rdf", "banana-sesame").map(banana)
It all compiles fine until it gets to the point where it does the fast optimizing. Then I get the following error:
Referring to non-existent class org.w3.banana.sesame.Sesame$
I tried changing Seasame for Plantain but got the same outcome.
Am I missing something?
I was using the "%%" notation which is for a jvm module.
Changed it to "%%%" and it was able to find the correct library.
NOTE. I had to use Plantain as this is the only one currently compiled for scalajs

Why adding import `import cats.instances.future._` will result an compilation error for implicit Functor[Future]

The scala code is using cats and works well:
import cats.implicits._
import cats.Functor
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
object Hello extends App {
Functor[Future].map(Future("hello"))(_ + "!")
}
But if I add this import:
import cats.instances.future._
It will report such compilation errors:
Error:(18, 10) could not find implicit value for parameter instance: cats.Functor[scala.concurrent.Future]
Functor[Future].map(Future("hello"))(_ + "!")
Why it happens, and how can I debug it to find reason? I used all kinds of ways I know, but can't find anything.
The build.sbt file is:
name := "Cats Implicit Functor of Future Compliation Error Demo"
version := "0.1"
organization := "org.my"
scalaVersion := "2.12.4"
sbtVersion := "1.0.4"
libraryDependencies ++= Seq(
"org.typelevel" %% "cats-core" % "1.0.1"
)
The object cats.implicits has the FutureInstances trait as a linear supertype. The FutureInstances has an implicit catsStdInstancesForFuture method, which produces a Monad[Future], which in turn is a Functor[Future].
On the other hand, the object cats.instances.future also mixes in FutureInstances, so it again provides an implicit method catsStdInstancesForFuture, but through another pathway.
Now the compiler has two possibilities to generate a Functor[Future]:
by invoking cats.instances.future.catsStdInstancesForFuture
by invoking cats.implicits.catsStdInstancesForFuture
Since it cannot decide which one to take, it exits with an error message.
To avoid that, don't use cats.implicits._ together with cats.instances.future._. Either omit one of the imports, or use the
`import packagename.objectname.{member1name, member2name}`
to select only those implicits that you need.
Adding "-print" to scalacOptions could help when debugging implicits:
scalacOptions ++= Seq(
...
"-print",
...
)
It will print out the desugared code with cats.implicits. and cats.instances.-pieces added everywhere. Unfortunately, it tends to produce quite a lot of noise.
The more fundamental reason why this happens is that there is no way to define higher-dimensional-cells (kind-of "homotopies") between the two (equivalent) pathways that lead to a Functor[Future]. If we had a possibility to tell the compiler that it doesn't matter which path to take, then everything would be much nicer. Since we can't do it, we have to make sure that there is always only one way to generate an implicit Functor[Future].
The problem is that the instances are imported twice, meaning scalac cannot disambiguate between them and doesn't know which one to use and then fails.
So either you use the implicits._ import or you import specific instances with instances.<datatype>._, but never both!
You can look at a more in depth look of cats imports here: https://typelevel.org/cats/typeclasses/imports.html

Reproducing Shapeless examples of HList-style operations on standard tuples

I'm very new to Scala, and have been looking at the shapeless package to provide HList-like operations for Scala's tuples.
I'm running scala 2.10.5, and I've successfully installed the package (version 2.2.0-RC6) as well as all dependencies.
When I try to run the following example (from the shapeless feature overview) in the REPL,
scala> import shapeless._; import syntax.std.tuple._
scala > (23, "foo", true).head
I get the following error message:
<console>:17: error: could not find implicit value for parameter c: shapeless.ops.tuple.IsComposite[(Int, String, Boolean)]
(23, "foo", true).head
I'll bet this is a silly error on my part, and I've been digging through a lot of forums on this.
What am I missing?
Thanks in advance for your help.
You're likely missing the macro paradise dependency. Without that, I get the same error you see, with it, the example compiles.
Your build.sbt should include something like this:
libraryDependencies ++= Seq(
"com.chuusai" %% "shapeless" % "2.2.0-RC6",
compilerPlugin("org.scalamacros" % "paradise" % "2.0.1" cross CrossVersion.full)
)

Clean solution for dropping into REPL console in the middle of program execution

Is there any working solution for dropping into REPL console with for Scala 2.10?
This is mainly for debugging purpose - I want to pause in the middle of execution, and have a REPL console where I can inspect values and test the program's logic using complex expressions within my program at the current state of execution. Those who have programmed in Ruby might know similar function: the binding.pry.
AFAIK, Scala 2.9 and under used to have breakIf but it has been removed from the later versions. Using ILoop seems to be the new way but introduced issues due to sbt not adding scala-library to the classpath.
Several solutions such as this and this seem to offer a good workaround but my point is there must be a solution where I don't have to spend hours or even days just to make the REPL working.
In short, there's a lot more boilerplate steps involved - this is in contrast with binding.pry which is just a line of code with no additional boilerplate.
I am not aware if there's an issue introduced in executing the program as an sbt task as opposed to if running the program executable directly, but for development purpose I am currently running and testing my program using sbt task.
You could easily reimplement the breakIf method in your code. I don't think there is much cleaner way of doing that.
First you have to add a scala compiler library to your build.sbt
libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value
Once that's done you can implement breakIf
import scala.reflect.ClassTag
import scala.tools.nsc.Settings
import scala.tools.nsc.interpreter.{ILoop, NamedParam}
def breakIf[T](assertion: => Boolean, args: NamedParam*)(implicit tag: ClassTag[T]) = {
val repl = new ILoop()
repl.settings = new Settings()
repl.settings.embeddedDefaults[T]
repl.settings.Yreplsync.value = true
repl.in = repl.chooseReader(repl.settings)
repl.createInterpreter()
args.foreach(p => repl.bind(p.name, p.tpe, p.value))
repl.loop()
repl.closeInterpreter()
}
I think it's pretty straight forward, the only tricky part is that you have to set-up the classpath properly. You need to call embeddedDefaults with a class from your project (see my answer to another question).
You can use the new breakIf as follows:
val x = 10
breakIf[X](assertion = true, NamedParam("x", "Int", x))
Where X is just some of your classes.
I don't know if this answers your question, because it's hard to measure what is easy and what is hard.
Additionally just as a side note - if you want to use it for debugging purposes, why not use a debugger. I guess most of the debuggers can connect to a program, stop at a breakpoint and evaluate expressions in that context.
Edit
Seems like it doesn't work on current release of Scala 2.10, the working code seems to be:
import scala.reflect.ClassTag
import scala.tools.nsc.Settings
import scala.tools.nsc.interpreter.{ILoop, NamedParam}
def breakIf[T](assertion: => Boolean, args: NamedParam*)(implicit tag: ClassTag[T]) = {
val repl = new ILoop() {
override protected def postInitialization(): Unit = {
addThunk(args.foreach(p => intp.bind(p)))
super.postInitialization()
}
}
val settings = new Settings()
settings.Yreplsync.value = true
settings.usejavacp.value = true
settings.embeddedDefaults[T]
args.foreach(repl.intp.rebind)
repl.process(settings)
}
and usage is like
val x = 10
breakIf[X](assertion = true, NamedParam("x", x))
I was looking at this recently and found Ammonite to be a sufficient solution for my needs.
Add Ammonite to your library dependencies:
libraryDependencies += "com.lihaoyi" % "ammonite" % "1.6.0" cross CrossVersion.full
Invoke Ammonite where you want to drop to the REPL shell:
ammonite.Main().run()
Note that you have to pass any variables you want bound inside of run, e.g. run("var1" -> var1). Have a look at their example - Instantiating Ammonite.