diff --git a/slides.md b/slides.md index 8dccaa0..0b2c13f 100644 --- a/slides.md +++ b/slides.md @@ -26,6 +26,8 @@ - Mastodon: @tonivade@jvm.social - Github: https://github.com/tonivade + + --- # Encuesta @@ -53,7 +55,7 @@ * Lanzado en Marzo 2014 :rocket: * No existía ni tiktok :notes: ni openai :robot: * Ese mismo año se lanzó spring-boot v1.0. -* Docker y kubernetes daban sus primeros pasos. +* Docker y kubernetes daban sus primeros pasos :baby: + --- -# Records: Constructor Canónico - +# Records: Constructor Canónico :building_construction: ```java public record Movie(String title, int year, int duration) { @@ -139,7 +145,7 @@ @@ -155,7 +161,11 @@ } ``` -* copia defensiva para evitar modificar el contenido del record. +* Copia defensiva para evitar modificar el contenido del record. + + --- @@ -202,6 +212,8 @@ * Incluido en Java 21. + + --- # Null patterns @@ -217,6 +229,8 @@ }; ``` + + --- # Record patterns @@ -233,6 +247,14 @@ * Deconstructores, nos permite acceder a los componentes de los objectos. * Exhaustiveness. + + --- # Guarded patterns @@ -290,9 +312,10 @@ # Otros lenguajes con soporte ADTs -* Scala, Kotlin +* JVM: Scala, Kotlin, Clojure. * Rust * C# +* Otros lenguajes funcionales Hashkel, F#, OCaml, Lisp... --- @@ -303,6 +326,9 @@ * Cardinalidad. * Tienen propiedades algebraicas. + + --- # ADTs @@ -317,6 +343,10 @@ * Asociativa: `a + b + c <=> a + (b + c)` `a * b * c <=> a * (b * c)` + + --- # ADTs @@ -325,6 +355,10 @@ * Un `record` es un producto de tipos. * Un `sealed interface` es una suma de tipos. * ¿Pero eso para qué me sirve? + * Estructuras de datos. + * Estructuras de control. + * DSLs + * Manejo de errores. --- @@ -339,39 +373,42 @@ } ``` + + --- # 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<>(); + 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<>(); + case Empty _ -> new Empty<>(); }; } } @@ -383,13 +420,11 @@ ```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; + case Empty _ -> initial; }; } } @@ -483,6 +518,8 @@ } ``` + + --- # ADTs: Json @@ -511,7 +548,7 @@ } ``` -* ADTs son muy útiles para definir DSLs + --- @@ -530,6 +567,8 @@ } ``` + + --- # ADTs: DSLs @@ -547,6 +586,8 @@ } ``` + + --- # ADTs: DSLs @@ -684,6 +725,9 @@ * Preview en Java 23 (sep 2024). + + --- # Primitive types in patterns diff --git a/snippets/Json.java b/snippets/Json.java index bd48bbc..1f401c1 100644 --- a/snippets/Json.java +++ b/snippets/Json.java @@ -1,5 +1,10 @@ +import static java.util.Map.entry; +import static java.util.stream.Collectors.joining; +import static java.util.stream.Collectors.toMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; sealed interface Json { enum JsonNull implements Json { NULL } @@ -8,4 +13,51 @@ record JsonNumber(Number value) implements Json {} record JsonObject(Map value) implements Json {} record JsonArray(List value) implements Json {} + + default String asString() { + return switch (this) { + case JsonNull _ -> "null"; + case JsonBoolean b -> switch (b) { + case TRUE -> "true"; + case FALSE -> "false"; + }; + case JsonString(var value) -> "\"" + value + "\""; + case JsonNumber(var value) -> String.valueOf(value); + case JsonObject(var map) + -> map.entrySet().stream() + .map(entry -> "\"" + entry.getKey() + "\":" + entry.getValue().asString()) + .collect(joining(",", "{", "}")); + case JsonArray(var array) + -> array.stream() + .map(Json::asString) + .collect(joining(",", "[", "]")); + }; + } + + static Json string(String value) { + return new JsonString(value); + } + + static Json number(Number value) { + return new JsonNumber(value); + } + + static Json array(Json...elements) { + return new JsonArray(List.of(elements)); + } + + @SafeVarargs + static Json object(Map.Entry...entries) { + return new JsonObject(Stream.of(entries) + .collect(toMap(Map.Entry::getKey, Map.Entry::getValue))); + } + + static void main() { + var string = array( + object(entry("name", string("Toni")), entry("age", number(46)), entry("old", JsonBoolean.TRUE)), + object(entry("name", string("Baby")), entry("age", JsonNull.NULL), entry("old", JsonBoolean.FALSE)) + ).asString(); + + System.out.println(string); + } } \ No newline at end of file diff --git a/snippets/List.java b/snippets/List.java index 5bc0fc7..2a5f2df 100644 --- a/snippets/List.java +++ b/snippets/List.java @@ -11,8 +11,7 @@ return switch (this) { case NonEmpty(var head, var tail) -> new NonEmpty<>(mapper.apply(head), tail.map(mapper)); - case Empty() - -> new Empty<>(); + case Empty _ -> new Empty<>(); }; } @@ -22,8 +21,7 @@ -> new NonEmpty<>(head, tail.filter(filter)); case NonEmpty(var head, var tail) -> tail.filter(filter); - case Empty() - -> new Empty<>(); + case Empty _ -> new Empty<>(); }; } @@ -31,7 +29,7 @@ return switch (this) { case NonEmpty(var head, var tail) -> tail.fold(operator.apply(initial, head), operator); - case Empty() -> initial; + case Empty _ -> initial; }; } }