Translate

martes, 13 de octubre de 2020

Lista de comprensión en Haskell


Una lista de comprensión es una notación de alto nivel para especificar el cálculo de una lista.

El compilador transforma automáticamente las comprensiones de una lista en una expresión utilizando una familia de funciones básicas que operan en listas.

Las comprensiones de listas se inspiraron en la comprensión de conjuntos de notación matemática.

Ejemplos de comprensiones de conjuntos:

Un conjunto obtenido al multiplicar los elementos de otro conjunto por 3 es {3 × x | x ← {1,…, 10}}.

El conjunto de números pares es {2 × x | x ← N}.

El conjunto de números impares es

{2 × x + 1 | x ← N}.

El producto cruzado de dos conjuntos A y B es {(a, b) | a ← A, b ← B}.

Ejemplos de listas por comprensión

[3 * x | x <- [1..10]]

-> [3,6,9,12,15,18,21,24,27,30]

[2 * x | x <- [0..10]]

-> [0,2,4,6,8,10,12,14,16,18,20]

[2 * x + 1 | x <- [0..10]]

-> [1,3,5,7,9,11,13,15,17,19,21]

[[a, b] | a <- [10,11,12], b <- [20,21]]

-> [[10,20], [10,21], [11,20], [11,21], [12,20], [12,21]]

lunes, 12 de octubre de 2020

Virtualenv de Python


¿qué es virtualenv? Virtualenv es una herramienta que nos permite realizar entornos python aislados. Imagine que tiene una aplicación que necesita la versión 2 de una biblioteca, pero otra aplicación requiere la versión 3. ¿Cómo puede utilizar y desarrollar ambas aplicaciones?

Si instala todo en /usr/lib/python2.7/site-packages (o cualquiera que sea la ubicación estándar de su plataforma), es fácil terminar en una situación en la que involuntariamente actualice un paquete.

En otro caso, imagina que tienes una aplicación que está completamente desarrollada y no quieres hacer ningún cambio en las bibliotecas que está usando, pero al mismo tiempo comienzas a desarrollar otra aplicación que requiere las versiones actualizadas de esas bibliotecas.

¿Qué harás? ¡Usa virtualenv! Crea entornos aislados para su aplicación de Python y esto nos permitirá instalar bibliotecas de Python en ese entorno aislado en lugar de instalarlas globalmente.

Para instalarlo, simplemente escriba este comando en el shell:

$ pip install virtualenv

Los comandos más importantes son:

$ virtualenv myproject

$ source myproject/bin/activat

Este primero crea un entorno virtualenv aislado en la carpeta myproject y el segundo comando activa ese entorno aislado.

Mientras crea el virtualenv, debe tomar una decisión. ¿Quiere que este virtualenv use paquetes de los paquetes de sitio de su sistema o los instale en los paquetes de sitio del virtualenv? De forma predeterminada, virtualenv no dará acceso a los paquetes globales del sitio.

Si desea que virtualenv tenga acceso a los paquetes de sistema, tenemos que activar --system-site-packages al crear su virtualenv de esta manera:

$ virtualenv --system-site-packages mycoolproject

Y Virtualenv se puede desactivar con : 

$ deactivate

Ejecutar Python después de la desactivación usará la instalación de Python del sistema.

Puede usar smartcd, que es una biblioteca para bash y zsh y le permite alterar su entorno bash (o zsh) mientras hace cd. Puede ser muy útil activar y desactivar un virtualenv cuando cambia de directorio. 

Dejo link: https://docs.python-guide.org/dev/virtualenvs/

sábado, 10 de octubre de 2020

Secuencias en Haskell

 


A veces es útil tener una secuencia de números. En notación matemática estándar, puede escribir 0,1,…, n.

Haskell tiene una notación de secuencia para listas.

Escriba la secuencia entre corchetes, con el valor inicial, el operador .. y el valor final.

[0 .. 5] -> [0,1,2,3,4,5]

[100 .. 103] -> [100,101,102,103]

Los elementos se incrementan en 1 y las secuencias no se limitan a números

Hay muchos tipos enumerables en los que existe una forma natural de incrementar un valor.

Puede utilizar secuencias en cualquier tipo.

