Translate
jueves, 28 de noviembre de 2019
Defer, Panic, y Recover en Go
La visión de Go es particular, la verdad es que no se si es buena o mala pero claramente es particular. Para Go un error es algo que puede pasar y es parte del resultado. Para manejar esta visión tiene 3 palabras reservadas : Defer, Panic, y Recover.
Defer nos permiten pensar en cerrar cada archivo (por ejemplo) justo después de abrirlo, garantizando que, independientemente del número de declaraciones return en la función, los archivos se cerrarán. Es como el final de java, veamos un ejemplo :
func CopyFile(dstName, srcName string) (written int64, err error) {
src, err := os.Open(srcName)
if err != nil {
return
}
defer src.Close()
dst, err := os.Create(dstName)
if err != nil {
return
}
defer dst.Close()
return io.Copy(dst, src)
}
El comportamiento de las declaraciones diferidas es sencillo y predecible. Hay tres reglas simples:
1. Los argumentos de una función diferida se evalúan cuando se evalúa la declaración diferida.
En este ejemplo, la expresión "i" se evalúa cuando se llama a Println. La llamada diferida imprimirá "0" después de que regrese la función.
func a() {
i := 0
defer fmt.Println(i)
i++
return
}
2. Las llamadas a funciones diferidas se ejecutan en el orden último en entrar, primero en salir después de que vuelve la función circundante.
Esta función imprime "3210":
func b() {
for i := 0; i < 4; i++ {
defer fmt.Print(i)
}
}
3.Las funciones diferidas pueden leer y asignar a los valores de retorno nombrados de la función de retorno.
En este ejemplo, una función diferida incrementa el valor de retorno i después de que regresa la función circundante. Por lo tanto, esta función devuelve 2:
func c() (i int) {
defer func() { i++ }()
return 1
}
Esto es conveniente para modificar el valor de retorno de error de una función; Veremos un ejemplo de esto en breve.
Panic es una función incorporada que detiene el flujo de control ordinario y comienza a entrar en pánico. Cuando la función F llama Panic, la ejecución de F se detiene, las funciones diferidas en F se ejecutan normalmente y luego F vuelve a su llamador. Para la persona que llama, F entonces se comporta como una llamada al pánico. El proceso continúa en la pila hasta que todas las funciones en la rutina actual han regresado, momento en el cual el programa falla. El pánico puede iniciarse invocando el pánico directamente. También pueden ser causados por errores de tiempo de ejecución, como accesos de matriz fuera de los límites.
Recover es una función incorporada que recupera el control de una gorutina en pánico. La recuperación solo es útil dentro de las funciones diferidas. Durante la ejecución normal, una llamada a recuperar devolverá nulo y no tendrá otro efecto. Si la rutina actual está en pánico, una llamada a Recover capturará el valor dado al pánico y reanudará la ejecución normal.
Veamos un ejemplo todo mezclado:
package main
import "fmt"
func main() {
f()
fmt.Println("Returned normally from f.")
}
func f() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
}
}()
fmt.Println("Calling g.")
g(0)
fmt.Println("Returned normally from g.")
}
func g(i int) {
if i > 3 {
fmt.Println("Panicking!")
panic(fmt.Sprintf("%v", i))
}
defer fmt.Println("Defer in g", i)
fmt.Println("Printing in g", i)
g(i + 1)
}
La función g toma el int i, y entra en pánico si i es mayor que 3, o se llama a sí mismo con el argumento i + 1. La función f difiere una función que llama a recovery e imprime el valor recuperado (si no es nulo).
El programa generará:
Calling g.
Printing in g 0
Printing in g 1
Printing in g 2
Printing in g 3
Panicking!
Defer in g 3
Defer in g 2
Defer in g 1
Defer in g 0
Recovered in f 4
Returned normally from f.
Y eso es todo amigos!
miércoles, 27 de noviembre de 2019
DataStax publica un libro gratuito de Apache Cassandra
Me llego el siguiente mail de DataStax, sobre un libro de Cassandra:
|
domingo, 24 de noviembre de 2019
Empezando con Rust
Rust es un lenguaje que ha tomado relevancia este ultimo tiempo. En la ultima encuesta de stackoverflow gano la consideración de lenguaje más amado. Pero que tiene de especial? Vamos a dar juntos los primeros pasos.
Antes de empezar tenemos que instalar rust, como uso linux esto es tan fácil como ir a Synaptic y seleccionar los paquetes de rust o ir por consola y poner :
sudo apt update
sudo apt upgrade
sudo apt install rustc
sudo apt install cargo
Luego vamos a hablar de cargo.
Luego debemos hacer :
rustup install stable
rustup default stable
Crearemos un nuevo archivo fuente y llamado main.rs.
Los archivos de Rust siempre terminan con la extensión .rs. Si usa más de una palabra en su nombre de archivo, se debe usar un guión bajo para separarlos. Por ejemplo, hello_world.rs en lugar de helloworld.rs.
Ahora abramos el archivo main.rs que acaba de crear e ingresemos el siguiente código :
fn main () {
println! ("¡Hola, mundo!");
}
Guardemos el archivo y vamos a la terminal. En Linux, ingrese los siguientes comandos para compilar y ejecutar el archivo:
$ rustc main.rs
$ ./main
Hello, world!
Si te imprimió "Hello, world!" , esta mal porque escribimos ¡Hola, mundo! (jeje)
Vamos a seguir con Rust y pero por ahora les dejo link: https://www.rust-lang.org/
Antes de empezar tenemos que instalar rust, como uso linux esto es tan fácil como ir a Synaptic y seleccionar los paquetes de rust o ir por consola y poner :
sudo apt update
sudo apt upgrade
sudo apt install rustc
sudo apt install cargo
Luego vamos a hablar de cargo.
Luego debemos hacer :
rustup install stable
rustup default stable
Crearemos un nuevo archivo fuente y llamado main.rs.
Los archivos de Rust siempre terminan con la extensión .rs. Si usa más de una palabra en su nombre de archivo, se debe usar un guión bajo para separarlos. Por ejemplo, hello_world.rs en lugar de helloworld.rs.
Ahora abramos el archivo main.rs que acaba de crear e ingresemos el siguiente código :
fn main () {
println! ("¡Hola, mundo!");
}
Guardemos el archivo y vamos a la terminal. En Linux, ingrese los siguientes comandos para compilar y ejecutar el archivo:
$ rustc main.rs
$ ./main
Hello, world!
Si te imprimió "Hello, world!" , esta mal porque escribimos ¡Hola, mundo! (jeje)
Vamos a seguir con Rust y pero por ahora les dejo link: https://www.rust-lang.org/
Más de Prolog
El operador "is" permite evaluar expresiones: X is Y
Veamos un ejemplo:
longitud([],0).
longitud([_|Resto],N):-
longitud(Resto,N1), N is N1+1.
Luego tenemos los operadores lógicos
Luego tenemos los operadores lógicos
Con estos operadores podemos hacer lo siguiente:
Predicado de control. Corte (!) : El corte es un predicado predefinido que se denota mediante un punto de exclamación (!), no tiene argumentos, y cuya evaluación es siempre cierta.
Los cortes permiten al programador intervenir en el control del programa, puesto que su presencia hace que el sistema ignore ciertas ramas del árbol.
Su utilidad básica, dado que reduce el espacio de búsqueda de soluciones, es mejorar la eficiencia de los programas, evitando la exploración de partes del árbol de resolución de las que se sabe de antemano que no conducirán a ninguna nueva solución.
Veamos un ejemplo :
La representación anterior calcula correctamente los valores de la función, pero tiene el siguiente inconveniente.
Supóngase que se realiza la consulta:
?- f(0,Z), Z>1.
La respuesta de Prolog será “falso”, pero para llegar a dicha conclusión el sistema tiene que recorrer las 3 posibles ramas del árbol
Lo anterior es poco eficiente, puesto que, al ser las tres reglas que describen el predicado f mutuamente excluyentes, una vez que se ha encontrado una solución con una de ellas no tiene sentido probar con el resto. En efecto, la función que se esta calculando tiene la siguiente estructura condicional:
si X ≤ 10 entonces Y = 0;
si no: si X ≤ 20, entonces Y = 1;
si no: Y = 2
Esto se puede espresar de la siguiente manera con el operador ! :
Esto se puede espresar de la siguiente manera con el operador ! :
Con esta nueva versión, la respuesta de Prolog a la consulta
?- f(0,Z), Z>1.
será también “falso”, pero ahora, gracias a la introducción del corte en la primera regla, el sistema solo tendrá que explorar la primera rama del árbol.
Primeros pasos en Docker
Docker es un container management service, que en castellano sería un servicio administrador de contenedores. Es sin duda la tecnología más de moda en estos tiempos.
La idea es desarrollar en contenedores que pueden ser desplegados en cualquier equipo de esta manera la aplicación puede funcionar en cualquier pc y no tenemos el tipico problema de que una aplicación funcione en un computador y en otro no.
Docker esta formado por los siguientes componentes :
- Docker for Linux, Mac, Windows : este componente permite correr Docker sobre estas plataformas
- Docker Engine : Es usado para crear imágenes y contenedores
- Docker Hub : Se utiliza para registrar las imágenes y luego poder utilizarlas
- Docker Compose : Es utilizado para definir aplicaciones a partir de múltiples containers.
Para instalar docker podemos hacerlo del manual de la pagina oficial: https://docs.docker.com/install/
Una forma de ver si docker quedo bien instalado es hacer :
docker version
De esta forma si docker nos retorna la version, bueno… Anda!
Si necesitamos información de nuestro docker podemos hacer:
docker info
De esta manera vamos a tener información de nuestro contenedor.
Pero si de verdad queremos probar si funciona nuestro docker podemos probar una imagen por defecto, esto sería como un “Hola Mundo” de docker. Empecemos revisando la sintasis, para correr una imagen debemos hacer :
docker run image
Donde image es el nombre de la imagen que queremos correr.
Por ende si queremos correr la imagen “hello-world” :
docker run image hello-world
Este comando lo que va hacer es bajarte la imagen de “hello-world” y luego la va a ejecutar.
Creo que para empezar, bien!
Luego seguimos en posteriores post.
sábado, 23 de noviembre de 2019
Estado del Octoverso
GitHub ha publicado Estado del Octoverso que es un informe anual detallando, una serie de cifras y datos interesantes sobre los desarrolladores, repositorios, proyectos y lenguajes de programación que alberga la plataforma.
Con más de 40 millones de desarrolladores, incluyendo 10 millones de nuevos usuarios registrados en 2019, GitHub ya alcanza más de 44 millones de repositorios. En lo que va de año esos desarrolladores colaboraron usando más de 370 lenguajes de programación.
Lo que más me llamo la atención este año es que Python ha pasado a Java. Esto claramente se debe a que han aumentado los proyectos en maching learnig y sin duda en esta disciplina, python es el rey.
Entre los lenguajes que más crecieron esta dart y Rust :
Sin más dejo link : https://octoverse.github.com/
jueves, 14 de noviembre de 2019
Listas en prolog
Seguimos con Prolog
Una lista es una secuencia de elementos tales como:
[clara,tomas,jose,isabel]
La representación interna de las listas en PROLOG es con árboles binarios, donde la rama de la izquierda es el primer elemento –o cabeza– de la lista y la rama de la derecha es el resto –o cola– de la lista.
[]. Es una lista vacía. Y es el final de la lista (igual que funcional)
En el ejemplo anterior, la cabeza será clara y la cola
[tomas,jose,isabel].
El último elemento siempre es la lista vacía ([]).
Siendo miembro :
Una lista es una secuencia de elementos tales como:
[clara,tomas,jose,isabel]
La representación interna de las listas en PROLOG es con árboles binarios, donde la rama de la izquierda es el primer elemento –o cabeza– de la lista y la rama de la derecha es el resto –o cola– de la lista.
[]. Es una lista vacía. Y es el final de la lista (igual que funcional)
En el ejemplo anterior, la cabeza será clara y la cola
[tomas,jose,isabel].
El último elemento siempre es la lista vacía ([]).
La cabeza y la cola de una lista se pueden separar con el símbolo “|”.
[a,b,c]
[a|[b,c]]
[a,b|[c]]
[a,b,c|[]]
[a|X],[Y|[b,c]]
?- [a,b,c] == [a,b|[c]].
true.
El orden de los elementos en la lista importa y un elemento se puede repetir en una lista.
Supongamos que queremos determinar si un elemento es miembro de una lista. Los siguientes serían ejemplos del funcionamiento de la relación “miembro”.
miembro(b,[a,b,c]). %PROLOG respondería sí.
miembro(b,[a,[b,c]]). %PROLOG respondería no.
miembro([b,c],[a,[b,c]]). %PROLOG respondería sí.
Siendo miembro :
miembro(X,[X|_]).
miembro(X,[_|R]):-miembro(X,R).
sábado, 9 de noviembre de 2019
Sincronizar canales en Go
Podemos usar canales para sincronizar la ejecución entre goroutines. Veamos un ejemplo de un programa que espero a que termine una gorutine:
package main
import (
"fmt"
"time"
)
func worker(done chan bool) {
fmt.Print("working...")
time.Sleep(time.Second)
fmt.Println("done")
done <- true
}
func main() {
done := make(chan bool, 1)
go worker(done)
<-done
}
$ go run channel-synchronization.go
working...done
Cuando debemos esperar a que terminen varias gorutinas, podemos usar un WaitGroup.
Si eliminamos la línea <- done de este programa, el programa se cerraría incluso antes de que el worker comenzara.
Dejo link: https://gobyexample.com/channel-synchronization
Dejo link: https://gobyexample.com/channel-synchronization
viernes, 8 de noviembre de 2019
Libros de Java Code Geeks
martes, 5 de noviembre de 2019
Machine Learning (aprendizaje automático) con Python: una introducción práctica
Me llego un mail de edX sobre machine learning en python en castellano. Toma tu torta!
A anotarse y estudiar!!!
A anotarse y estudiar!!!
|
Suscribirse a:
Entradas (Atom)