Translate

lunes, 17 de febrero de 2020

El lenguaje de programación V, Parte 9

Seguimos con V


El modelo de concurrencia de V es muy similar a Go. Para ejecutar una función de modo concurrente simplemente se debe llamar con go foo (). En estos momentos se esta trabajando en rutinas y en un  planificador.


Si queremos probar nuestro codigo podemos hacerlo :

// hello.v
fn hello() string {
return 'Hello world'
}

// hello_test.v
fn test_hello() {
    assert hello() == 'Hello world'
}

Todas las funciones de prueba deben colocarse en archivos * _test.v y comenzar con test_.
Para ejecutar las pruebas, haga v hello_test.v. Para probar un módulo completo, haga v test mymodule.

Algo importante es que la palabra clave assert también se puede utilizar fuera de las pruebas.

Esto fue todo de V, si me piden una opinión es una buena combinación de Go y Rust. Que eso es bueno, pero no aporta mucho al mundo de la programación.


Dejo link: https://vlang.io/

sábado, 15 de febrero de 2020

El lenguaje de programación Raku

Hice un post de Raku, pero no mostré nada de código y quedo bastante incompleto. Por eso la idea de este post es mostrar un poco más. Vamos hacer una función que retorne el ultimo elemento de una lista :

use v6;

sub last-elem(@list) {
    @list[* - 1];
}

say last-elem(<a b c d e>);

nos retornará "e" veamos otro ejemplo, ahora vamos a retornar los 2 últimos elementos :

use v6;

sub last-two(@list)
{
    @list[* - 2, * - 1];
}

say "{last-two(<a b c d e>)}";

nos retornará "d" y "e", vamos hacer una función que busque un elemento por un indice pasado por parámetro :

use v6;

sub get-at(@list, $elem)
{
    @list[$elem];
}

say get-at(<a b c d e>, 4);

nos retornará "e" veamos otro ejemplo, ahora vamos a retornar una lista de reversa :

use v6;

sub reverse-list(@list)
{
    @list.reverse;
}

say "{reverse-list(<a b c d e>)}";
va retornar "e d c b a"

Por ultimo vamos a hacer una función que retorne n números :

use v6;

sub lotto-select($n, $m)
{
    gather for ^$n
    {
        take (1 ... $m).pick(1).first;
    }
}

say "{lotto-select(6, 49)}";

A mi entender tantos símbolos como @, $, etc, hacen difícil leer el codigo, sobre todo a las personas que no venimos de Perl


Dejo link: https://examples.p6c.dev/index.html

jueves, 13 de febrero de 2020

Libros de Java Code Geeks

Download IT Guides!


Drools supports the JSR-94 standard for its business rule engine and enterprise framework for the construction, maintenance, and enforcement of business policies in an organization,...

In the following sections we will discuss about object-oriented programming and its characteristics, general questions regarding Java and its functionality, collections in Java, garbage...

We are going to explain what reflection is in general and how can be used in Java. Real uses cases about different reflection uses are listed in the next chapters.

The principle is sometimes stated as a recommendation to the programmer, but sometimes stated as requirement of the programming language, assuming it is self-understood why abstractions...

martes, 11 de febrero de 2020

Perl 6, mejor conocido como Raku

A Perl 6 le metieron tantos cambios que lo más coherente era llamarlo de otra manera y de esta forma nace Raku.

Raku tiene la intención de llevar adelante los altos ideales de la comunidad Perl. Raku ha sido desarrollado por un equipo de voluntarios dedicados y entusiastas, y continúa desarrollándose.

Raku se ve altamente influido por la programación funcional, de esta manera, tiene clausuras, lazy evaluation, patter matching.

Programación orientada a objetos tambien se hace presente y incluye genéricos, roles y polimorfismo.

Paralelismo, concurrencia y asincronía, tambien incluido el soporte multinúcleo

Gramáticas definibles para la coincidencia de patrones y el procesamiento de cadenas generalizado
Mecanografía opcional y gradual

Dejo link : https://www.raku.org/

lunes, 10 de febrero de 2020

El lenguaje de programación V, Parte 8

Seguimos con V

V puede manejar datos nulos con resultados opcionales :