Los caracteres son enumerables y se pueden expresar listas de esta manerá.

Por ejemplo:

[’A’ .. ’z’]

-> ['a', 'b', 'c', 'd', 'e', ​​'f', 'g', 'h', 'i', 'j', 'k', 'l', ' m ',' n ',' o ',' p ',' q ',' r ',' s ',' t ',' u ',' v ',' w ',' x ',' y ' , 'z']

es una lista de caracteres;

[’0’ .. ’9’]

-> [’0’, ’1’, ’2’, ’3’, ’4’, ’5’, ’6’, ’7’, ’8 ',' 9’]

es una lista de caracteres (que resultan ser los dígitos);

[0 .. 9]

-> [0,1,2,3,4,5,6,7,8,9]

es una lista de números.


Listas en Haskell


Una estructura de datos clave en todo lenguaje es la lista

Una lista es un valor único que contiene varios otros valores.

En haskell una lista esta representada por elementos se escriben entre paréntesis cuadrados, separados por comas.

['3', 'a']

[2.718, 50.0, -1.0]

Una función solo puede devolver un resultado. Sin embargo, las listas le permiten empaquetar varios valores en un objeto, que puede ser devuelto por una función.

Aquí hay una función (minmax) que devuelve el menor y el mayor de dos números:

minmax = \ x y -> [min x y, max x y]

minmax 3 8 -> [3,8]

minmax 8 3 -> [3,8]


Los elementos de una lista se evalúan perezosamente, de esta forma se pueden hacer listas infinitas. 

Puedes escribir una lista constante

mylist = [2,4,6,8]

Los elementos pueden ser expresiones y se evalúan solo cuando se utilizan. Suponga que define:

respuesta = 42

lista = [7, respuesta + 1, 7 * 8]

Si imprimimos esto : 

lista -> [7, 43, 56]

Pero mientras no se acceda a la expresión, no se evaluará.

El operador (++) toma dos listas existentes y retorna una nueva que contiene todos los elementos.

El operador se pronuncia append y se escribe como dos caracteres + consecutivos.

[23, 29] ++ [48, 41, 44] -> [23, 29, 48, 41, 44]

La longitud del resultado es siempre la suma de las longitudes de las listas originales.

Si xs es una lista, entonces [] ++ xs = xs = xs ++ [].



viernes, 9 de octubre de 2020

Enumeraciones en Python

Enumerate es una funcionalidad incorporada de Python. Nos permite recorrer algo y tener un contador automático. Aquí hay un ejemplo:

my_list = ['apple', 'banana', 'grapes', 'pear']

for counter, value in enumerate(my_list):

    print counter, value


# Output:

# 0 apple

# 1 banana

# 2 grapes

# 3 pear

¡Y hay más! enumerate también acepta un argumento opcional que nos permite especificar el índice de inicio del contador.

my_list = ['apple', 'banana', 'grapes', 'pear']

for c, value in enumerate(my_list, 1):

    print(c, value)


# Output:

# 1 apple

# 2 banana

# 3 grapes

# 4 pear

Un ejemplo de dónde resulta útil el argumento opcional de enumerate es la creación de tuplas que contienen el índice y el elemento de lista mediante una lista. Aquí hay un ejemplo:

my_list = ['apple', 'banana', 'grapes', 'pear']

counter_list = list(enumerate(my_list, 1))

print(counter_list)

# Output: [(1, 'apple'), (2, 'banana'), (3, 'grapes'), (4, 'pear')]

Dejo link : https://book.pythontips.com/en/latest/enumerate.html


jueves, 8 de octubre de 2020

Funciones en Haskell


Haskell es un lenguaje funcional, por lo que el concepto de función es esencial para el lenguaje. Una función toma uno o más argumentos y calcula un resultado. Dados los mismos argumentos, el resultado siempre será el mismo. Esto es similar a una función matemática y significa que en Haskell no hay efectos secundarios. Hay dos operaciones fundamentales en las funciones: definición de función (creando una función) y aplicación de función (usando una función para calcular un resultado).

En Haskell, muchas funciones están predefinidas en una biblioteca estándar llamada preludio.

