diff --git a/.sdkmanrc b/.sdkmanrc index 743a627..b9b7bcd 100644 --- a/.sdkmanrc +++ b/.sdkmanrc @@ -1 +1,3 @@ -java=22-tem +# Enable auto-env through the sdkman_auto_env config +# Add key=value pairs of SDKs to use below +java=23.ea.18-open diff --git a/build.sh b/build.sh index 572d280..3c0bcd8 100755 --- a/build.sh +++ b/build.sh @@ -1,6 +1,6 @@ #!/bin/bash -rm -rf bin && mkdir -p bin && javac --enable-preview --source 22 -d bin snippets/*.java +rm -rf bin && mkdir -p bin && javac --enable-preview --source 23 -d bin snippets/*.java marp slides.md -o slides.html marp slides.md -o slides.pdf diff --git a/slides.md b/slides.md index e23dc57..e54814f 100644 --- a/slides.md +++ b/slides.md @@ -48,7 +48,7 @@ --- -# Java 8 +# Java 8 :older_man: * Lanzado en Marzo 2014 :rocket: * No existía ni tiktok :notes: ni openai :robot: @@ -187,7 +187,6 @@ ``` * Incluido en Java 21. -* Exhaustiveness. --- @@ -203,11 +202,25 @@ * Incluido en Java 21. * Deconstructores, nos permite acceder a los componentes de los objectos. +* Exhaustiveness. --- +# Guarded patterns + +```java +var result = switch (point) { + case Point(var x, var y) when y == 0 -> processX(x); + case Point(var x, var y) -> processXY(x, y); +}; +``` + +* Podemos añadir condiciones adicionales usando `when` + +--- + # Unnamed variables and patterns ```java @@ -234,12 +247,26 @@ --- +# Otros lenguajes con soporte ADTs + +* Scala, Kotlin +* Rust +* C# + +--- + # ADTs * Productos y sumas de tipos. `a + b` `a * b` * Cardinalidad. -* Tienen propiedades algebraicas: +* Se les llama algebraicos porque tienen propiedades algebraicas. + +--- + +# ADTs + +* Propiedades algebraicas: * Identidad: `a + 0 <=> a` `a * 1 <=> a` * Distributiva: @@ -273,6 +300,62 @@ --- +# ADTs: List (map) + +```java +sealed interface List { + + default List map(Function mapper) { + return switch (this) { + case NonEmpty(var head, var tail) + -> new NonEmpty<>(mapper.apply(head), tail.map(mapper)); + case Empty() + -> new Empty<>(); + }; + } +} +``` + +--- + +# ADTs: List (filter) + +```java +sealed interface List { + + default List filter(Predicate filter) { + return switch (this) { + case NonEmpty(var head, var tail) when filter.test(head) + -> new NonEmpty<>(head, tail.filter(filter)); + case NonEmpty(var head, var tail) + -> tail.filter(filter); + case Empty() + -> new Empty<>(); + }; + } +} +``` + +--- + +# ADTs: List (fold) + +```java +sealed interface List { + + default T fold(T initial, BinaryOperator operator) { + return switch (this) { + case NonEmpty(var head, var tail) + -> tail.fold(operator.apply(initial, head), operator); + case Empty() + -> initial; + }; + } +} +``` + +--- + # ADTs: Tree ```java @@ -299,6 +382,55 @@ --- +# ADTs: Optional (map) + +```java +sealed interface Optional { + + default Optional map(Function mapper) { + return switch (this) { + case Present(var value) -> new Present<>(mapper.apply(value)); + case Empty _ -> new Empty<>(); + }; + } +} +``` + +--- + +# ADTs: Optional (filter) + +```java +sealed interface Optional { + + default Optional filter(Predicate filter) { + return switch (this) { + case Present(var value) when filter.test(value) -> this; + case Present _ -> new Empty<>(); + case Empty _ -> new Empty<>(); + }; + } +} +``` + +--- + +# ADTs: Optional (fold) + +```java +sealed interface Optional { + + default R fold(Supplier onEmpty, Function onPresent) { + return switch (this) { + case Present(var value) -> onPresent.apply(value); + case Empty _ -> onEmpty.get(); + }; + } +} +``` + +--- + # ADTs: Either ```java @@ -378,7 +510,7 @@ ```java var result = switch (obj) { - case int i -> String.format("int %d", i); + case int i -> String.format("int %d", i); case long l -> String.format("long %d", l); case double d -> String.format("double %f", d); case String s -> String.format("String %s", s); @@ -390,6 +522,26 @@ --- +# Primitive types in patterns + +```java +jshell> int i = 0; +i ==> 0 +jshell> i instanceof byte b +$2 ==> true +``` + +```java +jshell> int i = 123213; +i ==> 123213 +jshell> i instanceof byte b +$4 ==> false +``` + +* Castings seguros + +--- + # Bola de cristal :crystal_ball: @@ -435,8 +587,6 @@ }; ``` -* ??? - --- # ¿Qué falta todavía? diff --git a/snippets/List.java b/snippets/List.java index 5200b03..5bc0fc7 100644 --- a/snippets/List.java +++ b/snippets/List.java @@ -1,3 +1,4 @@ +import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Predicate; @@ -8,21 +9,29 @@ default List map(Function mapper) { return switch (this) { - case NonEmpty(var head, var tail) + case NonEmpty(var head, var tail) -> new NonEmpty<>(mapper.apply(head), tail.map(mapper)); - case Empty() + case Empty() -> new Empty<>(); }; } default List filter(Predicate filter) { return switch (this) { - case NonEmpty(var head, var tail) when filter.test(head) + case NonEmpty(var head, var tail) when filter.test(head) -> new NonEmpty<>(head, tail.filter(filter)); - case NonEmpty(var head, var tail) + case NonEmpty(var head, var tail) -> tail.filter(filter); - case Empty() + case Empty() -> new Empty<>(); }; } + + default T fold(T initial, BinaryOperator operator) { + return switch (this) { + case NonEmpty(var head, var tail) + -> tail.fold(operator.apply(initial, head), operator); + case Empty() -> initial; + }; + } } diff --git a/snippets/Switches.java b/snippets/Switches.java index 066373d..a25ee71 100644 --- a/snippets/Switches.java +++ b/snippets/Switches.java @@ -30,4 +30,22 @@ }; } + record Point(int x, int y) {} + + void method4(Point point) { + + var result = switch (point) { + case Point(var x, var y) when y == 0 -> processX(x); + case Point(var x, var y) -> processXY(x, y); + }; + } + + int processX(int x) { + return 0; + } + + int processXY(int x, int y) { + return 0; + } + }