abandon calling `get` on Option and generate compile error
Asked Answered
E

2

7

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?

Emergency answered 17/10, 2014 at 9:31 Comment(7)
Duplicate of #20055906 ?Yonita
You have any sample code to illustrate your problem ?Polak
I don't think this should be a duplicate, the questions are similar but there is a Solution to this one that can not easyly be adaped to the other.Nonalcoholic
@bmaderbacher, if there's a solution, give it. I don't see how this differs from the suggested duplicateNickens
@Paul I've added my answer. The suggested duplicate could only be solved by writing custom linter rules, in my opinion this is significantly different form simply using a set of predefined rules.Nonalcoholic
OK, that's good. I think you could usefully answer the other question too, even if you as you say custom rules are requiredNickens
@Paul I haven't tried to write my own rules yet, but if I've time to do so I may answer the other question too.Nonalcoholic
N
9

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.

Nonalcoholic answered 17/10, 2014 at 10:39 Comment(0)
A
3

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.

Arran answered 17/10, 2014 at 13:37 Comment(1)
+1 The problem with the current state of Maybe is that there are many standard functions, even in scalaz, that only support Option.Nonalcoholic

© 2022 - 2024 — McMap. All rights reserved.