Um passeio pela biblioteca padrão
Você já conheceu a linguagem. Agora conheça a biblioteca. A maior parte dos programas reais passa o tempo chamando funções da biblioteca padrão — interpretando entradas, transformando coleções, lendo arquivos, conversando com JSON. Este capítulo é um passeio guiado pelas peças que você mais vai usar.
Uma regra antes de começar: `string` e `Vector<T>` são embutidos (sempre disponíveis), e todo o resto precisa de um `import`. O caminho de importação espelha o arquivo: stdlib::hashmap é um módulo, stdlib::math é outro.
Strings
Os métodos de string não precisam de importação. Os que você vai usar o tempo todo:
let s: string = " Hello, Glide ";
println!(s.trim()); // "Hello, Glide"
println!(s.trim().to_lower()); // "hello, glide"
println!(s.contains("Glide")); // true
println!(s.replace("Glide", "World")); // " Hello, World "
let csv: string = "a,b,c";
let parts: *Vector<string> = csv.split(","); // ["a", "b", "c"]
println!(parts.len()); // 3
Converter texto em números vem em dois sabores: um parse_int direto (retorna 0 para entradas inválidas) e um try_parse_int seguro (retorna !i32 para que você trate a falha):
let n: i32 = "42".parse_int(); // 42
let r: !i32 = "oops".try_parse_int(); // err(...)
if r.ok { println!(r.val); } else { println!("not a number"); }
Vetores
Vector<T> é a coleção principal — embutida, dinâmica, possui seus conteúdos. Além de push / get / len, ela traz um kit funcional completo:
let v: *Vector<i32> = Vector::new();
v.push_all!(1, 2, 3, 4, 5);
let doubled: *Vector<i32> = v.map(double); // [2,4,6,8,10]
let evens: *Vector<i32> = v.filter(is_even); // [2,4]
let total: i32 = v.fold(0, add); // 15
println!(v.sum()); // 15 (apenas Vector<i32>)
fn double(x: i32) -> i32 { return x * 2; }
fn is_even(x: i32) -> bool { return x % 2 == 0; }
fn add(acc: i32, x: i32) -> i32 { return acc + x; }
map, filter, fold, take, skip, any, all, find, reverse, extend — todos recebem ponteiros de função simples (sem closures por enquanto). Para um Vector<string>, .join(sep) une tudo de volta em uma única string:
let words: *Vector<string> = Vector::new();
words.push_all!("rock", "the", "casbah");
println!(words.join(" ")); // "rock the casbah"
HashMaps
HashMap<V> é uma tabela hash com chaves do tipo string; o valor pode ser qualquer tipo V. Importe-a assim:
import stdlib::hashmap::*;
fn main() -> i32 {
let scores: *HashMap<i32> = HashMap::new();
scores.insert("alice", 30);
scores.insert("bob", 25);
if scores.contains("alice") {
println!("alice:", scores.get("alice")); // 30
}
for k in scores.keys() {
println!(k, "=>", scores.get(k));
}
return 0;
}
insert, get, contains, remove, len, keys(), values() e entries() (um *Vector<*Pair<string, V>>) cobrem quase tudo. As chaves são sempre string.
Math
stdlib::math oferece os auxiliares numéricos que não são operadores:
import stdlib::math::*;
fn main() -> i32 {
println!(ipow(2, 10)); // 1024 (potência inteira)
println!(gcd(48, 36)); // 12
println!(abs_int(-7)); // 7
println!(max_int(3, 9)); // 9
println!(min_f64(1.5, 2.5)); // 1.5
return 0;
}
Time
stdlib::time fornece um tipo Duration e acesso ao relógio:
import stdlib::time::*;
fn main() -> i32 {
let d: Duration = Duration::from_secs(90);
println!(d.to_string()); // "1m 30s"
let sw: Stopwatch = Stopwatch::start();
// ... faz o trabalho ...
let elapsed: Duration = sw.elapsed();
println!("took", elapsed.to_string());
return 0;
}
Duration::from_millis / from_secs / from_minutes / from_hours constroem durações; .add / .sub combinam duas durações. Um Stopwatch é a forma limpa de medir o tempo decorrido — Stopwatch::start() e depois sw.elapsed(). (Lembre do capítulo de concorrência que after(d) transforma uma Duration em um canal de timeout.)
Arquivos e o ambiente
stdlib::fs lê e escreve arquivos; stdlib::env acessa o ambiente do processo.
import stdlib::fs::*;
import stdlib::env::*;
fn main() -> i32 {
if fs_exists("config.txt") {
let text: string = fs_read("config.txt");
let lines: *Vector<string> = fs_read_lines("config.txt");
println!("config has", lines.len(), "lines");
}
fs_write("out.txt", "generated by glide\n");
let home: string = env_get("HOME"); // "" se não definido
if env_has("DEBUG") { println!("debug mode"); }
return 0;
}
As funções fs_* são deliberadamente simples e planas: fs_read, fs_write, fs_exists, fs_read_lines, fs_list(dir, suffix), fs_mkdir_p, fs_remove_file e outras. fs_read_or_default(path, fallback) é a forma de uma linha para "lê isso, ou usa um valor padrão se estiver faltando."
JSON
stdlib::json analisa e constrói JSON por meio de um único tipo, *JsonValue. A leitura é o caso mais comum:
import stdlib::json::*;
fn main() -> i32 {
let doc: *JsonValue = JsonValue::parse("{\"name\":\"alice\",\"age\":30}");
// getters tipados retornam !T — trate o caso de ausência ou tipo errado:
let name: !string = doc.get_string("name");
if name.ok { println!("name:", name.val); } // alice
let age: !i32 = doc.get_int("age");
if age.ok { println!("age:", age.val); } // 30
return 0;
}
Construir JSON funciona ao contrário — monte os valores e chame emit() para obter o texto:
import stdlib::json::*;
fn main() -> i32 {
let obj: *JsonValue = JsonValue::object();
obj.obj_set("id", JsonValue::int(7));
obj.obj_set("ok", JsonValue::bool(true));
println!(obj.emit()); // {"id":7,"ok":true}
return 0;
}
O restante da biblioteca, capítulo por capítulo
Este passeio arranhamos a superfície. Os capítulos que se seguem são a referência aprofundada — cada função pública, com exemplos elaborados — um capítulo por módulo:
- Prelude — o que está em escopo sem nenhuma importação (
println!,format!, a maquinaria de!T/?T) - Strings · Vetores · Coleções (
HashMap,HashSet,Pair) · Iteradores - Math · Time
- Arquivos e I/O · OS · Ambiente · Processo
- JSON · Regex · Random · Encoding e hashing (base64, hex, crypto, compress)
- Logging · Primitivas de sincronização · CLI / argparse · Networking · Mail · Sistema
O networking culmina em Construindo um servidor HTTP; testes ficam em Testes e benchmarks.
Recap
O que vem a seguir
Você já viu o formato da biblioteca. O próximo capítulo — Prelude — inicia a referência módulo a módulo com o que está sempre em escopo, e os capítulos seguintes percorrem cada módulo stdlib:: por vez.