Translate

viernes, 12 de marzo de 2021

Primeros pasos con Clojure, parte 30

 Seguimos con Clojure..


Clojure no es un lenguaje funcional puro, por lo tanto tiene funciones con efecto secundario. Vamos a ver algunas : 


dotimes :

user=> (dotimes [i 3]

         (println i))

0

1

2

nil

Muy parecido a un for, empieza de 0 y sigue hasta 3 - 1.


doseq :

user=> (doseq [n (range 3)]

         (println n))

0

1

2

nil

Itera sobre una secuencia (evaluandola si es lazy). Tambien existe la variante que procesa todas las permutaciones del contenido de la secuencia, veamos un ejemplo : 

user=> (doseq [letter [:a :b]

               number (range 3)] ; list of 0, 1, 2

         (prn [letter number]))

[:a 0]

[:a 1]

[:a 2]

[:b 0]

[:b 1]

[:b 2]

nil


for : 

user=> (for [letter [:a :b]

             number (range 3)] ; list of 0, 1, 2

         [letter number])

([:a 0] [:a 1] [:a 2] [:b 0] [:b 1] [:b 2])


La función for se utiliza para generar listas, como listas por comprensión. 

Primeros pasos con Clojure, parte 29

Seguimos con Clojure... 


cond es una serie de condiciones y expresiones. Cada condición se evalúa en orden y la expresión se evalúa y devuelve el resultado de la primera expresión en que condición fue verdadera.

(let [x 5]

  (cond

    (< x 2) "x is less than 2"

    (< x 10) "x is less than 10"))


Si no se cumple ninguna condición, se devuelve nil. Un modismo común es usar una condición final de :else. Las palabras clave (como :else) siempre se evalúan como verdaderas, por lo que siempre se seleccionará de forma predeterminada.


(let [x 11]

  (cond

    (< x 2)  "x is less than 2"

    (< x 10) "x is less than 10"

    :else  "x is greater than or equal to 10"))


case compara un argumento con una serie de valores para encontrar una coincidencia. ¡Esto se hace en tiempo constante (no lineal)! Sin embargo, cada valor debe ser un literal en tiempo de compilación (números, cadenas, palabras clave, etc.).

A diferencia de cond, case arrojará una excepción si ningún valor coincide.

user=> (defn foo [x]

         (case x

           5 "x is 5"

           10 "x is 10"))

#'user/foo


user=> (foo 10)

x is 10


user=> (foo 11)

IllegalArgumentException No matching clause: 11


case puede tener una expresión final que se evaluará si ninguna prueba coincide.


user=> (defn foo [x]

         (case x

           5 "x is 5"

           10 "x is 10"

           "x isn't 5 or 10"))

#'user/foo


user=> (foo 11)

x isn't 5 or 10

Libros Gratuitos de Java Code Geeks

 

Download IT Guides!

 

JMeter Tutorial

JMeter is an application that offers several possibilities to configure and execute load, performance and stress tests using different technologies and protocols. It allows simulating...

 
 

Java Design Patterns

A design pattern is a general reusable solution to a commonly occurring problem within a given context in software design. A design pattern is not a finished design that can be...

 
 

Elasticsearch Tutorial

Elasticsearch is a search engine based on Lucene. It provides a distributed, multitenant-capable full-text search engine with an HTTP web interface and schema-free JSON documents....

 
 

Docker Containerization Cookbook

Docker is the world's leading software containerization platform. Docker containers wrap a piece of software in a complete filesystem that contains everything needed to run: code,...

 

Libros Gratuitos de Web Code Geeks

 

Download IT Guides!

 

Building Web Apps With Node.js

Node.js applications are designed to maximize throughput and efficiency, using non-blocking I/O and asynchronous events. Node.js applications run single-threaded, although Node.js uses...

 
 

AngularJS Programming Cookbook

It aims to simplify both the development and the testing of such applications by providing a framework for clientside model-view-controller (MVC) and model-view-viewmodel (MVVM)...

 
 

GWT Programming Cookbook

Google Web Toolkit, or GWT Web Toolkit, is an open source set of tools that allows web developers to create and maintain complex JavaScript front-end applications in Java. Other than a...

 
 

Git Tutorial

Git is, without any doubt, the most popular version control system. Ironically, there are other version control systems easier to learn and to use, but, despite that, Git is the favorite...

 

Libro Gratuito : Infrastructure as Code, Dynamic Systems for the Cloud Age

 



Development teams for companies worldwide are attempting to build large infrastructure codebases.

Download this eBook and learn how to effectively use principles, practices, and patterns pioneered by DevOps teams to manage cloud-age infrastructure.
 
GET THE EBOOK

