23

Attribute in .NET is a very popular feature. And Java added Annotation after 1.5 Annotations are used everywhere, see Java EE and Spring. But few scala library use annotation. lift-json don't use it. lift-record don't use it. Squeryl don't use it. subcut don't use it.(it has annotation for compiler plugin) ... Just named a few.

They use annotation only when they need some compiler magic. @tailrec, @inline, @BeanProperty, @Inject(in subcut) ...

Scala has super flexible type system, trait, implicit and Menifest[X]. So they don't need runtime meta-data?

Is there any scala project use annotation heavily?

p.s. I think the Dynamic should be annotation but not trait.

Chris Martin
  • 30,334
  • 10
  • 78
  • 137
iron9light
  • 1,205
  • 1
  • 13
  • 17
  • 3
    What practical problem does this lake of use of annotations have? – Mat Dec 22 '11 at 20:19
  • Dynamic is a Type. Why should it be an annotation? – Jan Dec 22 '11 at 20:29
  • Because there's no methods inside, and when you use it, you have your own type, Dynamic just tell you your type is dynamic. – iron9light Dec 22 '11 at 20:37
  • Re: dynamic, One could argue the same about Serialization, which scala had as an annotation because it made more sense, and moved back to using java.io.Serialziation because it confused people. – jsuereth Dec 23 '11 at 12:47

4 Answers4

29

In general, we don't use annotations because we don't really need them for a lot of things.

The few places I've seen annotations used:

  • Extra type systems (e.g. the CPS plugin for delimited continuations or the effect tracking plugin.
  • Interfacing with legacy Java interfaces. (scala-mojo-support)
  • Enforcing/enabling compiler optimisations, like @inline or @tailrec.

In Scala, we don't really need a dependency injection framework, as there's a few ways to do dependency injection that doesn't require an external tool. You can have the DI config separate from core code, but still be written in Scala. See: https://github.com/jsuereth/scala-in-depth-source/blob/master/chapter11/src/main/scala/scalax/config/Test.scala

So the basic answer is, there's nothing wrong with annotations, we just don't need them that often (yet).

jsuereth
  • 5,604
  • 40
  • 40
  • I think annotation for cps, the @cpsParam, is a TypeConstraint, more than traditional annotation which only provide runtime meta-data. – iron9light Dec 23 '11 at 09:08
  • It's more that Scala is more flexible in what can be annotated than Java/C#. It's still just an annotation, uses the same AST as other annotations, but happens to be on a type. Java annotations can also *not* be available at runtime, but only compile/apt time. This is done via the `@Retention` setting on an annotation class. – jsuereth Dec 23 '11 at 12:46
13

For me it's often an issue of compiler enforced type safety. Take a look at Squeryl and how it differs from a Java ORM like Hibernate. Where Hibernate would use an @Id annotation to denote a primary key, in Squeryl you create an id member, which is specified by the KeyedEntity trait. Methods that require an entity with a primary key (update & delete for instance) will crash loudly at compile time if one hasn't been defined. There are several other places within Squeryl where typesafe constructs replace annotations like collection mapping and date/time handling.

I think that this is a common way of thinking in the Scala community. Annotations are more of a run time feature and aren't as well regarded. The Scala compiler is very powerful and pushing more of your code into constructs it can validate makes sense for those who are willing to accept the complexity that comes along with that.

Dave Whittaker
  • 3,102
  • 13
  • 14
2

You've pretty much answered your own question when you said that they're used for compiler magic. For the other uses it's usually some kind of runtime magic, where the two main tools are reflection and byte code transformation.

For the JSON case, the choices for the conversion would be the following: 1. A function or class that parses your JValue and builds your class T. 2. Reflection over the target classes to determine their layout and what is optional, then some "dynamic" code which runs over that parsed data to create and then eventually cast to the appropriate type.

Sean Parsons
  • 2,832
  • 21
  • 17
0

All the annotations like @tailrec and @inline are compile-time only. They extend StaticAnnotation, which is, AFAIK, the only annotation support in Scala, and they won't be retained at runtime. I think the philosophy is to avoid runtime annotations because those are retrieved via reflection, a world where the compiler can no longer help you beyond standard classes due to type erasure, but most importantly, because it's runtime and the goal is to decide what you're trying to decide at compile-time.

Look at using annotations to model a JSON output for example: In Java you would know if it works OK when you run your program. In Scala you could use type classes to model how each type is expressed in JSON. If you miss one definition, the compile will tell you. An excellent example is spray-json.

Dave Whittaker gives another great example in his answer.

Community
  • 1
  • 1
Carlos Ferreyra
  • 275
  • 3
  • 10