Mostrando las entradas con la etiqueta V. Mostrar todas las entradas
Mostrando las entradas con la etiqueta V. Mostrar todas las entradas

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/

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/

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/

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/

miércoles, 15 de enero de 2020

El lenguaje de programación V, Parte 2

Seguimos con V 


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:

s := r'hello\nworld'
println(s) // "hello\nworld"

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

0


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/

viernes, 1 de noviembre de 2019

¿Cuál es el mejor y más nuevo lenguaje de programación?


Encontré dicha pregunta en quora, y la respuesta :

  • Julia (Influenciado por: Fortran, Lisp, Lua, Python, Perl, Ruby y MATLAB)
  • Kotlin (Influenciado por: JavaScript, Java, C# y Scala)
  • Elm (Influenciado por: Standard ML, F#, Haskell y OCaml)
  • Elixir (Influenciado por: LFE, Clojure, Erlang and Ruby)
  • Rust (Influenciado por: C#, Ruby, C++, Alef, Haskell, NIL, Cyclone, Limbo y Erlang)
  • Crystal (Influenciado por: C, Ruby, C# and Python)
  • Groovy (Influenciado por: Python, Java, Smalltalk, Objective-C y Perl)
  • R (Influenciado por: S, XLispStat, Common Lisp y Scheme)
  • Hack (por Facebook)
  • Go (Influenciado por: C, Python, Smalltalk, Alef, CSP, Modula, Pascal, Limbo y BCPL)
  • Dart (por Google)
  • Bosque (Nuevo lenguaje de programación de Microsoft)
  • Ballerina (Basado en Java, Javascript, Go, Rust, C#)
  • V (Basado en Go y Rust)

La verdad no conocía a Bosque, Ballerina y V. 

Más allá de dicha respuesta, a mi entender, todo depende de a que te vas a dedicar, por ejemplo: 

Si vas a hacer una aplicación base, base de datos, sistema operativos, aplicaciones de escritorio: 
  • V
  • Go 
  • Rust

Si te queres dedicar a ciencia de datos : 
  • Julia
  • R

Si queres hacer back-end de aplicaciones : 
  • Kotlin
  • Groovy
  • Bosque
  • Ballerina
  • Hack
  • Elixir

Aplicaciones front-end :
  • Elm
  • Dart

Me puedo equivocar, pero es mi opinión. 

Otra cosa, faltan lenguajes que siempre nuevos, como Scala, Idris, Swift o tantos otros...

Opinen!