struct User {
id int
name string
}

struct Repo {
users []User
}

fn new_repo() Repo {
return Repo {
users: [User{1, 'Andrew'}, User {2, 'Bob'}, User {10, 'Charles'}]
}
}

fn (r Repo) find_user_by_id(id int) ?User {
for user in r.users {
if user.id == id {
return user
}
}
return error('User $id not found')
}

fn main() {
repo := new_repo()
user := repo.find_user_by_id(10) or { // Los tipos de opciones deben manejarse mediante bloques `or`
return  // El bloque `or` debe terminar con` return`, `break` o` continue`
}
println(user.id) // "10"
println(user.name) // "Charles"
}

V combina Opcionales y Resultado en un solo tipo, por lo que no necesita decidir cuál usar.

Si no necesita devolver un error, simplemente puede devolver none.

Esta es la forma principal de manejar los errores en V. Es similar a Go, pero la ventaja es que los errores pueden ser manejados, y manejarlos es mucho menos complicado.

err se define dentro de un bloque or y se establece el mensaje de error. err está vacío si no se devolvió algún error.

user := repo.find_user_by_id(7) or {
println(err) // "User 7 not found"
return
}

También puede propagar errores:

resp := http.get(url)?
println(resp.body)

http.get devuelve? http.Response. Se llamó con?, Por lo que el error se propaga a la función de llamada (que debe devolver un opcional) o en caso de que los cables principales entren en pánico.

Básicamente, el código anterior es una versión más corta de

resp := http.get(url) or {
panic(err)
}
println(resp.body)

V no tiene una forma de forzar el desenvolvimiento de un opcional (como el desenvolvimiento de Rust () o el de Swift). Tienes que usar o {panic (err)} en su lugar.

V también tienen generics :

struct Repo<T> {
db DB
}

fn new_repo<T>(db DB) Repo<T> {
return Repo<T>{db: db}
}

// Esta es una función genérica.
fn (r Repo<T>) find_by_id(id int) ?T {
table_name := T.name // en este ejemplo, obtener el nombre del tipo nos da el nombre de la tabla
return r.db.query_one<T>('select * from $table_name where id = ?', id)
}

db := new_db()
users_repo := new_repo<User>(db)
posts_repo := new_repo<Post>(db)
user := users_repo.find_by_id(1)?
post := posts_repo.find_by_id(1)?


Dejo link: https://vlang.io/


viernes, 7 de febrero de 2020

El lenguaje de programación V, Parte 7



Seguimos con V

V es un lenguaje muy modular. Se recomienda crear módulos reutilizables y es muy simple hacerlo. Para crear un nuevo módulo, crea un directorio con el nombre del módulo y los archivos .v con código:

cd ~/code/modules
mkdir mymodule
vim mymodule/mymodule.v

module mymodule

pub fn say_hi() {
println('hola desde mi modulo!')
}

Puede tener tantos archivos .v en mymodule / como desee.
Compílelo con v build module

~/code/modules/mymodule.

Eso es todo, ahora puedes usarlo en tu código:

module main

import mymodule

fn main() {
mymodule.say_hi()
}

Tenga en cuenta que debe especificar el módulo cada vez que llama a una función externa. Esto hace que el código sea mucho más legible y fácil de entender, ya que siempre está claro qué función se llama desde qué módulo. Especialmente en proyectos grandes.

Los nombres de los módulos deben ser cortos, de menos de 10 caracteres. No se permiten importaciones circulares.

Puede crear módulos en cualquier lugar.

Todos los módulos se compilan en un solo ejecutable.

Si desea escribir un módulo que invoque automáticamente algún código de configuración cuando se importe (tal vez desee llamar a algunas funciones de la biblioteca C), escriba una función de inicio del módulo dentro del módulo:

fn init() {
// your setup code here ...
}

La función init no puede ser pública. Se llamará automáticamente.

Un tipo implementa una interfaz mediante la implementación de sus métodos. No hay una declaración explícita de intención, no hay palabras clave "implementa".

struct Dog {}
struct Cat {}

fn (d Dog) speak() string {
return 'woof'
}

fn (c Cat) speak() string {
return 'meow'
}

