Este artigo apresenta uma visão geral da linguagem de programação V (VLANG)
Antes de falarmos sobre as características da linguagem, é bom avisar que, até o momento em que estou escrevendo esse artigo (Julho/2020), a linguagem V ainda não tinha um release oficial e, portanto, ainda não estava preparada para ser usada em ambientes de produção. Além disso sua documentação é escassa e incompleta.
Trata-se de uma linguagem de uso geral, com foco em desenvolvimento de sistemas back end, infraestrutura, bancos de dados, aplicações WEB e gráficas.
Histórico e Características
A linguagem V está sendo desenvolvida por Alexander Medvednikov e uma comunidade de programadores no GITHUB, e pode-se dizer que é uma mistura entre GOLANG e RUST.
Vejamos algumas de suas características:
-
- Sintaxe GO like;
- Estaticamente compilada, mas com inferência de tipos;
- Variáveis imutáveis por padrão;
- Generics;
- Pointers e unsafe blocks;
- Funções com múltiplos valores de retorno;
- Limpeza da memória na compilação, sem garbage collection no estilo de Rust;
- Concorrência no estilo de GO
Vamos explorar alguns aspectos da linguagem…
Instalação
Mais simples, impossível:
-
- Baixar o zip do site oficial e descompactar.
- Configurar o PATH para a pasta raiz da instalação
- Configurar a IDE Visual Studio Code com a extensão V.
Alô Mundo
// Primeiro programa V fn main() { println('hello world') }
Observações:
-
- Assim como em GO, os separadores de comando (ponto e vírgula) não são necessários;
- Parecido com RUST, as funções iniciam com a palavra reservada fn;
- Do mesmo modo como em GO, a função main é um entry point. No entanto, a declaração do pacote não é obrigatória;
- Diferente de GO, a função println é embutida;
- A declaração da função main pode ser omitida caso se trate de um programa de um arquivo só, tipo um script. Dessa forma, o nosso programa “Alô Mundo” se resumiria à uma única linha.
Para compilar e executar o programa alo.v:
<span style="color: #00ff00;"><span style="font-size: 18pt;">v run alo.v</span></span>
Tipos de dados
Os principais tipos de dados primitivos em V são:
-
- Valores booleanos true e false: bool;
- Inteiros com sinal: i8, i16, int e i64;
- Inteiros sem sinal: byte, u16, u32 e u64
- Caracteres unicode : rune
- Ponto flutuantes: f32 e f64
A principal diferença aqui é que o tipo int é sempre de 32 bits, independe do hardware.
Variáveis
Aqui começam algumas diferenças em relação às outras linguagens. Vejamos:
-
- Variáveis em V são imutáveis por padrão, a não ser que você use o modificador mut.
- Variáveis sempre possuem um valor, não existe null, nil, etc.
- Variáveis são declaradas por inferência, sempre;
- Não existe escopo global. A declaração tem que ser somente dentro das funções;
- Não existe shadowing: nomes de variáveis não podem se repetir em blocos internos .
O design de V é baseado em parte na premissa “só existe uma forma de fazer isso”, então a declaração de variáveis só pode ser feita através da inicialização com o operador “:=“.
Veja um exemplo com comentários:
v := 1 // Erro de compilação - não existem variáveis globais fn main() { mut a := 10 // Válido - a variável 'a' será do tipo int mut b := 1.5 // Válido - a variável 'b' será do tipo f64 c := a + b // Válido - a variável 'c' será do tipo f64 c = 1.5 // Erro de compilação - a variável 'c' não é mutável println($a $b $c) // Válido vai imprimir os valores de 'a','b' e 'c' { d := 5 // Válido - a variável 'd' será do tipo int a := 1 // Erro de compilação - shadowing não permitido } }
Observações:
- Veja que a variável c da linha 5 é a soma de um float com um int. Aqui foi feito um cast automático, diferente de GO, que daria um erro de compilação. Mas veja que o cast automático não é feito em todas as situações.
- Um ponto interessante da função println é que ela aceita um único argumento do tipo string. As variáveis podem ser impressas através de placeholders com prefixo $ que lembram um pouco o PHP.
Estruturas de controle
A estrutura condicional IF em V é parecida com a linguagem GO, mas diferentemente de C, os parênteses nas condições não são necessários e as chaves são obrigatórias:
fn main() { v := 0 if v < 0 { println("O número $v é negativo") } else if v > 0 { println("O número $v é positivo") } else { println("O número $v é neutro") } }
fn main() { idade := 11 v := (if idade > 17 { 'Maior de idade' } else { 'Menor de idade' }) println(v) // Vai imprimir: Menor de idade }
A estrutura match é semelhante ao switch de GO:
fn main() { uf := 'sp' match uf { 'sp' { println('São Paulo') } 'mg' { println('Minas Gerais') } 'rg' { println('Rio de Janeiro') } 'es' { println('Espírito Santo') } else { println('Outras regiões') } } }
A estrutura de repetição FOR segue o mesmo padrão de GO, com vários sabores:
for i := 0; i < 10; i++ { // Pula o número 3 if i == 3 { continue } // Para no número 7 if i > 7 { break } println(i) }
fn main() { mut pares := [0, 2, 4, 6, 8, 10] for i, v in pares { println('Índice = $i, valor = $v') } }
for i in 0..10 { print(i) }
Estruturas de Dados
As estruturas de dados básicas em V são:
-
- Strings: Cadeia imutável de caracteres unicode. Internamente, array de bytes
- Arrays: Coleção de dados indexados do mesmo tipo de tamanho variável
- Maps: Coleção de pares key-value
- Structs: Conjunto de variáveis de tipos diferentes agrupadas logicamente
Vejamos alguns exemplos:
fn main() { nome := 'João' println('Alô, $nome!') println(nome.len) nomecompleto := nome + ' Silva' println(nomecompleto[0..3]) }
fn main() { mut numeros := []int{} // Criação de array vazio numeros << 5 // adicionou elemento 5 println(numeros) //[5] println(numeros[0]) // 5 numeros[0] = 1 println(numeros) //[1] println(numeros.len) // 1 numeros << [2,3,4] // adicionou 2,3,e 4 println(numeros) // [1,2,3,4] numeros.delete(1) // deletou elemento de índice 1 println(numeros) //[1,3,4] println(3 in numeros) // true }
fn main() { mut uf := map[string]string uf['sp'] = 'São Paulo' uf['rj'] = 'Rio de Janeiro' println(uf['sp']) // "São Paulo" println(uf['mg']) // "0" println('sp' in uf) // true uf.delete('rj') println(uf) // {'sp': 'São Paulo', '': ''} }
Funções
Vamos ver alguns exemplos de funções:
fn div(n1, n2 f64) (bool, f64) { mut err := false mut ret := 0.0 if n2 == 0{ err = true } else { ret = n1 / n2 } return err,ret } fn main() { e,r := div(6,2) println("$e $r") }
fn produto_escalar(n f64, mut vetor [] f64) { for i in 0..vetor.len { vetor[i] *= 2 } } fn main() { mut nums := [1.0, 2.0, 3.0] produto_escalar(4, mut nums) println(nums) // "[4.0, 8.0, 12.0]" }
Outras características
-
- Para efeitos de modularização, V trabalha com packages de forma parecida com outras linguagens. Ele vem com um gerenciador de pacotes tipo NodeJS que facilita a instalação das aplicações.
- Para que um membro de um pacote seja exportável, ou seja, visível em outros pacotes, existe o modificador pub, ao contrário de GO que faz isso através de letras capitalizadas. Na minha opinião essa abordagem de V para membros públicos é mais clara que em GO.
- A V standard library (vlib) já possui um número considerável de pacotes e está em fase de crescimento.
- V possui uma biblioteca GUI nativa com controles nativos e uma biblioteca gráfica de plataforma cruzada compatível com OpenGL. Veja aqui um port de DOOM em V.
Conclusões
Pelo exposto, percebemos que a linguagem V, pelas suas características de segurança, rapidez, e facilidade de uso é muito promissora.
Neste artigo oferecemos apenas uma pequena visão da linguagem. Para saber mais, consulte as seguintes referências:
Até mais!