Este libro está dirigido a personas que participan en la provisión y el uso de infraestructura para entregar y ejecutar software. Puede tener experiencia en sistemas e infraestructura, o en desarrollo y entrega de software. Su función puede ser ingeniería, pruebas, arquitectura o administración. Se asume que tiene cierta exposición a la nube o infraestructura virtualizada y herramientas para automatizar la infraestructura mediante código.

Los lectores nuevos en Infrastructure as Code deberían encontrar este libro como una buena introducción al tema, aunque sacará el máximo provecho de él si está familiarizado con el funcionamiento de las plataformas de infraestructura en la nube y los conceptos básicos de al menos una herramienta de codificación de infraestructura.

Aquellos que tienen más experiencia trabajando con estas herramientas deben encontrar una combinación de conceptos y enfoques nuevos y familiares. El contenido debe crear un lenguaje común y articular desafíos y soluciones de manera que los profesionales y equipos experimentados encuentren útiles.

martes, 9 de marzo de 2021

Pattern matching en Python.


Antes de empezar, si no sabes que es pattern matching, lee este post : https://emanuelpeg.blogspot.com/2014/04/pattern-matching.html

El PEP 634 nos muestra como va a ser el pattern matching en Python 3.10. Veamos el ejemplo que es super claro : 


match subject:

    case <pattern_1>:

        <action_1>

    case <pattern_2>:

        <action_2>

    case <pattern_3>:

        <action_3>

    case _:

        <action_wildcard>


Muy parecido a scala pero en vez de => usa los 2 puntos. 

Para que quede aun más claro veamos un ejemplo de uso: 


def http_error(status):

    match status:

        case 400:

            return "Bad request"

        case 404:

            return "Not found"

        case 418:

            return "I'm a teapot"

        case _:

            return "Something's wrong with the Internet"


y también se va a poder enumerar opciones con el |  : 


case 401 | 403 | 404:

    return "Not allowed"


A la vez, igual que en scala se va poder hacer matching con el valor y estructura de los objetos : 


# point is an (x, y) tuple

match point:

    case (0, 0):

        print("Origin")

    case (0, y):

        print(f"Y={y}")

    case (x, 0):

        print(f"X={x}")

    case (x, y):

        print(f"X={x}, Y={y}")

    case _:

        raise ValueError("Not a point")


Y como este matching más complejo podemos utilizar mejor el wildcard, etc... pero este post no trata de hablar de toda la potencia de esta nueva característica sino de trasnmitir la noticia. 


Dejo link : 

https://docs.python.org/3.10/whatsnew/3.10.html#pep-634-structural-pattern-matching

viernes, 5 de marzo de 2021

Primeros pasos con Clojure, parte 28

 Seguimos con Clojure... 


En Clojure, todos los valores son lógicamente verdaderos o falsos. Los únicos valores "falsos" son falsos y nulos; todos los demás valores son lógicamente verdaderos.


user=> (if true :truthy :falsey)

:truthy

user=> (if (Object.) :truthy :falsey) ; objects are true

:truthy

user=> (if [] :truthy :falsey) ; empty collections are true

:truthy

user=> (if 0 :truthy :falsey) ; zero is true

:truthy

user=> (if false :truthy :falsey)

:falsey

user=> (if nil :truthy :falsey)

:falsey


El if solo toma una sola expresión para el "entonces" y "si no". Si necesitamos más devemos utilizar el do para crear bloques más grandes que sean una sola expresión.


(if (even? 5)

  (do (println "even")

      true)

  (do (println "odd")

      false))


when es un if con solo una rama then. Verifica una condición y luego evalúa cualquier número de declaraciones como un cuerpo (por lo que no se requiere do).  Y devuelve el valor de la última expresión. Si la condición es falsa, se devuelve nil.


(when (neg? x)

  (throw (RuntimeException. (str "x must be positive: " x))))


Libros gratuitos de microservicios en español


Quiero compartir un conjunto de libros de microservicios e integración en castellano. Y sin más...

Dejo link: https://assets.softwareag.com/spanish-ebooks

martes, 2 de marzo de 2021

Primeros pasos con Clojure, parte 27

Seguimos con Clojure... 




En Clojure, ¡todo es una expresión! Todo devuelve un valor y un bloque de varias expresiones devuelve el último valor. Las expresiones que realizan exclusivamente efectos secundarios devuelven cero.

Los operadores de control de flujo también se pueden ampliar a través de macros, que permiten ampliar el compilador mediante el código de usuario.

if es la expresión condicional más importante: consta de una condición, un "entonces" y un "más". if solo evaluará la rama seleccionada por el condicional.