interface Speaker {
speak() string
}

fn perform(s Speaker) {
println(s.speak())
}

dog := Dog{}
cat := Cat{}
perform(dog) // "woof"
perform(cat) // "meow"

V también tiene enums :

enum Color {
red green blue
}

fn main() {
mut color := Color.red
// V sabe que color es un color por ende podemos suprimir Color.
color = .green
println(color) // "1"
if color == .green {
println("it's green")
}
}

Dejo link: https://vlang.io/

Dé un vistazo a cómo se verá el futuro con IA


Me llego el siguiente mail de microsoft, sobre un ebook gratuito :

Microsoft
 
Dé un vistazo a cómo se verá el futuro con IA
Dé un vistazo a cómo se verá el futuro con IA
 
 
 
Futuro calculado: la inteligencia artificial y la sociedad
 
Lea este e-book, El futuro calculado, para obtener una perspectiva detallada sobre la inteligencia artificial (IA) y su promesa de ampliar el ingenio humano en las generaciones actuales y futuras. Los temas incluyen:
  • El futuro de la IA y su potencial para ayudar a la sociedad.
  • Principios y políticas para el uso responsable de la IA.
  • El impacto de la IA y las tecnologías relacionadas en el lugar de trabajo del futuro.
 
Descargue el eBook gratuito >
 
 

martes, 28 de enero de 2020

El lenguaje de programación V, Parte 6



Seguimos con V

V tiene funciones de orden superior :

fn sqr(n int) int {
        return n * n
}

fn run(value int, op fn(int) int) int {
        return op(value)
}

fn main()  {
        println(run(5, sqr)) // "25"
}

Si un argumento de función es inmutable, V puede pasarlo por valor o por referencia. El compilador toma la decisión, y el desarrollador no necesita pensar en ello.
Ya no necesita recordar si debe pasar la estructura por valor o por referencia.

Hay una manera de garantizar que la estructura siempre se pase por referencia agregando &:

fn (foo &Foo) bar() {
println(foo.abc)
}

En general, las referencias V son similares a los punteros Go y las referencias C ++. Por ejemplo, una definición de estructura de árbol se vería así:

struct Node<T> {
val   T
left  &Node
right &Node
}

Las variables globales no están permitidas, por lo que esto puede ser realmente útil.

Al nombrar constantes, se debe usar snake_case. Muchas personas prefieren todos las letras en mayúsculas: TOP_CITIES. Esto no funcionaría bien en V, porque los consts son mucho más poderosos que en otros lenguajes. Pueden representar estructuras complejas, y esto se usa con bastante frecuencia ya que no hay globales:

println('Top cities: $TOP_CITIES.filter(.usa)')
vs
println('Top cities: $top_cities.filter(.usa)')

Con println podemos imprimir lo que se nos de la gana:

println(1) // "1"
println('hi') // "hi"
println([1,2,3]) // "[1, 2, 3]"
println(User{name:'Bob', age:20}) // "User{name:'Bob', age:20}"

Dejo link: https://vlang.io/

Comandos útiles en Docker


Bueno, esto es un post para mi, más que nada, quiero documentar comandos útiles de docker que he usado y seguro me voy a olvidar.

Si debemos copiar un archivo a nuestro contenedor utilizamos docker cp

docker cp foo.txt nombreDeContenedor:/foo.txt

Necesitamos hacer algo con un archivo dentro del contenedor, mover, borrar, copiar, etc... archivos. Podemos utilizar docker exec, veamos un ejemplo, creemos un archivo :

docker exec -it nombreDeContenedor touch /tmp/ejemplo.txt

Hacer una carpeta:

docker exec -it ejemplo mkdir path/nombreDeLaCarpeta

Listar los contenedores que tengo:

docker container ls

Necesitamos saber si nuestro contenedor esta corriendo:

docker ps

Parar el contenedor :

docker stop nombreDeContenedor

Iniciar un contenedor :

docker start nombreDeContenedor

Remover un contenedor:

docker rm nombreDeContenedor

Queremos bajar una imagen :

docker pull nombreImagen

Queremos ver las imagenes que tenemos descargadas :

docker images

