As an experiment — that’s a big emphasis on the word “experiment” there — I decided to create an @impure
annotation for my current Scala project. The annotation is a “do nothing” annotation, so it doesn’t actually check the code in the way the @tailrec
annotation works, for example.
What it does is serve to nag me. As I get into functional programming, my plan is to put the annotation on my impure Scala methods and functions as I create them. In theory it will bother me that they’re there, and then I’ll do something to try to make them pure.
Another use is that it serves as a way to make sure that I know that certain functions are impure. For instance, in my universe, I/O functions are always impure, so @impure
can possibly serve as a way to tag impure I/O functions (a little like returning IO
in Haskell functions, but in this case just a very experimental tag).
A simple example
As a simple example, I might write a Scala class like this, forcing myself to put the @impure
annotation before the randomInt
method definition:
class Numbers { @impure def randomInt(): Int = scala.util.Random.nextInt }
This is a trivial example, but as mentioned there are two possible benefits of this:
- It makes it clear to anyone who looks at the method signature or Scaladoc that this method is impure.
- If there’s some way to make the function pure in the future (such as when I learn more about FP), I can come back and re-work the function then.
Of course the big technical downfall of this experiment is that there’s nothing to force me to use this annotation. So I’m going with the “Scout’s Honor” method of enforcement. I’m hoping that this “first idea” might spark another idea somewhere along the line.
Creating the Scala annotation
Creating the annotation in Scala is easy. Here’s the entire code required to define the annotation:
package com.alvinalexander.annotations import scala.annotation.meta._ /** * An annotation that designates that a method is an "impure" function, * i.e., that its result depends on something more than its input parameters, * or that it has one or more external side effects. */ class impure extends scala.annotation.StaticAnnotation
You may also be able to create Scala annotations using macros, though I haven’t looked at those details.
For about two seconds I thought about creating a @pure
annotation, but since my code should be 80-90% or more “pure” with the rest being impure, I quickly decided against that. So as a rule, my methods/functions will be pure unless otherwise annotated.
A Scala annotation that takes parameters
You can also define a Scala annotation that takes parameters. For example, this is the definition of the @deprecated
annotation in the Scala 2.10.x code base:
import scala.annotation.meta._ /** * An annotation that designates that a definition is deprecated. * Access to the member then generates a deprecated warning. * * @param message the message to print during compilation if the definition is accessed * @param since a string identifying the first version in which the definition was deprecated * @since 2.3 */ @getter @setter @beanGetter @beanSetter class deprecated(message: String = "", since: String = "") extends scala.annotation.StaticAnnotation
(Here’s a link to the “deprecated” class.)
Using my @impure annotation
Getting back to my @impure
annotation, here are two more examples of how to use it. All you really have to do is (1) import it, and then (2) put it before your method definitions:
package annotations // [1] import it import com.alvinalexander.annotations.impure object AnnotationsTest extends App { var age = 42 addToAge(1) echo("hello") // [2] use it @impure def addToAge(i: Int) { age += i } @impure def echo(s: String) { println(s) } }
A Java version of the annotation
As a “note to self” more than anything else, you can also create the annotation in Java, like this:
package com.alvinalexander.annotations; // needed for @Documented import java.lang.annotation.*; @Documented public @interface impure {}
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |
Annotations resources
Here are a few links to some Java and Scala annotations tutorials:
- oracle - java annotations
- jenkov.com - java annotations
- mkyong.com - java annotations/
- Scala Macro Annotations
Summary
In summary, as I mentioned, I have no idea whether this is a good idea or not, it’s just an experiment. The idea has just been in the back of my mind for a while, so I thought I’d do the “simplest thing that could possibly work” and give it a try. Whether or not it bugs me enough to make my code more “functional” (by guilt), only time will tell.