user=> (str "2 is " (if (even? 2) "even" "odd"))

2 is even

user=> (if (true? false) "impossible!") ;; else is optional

nil

domingo, 28 de febrero de 2021

Rakudo

Rakudo es un compilador de Raku para MoarVM y la máquina virtual de Java, que implementa la especificación de Raku.

Desarrollado originalmente dentro del proyecto Parrot, el repositorio de código fuente de Rakudo se separó del proyecto en febrero de 2009 para que pudiera desarrollarse de forma independiente, aunque todavía había muchas dependencias en ese momento. Rakudo está escrito en C, Raku y el subconjunto ligero de Raku "NQP" 

Rakudo fue lanzado en febrero de 2009, con el nombre en código Viena en honor al grupo Perl mongers que había patrocinado a uno de sus desarrolladores desde abril de 2008. Las versiones posteriores han utilizado nombres en clave basados en grupos Perl mongers.

El primer lanzamiento importante de una distribución tanto de compilador como de módulos (llamado "Rakudo *" o "Rakudo Star") fue el 29 de julio de 2010.

Cuestiones para el que no sabe, raku es el nuevo pearl (esto es por las dudas) y otra cosa busque en todo internet como corre rakudo en la jvm pero no encontre nada. Así que el que quiera aportar medeja el ejemplo en los comentarios. 

Dejo link : https://rakudo.org/

sábado, 27 de febrero de 2021

Haciendo aplicaciones asíncronas con Kotlin y Ktor


Le empresa JetBrains me parece una de las mejores hoy en día en el mundo del desarrollo. Tiene productos buenos y apuesta fuerte. Por eso siempre la sigo y encontre en su paginas este framework. 

Ktor es un framework mantenido por JetBrains. Fue construido con Kotlin desde cero. Ktor fomenta un enfoque minimalista para el diseño de aplicaciones, ya que solo necesita configurar la funcionalidad que el proyecto requiere. Con las corrutinas de Kotlin, Ktor es verdaderamente asincrónico y altamente escalable. Ktor también incluye un cliente HTTP que se implementa como una biblioteca multiplataforma y se usa ampliamente en el desarrollo de aplicaciones móviles con Kotlin.

Si bien el objetivo de Ktor es proporcionar un marco de aplicación multiplataforma de extremo a extremo para aplicaciones independiente de la plataforma. Actualmente faltan algunas plataformas. El framework admite escenarios de servidor y cliente JVM, así como clientes de JavaScript, iOS y Android, y se esta trabajando para utilizarlo en otros tipos de clientes. 

Mucho bla, bla, veamos un ejemplo de código: 

package com.example


import io.ktor.application.*

import io.ktor.response.*

import io.ktor.routing.*


fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)


@Suppress("unused") // Referenced in application.conf

@kotlin.jvm.JvmOverloads

fun Application.module(testing: Boolean = false) {

    routing {

        get {

            call.respondText("Hola Mundo!")

        }

    }

}

Si vamos a un browser http://localhost:8080 y vamos a ver "Hola Mundo!"

Dejo link: https://ktor.io/

jueves, 25 de febrero de 2021

Libros Gratuitos de Java code Geeks

 

Download IT Guides!

 

Spring Interview Questions

The majority of the things you may be asked is collected in the list below. All core modules, from basic Spring functionality such as Spring Beans, up to Spring MVC framework are...

 
 

Android UI Design

Android’s user interface is based on direct manipulation, using touch inputs that loosely correspond to real-world actions, like swiping, tapping, pinching and reverse pinching to...

 
 

JPA Minibook

The basic Java framework to access the database is JDBC. Unfortunately, with JDBC, a lot of hand work is needed to convert a database query result into Java classes. Other disadvantages...

 
 

Microservices for Java Developers

Microservices are a software development technique – a variant of the service-oriented architecture (SOA) structural style – that arranges an application as a collection of loosely...

 

domingo, 21 de febrero de 2021

Primeros pasos con Clojure, parte 26

 Seguimos con Clojure... 

Una alternativa al uso de mapas es crear un "registro". Los registros están diseñados específicamente para este caso de uso y generalmente tienen un mejor rendimiento. Además, tienen un "tipo" con nombre que se puede utilizar para comportamiento polimórfico.

Los registros se definen con la lista de nombres de campo para instancias de registros. Se tratarán como claves de palabras clave en cada instancia de registro.


;; Define a record structure

(defrecord Person [first-name last-name age occupation])


;; Positional constructor - generated

(def kelly (->Person "Kelly" "Keen" 32 "Programmer"))


;; Map constructor - generated

(def kelly (map->Person

             {:first-name "Kelly"

              :last-name "Keen"

              :age 32

              :occupation "Programmer"}))