¡Pero la esencia de la programación funcional es definir sus propias funciones para resolver sus problemas!

Una función se define mediante una ecuación.

f = \ x -> x + 1 - función lambda

- o

f x = x + 1 - función nombrada

Esto es equivalente af (x) = x + 1 en notación matemática.

El lado izquierdo de la ecuación parece una variable, y eso es lo que es

El lado derecho es una expresión que usa las variables locales listadas entre paréntesis y define el resultado de la expresión.

Una definición de función es una ecuación, p. Ej. f = ∖ x → x + 1

El lado izquierdo da el nombre de la función;

El lado derecho (el "cuerpo") es una expresión que da los parámetros formales y el valor de la aplicación. La expresión puede usar los parámetros.

Una aplicación es una expresión como f 31, donde 31 es el argumento.

La aplicación se evalúa reemplazándola con el cuerpo de la función, donde los parámetros formales son reemplazados por los argumentos.

Ejemplo de aplicacion

f = \ x -> x + 1

  f 3

-> {vincular x = 3}

  (x + 1) donde x = 3

-> {sustituye 3 por x}

  3 + 1

->

4

Podríamos tener funciones con multiples argumentos, una función con tres argumentos:

add3nums = \ x y z -> x + y + z

Para usarlo,

10 + 4 * add3nums 1 2 3

  10 + (4 * (add3nums 1 2 3))

  ->

  10 + (4 * (1 + 2 + 3))

  ->

  10 + (4 * 6)

  ->

  10 + 24

  ->

  34


miércoles, 7 de octubre de 2020

Libros Gratuitos de Java Code Geeks

 

Download IT Guides!

 

Selenium Programming Cookbook