Remover una imagen :

docker rmi nombreImagen

Queremos ver información de las imagenes , tamaño , fecha creacion  nombre …

docker info

Y estos son los comandos que más uso ...




sábado, 25 de enero de 2020

Como levantar una base de datos Oracle en Docker?


Vamos a correr una base de datos oracle en un contenedor docker.

Antes que nada vamos instalar docker : https://docs.docker.com/install/

Luego de instalar docker, se debe hacer una cuenta y aceptar los términos y condiciones de uso de la imagen de Oracle 12.2.1c en el siguiente link:

https://hub.docker.com/u/emanuelpeg/content/sub-58a32504-c6af-4941-8558-061121a0243d

Luego debemos correr docker, para ello podemos ejecutar esta comando en Fedora :

sudo systemctl start docker

Luego debemos loguearnos por consola con el siguiente comando:

docker login

Con este comando, nos logiamos, y docker va a saber que aceptamos los términos y condiciones.

Luego debemos bajar la imagen con :

docker pull store/oracle/database-enterprise:12.2.0.1

Con este comando, bajamos la imagen de oracle, la imagen sería un template con el cual podemos crear containers que tengan base de datos propiamente dichas.

Luego tenemos que crear un container que es la instancia propia de la base, vamos a llamar ejemplo a nuestro container.

docker run -d -it --name ejemplo -p 1521:1521 store/oracle/database-enterprise:12.2.0.1

Como se puede ver se mapeo el puerto 1521 con el 1521 del equipo, esto se puede cambiar si el puerto esta siendo utilizado.

Con docker ps podemos ver si levanto el container con :

docker ps

CONTAINER ID        IMAGE                                      COMMAND                 CREATED             STATUS                             PORTS                              NAMES

c8aea60c0230       store/oracle/database-enterprise:12.2.0.1   "/bin/sh -c '/bin/ba…"   38 seconds ago      Up 36 seconds (health: starting)   0.0.0.0:1521->1521/tcp, 5500/tcp   ejemplo

Docker creo un container con la base de datos oracle y publico el puerto 1521 para que podamos conectarnos.

Los datos de conexión son :

User : SYS (dba user)
Password : Oradoc_db1
Oracle-sid : ORCLCDB

Estos datos son creados a partir de la imagen de oracle, y simplemente son datos por defecto.

Debemos conectarnos con estos datos para utilizar la base. Para ello utilizamos sqlplus :

$ docker exec -it ejemplo bash -c "source /home/oracle/.bashrc; sqlplus  sys/Oradoc_db1@ORCLCDB as sysdba"

Con sqlplus podemos crear usuarios, base de datos, tablas, etc...

Para importar base de datos necesitamos tener un .dmp de la base a importar, yo importaré baseDeEjemplo.dmp

Creamos una carpeta para guardar los backups :

docker exec -it ejemplo mkdir /home/oracle/backups

Debemos copiar este archivo al container :

docker cp baseDeEjemplo.dmp ejemplo:/home/oracle/backups

Ahora debemos importar el dump, con el siguiente comando:

docker exec -it ejemplo bash -c "source /home/oracle/.bashrc; impdp usario/pass@ORCLCDB remap_schema=origen:destino directory= backups dumpfile=baseDeEjemplo.dmp logfile=unLog.log”

Se debe tener la carpeta backup registrada en oracle.

Para conectarnos con un cliente debemos utilizar los siguientes datos :

host=0.0.0.0:1521
SID=ORCLCDB
password = sys
username = Oradoc_db1

Por último, si dejamos de utilizar docker podemos parar el container con

docker stop ejemplo

y podemos iniciar la instancia con start

docker start ejemplo

Dejo link: https://hub.docker.com/u/emanuelpeg/content/sub-58a32504-c6af-4941-8558-061121a0243d?ref=login

jueves, 23 de enero de 2020

Sextos pasos en GIT


Seguimos con GIT. 

Administrando branches : Si deseamos lista todas las branches :

$ git branch

Siempre hay una branch llamada ”master”, y es en la que comienzas por defecto.

