Translate
jueves, 16 de enero de 2020
El lenguaje de programación V, Parte 3
Seguimos con V
Veamos un ejemplo del condicional :
a := 10
b := 20
if a < b {
println('$a < $b')
} else if a > b {
println('$a > $b')
} else {
println('$a == $b')
}
Si las declaraciones son bastante directas y similares a la mayoría de los otros lenguajes.
A diferencia de otros lenguajes tipo C, no hay paréntesis que rodeen la condición, y las llaves siempre son necesarias.
si, se puede usar como una expresión:
num := 777
s := if num % 2 == 0 {
'even'
}
else {
'odd'
}
println(s) // "odd"
in permite verificar si una matriz o un mapa contiene un elemento.
nums := [1, 2, 3]
println(1 in nums) // true
m := {'one': 1, 'two': 2}
println('one' in m) // true
También es útil para escribir expresiones booleanas más claras y compactas:
if parser.token == .plus || parser.token == .minus ||
parser.token == .div || parser.token == .mult {
...
}
if parser.token in [.plus, .minus, .div, .mult] {
...
}
V optimiza tales expresiones, por lo tanto, si las declaraciones anteriores producen el mismo código de máquina, no se crean matrices.
V tiene solo una construcción de bucle: for.
numbers := [1, 2, 3, 4, 5]
for num in numbers {
println(num)
}
names := ['Sam', 'Peter']
for i, name in names {
println('$i) $name') // Output: 0) Sam
}
El valor en el bucle se usa para recorrer elementos de una matriz. Si se requiere un índice, se puede usar una forma alternativa para el índice.
Tengamos en cuenta que el valor es de solo lectura. Si necesita modificar la matriz mientras realiza el bucle, debe usar la indexación:
mut numbers := [1, 2, 3, 4, 5]
for i, num in numbers {
println(num)
numbers[i] = 0
}
mut sum := 0
mut i := 0
for i <= 100 {
sum += i
i++
}
println(sum) // "5050"
Esta forma del bucle es similar a los bucles while en otros lenguajes.
El bucle dejará de iterar una vez que la condición booleana se evalúe como falsa.
No hay paréntesis que rodeen la condición, y siempre se requieren llaves.
mut num := 0
for {
num++
if num >= 10 {
break
}
}
println(num) // "10"
La condición puede omitirse, esto da como resultado un bucle infinito.
for i := 0; i < 10; i++ {
// Don't print 6
if i == 6 {
continue
}
println(i)
}
Finalmente, está el estilo tradicional C para loop. Es más seguro que la forma `while` porque con esta última es fácil olvidarse de actualizar el contador y quedarse atascado en un bucle infinito.
Aquí no necesito ser declarado con mut ya que siempre será mutable por definición.
Dejo link:
https://vlang.io/
miércoles, 15 de enero de 2020
Libros Gratis de Java Geeks
El lenguaje de programación V, Parte 2
Seguimos con V
fn main() {
age = 21
}
fn main() {
age = 21
}
Esto no compila porque age no esta declarada, pero podemos arreglarlo :
fn main() {
age := 21
}
En el modo de desarrollo, este código generará una advertencia de "variable no utilizada". En el modo de producción (v -prod foo.v) no se compilará en absoluto, como en Go:
fn main() {
a := 10
if true {
a := 20
}
}
A diferencia de la mayoría de los lenguajes, V no permite sobre escribir una variable por el ámbito de las variables, lo anterior no está permitido. Declarar una variable con un nombre que ya se utiliza en un ámbito primario dará como resultado un error de compilación.
Los tipos que tenemos son :
string
i8 i16 int i64 i128 (soon)
byte u16 u32 u64 u128 (soon)
rune // represents a Unicode code point
f32 f64
byteptr
voidptr
Veamos ejemplo de String :
name := 'Bob'
println('Hello, $name!') // `$` is used for string interpolation
println(name.len)
bobby := name + 'by' // + is used to concatenate strings
println(bobby) // "Bobby"
println(bobby[1..3]) // "ob"
mut s := 'hello '
s += 'world' // `+=` is used to append to a string
println(s) // "hello world"
En V, una cadena es una matriz de bytes de solo lectura. Los datos de cadena se codifican con UTF-8.
Los Strings son inmutables.
Las comillas simples y dobles se pueden usar para denotar cadenas. Por coherencia, vfmt convierte las comillas dobles en comillas simples a menos que la cadena contenga un carácter de comilla simple.
La sintaxis de interpolación es bastante simple. También funciona con campos: 'age = $ user.age'. Si necesita expresiones más complejas, use $ {}: 'puede registrarse = $ {user.age> 13}'.
Todos los operadores en V deben tener valores del mismo tipo en ambos lados. Este código no se compilará si age es un int:
println ('edad =' + edad)
Tenemos que convertir la edad en una cadena:
println ('edad =' + edad.str ())
o use la interpolación de cadenas (preferido):
println ('edad = $ edad')
Para denotar literales de caracteres, usemos `
a := `a`
assert 'aloha!'[0] == `a`
Para cadenas sin escapar, anteponer r:
Veamos unos ejemplos de arreglos :
mut nums := [1, 2, 3]
println(nums) // "[1, 2, 3]"
println(nums[1]) // "2"
nums << 4
println(nums) // "[1, 2, 3, 4]"
nums << [5, 6, 7]
println(nums) // "[1, 2, 3, 4, 5, 6, 7]"
mut names := ['John']
names << 'Peter'
names << 'Sam'
// names << 10 <-- No compila. `names` es un arreglo de tipo strings.
println(names.len) // "3"
println('Alex' in names) // "false"
names = [] // names ahora es vacío.
// También podemos preasignar una cierta cantidad de elementos.
ids := [0].repeat(50)
El tipo de matriz está determinado por el primer elemento: [1, 2, 3] es una matriz de entradas.
['a', 'b'] es una matriz de cadenas ([] cadena).
Todos los elementos deben tener el mismo tipo. [1, 'a'] si no, no se compilará.
<< es un operador que agrega un valor al final de la matriz. También puede agregar una matriz completa.
El campo .len devuelve la longitud de la matriz. Tenga en cuenta que es un campo de solo lectura y que el usuario no puede modificarlo. Todos los campos exportados son de solo lectura por defecto en V.
val en la matriz devuelve verdadero si la matriz contiene val.
Todos los arreglos pueden imprimirse fácilmente con println (arr) y convertirse en una cadena con s: = arr.str ().
Las matrices se pueden filtrar y asignar de manera eficiente con los métodos .filter () y .map ():
nums := [1, 2, 3, 4, 5, 6]
even := nums.filter(it % 2 == 0)
println(even) // [2, 4, 6]
words := ['hello', 'world']
upper := words.map(it.to_upper())
println(upper) // ['HELLO', 'WORLD']
Es una variable especial que se refiere a un elemento en los métodos de filter o map.
Unos ejemplo de mapa :
mut m := map[string]int //definimos el mapa.
m['one'] = 1
m['two'] = 2
println(m['one']) // "1"
println(m['bad_key']) // "0"
println('bad_key' in m) // Use `in` para detectar si dicha clave existe
m.delete('two')
numbers := {
'one': 1,
'two': 2,
}
Puff me quedo largo el post, en un rato sigo...
Dejo link:
martes, 14 de enero de 2020
El lenguaje de programación V
V provee código simple, legible y mantenible.
A pesar de ser simple, V le da mucho poder al desarrollador. Cualquier cosa que puedas hacer en otros lenguajes, puedes hacerlo en V.
V tiene o no tiene :
- No nulo
- No hay variables globales.
- Sin valores indefinidos
- Sin comportamiento indefinido
- Comprobación de límites
- Opciones / tipos de resultados
- Genéricos
- Variables inmutables por defecto
- Funciones puras por defecto
- Estructuras inmutables por defecto
- Tan rápido como C
- interoperabilidad con C sin ningún costo
- Cantidad mínima de asignaciones
- Compila a binarios nativos sin dependencias: un servidor web simple es solo 65 KB
V es un lenguaje de programación compilado, estáticmente tipado, diseñado para construir software mantenible.
Es similar a Go y también está influenciado por Oberon, Rust, Swift.
Veamos el "hola mundo" en V:
fn main() {
println('hello world')
}
Las funciones se declaran con fn. El tipo de retorno va después del nombre de la función. En este caso, main no devuelve nada, por lo que se omite el tipo.
Al igual que en C y todos los lenguajes relacionados, main es un punto de entrada.
println es una de las pocas funciones integradas. Imprime el valor a la salida estándar.
La declaración fn main () se puede omitir en programas de un archivo. Esto es útil cuando se escriben pequeños programas, "scripts" o simplemente se aprende el lenguaje.
Esto significa que un programa "hello world" puede ser tan simple como :
println('hello world')
// Esto es un comentario
/* Y ahora que lo saben, veamos ejemplos
/* y esto tambien se puede hacer ... */
*/
fn main() {
println(add(77, 33))
println(sub(100, 50))
}
fn add(x int, y int) int {
return x + y
}
fn sub(x, y int) int {
return x - y
}
//La Funciones pueden retornar múltiples valores.
fn foo() (int, int) {
return 2, 3
}
a, b := foo()
println(a) // 2
println(b) // 3
/* Las funciones, como consts y tipos, son privadas de forma predeterminada. Para permitir que otros módulos los usen, anteponga pub. */
pub fn public_function() {
}
fn private_function() {
}
Las variables se declaran e inicializan con: =. Esta es la única forma de declarar variables en V. Esto significa que las variables siempre tienen un valor inicial.
El tipo de la variable se infiere del valor en el lado derecho. Para forzar un tipo diferente, use la conversión de tipo.
A diferencia de la mayoría de los otros lenguajes, V solo permite definir variables en las funciones. No se permiten variables globales (nivel de módulo). No hay estado global en V.
Veamos ejemplos :
mut age := 20
println(age)
age = 21
println(age)
Para cambiar el valor de la variable podemos usar =. En V, las variables son inmutables por defecto. Para poder cambiar el valor de la variable, debe declararla con mut.
Tenga en cuenta la diferencia entre: = y =
: = se usa para declarar e inicializar, = se usa para asignar.
Puff me quedo largo el post, en un rato sigo...
Dejo link:
https://vlang.io/
sábado, 11 de enero de 2020
Empezando con Rust, parte 5
Vamos a hacer un pequeño juego en el cual el usuario elige un número y si es igual a un número que se calcula aleatoriamente, gana de otro modo pierde.
use std::io;
use rand::Rng;
fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1, 101);
println!("The secret number is: {}", secret_number);
println!("Please input your guess.");
let mut guess = String::new();
io::stdin().read_line(&mut guess)
.expect("Failed to read line");
println!("You guessed: {}", guess);
}
Primero, importamos rand :: Rng que define los métodos que implementan los generadores de números aleatorios.
La función rand :: thread_rng nos dará el generador de números aleatorios en particular que vamos a utilizar: uno que sea local al hilo de ejecución actual y que el sistema operativo sembró. Luego llamamos al método gen_range en el generador de números aleatorios. El método gen_range toma dos números como argumentos y genera un número aleatorio entre ellos. Es inclusivo en el límite inferior pero exclusivo en el límite superior, por lo que debemos especificar 1 y 101 para solicitar un número entre 1 y 100.
La segunda línea que agregamos a la mitad del código imprime el número secreto. Esto es útil mientras desarrollamos el programa para poder probarlo, pero lo eliminaremos de la versión final.
Al Intenta ejecutar el programa varias veces:
$ cargo run
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 2.53 secs
Running `target/debug/guessing_game`
Guess the number!
The secret number is: 7
Please input your guess.
4
You guessed: 4
$ cargo run
Running `target/debug/guessing_game`
Guess the number!
The secret number is: 83
Please input your guess.
5
You guessed: 5
Ahora que tenemos la entrada del usuario y un número aleatorio, podemos compararlos:
use std::io;
use std::cmp::Ordering;
use rand::Rng;
fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1, 101);
let mut guess = String :: new ();
io :: stdin (). read_line (& mut guess) .expect ("Error al leer la línea");
let guess: u32 = guesss.trim (). parse ().expect ("¡Escriba un número!");
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => println!("You win!"),
}
}
Con : let guess: u32 = guesss.trim(). parse().expect ("¡Escriba un número!"); creamos una variable llamada guess. Pero espera, ¿el programa ya no tiene una variable llamada guess? Lo hace, pero Rust nos permite sobreescribir el valor anterior. Esta característica se usa a menudo en situaciones en las que desea convertir un valor de un tipo a otro. Esto nos permite reutilizar el nombre de la variable de guess en lugar de obligarnos a crear dos variables únicas, como por ejemplo, guess_str y guess.
Ojo, tenemos que hacer esto porque no podemos comparar números con String por lo que llevamos todo a números.
La expresión guesss.trim(). parse(). El método trim eliminará cualquier espacio en blanco al principio y al final.
Aquí podemos ver un tipo llamado std :: cmp :: Ordering que es de la biblioteca estándar. Ordering es otra enumeración, pero las variantes para Ordenar son Menor, Mayor e Igual. Estos son los tres resultados que son posibles cuando compara dos valores.
Veamos un ejemplo de lo que sucedería con la expresión de coincidencia utilizada aquí. Digamos que el usuario pone 50 y el número secreto generado aleatoriamente esta vez es 38. Cuando el código compara 50 a 38, el método cmp devolverá Ordering :: Greater, porque 50 es mayor que 38. La expresión de coincidencia obtiene el Ordering: : Mayor valor y comienza a verificar el patrón.
¡Ejecutemos el programa ahora!
$ cargo run
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 0.43 secs
Running `target/debug/guessing_game`
Guess the number!
Please input your guess.
76
You guessed: 76
Too big!
Y con este pequeño juego me despido hasta la próxima!
use std::io;
use rand::Rng;
fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1, 101);
println!("The secret number is: {}", secret_number);
println!("Please input your guess.");
let mut guess = String::new();
io::stdin().read_line(&mut guess)
.expect("Failed to read line");
println!("You guessed: {}", guess);
}
Primero, importamos rand :: Rng que define los métodos que implementan los generadores de números aleatorios.
La función rand :: thread_rng nos dará el generador de números aleatorios en particular que vamos a utilizar: uno que sea local al hilo de ejecución actual y que el sistema operativo sembró. Luego llamamos al método gen_range en el generador de números aleatorios. El método gen_range toma dos números como argumentos y genera un número aleatorio entre ellos. Es inclusivo en el límite inferior pero exclusivo en el límite superior, por lo que debemos especificar 1 y 101 para solicitar un número entre 1 y 100.
La segunda línea que agregamos a la mitad del código imprime el número secreto. Esto es útil mientras desarrollamos el programa para poder probarlo, pero lo eliminaremos de la versión final.
Al Intenta ejecutar el programa varias veces:
$ cargo run
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 2.53 secs
Running `target/debug/guessing_game`
Guess the number!
The secret number is: 7
Please input your guess.
4
You guessed: 4
$ cargo run
Running `target/debug/guessing_game`
Guess the number!
The secret number is: 83
Please input your guess.
5
You guessed: 5
use std::io;
use std::cmp::Ordering;
use rand::Rng;
fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1, 101);
let mut guess = String :: new ();
io :: stdin (). read_line (& mut guess) .expect ("Error al leer la línea");
let guess: u32 = guesss.trim (). parse ().expect ("¡Escriba un número!");
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => println!("You win!"),
}
}
Con : let guess: u32 = guesss.trim(). parse().expect ("¡Escriba un número!"); creamos una variable llamada guess. Pero espera, ¿el programa ya no tiene una variable llamada guess? Lo hace, pero Rust nos permite sobreescribir el valor anterior. Esta característica se usa a menudo en situaciones en las que desea convertir un valor de un tipo a otro. Esto nos permite reutilizar el nombre de la variable de guess en lugar de obligarnos a crear dos variables únicas, como por ejemplo, guess_str y guess.
Ojo, tenemos que hacer esto porque no podemos comparar números con String por lo que llevamos todo a números.
La expresión guesss.trim(). parse(). El método trim eliminará cualquier espacio en blanco al principio y al final.
Aquí podemos ver un tipo llamado std :: cmp :: Ordering que es de la biblioteca estándar. Ordering es otra enumeración, pero las variantes para Ordenar son Menor, Mayor e Igual. Estos son los tres resultados que son posibles cuando compara dos valores.
Veamos un ejemplo de lo que sucedería con la expresión de coincidencia utilizada aquí. Digamos que el usuario pone 50 y el número secreto generado aleatoriamente esta vez es 38. Cuando el código compara 50 a 38, el método cmp devolverá Ordering :: Greater, porque 50 es mayor que 38. La expresión de coincidencia obtiene el Ordering: : Mayor valor y comienza a verificar el patrón.
¡Ejecutemos el programa ahora!
$ cargo run
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 0.43 secs
Running `target/debug/guessing_game`
Guess the number!
Please input your guess.
76
You guessed: 76
Too big!
miércoles, 8 de enero de 2020
Quintos pasos en GIT
Seguimos con GIT.
Supongamos que estás trabajando en alguna prestación, y que por alguna razón, necesitas volver a una versión vieja y poner temporalmente algunos ”print” para ver como funciona algo. Entonces:
$ git commit -a
$ git checkout HASH_SHA1
Ahora puedes agregar cualquier código temporal horrible por todos lados. Incluso puedes hacer commit de estos cambios. Cuando termines,
$ git checkout master
para volver a tu trabajo original. Observa que arrastrarás cualquier cambio del que no hayas hecho commit.
¿Que pasa si quisieras cambiar los cambios temporales? Fácil:
$ git checkout -b sucio
y haz commit antes de volver a la branch master. Cuando quieras volver a los cambios sucios, simplemente escribe:
$ git checkout sucio
Al fin podemos contar toda la historia:los archivos cambian al estado pedido, pero debemos dejar al branch master. Cualquier commit de aquí en adelante, llevan tus archivos por un nuevo camino, el podrá ser nombrado posteriormente.
En otras palabras, luego de traer un estado viejo, Git automáticamente te pone en una nueva branch sin nombre, la cual puede ser nombrada y salvada con git checkout -b.
Algunos proyectos requieren que tu código sea evaluado antes de que puedas subirlo. Para hacer la vida más fácil para aquellos que revisan tu código, si tienes algún cambio grande para hacer, puedes partirlo en dos o mas partes, y hacer que cada parte sea evaluada por separado.
¿Que pasa si la segunda parte no puede ser escrita hasta que la primera sea aprobada y subida? En muchos sistemas de control de versiones, deberías enviar primero el código a los evaluadores, y luego esperar hasta que esté aprobado antes de empezar con la segunda parte.
En realidad, eso no es del todo cierto, pero en estos sistemas, editar la Parte II antes de subir la Parte I involucra sufrimiento e infortunio. En Git, los branches y merges son indoloros (un termino técnico que significa rápidos y locales). Entonces, luego de que hayas hecho commit de la primera parte y la
hayas enviado a ser revisada:
$ git checkout -b parte2
Luego, escribe la segunda parte del gran cambio sin esperar a que la primera sea aceptada. Cuando la primera parte sea aprobada y subida,
$ git checkout master
$ git merge parte2
$ git branch -d parte2 # ya no se necesita esta branch
y la segunda parte del cambio está lista para la evaluación. ¡Pero esperen! ¿Qué pasa si no fuera tan simple? Digamos que tuviste un error en la primera parte, el cual hay que corregir antes de subir los cambios. ¡No hay problema! Primero, vuelve a la branch master usando
$ git checkout master
Soluciona el error en la primera parte del cambio y espera que sea aprobado. Si no lo es, simplemente repite este paso. Probablemente quieras hacer un merge de la versión arreglada de la Parte I con la Parte II:
$ git checkout parte2
$ git merge master
Ahora es igual que lo anterior. Una vez que la primera parte sea aprobada:
$ git checkout master
$ git merge parte2
$ git branch -d parte2
y nuevamente, la segunda parte está lista para ser revisada. Es fácil extender este truco para cualquier cantidad de partes.
Quizás quieras trabajar en todos los aspectos de un proyecto sobre la misma branch. Quieres dejar los trabajos-en-progreso para ti y quieres que otros vean tus commits solo cuando han sido pulcramente organizados. Inicia un par de branches:
$ git checkout -b prolijo
$ git checkout -b mezcla
A continuación, trabaja en lo que sea: soluciona bugs, agrega prestaciones, agrega código temporal o lo que quieras, haciendo commits seguidos a medida que avanzas. Entonces:
$ git checkout prolijo
$ git cherry-pick HASH_SHA1
aplica un commit dado a la branch ”prolijo”. Con cherry-picks apropiados, puedes construir una rama que contenga solo el código permanente, y los commits relacionados juntos en un grupo.
domingo, 5 de enero de 2020
Probando Fedora KDE
Bueno, reinstale mi notebook y opte por Fedora KDE. Por que? que se yo, estaba un tanto aburrido de las distros basadas en Debian, que son mis preferidas. Me daba curiosidad y KDE se ve cada vez mejor.
Que paso? Como puntos débiles tengo:
- No pude hacer andar Samba
- El market place no es tan completo como otras distros, use mucho la consola para instalar cosas que en otras distros lo puedo hacer en unos cuantos clicks.
- Antes del login, por alguna razón demora minutos en levantar (si alguien me ayuda con esto sería genial)
- En el centro de aplicaciones no vi ni skype, ni spotify, etc...
Puntos fuertes:
- KDE la rompe, me gusto mucho, fácil de usar y rápido.
- Tiene un montón de herramientas para red y se siente orgánico.
- Es rápido y fachero
- Me gusta!
Mi opinión personal es que Fedora crecería mucho más si le daría más bola a la usabilidad, es decir un tanto más amigable como Ubuntu. Y ustedes dirán, si dijiste que era fácil de usar, eso no es ser amigable? y yo les contestaría, si pero no solo eso... Le falta algo como para sentirte en tu casa, por ejemplo el centro de aplicaciones, no vi los comentarios de los usuarios muy fácilmente, para mandar el feedback de un error me pidio una cuenta a no se que y así...
Sin más dejo algunos screenshot y el link al final:
Dejo link: https://spins.fedoraproject.org/es/kde/
GraalVM 19.3 soporta a JDK 11
GraalVM, una máquina virtual políglota que proporciona un tiempo de ejecución compartido para ejecutar aplicaciones escritas en múltiples lenguajes como Java, C, Python y JavaScript, ha lanzado la versión 19.3 con soporte para JDK 11. Las versiones anteriores de GraalVM se basaban en JDK 8.
Las numerosas funciones de lenguaje y mejoras de plataforma como cadenas compactas, inferencia de tipo variable, Java Platform Module System (JPMS) y cliente HTTP, que se entregaron entre la versión Java 9 y la versión Java 11 ahora pueden ser utilizadas por aplicaciones JVM creadas en GraalVM.
Por ejemplo, el siguiente fragmento muestra cómo se puede construir e invocar una solicitud simple a una API REST de bitcoin utilizando el nuevo cliente HTTP Java 11:
public class BPI {
public static void main(String... args) {
var request = HttpRequest
.newBuilder()
.uri(URI.create("https://api.coindesk.com/v1/bpi/currentprice.json"))
.GET()
.build();
var response = HttpClient
.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofInputStream());
var json = Json
.createReader(response.body())
.readObject()
.getJsonObject("bpi");
…
System.out.printf("Current Bitcoin Price: $%s %s", price, indicator);
}
}
Con JAVA_HOME y PATH apuntando a una instalación de GraalVM, las clases basadas en Java 11 como la clase de ejemplo anterior se pueden compilar utilizando el compilador javac o una herramienta de compilación como Maven.
La utilidad de generación de imágenes nativas de GraalVM también se ha actualizado para admitir Java 11 como una característica de tecnología. Una imagen nativa es un código de bytes Java compilado con anticipación empaquetado como un ejecutable independiente. La imagen nativa generalmente logra un tiempo de inicio más rápido. La imagen nativa no es compatible con Java Platform Module System y no tiene introspección de módulo en tiempo de ejecución de imagen. La utilidad de imagen nativa es un paquete opcional que se puede instalar usando el Actualizador GraalVM, gu. gu es un administrador de paquetes que descarga e instala paquetes no incluidos en la distribución principal de GraalVM.
Para aquellos que usan Maven como herramienta de compilación, se proporciona un complemento Maven para ayudar en el proceso de generación de imágenes.
También tenga en cuenta que dado que el recolector de basura Garbage-First (G1) es el recolector de basura predeterminado en Java 11, se debe tener cuidado al migrar aplicaciones sensibles al rendimiento de GraalVM basado en JDK 8 a GraalVM basado en JDK 11.
Además del soporte para JDK 11, esta primera versión de soporte a largo plazo (LTS) de GraalVM proporciona mejoras en la generación de imágenes nativas, el compilador GraalVM, herramientas como cobertura de código y GraalVM VisualVM junto con actualizaciones en tiempo de ejecución de los lenguajes NodeJS, Python y R.
Dejo link: https://www.graalvm.org/
Las numerosas funciones de lenguaje y mejoras de plataforma como cadenas compactas, inferencia de tipo variable, Java Platform Module System (JPMS) y cliente HTTP, que se entregaron entre la versión Java 9 y la versión Java 11 ahora pueden ser utilizadas por aplicaciones JVM creadas en GraalVM.
Por ejemplo, el siguiente fragmento muestra cómo se puede construir e invocar una solicitud simple a una API REST de bitcoin utilizando el nuevo cliente HTTP Java 11:
public class BPI {
public static void main(String... args) {
var request = HttpRequest
.newBuilder()
.uri(URI.create("https://api.coindesk.com/v1/bpi/currentprice.json"))
.GET()
.build();
var response = HttpClient
.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofInputStream());
var json = Json
.createReader(response.body())
.readObject()
.getJsonObject("bpi");
…
System.out.printf("Current Bitcoin Price: $%s %s", price, indicator);
}
}
Con JAVA_HOME y PATH apuntando a una instalación de GraalVM, las clases basadas en Java 11 como la clase de ejemplo anterior se pueden compilar utilizando el compilador javac o una herramienta de compilación como Maven.
La utilidad de generación de imágenes nativas de GraalVM también se ha actualizado para admitir Java 11 como una característica de tecnología. Una imagen nativa es un código de bytes Java compilado con anticipación empaquetado como un ejecutable independiente. La imagen nativa generalmente logra un tiempo de inicio más rápido. La imagen nativa no es compatible con Java Platform Module System y no tiene introspección de módulo en tiempo de ejecución de imagen. La utilidad de imagen nativa es un paquete opcional que se puede instalar usando el Actualizador GraalVM, gu. gu es un administrador de paquetes que descarga e instala paquetes no incluidos en la distribución principal de GraalVM.
Para aquellos que usan Maven como herramienta de compilación, se proporciona un complemento Maven para ayudar en el proceso de generación de imágenes.
También tenga en cuenta que dado que el recolector de basura Garbage-First (G1) es el recolector de basura predeterminado en Java 11, se debe tener cuidado al migrar aplicaciones sensibles al rendimiento de GraalVM basado en JDK 8 a GraalVM basado en JDK 11.
Además del soporte para JDK 11, esta primera versión de soporte a largo plazo (LTS) de GraalVM proporciona mejoras en la generación de imágenes nativas, el compilador GraalVM, herramientas como cobertura de código y GraalVM VisualVM junto con actualizaciones en tiempo de ejecución de los lenguajes NodeJS, Python y R.
Dejo link: https://www.graalvm.org/
jueves, 2 de enero de 2020
Libros Gratuitos de Java Code Geek
|
|
lunes, 30 de diciembre de 2019
Feliz año nuevo!!!
El 2019 se fue un gran año, para la tecnología y para el blog...
Sin más espero que tengan un excelente año!!!
jueves, 26 de diciembre de 2019
Empezando con Rust, parte 4
Seguimos con Rust...
Ahora vamos a modificar la función main de este modo:
use std::io;
fn main() {
println!("Guess the number!");
println!("Please input your guess.");
let mut guess = String::new();
io::stdin().read_line(&mut guess)
.expect("Failed to read line");
println!("You guessed: {}", guess);
}
Este código contiene mucha información, así que repasemos línea por línea. Para obtener la entrada del usuario y luego imprimir el resultado como salida, necesitamos la biblioteca io (entrada / salida) . La biblioteca io proviene de la biblioteca estándar (que se conoce como std):
use std::io;
La función principal es el punto de entrada al programa:
fn main() {
La sintaxis fn declara una nueva función, los paréntesis, (), indican que no hay parámetros, y el corchete, {, inicia el cuerpo de la función.
println! es una macro que imprime una cadena en la pantalla:
println!("Guess the number!");
println!("Please input your guess.");
Ahora vamos a modificar la función main de este modo:
use std::io;
fn main() {
println!("Guess the number!");
println!("Please input your guess.");
let mut guess = String::new();
io::stdin().read_line(&mut guess)
.expect("Failed to read line");
println!("You guessed: {}", guess);
}
Este código contiene mucha información, así que repasemos línea por línea. Para obtener la entrada del usuario y luego imprimir el resultado como salida, necesitamos la biblioteca io (entrada / salida) . La biblioteca io proviene de la biblioteca estándar (que se conoce como std):
use std::io;
La función principal es el punto de entrada al programa:
fn main() {
La sintaxis fn declara una nueva función, los paréntesis, (), indican que no hay parámetros, y el corchete, {, inicia el cuerpo de la función.
println! es una macro que imprime una cadena en la pantalla:
println!("Guess the number!");
println!("Please input your guess.");
A continuación, crearemos un lugar para almacenar la entrada del usuario, así:
let mut guess = String::new();
Tenga en cuenta que esta es una declaración let, que se utiliza para crear una variable. Aquí hay otro ejemplo:
let foo = bar;
Esta línea crea una nueva variable llamada foo y la vincula al valor de la variable de bar. En Rust, las variables son inmutables por defecto. El siguiente ejemplo muestra cómo usar mut antes del nombre de la variable para hacer que una variable sea mutable:
let foo = 5; // immutable
let mut bar = 5; // mutable
Volvamos al programa de juego de adivinanzas. Ahora sabe que let mut guess introducirá una variable mutable llamada guess. En el otro lado del signo igual (=) está el valor al que está vinculado la conjetura, que es el resultado de llamar a String :: new, una función que devuelve una nueva instancia de una cadena. String es un tipo de cadena proporcionado por la biblioteca estándar que es un bit de texto codificado en UTF-8 que puede crecer.
La sintaxis :: indica que new es una función asociada del tipo String. Una función asociada se implementa en un tipo, en este caso String, en lugar de en una instancia particular de un String. Lo podríamos pensar como un método estático.
Esta nueva función crea una nueva cadena vacía.
Para resumir, let mut guess = String :: new (); ha creado una variable mutable que actualmente está vinculada a una nueva instancia vacía de una Cadena.
Recuerde que incluimos la funcionalidad de entrada / salida de la biblioteca estándar con use std :: io; en la primera línea del programa. Ahora llamaremos a la función stdin desde el módulo io:
io::stdin().read_line(&mut guess)
.expect("Failed to read line");
La función stdin devuelve una instancia de std :: io :: Stdin, que es un tipo que representa un identificador de la entrada estándar para su terminal.
La siguiente parte del código, .read_line (& mut guess), llama al método read_line en el identificador de entrada estándar para obtener información del usuario. También estamos pasando un argumento a read_line: & mut guess.
El trabajo de read_line es tomar lo que el usuario escriba en la entrada estándar y colocarlo en una cadena, por lo que toma esa cadena como argumento. El argumento de cadena debe ser mutable para que el método pueda cambiar el contenido de la cadena agregando la entrada del usuario.
El & indica que este argumento es una referencia, lo que le brinda una manera de permitir que múltiples partes de su código accedan a un dato sin necesidad de copiar esos datos en la memoria varias veces. Las referencias son una característica compleja, y una de las principales ventajas de Rust es lo seguro y fácil que es usar referencias. No necesita conocer muchos de esos detalles para finalizar este programa. Por ahora, todo lo que necesita saber es que, como las variables, las referencias son inmutables por defecto. Por lo tanto, necesita escribir & mut guess en lugar de & guess para hacerlo mutable.
No hemos terminado con esta línea de código. Aunque lo que hemos discutido hasta ahora es una sola línea de texto, es solo la primera parte de la única línea lógica de código. La segunda parte es este método:
.expect("Failed to read line");
Cuando llama a un método con la sintaxis .foo(), a menudo es aconsejable introducir una nueva línea y otros espacios en blanco para ayudar a dividir las líneas largas. Podríamos haber escrito este código como:
io::stdin().read_line(&mut guess).expect("Failed to read line");
Sin embargo, una línea larga es difícil de leer, por lo que es mejor dividirla: dos líneas para dos llamadas a métodos.
read_line coloca lo que el usuario escribe en la cadena que lo estamos pasando, pero también devuelve un valor, en este caso, un io :: Result. Rust tiene varios tipos llamados Result en su biblioteca estándar: un Result genérico y versiones específicas para submódulos, como io :: Result.
Los tipos de resultados son enumeraciones, a menudo denominadas enums. Una enumeración es un tipo que puede tener un conjunto fijo de valores, y esos valores se denominan variantes de la enumeración.
Para Result, las variantes son Ok o Err. La variante Ok indica que la operación fue exitosa, y dentro de Ok está el valor generado con éxito. La variante Err significa que la operación falló, y Err contiene información sobre cómo o por qué falló la operación.
El propósito de estos tipos de resultados es codificar la información de manejo de errores. Los valores del tipo Resultado, como los valores de cualquier tipo, tienen métodos definidos en ellos. Una instancia de io :: Result tiene un método de espera al que puede llamar. Si esta instancia de io :: Result es un valor de Err, esperar hará que el programa se bloquee y muestre el mensaje que pasó como un argumento para esperar. Si el método read_line devuelve un Err, probablemente sea el resultado de un error proveniente del sistema operativo subyacente. Si esta instancia de io :: Result es un valor Ok, esperar tomará el valor de retorno que Ok tiene y le devolverá ese valor para que pueda usarlo. En este caso, ese valor es el número de bytes en lo que el usuario ingresó en la entrada estándar.
Si no llama a wait, el programa se compilará, pero recibirá una advertencia:
$ cargo build
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
warning: unused `std::result::Result` which must be used
--> src/main.rs:10:5
|
10 | io::stdin().read_line(&mut guess);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unused_must_use)] on by default
Rust le advierte que no ha utilizado el valor Resultado devuelto por read_line, lo que indica que el programa no ha manejado un posible error.
La forma correcta de suprimir la advertencia es escribir realmente el manejo de errores, pero debido a que solo desea bloquear este programa cuando se produce un problema, puede usar expect.
Además de los corchetes de cierre, solo hay una línea más para discutir en el código agregado hasta ahora, que es el siguiente:
println!("You guessed: {}", guess);
Esta línea imprime la cadena en la que guardamos la entrada del usuario. El conjunto de llaves, {}, es un marcador de posición: piense en {} como pequeñas pinzas de cangrejo que mantienen un valor en su lugar. Puede imprimir más de un valor usando llaves: el primer conjunto de llaves contiene el primer valor que aparece después de la cadena de formato, el segundo conjunto contiene el segundo valor, y así sucesivamente. Impresión de múltiples valores en una llamada a println! se vería así:
let x = 5;
let y = 10;
println!("x = {} and y = {}", x, y);
Este código imprimiría x = 5 e y = 10.
Y listo!! puf escribi mucho...
No hemos terminado con esta línea de código. Aunque lo que hemos discutido hasta ahora es una sola línea de texto, es solo la primera parte de la única línea lógica de código. La segunda parte es este método:
.expect("Failed to read line");
Cuando llama a un método con la sintaxis .foo(), a menudo es aconsejable introducir una nueva línea y otros espacios en blanco para ayudar a dividir las líneas largas. Podríamos haber escrito este código como:
io::stdin().read_line(&mut guess).expect("Failed to read line");
Sin embargo, una línea larga es difícil de leer, por lo que es mejor dividirla: dos líneas para dos llamadas a métodos.
read_line coloca lo que el usuario escribe en la cadena que lo estamos pasando, pero también devuelve un valor, en este caso, un io :: Result. Rust tiene varios tipos llamados Result en su biblioteca estándar: un Result genérico y versiones específicas para submódulos, como io :: Result.
Los tipos de resultados son enumeraciones, a menudo denominadas enums. Una enumeración es un tipo que puede tener un conjunto fijo de valores, y esos valores se denominan variantes de la enumeración.
Para Result, las variantes son Ok o Err. La variante Ok indica que la operación fue exitosa, y dentro de Ok está el valor generado con éxito. La variante Err significa que la operación falló, y Err contiene información sobre cómo o por qué falló la operación.
El propósito de estos tipos de resultados es codificar la información de manejo de errores. Los valores del tipo Resultado, como los valores de cualquier tipo, tienen métodos definidos en ellos. Una instancia de io :: Result tiene un método de espera al que puede llamar. Si esta instancia de io :: Result es un valor de Err, esperar hará que el programa se bloquee y muestre el mensaje que pasó como un argumento para esperar. Si el método read_line devuelve un Err, probablemente sea el resultado de un error proveniente del sistema operativo subyacente. Si esta instancia de io :: Result es un valor Ok, esperar tomará el valor de retorno que Ok tiene y le devolverá ese valor para que pueda usarlo. En este caso, ese valor es el número de bytes en lo que el usuario ingresó en la entrada estándar.
Si no llama a wait, el programa se compilará, pero recibirá una advertencia:
$ cargo build
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
warning: unused `std::result::Result` which must be used
--> src/main.rs:10:5
|
10 | io::stdin().read_line(&mut guess);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unused_must_use)] on by default
Rust le advierte que no ha utilizado el valor Resultado devuelto por read_line, lo que indica que el programa no ha manejado un posible error.
La forma correcta de suprimir la advertencia es escribir realmente el manejo de errores, pero debido a que solo desea bloquear este programa cuando se produce un problema, puede usar expect.
Además de los corchetes de cierre, solo hay una línea más para discutir en el código agregado hasta ahora, que es el siguiente:
println!("You guessed: {}", guess);
Esta línea imprime la cadena en la que guardamos la entrada del usuario. El conjunto de llaves, {}, es un marcador de posición: piense en {} como pequeñas pinzas de cangrejo que mantienen un valor en su lugar. Puede imprimir más de un valor usando llaves: el primer conjunto de llaves contiene el primer valor que aparece después de la cadena de formato, el segundo conjunto contiene el segundo valor, y así sucesivamente. Impresión de múltiples valores en una llamada a println! se vería así:
let x = 5;
let y = 10;
println!("x = {} and y = {}", x, y);
Este código imprimiría x = 5 e y = 10.
Y listo!! puf escribi mucho...
Java Code Geeks
Quiero compartir estos libros gratuitos de Java Code Geeks :
|
|
martes, 24 de diciembre de 2019
Cuartos pasos en GIT
En Git, y otros sistemas de control de versiones distribuidos, clonar es la operación standard. Para obtener archivos se crea un clon de un repositorio entero. En otras palabras, prácticamente se crea una copia idéntica del servidor central. Todo lo que se pueda hacer en el repositorio principal, también podrás hacerlo.
Nosotros podemos inicializar un repositorio en un servidor central y luego clonarlo en nuestro equipo:
$ git clone otra.computadora:/ruta/a/archivos
y luego de clonarlo podemos hacer commit o pull :
$ git commit -a
$ git pull otra.computadora:/ruta/a/archivos HEAD
va a traer (pull) el estado de los archivos desde la otra máquina hacia la que estás trabajando. Si hiciste cambios que generen conflictos en un archivo, Git te va a avisar y deberías hacer commit luego de resolverlos.
Muchas veces deseamos hacer un fork de un proyecto, porque queremos probar una tecnología o porque queremos hacer cambios grandes, sin estorbar nuestro día a día por lo que podemos hacer un fork del proyecto y luego mergearlo cuando queramos, Entonces en tu servidor:
$ git clone git://servidor.principal/ruta/a/archivos
Y luego clonamos dicho fork en cada uno de los cliente, si terminamos el cambio de tecnología podemos mergear con el repositorio principal.
Empezando con Rust, parte 3
Seguimos con Rust...
Ahora implementaremos un clásico problema de programación : un juego de adivinanzas. Así es como va a funcionar: el programa generará un número entero aleatorio entre 1 y 100. Luego le pedirá al jugador que ingrese una suposición. Después de ingresar una suposición, el programa indicará si la suposición es demasiado baja o demasiado alta. Si la suposición es correcta, el juego imprimirá un mensaje de felicitación y saldrá.
Creemos un nuevo proyecto usando Cargo, así:
$ cargo new guessing_game
$ cd guessing_game
El primer comando, cargo new, toma el nombre del proyecto (guesssing_game) como primer argumento. El segundo comando cambia al directorio del nuevo proyecto.
Mire el archivo generado Cargo.toml:
[package]
name = "guessing_game"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
edition = "2018"
[dependencies]
Por supuesto cambiamos la info que viene por defecto.
cargo new genera un programa "¡Hola, mundo!" algo así:
fn main() {
println!("Hello, world!");
}
Ahora compilemos este programa "¡Hola, mundo!" Y ejecútelo en el mismo paso con el comando de ejecución de cargo:
$ cargo run
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 1.50 secs
Running `target/debug/guessing_game`
Hello, world!
El comando de ejecución es útil cuando necesitamos ejecutar rápidamente en un proyecto.
Ya tenemos nuestro proyecto, ahora a seguir en otro post ...
Ahora implementaremos un clásico problema de programación : un juego de adivinanzas. Así es como va a funcionar: el programa generará un número entero aleatorio entre 1 y 100. Luego le pedirá al jugador que ingrese una suposición. Después de ingresar una suposición, el programa indicará si la suposición es demasiado baja o demasiado alta. Si la suposición es correcta, el juego imprimirá un mensaje de felicitación y saldrá.
Creemos un nuevo proyecto usando Cargo, así:
$ cargo new guessing_game
$ cd guessing_game
El primer comando, cargo new, toma el nombre del proyecto (guesssing_game) como primer argumento. El segundo comando cambia al directorio del nuevo proyecto.
Mire el archivo generado Cargo.toml:
[package]
name = "guessing_game"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
edition = "2018"
[dependencies]
Por supuesto cambiamos la info que viene por defecto.
cargo new genera un programa "¡Hola, mundo!" algo así:
fn main() {
println!("Hello, world!");
}
Ahora compilemos este programa "¡Hola, mundo!" Y ejecútelo en el mismo paso con el comando de ejecución de cargo:
$ cargo run
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 1.50 secs
Running `target/debug/guessing_game`
Hello, world!
El comando de ejecución es útil cuando necesitamos ejecutar rápidamente en un proyecto.
Ya tenemos nuestro proyecto, ahora a seguir en otro post ...
Suscribirse a:
Entradas (Atom)