Los registros se utilizan casi exactamente igual que los mapas, con la salvedad de que no se pueden invocar como una función como los mapas.


user=> (:occupation kelly)

"Programmer"



viernes, 19 de febrero de 2021

Primeros pasos con Clojure, parte 25

Seguimos con Clojure... 

Cuando necesitemos representar mucha información de dominio con el mismo conjunto de campos conocidos de antemano, se puede utilizar un mapa con nombre de atributos como claves. Algo así : 

(def person

  {:first-name "Kelly"

   :last-name "Keen"

   :age 32

   :occupation "Programmer"})

Dado que se trata de un mapa, las formas que ya hemos analizado para buscar un valor por clave también funcionan:

user=> (get person :occupation)

"Programmer"


user=> (person :occupation)

"Programmer"


Pero realmente, la forma más común de obtener valores de campo para este uso es invocando la palabra clave. Al igual que con los mapas y conjuntos, las palabras clave también son funciones. Cuando se invoca una palabra clave, se busca a sí misma en la estructura de datos asociativa que se le pasó.


user=> (:occupation person)

"Programmer"


La invocación de palabras clave también toma un valor predeterminado opcional:


user=> (:favorite-color person "beige")

"beige"


Como se trata de un mapa, podemos usar assoc para agregar o modificar campos:


user=> (assoc person :occupation "Baker")

{:age 32, :last-name "Keen", :first-name "Kelly", :occupation "Baker"}


Y dissoc para eliminar campos:


user=> (dissoc person :age)

{:last-name "Keen", :first-name "Kelly", :occupation "Programmer"}


Es común ver entidades anidadas dentro de otras entidades:


(def company

  {:name "WidgetCo"

   :address {:street "123 Main St"

             :city "Springfield"

             :state "IL"}})


Puede usar get-in para acceder a los campos en cualquier nivel dentro de las entidades anidadas:


user=> (get-in company [:address :city])

"Springfield"


También puede utilizar assoc-in o update-in para modificar entidades anidadas:


user=> (assoc-in company [:address :street] "303 Broadway")

{:name "WidgetCo",

 :address

 {:state "IL",

  :city "Springfield",

  :street "303 Broadway"}}





miércoles, 17 de febrero de 2021

Primeros pasos con Clojure, parte 24

 


 Seguimos con Clojure... 

Hay otras dos funciones que son útiles para comprobar si un mapa contiene una entrada.


user=> (contains? scores "Fred")
true

user=> (find scores "Fred")
["Fred" 1400]

La función contains? es un predicado para verificar la contención. La función find busca la entrada clave / valor en un mapa, no solo el valor.

También puede obtener solo las claves o solo los valores en un mapa:

user=> (keys scores)
("Fred" "Bob" "Angela")

user=> (vals scores)
(1400 1240 1024)

Si bien los mapas están desordenados, existe la garantía de que las funciones keys, vals y otras corran en orden de "secuencia" siempre recorrerán las entradas de una instancia de mapa en particular en el mismo orden.

La función zipmap se puede utilizar para "comprimir" juntas dos secuencias (las claves y los valores) en un mapa:

user=> (def players #{"Alice" "Bob" "Kelly"})
#'user/players

user=> (zipmap players (repeat 0))
{"Kelly" 0, "Bob" 0, "Alice" 0}

La función de merge se puede utilizar para combinar varios mapas en un solo mapa:

user=> (def new-scores {"Angela" 300 "Jeff" 900})
#'user/new-scores

user=> (merge scores new-scores)
{"Fred" 1400, "Bob" 1240, "Jeff" 900, "Angela" 300}

Si ambos mapas contienen la misma clave, gana el de la derecha. Alternativamente, puede usar merge-with para proporcionar una función para invocar cuando hay un conflicto:

user=> (def new-scores {"Fred" 550 "Angela" 900 "Sam" 1000})
#'user/new-scores

user=> (merge-with + scores new-scores)
{"Sam" 1000, "Fred" 1950, "Bob" 1240, "Angela" 1924}

En el caso de un conflicto, se llama a la función en ambos valores para obtener el nuevo valor.

De forma similar a los conjuntos ordenados, los mapas ordenados mantienen las claves ordenadas según un comparador, utilizando comparar como función de comparación predeterminada.

user=> (def sm (sorted-map
         "Bravo" 204
         "Alfa" 35
         "Sigma" 99
         "Charlie" 100))
{"Alfa" 35, "Bravo" 204, "Charlie" 100, "Sigma" 99}

user=> (keys sm)
("Alfa" "Bravo" "Charlie" "Sigma")

user=> (vals sm)
(35 204 100 99)