Selenium is a portable software testing framework for web applications. Selenium provides a record/playback tool for authoring tests without learning a test scripting language (Selenium...

 
 

Spring Data Programming Cookbook

Spring Data’s mission is to provide a familiar and consistent, Spring-based programming model for data access while still retaining the special traits of the underlying data store. It...

 
 

Android Programming Cookbook

Android is a mobile operating system developed by Google, based on the Linux kernel and designed primarily for touchscreen mobile devices such as smartphones and tablets. Android's user...

 
 

Java NIO Programming Cookbook

java.nio (NIO stands for non-blocking I/O) is a collection of Java programming language APIs that offer features for intensive I/O operations. It was introduced with the J2SE 1.4 release...

 

lunes, 5 de octubre de 2020

Function caching de Python


El almacenamiento en caché de funciones nos permite almacenar en caché los valores de retorno de una función en función de los argumentos. Puede ahorrar tiempo cuando se llama periódicamente a una función vinculada a entrada/salida con los mismos argumentos. Antes de Python 3.2, teníamos que escribir una implementación personalizada. En Python 3.2+ hay un decorador lru_cache que nos permite almacenar en caché y deseleccionar rápidamente los valores de retorno de una función.

Veamos cómo podemos usarlo en Python 3.2+ 

Implementemos una secuencia de Fibonacci y usemos lru_cache.


from functools import lru_cache


@lru_cache(maxsize=32)

def fib(n):

    if n < 2:

        return n

    return fib(n-1) + fib(n-2)


>>> print([fib(n) for n in range(10)])

# Output: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]


El argumento maxsize le dice a lru_cache cuántos valores de retorno recientes se almacenan en caché.

También podemos eliminar en caché fácilmente los valores de retorno usando:

fib.cache_clear()

domingo, 4 de octubre de 2020

Test para comprobar de que todos los métodos de los servicios están anotados con @Transactional


Si bien es medio viejo esto, lo use hace poco en un proyecto (tambien medio viejo) pero pensé que les podría ser útil. 

Un método común para establecer límites de transacciones en Spring Framework es utilizar su gestión de transacciones impulsada por anotaciones y anotar métodos de servicio con la anotación @Transactional. Parece bastante simple, ¿verdad? Si y no. Aunque la gestión de transacciones impulsada por anotaciones de Spring Framework es fácil de configurar y usar, hay algunas cosas que debe recordar hacer:

  • Debe recordar anotar cada método de servicio con la anotación @Transactional. Esto puede parecer una tarea fácil, pero como probablemente eres un ser humano, también eres capaz de cometer errores. Un error como este podría dejar la base de datos de su aplicación en un estado inconsistente si algo sale mal mientras su aplicación escribe información en la base de datos.
  • Si desea revertir la transacción cuando un método de servicio arroja una excepción marcada, debe especificar la clase de excepción marcada lanzada como un valor de la propiedad rollbackFor de la anotación @Transactional. Esto es necesario porque, por defecto, Spring Framework no revertirá la transacción cuando se lanza una excepción marcada. Si el atributo rollbackFor es de la anotación @Transactional no está configurado y se lanza una excepción marcada cuando su aplicación está escribiendo información en la base de datos, la base de datos de su aplicación podría terminar en un estado inconsistente.

Afortunadamente, es bastante fácil implementar una prueba que garantice qu

  • Cada método de una clase de servicio, excepto los getter y setter, se anota con una anotación @Transactional.
  • Cada excepción checked que lanza un método de servicio se establece como un valor de la propiedad rollbackFor de la anotación @Transactional.
  • Como beneficio adicional, esta prueba también verificará que cada clase de servicio esté anotada con la anotación @Service.

Sin más el test : 

public class ServiceAnnotationTest {

 

    private static final String PACKAGE_PATH_SEPARATOR = ".";

 

    /*

     * A string which is used to identify getter methods. All methods whose name contains the given string

     * are considered as getter methods.

     */

    private static final String GETTER_METHOD_NAME_ID = "get";

    private static final String FILE_PATH_SEPARATOR = System.getProperty("file.separator");

 

    /*

     * The file path to the root folder of service package. If the absolute path to the service package

     * is /users/foo/classes/com/bar/service and the classpath base directory is /users/foo/classes,

     * the value of this constant must be /com/bar/service.

     */

    private static final String SERVICE_BASE_PACKAGE_PATH = "/com/bar/service";

 

    /*

     * A string which is used to identify setter methods. All methods whose name contains the given string

     * are considered as setter methods.

     */

    private static final String SETTER_METHOD_NAME_ID = "set";

 

    /*

     * A string which is used to identify the test classes. All classes whose name contains the given string

     * are considered as test classes.

     */

    private static final String TEST_CLASS_FILENAME_ID = "Test";

 

    private List<Class> serviceClasses;

 

    /**

     * Iterates through all the classes found under the service base package path (and its sub directories)

     * and inserts all service classes to the serviceClasses array.

     *

     * @throws IOException

     * @throws ClassNotFoundException

     */

    @Before

    public void findServiceClasses() throws IOException, ClassNotFoundException {

        serviceClasses = new ArrayList<Class>();

        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

        Resource[] resources = resolver.getResources("classpath*:" + SERVICE_BASE_PACKAGE_PATH + "/**/*.class");

        for (Resource resource : resources) {

            if (isNotTestClass(resource)) {

                String serviceClassCandidateNameWithPackage = parseClassNameWithPackage(resource);

                ClassLoader classLoader = resolver.getClassLoader();

                Class serviceClassCandidate = classLoader.loadClass(serviceClassCandidateNameWithPackage);

                if (isNotInterface(serviceClassCandidate)) {

                    if (isNotException(serviceClassCandidate)) {

                        if (isNotEnum(serviceClassCandidate)) {

                            if (isNotAnonymousClass(serviceClassCandidate)) {

                                serviceClasses.add(serviceClassCandidate);

                            }

                        }

                    }

                }

            }

        }

    }

 

    /**

     * Checks if the resource given a as parameter is a test class. This method returns

     * true if the resource is not a test class and false otherwise.

     *

     * @param resource

     * @return

     */

    private boolean isNotTestClass(Resource resource) {

        return !resource.getFilename().contains(TEST_CLASS_FILENAME_ID);

    }

 

    /**

     * Checks if the resource given as a parameter is an exception class. This method returns true

     * if the class is not an exception class and false otherwise.

     *

     * @param exceptionCanditate

     * @return

     */

    private boolean isNotException(Class exceptionCanditate) {

        return !Exception.class.isAssignableFrom(exceptionCanditate) &&

                !RuntimeException.class.isAssignableFrom(exceptionCanditate) &&

                !Throwable.class.isAssignableFrom(exceptionCanditate);

    }

 

    /**

     * Parses a class name from the absolute path of the resource given as a parameter

     * and returns the parsed class name. E.g. if the absolute path of the resource is

     * /user/foo/classes/com/foo/Bar.class, this method returns com.foo.Bar.

     *

     * @param resource

     * @return

     * @throws IOException

     */

    private String parseClassNameWithPackage(Resource resource) throws IOException {

        String pathFromClasspathRoot = parsePathFromClassPathRoot(resource.getFile().getAbsolutePath());

        String pathWithoutFilenameSuffix = parsePathWithoutFilenameSuffix(pathFromClasspathRoot);

        return buildClassNameFromPath(pathWithoutFilenameSuffix);

    }

 

    /**

     * Parses the path which starts from the classpath root directory by using the

     * absolute path given as a parameter. Returns the parsed path.

     * E.g. If the absolute path is /user/foo/classes/com/foo/Bar.class and the classpath

     * root directory is /user/foo/classes/, com/foo/Bar.class is returned.

     *

     * @param absolutePath

     * @return

     */

    private String parsePathFromClassPathRoot(String absolutePath) {

        int classpathRootIndex = absolutePath.indexOf(SERVICE_BASE_PACKAGE_PATH);

        return absolutePath.substring(classpathRootIndex + 1);

    }

 

    /**

     * Removes the file suffix from the path given as a parameter and returns new path

     * without the suffix. E.g. If path is com/foo/Bar.class, com/foo/Bar is returned.

     *

     * @param path

     * @return

     */

    private String parsePathWithoutFilenameSuffix(String path) {

        int prefixIndex = path.indexOf(PACKAGE_PATH_SEPARATOR);

        return path.substring(0, prefixIndex);

    }

 

    /**

     * Builds a class name with package information from a path given as a parameter and

     * returns the class name with package information. e.g. If a path com/foo/Bar is given

     * as a parameter, com.foo.Bar is returned.

     *

     * @param path

     * @return

     */

    private String buildClassNameFromPath(String path) {

        return path.replace(FILE_PATH_SEPARATOR, PACKAGE_PATH_SEPARATOR);

    }

 

    /**

     * Checks if the class given as an argument is an interface or not.

     * Returns false if the class is not an interface and true otherwise.

     *

     * @param interfaceCanditate

     * @return

     */

    private boolean isNotInterface(Class interfaceCanditate) {

        return !interfaceCanditate.isInterface();

    }

 

    /**

     * Checks if the class given as an argument is an Enum or not.

     * Returns false if the class is not Enum and true otherwise.

     *

     * @param enumCanditate

     * @return

     */

    private boolean isNotEnum(Class enumCanditate) {

        return !enumCanditate.isEnum();

    }

 

    /**

     * Checks if the class given as a parameter is an anonymous class.

     * Returns true if the class is not an anonymous class and false otherwise.

     *

     * @param anonymousClassCanditate

     * @return

     */

    private boolean isNotAnonymousClass(Class anonymousClassCanditate) {

        return !anonymousClassCanditate.isAnonymousClass();

    }

 

    /**

     * Verifies that each method which is declared in a service class and which is not a

     * getter or setter method is annotated with Transactional annotation. This test

     * also ensures that the rollbackFor property of Transactional annotation specifies

     * all checked exceptions which are thrown by the service method.

     */

    @Test

    public void eachServiceMethodHasTransactionalAnnotation() {

        for (Class serviceClass : serviceClasses) {

            Method[] serviceMethods = serviceClass.getMethods();

            for (Method serviceMethod : serviceMethods) {

                if (isMethodDeclaredInServiceClass(serviceMethod, serviceClass)) {

                    if (isNotGetterOrSetterMethod(serviceMethod)) {

                        boolean transactionalAnnotationFound = serviceMethod.isAnnotationPresent(Transactional.class);

                        assertTrue("Method " + serviceMethod.getName() + " of " + serviceClass.getName() + " class must be annotated with @Transactional annotation.", transactionalAnnotationFound);

                        if (transactionalAnnotationFound) {

                            if (methodThrowsCheckedExceptions(serviceMethod)) {

                                boolean rollbackPropertySetCorrectly = rollbackForPropertySetCorrectlyForTransactionalAnnotation(serviceMethod.getAnnotation(Transactional.class), serviceMethod.getExceptionTypes());

                                assertTrue("Method " + serviceMethod.getName() + "() of " + serviceClass.getName() + " class must set rollbackFor property of Transactional annotation correctly", rollbackPropertySetCorrectly);

                            }

                        }

                    }

                }

            }

        }

    }

 

    /**

     * Checks that the method given as a parameter is declared in a service class given as

     * a parameter. Returns true if the method is declated in service class and false

     * otherwise.

     *

     * @param method

     * @param serviceClass

     * @return

     */

    private boolean isMethodDeclaredInServiceClass(Method method, Class serviceClass) {

        return method.getDeclaringClass().equals(serviceClass);

    }

 

    /**

     * Checks if the method given as parameter is a getter or setter method. Returns true

     * if the method is a getter or setter method an false otherwise.

     *

     * @param method

     * @return

     */

    private boolean isNotGetterOrSetterMethod(Method method) {

        return !method.getName().contains(SETTER_METHOD_NAME_ID) && !method.getName().contains(GETTER_METHOD_NAME_ID);

    }

 

    /**

     * Checks if the method given as a parameter throws checked exceptions. Returns true

     * if the method throws checked exceptions and false otherwise.

     *

     * @param method

     * @return

     */

    private boolean methodThrowsCheckedExceptions(Method method) {

        return method.getExceptionTypes().length > 0;

    }

 

    /**

     * Checks if the transactional annotation given as a parameter specifies all checked exceptions

     * given as a parameter as a value of rollbackFor property. Returns true if all exceptions

     * are specified and false otherwise.

     *

     * @param annotation

     * @param thrownExceptions

     * @return

     */

    private boolean rollbackForPropertySetCorrectlyForTransactionalAnnotation(Annotation annotation, Class<?>[] thrownExceptions) {

        boolean rollbackForSet = true;

 

        if (annotation instanceof Transactional) {

            Transactional transactional = (Transactional) annotation;

            List<Class<? extends Throwable>> rollbackForClasses = Arrays.asList(transactional.rollbackFor());

            for (Class<?> thrownException : thrownExceptions) {

                if (!rollbackForClasses.contains(thrownException)) {

                    rollbackForSet = false;

                    break;

                }

            }

        }

 

        return rollbackForSet;

    }

 

    /**

     * Verifies that each service class is annotated with @Service annotation.

     */

    @Test

    public void eachServiceClassIsAnnotatedWithServiceAnnotation() {

        for (Class serviceClass : serviceClasses) {

            assertTrue(serviceClass.getSimpleName() + " must be annotated with @Service annotation", serviceClass.isAnnotationPresent(Service.class));

        }

    }

}

Dejo link : https://www.petrikainulainen.net/programming/tips-and-tricks/testing-that-all-service-methods-are-annotated-with-transactional-annotation/



Que diferencia tiene Unit y Nothing en Kotlin o en Scala??

Que diferencia tiene Unit y Nothing en Kotlin o en Scala?? Dado que kotlin se ha "inspirado" en muchas cosas de Scala. Por lo tanto creo que en este caso los 2 lenguajes son iguales. (En realidad no estoy tan seguro, comenten si tienen otra información)


Antes de hablar de diferencias, veamos similitudes : 

Unit:  Unit en Kotlin o Scala corresponde al void en Java y de C. Al igual que void, Unit es el tipo de retorno de cualquier función que no devuelva ningún valor significativo, y es opcional mencionar Unit como tipo de retorno. Pero a diferencia de void, Unit es una clase real (en kotlin) o object (en Scala) con una sola instancia.

Nothing: Nothing es un tipo en Kotlin que represente "un valor que nunca existe", eso significa simplemente "ningún valor en absoluto".

Nothing se puede usar como el tipo de retorno de una función que nunca devuelve la ejecución del código, como, en bucle para siempre o siempre arroja Exception. Java no tiene nada similar al tipo Nothing.

Veamos unos ejemplos donde debemos utilizar Nothing como tipo de retorno.


Supongamos que hay una función reportError() que siempre lanza una RuntimeException. En una aplicación real, este reportError() puede agregar algunos registros útiles adicionales antes de lanzar la excepción o arroja diferentes excepciones basadas en diferentes condiciones.

En java se implementaría : 

void reportError() {

    throw new RuntimeException();

}

En Kotlin : 

fun reportError(): Nothing {

    throw RuntimeException()

}

En Scala : 

def reportError(): Nothing {

    throw RuntimeException()

}


Como vemos Nothing debe ser escrito explícitamente como el tipo de retorno; de lo contrario, el tipo de retorno seguirá siendo Unit.

¿Qué pasará si colocamos por error alguna linea de código después de llamar a este método reportError ()?

// Java

int i = 0;

void exampleOne() {

    reportError(); // throws RuntimeException

    i = 1; // This is unreachable code. But there is no warning.

}

En java no pasaría nada, pero pero en kotlin nos avisaría : 


// Kotlin

var i = 0;

fun exampleOne() {

    reportError(); // throws RuntimeException

    i = 1; // We will get an 'Unreachable code' warning here. 

}

En Kotlin tendríamos un warning. 


Otra cuestión importante es que Nothing implementa o se puede hacer pasar por diferentes tipos, lo que permite que hagamos lo siguiente : 

  /** `???` can be used for marking methods that remain to be implemented.

   *  @throws NotImplementedError

   */

  def ??? : Nothing = throw new NotImplementedError

Y luego utilizar ??? para marcar una función que nos falta implementar. 

  /**

   * Filtra los elementos pares

   */

  def filtrarPares(xs: List[Int]): List[Int] = ???

Y tiene más usos Nothing por ejemplo Nil que es la lista vacia es de tipo List[Nothing] dado que este tipo puede hacerse pasar por otros tipos. 

Ojo que hay algunas diferencias entre Scala y Kotlin más que nada en los nulleables de kotlin pero la idea general es esta.

Y creo que estamos, si me olvide de algo, para eso están los comentarios!

viernes, 2 de octubre de 2020

Desactivar o activar las constraints de una o muchas tablas en base de datos Oracle


Muchas veces en nuestra vida profesional tenemos que insertar datos por X motivos ignorando las constraints. Vale aclarar que esto es peligroso y no se tendría que hacer nunca pero pero la vida nos lleva por mal camino a veces. Entonces podemos hacer esto para desactivar las constraints de mis tablas : 

begin

for i in (select constraint_name, table_name from user_constraints where table_name in ('tabla1', 'tabla2', 'tabla3')) LOOP

execute immediate 'alter table '||i.table_name||' disable constraint '||i.constraint_name||'';

end loop;

end;

/

Y para habilitarlas: 


begin

for i in (select constraint_name, table_name from user_constraints where table_name in ('tabla1', 'tabla2', 'tabla3')) LOOP

execute immediate 'alter table '||i.table_name||' ENABLE constraint '||i.constraint_name||'';

end loop;

end;

/


Y Listo! 

martes, 29 de septiembre de 2020

Con que framework debo desarrollar un sistema web??


Esta pregunta me la hizo un alumno y quiero compartir mi respuesta. 

Existen muchas opciones pero es bueno ir por donde va la industria, es decir utilizar lo más usado. Claramente hoy en día se utiliza un framework backend + un framewor front.Comunicados por Apis Rest.  

Por front podemos elegir : Angular, React o Vue , el mercado esta ahí. 

Por back tenes muchas opciones: java - spring boot, solución super probada y te va andar muy bien.

dot net - dot net core con MVC, un poco más nuevo pero anda muy bien y se usa mucho. 

Python: Django, viejito pero bueno,

Javascript con node y express. 

Y si te interesa arriesgarte y optar por algo nuevo tenes Go, con Echo o otros frameworks. 

Java 15 fue liberado!!

 


Y como era de esperar tenemos otra versión de java, que dado que viene tan seguido, se ha perdido la expectativa dado la periodicidad y la cantidad de cosas que tenemos para aprender. 

En esta versión no tenemos grandes cambios a nivel de lenguaje. La lista final completa de características es:

  • JEP 339: Edwards-Curve Digital Signature Algorithm (EdDSA)
  • JEP 360: Sealed Classes (Preview)
  • JEP 371: Hidden Classes
  • JEP 372: Remove the Nashorn JavaScript Engine
  • JEP 373: Reimplement the Legacy DatagramSocket API
  • JEP 374: Disable and Deprecate Biased Locking
  • JEP 375: Pattern Matching for instanceof (Second Preview)
  • JEP 377: ZGC: A Scalable Low-Latency Garbage Collector
  • JEP 378: Text Blocks
  • JEP 379: Shenandoah: A Low-Pause-Time Garbage Collector
  • JEP 381: Remove the Solaris and SPARC Ports
  • JEP 383: Foreign-Memory Access API (Second Incubator)
  • JEP 384: Records (Second Preview)
  • JEP 385: Deprecate RMI Activation for Removal

Cabe señalar que Java 15 no es una versión de soporte a largo plazo, por lo que queda por ver hasta qué punto los desarrolladores adoptarán esta nueva versión. Hasta la fecha, ninguna de las versiones que no son LTS ha tenido una adopción significativa.

Dejo link: https://jdk.java.net/15/

Y si la quieren descargar la versión libre : 

https://adoptopenjdk.net/

domingo, 27 de septiembre de 2020

Ecuaciones en Haskell


Para los que venimos de otros lenguajes, tenemos que saber que no hay ecuaciones en lenguajes imperativos. En Haskell las ecuaciones se utilizan para dar nombre a los valores.

respuesta = 42

Una ecuación en Haskell es una ecuación matemática: dice que el lado izquierdo y el lado derecho denotan el mismo valor.

El lado izquierdo debe ser un nombre al que le esté dando un valor. Por ejemplo : 

   x = 5 * y

No podemos escribir ecuaciones como lo hacemos en la matemática, por ejemplo esto esta mal : 

   2 * x = (3 * x) ** 2 - No se permite la reasignación en un FPL puro

Las ecuaciones no son asignaciones y una variable o nombre solo puede tener un valor. Puse variable o nombre dado que los nombres a menudo se denominan "variables", pero no varían. ¡Las variables son constantes!

    n = 1 

    x = 3 * n 

    n = x   -- Error: solo puede tener una definición de n

Una vez que le da un valor a un nombre, ¡nunca podrá cambiarlo! Esto es parte del significado de "puro" y "sin efectos secundarios"

¿Qué pasa con n = n + 1? En lenguajes imperativos, frecuentemente decimos n: = n + 1. Pero esto es una tarea, no una ecuación

En Haskell, es válido escribir n = n + 1. Pero Haskell lo intentará y fallará. Dado que tratará de resolver n con n de forma recursiva. 

Pero como se puede vivir sin asignaciones? Pensemos en una declaración de asignación como si hiciera tres cosas:

  • Evalúa el lado derecho: calcula un valor útil.
  • Descarta el valor de la variable del lado izquierdo: destruye un valor que podría ser útil o no.
  • Guarda el valor útil del RHS en la variable.

En un lenguaje puramente funcional, nunca destruimos los viejos valores. Simplemente calculamos nuevos útiles. Si el valor anterior era realmente inútil, el recolector de basura reclamará su almacenamiento.

viernes, 25 de septiembre de 2020

Lambdas en Python


Las lambdas son funciones que se definan al vuelo y no tienen nombre, se conocen como funciones anónimas en algunos otros lenguajes. Es posible que desee utilizar lambdas cuando no desee utilizar una función dos veces en un programa. Son como funciones normales e incluso se comportan como ellas. Por ejemplo: 

add = lambda x, y: x + y

print(add(3, 5))

# Output: 8


Podemos utilizar para indicar como ordenar nuestras listas :

a = [(1, 2), (4, 1), (9, 10), (13, -3)]

a.sort(key=lambda x: x[1])

print(a)

# Output: [(13, -3), (4, 1), (1, 2), (9, 10)]


Y podemos ordenar listas concurrentemente: 

data = zip(list1, list2)

data = sorted(data)

list1, list2 = map(lambda t: list(t), zip(*data))