From 781cc2483c71f5952ecd3eccc1a7a4c5afb4869e Mon Sep 17 00:00:00 2001 From: Luc Henninger Date: Thu, 22 Sep 2022 17:00:53 +0200 Subject: [PATCH 1/8] Add code tabs for _tour/compound-types --- _tour/compound-types.md | 50 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/_tour/compound-types.md b/_tour/compound-types.md index 4cd53674b5..28194585c8 100644 --- a/_tour/compound-types.md +++ b/_tour/compound-types.md @@ -14,6 +14,8 @@ Sometimes it is necessary to express that the type of an object is a subtype of Suppose we have two traits `Cloneable` and `Resetable`: +{% tabs compound-types_1 class=tabs-scala-version %} +{% tab 'Scala 2' for=compound-types_1 %} ```scala mdoc trait Cloneable extends java.lang.Cloneable { override def clone(): Cloneable = { @@ -24,28 +26,66 @@ trait Resetable { def reset: Unit } ``` +{% endtab %} +{% tab 'Scala 3' for=compound-types_1 %} +```scala +trait Cloneable extends java.lang.Cloneable: + override def clone(): Cloneable = + super.clone().asInstanceOf[Cloneable] +trait Resetable: + def reset: Unit +``` +{% endtab %} +{% endtabs %} Now suppose we want to write a function `cloneAndReset` which takes an object, clones it and resets the original object: -``` +{% tabs compound-types_2 class=tabs-scala-version %} +{% tab 'Scala 2' for=compound-types_2 %} +```scala mdoc::fail def cloneAndReset(obj: ?): Cloneable = { val cloned = obj.clone() obj.reset cloned } ``` +{% endtab %} +{% tab 'Scala 3' for=compound-types_2 %} +```scala +def cloneAndReset(obj: ?): Cloneable = + val cloned = obj.clone() + obj.reset + cloned +``` +{% endtab %} +{% endtabs %} -The question arises what the type of the parameter `obj` is. If it's `Cloneable` then the object can be `clone`d, but not `reset`; if it's `Resetable` we can `reset` it, but there is no `clone` operation. To avoid type casts in such a situation, we can specify the type of `obj` to be both `Cloneable` and `Resetable`. This compound type is written like this in Scala: `Cloneable with Resetable`. +The question arises what the type of the parameter `obj` is. If it's `Cloneable` then the object can be `clone`d, but not `reset`; if it's `Resetable` we can `reset` it, but there is no `clone` operation. To avoid type casts in such a situation, we can specify the type of `obj` to be both `Cloneable` and `Resetable`. +{% tabs compound-types_3 class=tabs-scala-version %} +{% tab 'Scala 2' for=compound-types_3 %} +This compound type is written like this in Scala: `Cloneable with Resetable`. Here's the updated function: - -``` +```scala mdoc def cloneAndReset(obj: Cloneable with Resetable): Cloneable = { //... } ``` - Compound types can consist of several object types and they may have a single refinement which can be used to narrow the signature of existing object members. The general form is: `A with B with C ... { refinement }` +{% endtab %} +{% tab 'Scala 3' for=compound-types_2 %} +This compound type is written like this in Scala: `Cloneable & Resetable`. + +Here's the updated function: +```scala +def cloneAndReset(obj: Cloneable & Resetable): Cloneable = { + //... +} +``` +Compound types can consist of several object types and they may have a single refinement which can be used to narrow the signature of existing object members. +The general form is: `A & B & C ... { refinement }` +{% endtab %} +{% endtabs %} An example for the use of refinements is given on the page about [class composition with mixins](mixin-class-composition.html). From 9aeaf88b0c6513178d652cbb533e486afb07b371 Mon Sep 17 00:00:00 2001 From: Luc Henninger Date: Thu, 22 Sep 2022 19:32:39 +0200 Subject: [PATCH 2/8] Update compound-types.md Typo! --- _tour/compound-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/compound-types.md b/_tour/compound-types.md index 28194585c8..2312a98189 100644 --- a/_tour/compound-types.md +++ b/_tour/compound-types.md @@ -42,7 +42,7 @@ Now suppose we want to write a function `cloneAndReset` which takes an object, c {% tabs compound-types_2 class=tabs-scala-version %} {% tab 'Scala 2' for=compound-types_2 %} -```scala mdoc::fail +```scala mdoc:fail def cloneAndReset(obj: ?): Cloneable = { val cloned = obj.clone() obj.reset From ad4ccae93138b0ac10a5b1eacdcd150cbf0812d7 Mon Sep 17 00:00:00 2001 From: Luc Henninger Date: Thu, 22 Sep 2022 19:41:35 +0200 Subject: [PATCH 3/8] Update compound-types.md --- _tour/compound-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/compound-types.md b/_tour/compound-types.md index 2312a98189..aae5bff68c 100644 --- a/_tour/compound-types.md +++ b/_tour/compound-types.md @@ -66,7 +66,7 @@ The question arises what the type of the parameter `obj` is. If it's `Cloneable` This compound type is written like this in Scala: `Cloneable with Resetable`. Here's the updated function: -```scala mdoc +```scala mdoc:fail def cloneAndReset(obj: Cloneable with Resetable): Cloneable = { //... } From 95d4624672dd031151b54e914c451c613041d4c9 Mon Sep 17 00:00:00 2001 From: Luc Henninger Date: Fri, 23 Sep 2022 19:51:35 +0200 Subject: [PATCH 4/8] Update _tour/compound-types.md You're right ! Co-authored-by: Jamie Thompson --- _tour/compound-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/compound-types.md b/_tour/compound-types.md index aae5bff68c..2d0411e4a6 100644 --- a/_tour/compound-types.md +++ b/_tour/compound-types.md @@ -74,7 +74,7 @@ def cloneAndReset(obj: Cloneable with Resetable): Cloneable = { Compound types can consist of several object types and they may have a single refinement which can be used to narrow the signature of existing object members. The general form is: `A with B with C ... { refinement }` {% endtab %} -{% tab 'Scala 3' for=compound-types_2 %} +{% tab 'Scala 3' for=compound-types_3 %} This compound type is written like this in Scala: `Cloneable & Resetable`. Here's the updated function: From 080ae882ed807c501f415d81f4a4aa5579e49a61 Mon Sep 17 00:00:00 2001 From: Luc Henninger Date: Tue, 27 Sep 2022 13:45:45 +0200 Subject: [PATCH 5/8] Update _tour/compound-types.md Co-authored-by: Quentin Bernet --- _tour/compound-types.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/_tour/compound-types.md b/_tour/compound-types.md index 2d0411e4a6..36a2cd481e 100644 --- a/_tour/compound-types.md +++ b/_tour/compound-types.md @@ -72,7 +72,8 @@ def cloneAndReset(obj: Cloneable with Resetable): Cloneable = { } ``` Compound types can consist of several object types and they may have a single refinement which can be used to narrow the signature of existing object members. -The general form is: `A with B with C ... { refinement }` +Note that you can have more than two types: `A with B with C with ...`. +This means the same as thing as `(...(A with B) with C`) with ... )` {% endtab %} {% tab 'Scala 3' for=compound-types_3 %} This compound type is written like this in Scala: `Cloneable & Resetable`. From 28028df3056144c963fb24e97c1c0b6d6399d6a3 Mon Sep 17 00:00:00 2001 From: Luc Henninger Date: Tue, 27 Sep 2022 13:45:57 +0200 Subject: [PATCH 6/8] Update _tour/compound-types.md Co-authored-by: Quentin Bernet --- _tour/compound-types.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/_tour/compound-types.md b/_tour/compound-types.md index 36a2cd481e..59fda66979 100644 --- a/_tour/compound-types.md +++ b/_tour/compound-types.md @@ -85,7 +85,8 @@ def cloneAndReset(obj: Cloneable & Resetable): Cloneable = { } ``` Compound types can consist of several object types and they may have a single refinement which can be used to narrow the signature of existing object members. -The general form is: `A & B & C ... { refinement }` +Note that you can have more than two types: `A & B & C & ...`. +And `&` is associative, so parentheses can be added around any part without changing the meaning. {% endtab %} {% endtabs %} From 454ae7e9cc2c4bdc8b89ae4e89ad8bf166c00358 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Tue, 27 Sep 2022 14:51:19 +0200 Subject: [PATCH 7/8] bias towards intersection types --- _tour/compound-types.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/_tour/compound-types.md b/_tour/compound-types.md index 59fda66979..bb2abca5cd 100644 --- a/_tour/compound-types.md +++ b/_tour/compound-types.md @@ -1,6 +1,6 @@ --- layout: tour -title: Compound Types +title: Intersection Types, aka Compound Types partof: scala-tour num: 26 @@ -10,7 +10,10 @@ previous-page: abstract-type-members redirect_from: "/tutorials/tour/compound-types.html" --- -Sometimes it is necessary to express that the type of an object is a subtype of several other types. In Scala this can be expressed with the help of *compound types*, which are intersections of object types. +Sometimes it is necessary to express that the type of an object is a subtype of several other types. + +In Scala this can be expressed with the help of *intersection types*, (or *compound types* in +Scala 2) which are types that behave like any part of the intersection. Suppose we have two traits `Cloneable` and `Resetable`: @@ -18,7 +21,7 @@ Suppose we have two traits `Cloneable` and `Resetable`: {% tab 'Scala 2' for=compound-types_1 %} ```scala mdoc trait Cloneable extends java.lang.Cloneable { - override def clone(): Cloneable = { + override def clone(): Cloneable = { // makes clone public super.clone().asInstanceOf[Cloneable] } } @@ -30,7 +33,7 @@ trait Resetable { {% tab 'Scala 3' for=compound-types_1 %} ```scala trait Cloneable extends java.lang.Cloneable: - override def clone(): Cloneable = + override def clone(): Cloneable = // makes clone public super.clone().asInstanceOf[Cloneable] trait Resetable: def reset: Unit @@ -63,7 +66,7 @@ def cloneAndReset(obj: ?): Cloneable = The question arises what the type of the parameter `obj` is. If it's `Cloneable` then the object can be `clone`d, but not `reset`; if it's `Resetable` we can `reset` it, but there is no `clone` operation. To avoid type casts in such a situation, we can specify the type of `obj` to be both `Cloneable` and `Resetable`. {% tabs compound-types_3 class=tabs-scala-version %} {% tab 'Scala 2' for=compound-types_3 %} -This compound type is written like this in Scala: `Cloneable with Resetable`. +This compound type is written in Scala as `Cloneable with Resetable`. Here's the updated function: ```scala mdoc:fail @@ -71,12 +74,11 @@ def cloneAndReset(obj: Cloneable with Resetable): Cloneable = { //... } ``` -Compound types can consist of several object types and they may have a single refinement which can be used to narrow the signature of existing object members. Note that you can have more than two types: `A with B with C with ...`. -This means the same as thing as `(...(A with B) with C`) with ... )` +This means the same as thing as `(...(A with B) with C) with ... )` {% endtab %} {% tab 'Scala 3' for=compound-types_3 %} -This compound type is written like this in Scala: `Cloneable & Resetable`. +This intersection type is written in Scala as `Cloneable & Resetable`. Here's the updated function: ```scala @@ -84,8 +86,8 @@ def cloneAndReset(obj: Cloneable & Resetable): Cloneable = { //... } ``` -Compound types can consist of several object types and they may have a single refinement which can be used to narrow the signature of existing object members. -Note that you can have more than two types: `A & B & C & ...`. + +Note that you can have more than two types: `A & B & C & ...`. And `&` is associative, so parentheses can be added around any part without changing the meaning. {% endtab %} {% endtabs %} From def30dd07b7ae347de74f6d6ae7e3518e6330d7d Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Tue, 27 Sep 2022 15:20:03 +0200 Subject: [PATCH 8/8] remove comment about refinements example. The linked page has no such example. --- _tour/compound-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/compound-types.md b/_tour/compound-types.md index bb2abca5cd..2c12773600 100644 --- a/_tour/compound-types.md +++ b/_tour/compound-types.md @@ -92,4 +92,4 @@ And `&` is associative, so parentheses can be added around any part without chan {% endtab %} {% endtabs %} -An example for the use of refinements is given on the page about [class composition with mixins](mixin-class-composition.html). +