Skip to content

Add code tabs for _overviews/scala3-book/types-{introduction,generics}.md #2599

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion _overviews/scala3-book/types-generics.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,30 @@ Generic classes (or traits) take a type as _a parameter_ within square brackets
The Scala convention is to use a single letter (like `A`) to name those type parameters.
The type can then be used inside the class as needed for method instance parameters, or on return types:

{% tabs stack class=tabs-scala-version %}

{% tab 'Scala 2' %}
```scala
// here we declare the type parameter A
// v
class Stack[A] {
private var elements: List[A] = Nil
// ^
// Here we refer to the type parameter
// v
def push(x: A): Unit =
elements = elements.prepended(x)
def peek: A = elements.head
def pop(): A = {
val currentTop = peek
elements = elements.tail
currentTop
}
}
```
{% endtab %}

{% tab 'Scala 3' %}
```scala
// here we declare the type parameter A
// v
Expand All @@ -21,26 +45,42 @@ class Stack[A]:
// ^
// Here we refer to the type parameter
// v
def push(x: A): Unit = { elements = elements.prepended(x) }
def push(x: A): Unit =
elements = elements.prepended(x)
def peek: A = elements.head
def pop(): A =
val currentTop = peek
elements = elements.tail
currentTop
```
{% endtab %}
{% endtabs %}

This implementation of a `Stack` class takes any type as a parameter.
The beauty of generics is that you can now create a `Stack[Int]`, `Stack[String]`, and so on, allowing you to reuse your implementation of a `Stack` for arbitrary element types.

This is how you create and use a `Stack[Int]`:

{% tabs stack-usage class=tabs-scala-version %}
{% tab 'Scala 2' %}
```
val stack = new Stack[Int]
stack.push(1)
stack.push(2)
println(stack.pop()) // prints 2
println(stack.pop()) // prints 1
```
{% endtab %}
{% tab 'Scala 3' %}
```
val stack = Stack[Int]
stack.push(1)
stack.push(2)
println(stack.pop()) // prints 2
println(stack.pop()) // prints 1
```
{% endtab %}
{% endtabs %}

> See the [Variance section][variance] for details on how to express variance with generic types.

Expand Down
12 changes: 12 additions & 0 deletions _overviews/scala3-book/types-inferred.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,32 @@ next-page: types-generics

As with other statically typed programming languages, in Scala you can _declare_ a type when creating a new variable:

{% tabs xy %}
{% tab 'Scala 2 and 3' %}
```scala
val x: Int = 1
val y: Double = 1
```
{% endtab %}
{% endtabs %}

In those examples the types are _explicitly_ declared to be `Int` and `Double`, respectively.
However, in Scala you generally don’t have to declare the type when defining value binders:

{% tabs abm %}
{% tab 'Scala 2 and 3' %}
```scala
val a = 1
val b = List(1, 2, 3)
val m = Map(1 -> "one", 2 -> "two")
```
{% endtab %}
{% endtabs %}

When you do this, Scala _infers_ the types, as shown in the following REPL interaction:

{% tabs abm2 %}
{% tab 'Scala 2 and 3' %}
```scala
scala> val a = 1
val a: Int = 1
Expand All @@ -37,5 +47,7 @@ val b: List[Int] = List(1, 2, 3)
scala> val m = Map(1 -> "one", 2 -> "two")
val m: Map[Int, String] = Map(1 -> one, 2 -> two)
```
{% endtab %}
{% endtabs %}

Indeed, most variables are defined this way, and Scala’s ability to automatically infer types is one feature that makes it _feel_ like a dynamically typed language.
8 changes: 8 additions & 0 deletions _overviews/scala3-book/types-introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,27 @@ next-page: types-inferred
Scala is a unique language in that it’s statically typed, but often _feels_ flexible and dynamic.
For instance, thanks to type inference you can write code like this without explicitly specifying the variable types:

{% tabs hi %}
{% tab 'Scala 2 and 3' %}
```scala
val a = 1
val b = 2.0
val c = "Hi!"
```
{% endtab %}
{% endtabs %}

That makes the code feel dynamically typed.
And thanks to new features, like [union types][union-types] in Scala 3, you can also write code like the following that expresses very concisely which values are expected as arguments and which types are returned:

{% tabs union-example %}
{% tab 'Scala 3 Only' %}
```scala
def isTruthy(a: Boolean | Int | String): Boolean = ???
def dogCatOrWhatever(): Dog | Plant | Car | Sun = ???
```
{% endtab %}
{% endtabs %}

As the example suggests, when using union types, the types don’t have to share a common hierarchy, and you can still accept them as arguments or return them from a method.

Expand Down