O tipo Option significa que o valor pode ser do tipo Some (há algo) ou None (nada):
pubenumOption<T> {None,Some(T),}
Você pode usar funções como is_some() ou is_none() para verificar o valor da Option.
Macros
Macros são mais poderosos do que funções porque se expandem para produzir mais código do que o código que você escreveu manualmente. Por exemplo, uma assinatura de função deve declarar o número e o tipo de parâmetros que a função possui. Macros, por outro lado, podem receber um número variável de parâmetros: podemos chamar println!("hello") com um argumento ou println!("hello {}", name) com dois argumentos. Além disso, as macros são expandidas antes do compilador interpretar o significado do código, então uma macro pode, por exemplo, implementar um trait em um determinado tipo. Uma função não pode, porque é chamada em tempo de execução e um trait precisa ser implementado em tempo de compilação.
macro_rules!my_macro { () => {println!("Check out my macro!"); }; ($val:expr) => {println!("Look at this other macro: {}", $val); }}fnmain() {my_macro!();my_macro!(7777);}// Export a macro from a modulemod macros { #[macro_export]macro_rules!my_macro { () => {println!("Check out my macro!"); }; }}
Iterar
// Iterate through a vectorlet my_fav_fruits =vec!["banana", "raspberry"];letmut my_iterable_fav_fruits = my_fav_fruits.iter();assert_eq!(my_iterable_fav_fruits.next(), Some(&"banana"));assert_eq!(my_iterable_fav_fruits.next(), Some(&"raspberry"));assert_eq!(my_iterable_fav_fruits.next(), None); // When it's over, it's none// One line iteration with actionmy_fav_fruits.iter().map(|x|capitalize_first(x)).collect()// Hashmap iterationfor (key, hashvalue) in&*map {for key in map.keys() {for value in map.values() {
Caixa Recursiva
enumList {Cons(i32, List),Nil,}let list =Cons(1, Cons(2, Cons(3, Nil)));
Condicionais
if
let n =5;if n <0 {print!("{} is negative", n);} elseif n >0 {print!("{} is positive", n);} else {print!("{} is zero", n);}
match
O match é uma expressão que permite combinar um valor com uma série de padrões e executar o código correspondente ao padrão correspondente. É semelhante a um switch em outras linguagens de programação. O match é frequentemente usado em Rust para lidar com enumerações, mas também pode ser usado com outros tipos de dados.
match number {// Match a single value1=>println!("One!"),// Match several values2|3|5|7|11=>println!("This is a prime"),// TODO ^ Try adding 13 to the list of prime values// Match an inclusive range13..=19=>println!("A teen"),// Handle the rest of cases _ =>println!("Ain't special"),}let boolean =true;// Match is an expression toolet binary =match boolean {// The arms of a match must cover all the possible valuesfalse=>0,true=>1,// TODO ^ Try commenting out one of these arms};
Enquanto a condição especificada for verdadeira, o bloco de código dentro do while será executado repetidamente. A condição é verificada antes de cada iteração do loop. Se a condição for falsa, o loop será interrompido e a execução continuará após o bloco while.
letmut i =0;while i <5 {println!("O valor de i é: {}", i); i +=1;}
Este exemplo imprimirá o valor de i cinco vezes, começando em 0 e incrementando em 1 a cada iteração, até que i seja igual a 5.
letmut n =1;while n <101 {if n %15==0 {println!("fizzbuzz"); } elseif n %5==0 {println!("buzz"); } else {println!("{}", n); } n +=1;}
para
for n in1..101 {if n %15==0 {println!("fizzbuzz"); } else {println!("{}", n); }}// Use "..=" to make inclusive both endsfor n in1..=100 {if n %15==0 {println!("fizzbuzz"); } elseif n %3==0 {println!("fizz"); } elseif n %5==0 {println!("buzz"); } else {println!("{}", n); }}// ITERATIONSlet names =vec!["Bob", "Frank", "Ferris"];//iter - Doesn't consume the collectionfor name in names.iter() {match name {&"Ferris"=>println!("There is a rustacean among us!"), _ =>println!("Hello {}", name), }}//into_iter - COnsumes the collectionfor name in names.into_iter() {match name {"Ferris"=>println!("There is a rustacean among us!"), _ =>println!("Hello {}", name), }}//iter_mut - This mutably borrows each element of the collectionfor name in names.iter_mut() {*name =match name {&mut"Ferris"=>"There is a rustacean among us!", _ =>"Hello", }}
if let
O if let é uma expressão condicional que permite verificar se um valor corresponde a um padrão específico e, em seguida, executar um bloco de código correspondente. É uma forma mais concisa de escrever um match que lida apenas com um caso.
A sintaxe básica é a seguinte:
if let PATTERN = EXPRESSION {
// code to execute if the pattern matches
}
Onde PATTERN é o padrão que estamos verificando e EXPRESSION é a expressão que estamos avaliando. Se EXPRESSION corresponder a PATTERN, o bloco de código dentro das chaves será executado. Caso contrário, o código será ignorado.
O if let é frequentemente usado em conjunto com a função Option, que representa um valor opcional que pode ser Some(valor) ou None. Podemos usar o if let para verificar se um valor Option é Some e, em seguida, desempacotá-lo para usar o valor subjacente. Por exemplo:
let my_number = Some(42);
if let Some(x) = my_number {
println!("The number is {}", x);
}
Neste exemplo, estamos verificando se my_number é Some e, em seguida, desempacotando o valor 42 e atribuindo-o a x. Se my_number fosse None, o bloco de código seria ignorado.
let optional_word =Some(String::from("rustlings"));iflet word = optional_word {println!("The word is: {}", word);} else {println!("The optional word doesn't contain anything");}
enquanto deixar
letmut optional =Some(0);// This reads: "while `let` destructures `optional` into// `Some(i)`, evaluate the block (`{}`). Else `break`.whileletSome(i) = optional {if i >9 {println!("Greater than 9, quit!"); optional =None; } else {println!("`i` is `{:?}`. Try again.", i); optional =Some(i +1); }// ^ Less rightward drift and doesn't require// explicitly handling the failing case.}
Traits
Criar um novo método para um tipo
traitAppendBar {fnappend_bar(self) -> Self;}implAppendBarforString {fnappend_bar(self) -> Self{format!("{}Bar", self) }}let s =String::from("Foo");let s = s.append_bar();println!("s: {}", s);
Um Arc pode usar Clone para criar mais referências sobre o objeto para passá-las para as threads. Quando a última referência apontando para um valor está fora do escopo, a variável é descartada.
use std::sync::Arc;let apple =Arc::new("the same apple");for _ in0..10 {let apple =Arc::clone(&apple); thread::spawn(move|| {println!("{:?}", apple); });}
Threads
Neste caso, passaremos para a thread uma variável que ela poderá modificar.