Algunos aconsejan dejar la rama ”master” sin tocar y el crear nuevas branches para tus propios cambios. El branch ”master” es una convención útil. Otros pueden asumir que tu repositorio tiene un branch con este nombre, y que contiene la versión oficial del proyecto. Puedes renombrar o destruir la branch ”master”, pero también podrías respetar esta costumbre.

Después de un rato puedes notar que estás creando branches de corta vida de manera frecuente por razones similares: cada branch sirve simplemente para salvar el estado actual y permitirte saltar a un estado anterior para solucionar un bug de alta prioridad o algo.

Es análogo a cambiar el canal de la TV temporalmente, para ver que otra cosa están dando. Pero en lugar de apretar un par de botones, tienes que crear, hacer checkout y eliminar branches y commits temporales. Por suerte, Git tiene un atajo que es tan conveniente como un control remoto de TV:

$ git stash

Esto guarda el estado actual en un lugar temporal (un stash) y restaura el estado anterior. Tu directorio de trabajo se ve idéntico a como estaba antes de que comenzaras a editar, y puedes solucionar bugs, traer cambios desde otros repositorios, etc. Cuando quieras volver a los cambios del stash, escribe:

$ git stash apply

Puedes tener varios stashes, y manipularlos de varias maneras. Como es de imaginar, Git mantiene branches de manera interna para lograr este truco mágico.

Aplicaciones como Mozilla Firefox permiten tener varias pestañas y ventanas abiertas. Cambiar de pestaña te da diferente contenido en la misma ventana.

Los branches en git son como pestañas para tu directorio de trabajo. Siguiendo esta analogía, el clonar es como abrir una nueva ventana. La posibilidad de ambas cosas es lo que mejora la experiencia del usuario.

En un nivel más alto, varios window managers en Linux soportan múltiples escritorios. Usar branches en Git es similar a cambiar a un escritorio diferente, mientras clonar es similar a conectar otro monitor para ganar un nuevo escritorio.

Otro ejemplo es el programa screen. Esta joya permite crear, destruir e intercambiar entre varias sesiones de terminal sobre la misma terminal. En lugar de abrir terminales nuevas (clone), puedes usar la misma si ejecutas screen (branch). De hecho, puedes hacer mucho más con screen, pero eso es un asunto para otro manual.

Usar clone, branch y merge, es rápido y local en Git, animándote a usar la combinación que más te favorezca. Git te permite trabajar exactamente como prefieras.


miércoles, 22 de enero de 2020

C++ 17 en detalle

Quiero recomendarles el siguiente libro gratuito de C++ 17 :

Free ebook for every developer
Free tools for every developer
Download your copy of the eBook "C++17 IN DETAIL - Part 1"
Explore the Exciting Features of the New C++ Standard

What you will learn:
  • What was removed from the language and what is deprecated
  • How the language is more precise: for example, thanks to expression evaluation order guarantees
  • What the new features of templates are, like if constexpr or fold expressions
  • What the new standard attributes are
  • How you can write cleaner and more expressive code thanks to structured binding, inline variables, compile-time if or template argument deduction for classes

lunes, 20 de enero de 2020

El lenguaje de programación V, Parte 5




Seguimos con V

Al igual que Go, podemos definir métodos para estructuras :

struct User {
age int
}

fn (u User) can_register() bool {
return u.age > 16
}

user := User{age: 10}
println(user.can_register()) // "false"

user2 := User{age: 20}
println(user2.can_register()) // "true"

V no tiene clases. Pero puede definir métodos de tipos.

Un método es una función con un argumento receptor especial.

El receptor aparece en su propia lista de argumentos entre la palabra clave fn y el nombre del método.

En este ejemplo, el método can_register tiene un receptor de tipo Usuario llamado u. La convención no es usar nombres de receptores como self o this, sino un nombre corto, preferiblemente de una letra.

Las funciones V son puras por defecto, lo que significa que sus valores de retorno solo están determinados por sus argumentos, y su evaluación no tiene efectos secundarios.

Esto se logra por falta de variables globales y todos los argumentos de función son inmutables por defecto, incluso cuando se pasan referencias.

Sin embargo, V no es un lenguaje funcional puro. Es posible modificar los argumentos de la función utilizando la misma palabra clave mut:

