Skip to content

Commit 2bb286b

Browse files
flomebulbishabosha
andauthored
Add code tabs for _tour/annotations (#2566)
* Add code tabs for _tour/annotations * Update annotations.md * Update _tour/annotations.md Co-authored-by: Jamie Thompson <bishbashboshjt@gmail.com> * add code tabs for java annots Co-authored-by: Jamie Thompson <bishbashboshjt@gmail.com>
1 parent 639390b commit 2bb286b

File tree

1 file changed

+117
-23
lines changed

1 file changed

+117
-23
lines changed

_tour/annotations.md

Lines changed: 117 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,39 @@ redirect_from: "/tutorials/tour/annotations.html"
1111
---
1212

1313
Annotations associate meta-information with definitions. For example, the annotation `@deprecated` before a method causes the compiler to print a warning if the method is used.
14-
```
14+
15+
{% tabs annotations_1 class=tabs-scala-version %}
16+
{% tab 'Scala 2' for=annotations_1 %}
17+
```scala mdoc:fail
1518
object DeprecationDemo extends App {
1619
@deprecated("deprecation message", "release # which deprecates method")
1720
def hello = "hola"
1821

19-
hello
22+
hello
2023
}
2124
```
25+
{% endtab %}
26+
{% tab 'Scala 3' for=annotations_1 %}
27+
```scala
28+
object DeprecationDemo extends App:
29+
@deprecated("deprecation message", "release # which deprecates method")
30+
def hello = "hola"
31+
32+
hello
33+
```
34+
{% endtab %}
35+
{% endtabs %}
36+
2237
This will compile but the compiler will print a warning: "there was one deprecation warning".
2338

2439
An annotation clause applies to the first definition or declaration following it. More than one annotation clause may precede a definition and declaration. The order in which these clauses are given does not matter.
2540

2641

2742
## Annotations that ensure correctness of encodings
2843
Certain annotations will actually cause compilation to fail if a condition(s) is not met. For example, the annotation `@tailrec` ensures that a method is [tail-recursive](https://en.wikipedia.org/wiki/Tail_call). Tail-recursion can keep memory requirements constant. Here's how it's used in a method which calculates the factorial:
44+
45+
{% tabs annotations_2 class=tabs-scala-version %}
46+
{% tab 'Scala 2' for=annotations_2 %}
2947
```scala mdoc
3048
import scala.annotation.tailrec
3149

@@ -38,8 +56,26 @@ def factorial(x: Int): Int = {
3856
factorialHelper(x, 1)
3957
}
4058
```
41-
The `factorialHelper` method has the `@tailrec` which ensures the method is indeed tail-recursive. If we were to change the implementation of `factorialHelper` to the following, it would fail:
59+
{% endtab %}
60+
{% tab 'Scala 3' for=annotations_2 %}
61+
```scala
62+
import scala.annotation.tailrec
63+
64+
def factorial(x: Int): Int =
65+
66+
@tailrec
67+
def factorialHelper(x: Int, accumulator: Int): Int =
68+
if x == 1 then accumulator else factorialHelper(x - 1, accumulator * x)
69+
factorialHelper(x, 1)
4270
```
71+
{% endtab %}
72+
{% endtabs %}
73+
74+
The `factorialHelper` method has the `@tailrec` which ensures the method is indeed tail-recursive. If we were to change the implementation of `factorialHelper` to the following, it would fail:
75+
76+
{% tabs annotations_3 class=tabs-scala-version %}
77+
{% tab 'Scala 2' for=annotations_3 %}
78+
```scala mdoc:fail
4379
import scala.annotation.tailrec
4480

4581
def factorial(x: Int): Int = {
@@ -50,76 +86,134 @@ def factorial(x: Int): Int = {
5086
factorialHelper(x)
5187
}
5288
```
53-
We would get the message "Recursive call not in tail position".
89+
{% endtab %}
90+
{% tab 'Scala 3' for=annotations_3 %}
91+
```scala
92+
import scala.annotation.tailrec
5493

94+
def factorial(x: Int): Int =
95+
@tailrec
96+
def factorialHelper(x: Int): Int =
97+
if x == 1 then 1 else x * factorialHelper(x - 1)
98+
factorialHelper(x)
99+
```
100+
{% endtab %}
101+
{% endtabs %}
102+
103+
We would get the message "Recursive call not in tail position".
55104

56105
## Annotations affecting code generation
106+
107+
{% tabs annotations_4 class=tabs-scala-version %}
108+
{% tab 'Scala 2' for=annotations_4 %}
109+
57110
Some annotations like `@inline` affect the generated code (i.e. your jar file might have different bytes than if you hadn't used the annotation). Inlining means inserting the code in a method's body at the call site. The resulting bytecode is longer, but hopefully runs faster. Using the annotation `@inline` does not ensure that a method will be inlined, but it will cause the compiler to do it if and only if some heuristics about the size of the generated code are met.
58111

112+
{% endtab %}
113+
{% tab 'Scala 3' for=annotations_4 %}
114+
115+
Some annotations like `@main` affect the generated code (i.e. your jar file might have different bytes than if you hadn't used the annotation). A `@main` annotation on a method generates an executable program that calls the method as an entry point.
116+
117+
{% endtab %}
118+
{% endtabs %}
119+
59120
### Java Annotations ###
60121
When writing Scala code which interoperates with Java, there are a few differences in annotation syntax to note.
61122
**Note:** Make sure you use the `-target:jvm-1.8` option with Java annotations.
62123

63124
Java has user-defined metadata in the form of [annotations](https://docs.oracle.com/javase/tutorial/java/annotations/). A key feature of annotations is that they rely on specifying name-value pairs to initialize their elements. For instance, if we need an annotation to track the source of some class we might define it as
64125

65-
```
126+
{% tabs annotations_5 %}
127+
{% tab 'Java' for=annotations_5 %}
128+
```java
66129
@interface Source {
67-
public String URL();
130+
public String url();
68131
public String mail();
69132
}
70133
```
134+
{% endtab %}
135+
{% endtabs %}
71136

72137
And then apply it as follows
73138

74-
```
75-
@Source(URL = "https://coders.com/",
139+
{% tabs annotations_6 %}
140+
{% tab 'Java' for=annotations_6 %}
141+
```java
142+
@Source(url = "https://coders.com/",
76143
mail = "support@coders.com")
77-
public class MyClass extends TheirClass ...
144+
public class MyJavaClass extends TheirClass ...
78145
```
146+
{% endtab %}
147+
{% endtabs %}
79148

80149
An annotation application in Scala looks like a constructor invocation, for instantiating a Java annotation one has to use named arguments:
81150

82-
```
83-
@Source(URL = "https://coders.com/",
151+
{% tabs annotations_7 %}
152+
{% tab 'Scala 2 and 3' for=annotations_7 %}
153+
```scala
154+
@Source(url = "https://coders.com/",
84155
mail = "support@coders.com")
85156
class MyScalaClass ...
86157
```
158+
{% endtab %}
159+
{% endtabs %}
87160

88161
This syntax is quite tedious if the annotation contains only one element (without default value) so, by convention, if the name is specified as `value` it can be applied in Java using a constructor-like syntax:
89162

90-
```
163+
{% tabs annotations_8 %}
164+
{% tab 'Java' for=annotations_8 %}
165+
```java
91166
@interface SourceURL {
92167
public String value();
93168
public String mail() default "";
94169
}
95170
```
171+
{% endtab %}
172+
{% endtabs %}
96173

97-
And then apply it as follows
174+
And then apply it as follows:
98175

99-
```
176+
{% tabs annotations_9 %}
177+
{% tab 'Java' for=annotations_9 %}
178+
```java
100179
@SourceURL("https://coders.com/")
101-
public class MyClass extends TheirClass ...
180+
public class MyJavaClass extends TheirClass ...
102181
```
182+
{% endtab %}
183+
{% endtabs %}
103184

104-
In this case, Scala provides the same possibility
185+
In this case, Scala provides the same possibility:
105186

106-
```
187+
{% tabs annotations_10 %}
188+
{% tab 'Scala 2 and 3' for=annotations_10 %}
189+
```scala
107190
@SourceURL("https://coders.com/")
108191
class MyScalaClass ...
109192
```
193+
{% endtab %}
194+
{% endtabs %}
110195

111-
The `mail` element was specified with a default value so we need not explicitly provide a value for it. However, if we need to do it we can not mix-and-match the two styles in Java:
196+
The `mail` element was specified with a default value so we need not explicitly provide a value for it.
197+
However, if we need to provide one then in Java we must also explicitly name the `value` parameter:
112198

113-
```
199+
{% tabs annotations_11 %}
200+
{% tab 'Java' for=annotations_11 %}
201+
```java
114202
@SourceURL(value = "https://coders.com/",
115203
mail = "support@coders.com")
116-
public class MyClass extends TheirClass ...
204+
public class MyJavaClass extends TheirClass ...
117205
```
206+
{% endtab %}
207+
{% endtabs %}
118208

119-
Scala provides more flexibility in this respect
209+
Scala provides more flexibility in this respect, so we can choose to only name the `mail` parameter:
120210

121-
```
211+
{% tabs annotations_12 %}
212+
{% tab 'Scala 2 and 3' for=annotations_12 %}
213+
```scala
122214
@SourceURL("https://coders.com/",
123215
mail = "support@coders.com")
124-
class MyScalaClass ...
216+
class MyScalaClass ...
125217
```
218+
{% endtab %}
219+
{% endtabs %}

0 commit comments

Comments
 (0)