struct User {
mut:
is_registered bool
}

fn (u mut User) register() {
u.is_registered = true
}

mut user := User{}
println(user.is_registered) // "false"
user.register()
println(user.is_registered) // "true"

En este ejemplo, el receptor (que es simplemente el primer argumento) se marca como mutable, por lo que register() puede cambiar el objeto de usuario. Lo mismo funciona con argumentos no receptores:

fn multiply_by_2(arr mut []int) {
for i := 0; i < arr.len; i++ {
arr[i] *= 2
}
}

mut nums := [1, 2, 3]
multiply_by_2(mut nums)
println(nums) // "[2, 4, 6]"

Tengamos en cuenta que debe agregar mut antes de nums cuando llamemos a esta función. Esto deja en claro que la función que se llama modificará el valor.

Es preferible devolver valores en lugar de modificar argumentos. La modificación de argumentos solo debe hacerse en partes críticas de su aplicación para reducir las asignaciones y la copia.

Por esta razón, V no permite modificar argumentos primitivos como enteros, solo tipos complejos como matrices y mapas.

Se debe usarr user.register() o user = register (user) en lugar de register (mut user).

V facilita la devolución de una versión modificada de un objeto:

fn register(u User) User {
return { u | is_registered: true }
}

user = register(user)

Dejo link: https://vlang.io/

domingo, 19 de enero de 2020

El lenguaje de programación V, Parte 4

Seguimos con V 


Veamos un ejemplo de macheo:

os := 'windows'
print('V is running on ')
match os {
'darwin' { println('macOS.') }
'linux'  { println('Linux.') }
else     { println(os) }
}

s := match number {
1    { 'one' }
2    { 'two' }
else {
println('this works too')
'many'
}
}

Una declaración de coincidencia es una forma más corta de escribir una secuencia de declaraciones if - else. Cuando se encuentra una rama coincidente, se ejecutará el siguiente bloque de instrucciones y se devolverá la expresión final. La rama else se evaluará cuando ninguna otra rama coincida.

Tambien podemos utilizar enums:

enum Color {
red
blue
green
}

fn is_red_or_blue(c Color) bool {
return match c {
.red { true }
.blue { true }
else { false }
}
}


También tenemos structs : 

struct Point {
x int
y int
}

p := Point{
x: 10
y: 20
}
println(p.x) // Se accede a los campos de estructura utilizando un punto

Las estructuras se asignan en la pila. Para asignar una estructura en el montón y obtener una referencia a ella, use el prefijo &:

  // Sintaxis de inicialización alternativa para estructuras con 3 campos o menos
p: = &Point {10, 10}

// Las referencias tienen la misma sintaxis para acceder a los campos
println (p.x)

El tipo de p es &Point. Es una referencia a Point. Las referencias son similares a los punteros Go y las referencias de C ++.

V no tiene subclases, pero admite estructuras incrustadas como Go:

struct Button {
Widget
title string
}

button := new_button('Click me')
button.set_pos(x, y)

button.widget.set_pos(x,y)

Los campos de estructura son privados e inmutables por defecto (haciendo que las estructuras también sean inmutables). Sus modificadores de acceso se pueden cambiar con pub y mut. En total, hay 5 opciones posibles:

struct Foo {
a int     // privado inmutable (predeterminado)
mut:
b int     // privado mutable
c int     // (puede enumerar varios campos con el mismo modificador de acceso)
pub:
d int     // público inmutable (solo lectura)
pub mut:
e int     // público, pero mutable solo en el módulo principal
__global:
f int   // público y mutable tanto dentro como fuera del módulo principal
}               // (no se recomienda usar, es por eso que la palabra clave 'global'
                 // comienza con __)

Por ejemplo, aquí está el tipo de cadena definido en el módulo integrado:

struct string {
str byteptr
pub:
len int
}

Es fácil ver a partir de esta definición que la cadena es un tipo inmutable.

El puntero de byte con los datos de la cadena no es accesible fuera de la construcción. El campo de len es público, pero no mutable:

fn main() {
str := 'hello'
len := str.len // OK 
str.len++      // Compilation error 
}

Dejo link:


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/