Lucas Heim
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # Rust básico (não é o jogo!) Autores: Derick Martins, Lucas Heim e Nadine Schneider ## Introdução Rust é uma linguagem de programação multiparadigma, compilada, desenvolvida pela Mozilla. A linguagem foca em ser segura, concorrente e rápida, e atinge esses objetivos com alguns elementos, como a ausência de um coletor de lixo, a concorrência sem disputa de dados e a abstração sem _overhead_. Inicialmente, Rust era um projeto pessoal de um funcionário da Mozilla, Graydon Hoare, mas logo ela acabou ganhando suporte da empresa e cresceu, para hoje ser uma das 25 linguagens mais populares, conforme pesquisa da RedMonk. A principal motivação foi a construção de uma linguagem que diminuísse ao máximo a probabilidade de erros humanos, impedindo operações que podem gerar problemas. Dentre as empresas que utilizam Rust, estão a própria Mozilla, com partes do navegador Firefox desenvolvidos nela, o Dropbox e a npm (Node Package Manager). ## Hello World O programa a seguir possui a funcionalidade de printar a mensagem "Hello World" no console. ```rust= //Isso é um comentário em linha, e não aparecerá na execução do programa. /* Esse é um comentário com várias linhas, e também não aparecerá na execução do programa. */ /* A função main sempre irá ser executada quando o compilador binário for chamado */ fn main () { println!("Hello World"); /* A função println! na realidade não é uma função, mas sim um macro. */ } ``` ## Operações básicas Há outras formas de se printar "Hello World" utilizando o macro println!, visto na seção anterior: ```rust= fn main() { println!("{}, {}!", "Hello", "world"); // Hello, world! println!("{greeting}, {name}!", greeting="Hello", name="world"); // Hello, world! println!("{0}, {1}!", "Hello", "world"); // Hello, world! } ``` É possível também printar vários argumentos sem previamente saber o tamanho que será recebido no macro: ```rust= fn main (){ println!("{:?}", [9,1,5]); // [9, 1, 5] } ``` Para separar cada elemento por linha: ```rust= fn main () { println!("{:#?}", [9,1,5]); /* Saída: [ 9, 1, 5 ] */ } ``` Como na maioria das linguagens, Rust também oferece suporte à operadores aritméticos: ```rust= let numero = 5; let soma = numero + 2; //7 let subtracao = numero - 3; //2 let multiplicacao = numero * 3; //15 let divisao = numero / 2; // 2 (pois ambos os numeros são do tipo integer) let modulo = numero % 2; //1 let divisaoFloat = 5.0 / 2.0; //2.5 (pois ambos os numeros são do tipo float) ``` Ademais, possui operadores de comparação: ```rust= let a = 1; let b = 2; let c = a != b; //true let d = a == b; //false let e = a > b; //false let f = a < b; //true let g = a <= a; //true let h = a >= a; //true let i = true > false; //true (por que? true, quando convertido para integer, tem o valor de 1, e false tem o valor de 0) let j = 'a' > 'A'; //true (pois 'a' é maior que 'A' na tabela ASCII) ``` A linguagem Rust também disponibiliza a funcionalidade de achar o valor de algo dado um padrão. Isso é chamado de Pattern Matching. O comando usado para isso é o match. Por exemplo, é possível definir ações a partir de um valor encontrado num enumerador: ```rust= //definicao do enumerador, que representa os meses do ano enum Mes { Janeiro, Fevereiro, Marco, Abril, Maio, Junho, Julho, Agosto, Setembro, Outubro, Novembro, Dezembro } ``` ```rust= match mes { Mes::Dezembro | Month::Janeiro | Month::Fevereiro => println!(“É verao :|”), Mes::Marco | Mes::Abril | Mes::Maio => println!(“É outono :)”), Mes::Junho | Mes::Julho | Mes::Agosto => println!(“É inverno :D”), Mes::Setembro | Mes::Outubro | Mes::Novembro => println!(“É primavera :)”), } ``` No bloco acima, quando o mês faz parte da estação verão, é printado uma mensagem no console dizendo que é verão. O mesmo acontece para os outros meses e suas correspondentes estações. ## Variáveis e tipos de dados Por padrão variáveis em Rust são imutáveis. Apesar disso, você ainda tem a opção de tornar as suas variáveis mutáveis. Quando uma variável é imutável, assim que um valor passa a estar vinculado ao seu nome é impossível alterá-lo. Vejamos o exemplo a seguir: ```rust= fn main() { /* Aqui é atribuído o valor 5 à variável n e logo após o seu valor é impresso na tela*/ let n = 5; println!("O valor de x é: {}", n); /* Aqui está sendo atribuído o valor 6 à variável n, no entanto, neste ponto ocorrerá erro de compilação, pois, o Rust garante que a variável seja imutável */ n = 6; } ``` No Rust, o compilador garante que quando afirmamos que um valor não mudará, ele realmente não mudará. Isso significa que, quando você está lendo e escrevendo código, não precisa acompanhar como e onde um valor pode mudar, o que pode tornar o código mais fácil de raciocinar. No entanto, embora por padrão as variáveis sejam imutáveis isso não significa que não exista a possibilidade de alterá-las. Para isso, basta adicionar o *mut* na frente do nome da variável. ```rust= fn main() { /* Aqui é atribuído o valor 5 à variável mutável n e depois é impresso seu resultado em tela */ let mut n = 5; println!("O valor de n: {}", n); /* Neste ponto é atribuído o valor 6 à variável n, diferentemente do exemplo anterior, aqui não ocorrerá erro de compilação, pois através da cláusula mut definimos que n é uma variável mutável. */ n = 6; println!("O valor de n: {}", n); } ``` ### Constantes O conceito das variáveis por padrão não serem mutáveis pode ter lembrado as *constantes*, famosas em muitas linguagens de programação. As constantes também são vinculadas a um tipo de dados e são imutáveis, mas existentes algumas diferenças com relação às simples variáveis: 1. Não é permitido utilizar mut com constantes; 2. Elas são sempre imutáveis; 3. As constantes são declaradas utilizando como palavra-chave o *const*; 4. Constantes podem somente ser definidas através de expressões e nunca através de resultados de chamadas de funções ou de qualquer outra forma que o valor seria obtido em tempo de execução; Exemplo da declaração de uma constante, onde MAX_POINTS é seu nome e seu valor é 100.000. ```rust= const MAX_POINTS: u32 = 100_000; ``` Por convenção da linguagem, constantes são declaradas tendo seu nome em letras maiúsculas e com um underline entre as plavras. ### Sombreamento Podemos declarar novas variáveis com o mesmo nome de uma variável anterior, e a nova variável faz *sombra* à variável anterior. É dito então, que a primeira variável é sombreada pela segunda, o que significa que o valor da segunda variável é o que veremos quando usamos a variável. Podemos sombrear uma variável usando o mesmo nome da variável e repetindo o uso da palavra-chave *let* da seguinte forma: ```rust= fn main() { /* Inicialmente o valor 5 é atribuído a variável n */ let n = 5; /* Em seguida, é feito sombreamento da variável n, utilizando o let, e é somado o valor n + 1. Tornando assim o valor igual a 6 */ let n = n + 1; /* Neste último let é feito mais um sombreamento, pegando o valor de n e multiplicando por 2 */ let n = n * 2; println!("O valor de n é: {}", n); } ``` Se a plavra-chave *let* não for utilizada, ocorrerá erro de compilação, como já mencionado. ### Tipos de dados O Rust é uma linguagem tipada estatisticamente , o que significa que ele deve conhecer os tipos de todas as variáveis em tempo de compilação. O compilador geralmente pode inferir o tipo que queremos usar com base no valor e em como o usamos. O Rust possui quatro tipos escalares primários: inteiros, números de ponto flutuante, booleanos e caracteres. E possui dois tipos de compostos primitivos: tuplas e matrizes. Veremos os principais tipos de dados. #### Integer Um inteiro é um número sem um componente fracionário. Os tipos inteiros podem ser declarados utilizando um indicativo informando se são assinados ou não, por exemplo, i32 indica que o inteiro deve ser assinado e u32 indica que o inteiro não precisa ser assinado, neste caso, ambos utilizam 32 bits de espaço. Um inteiro assinado *(i)* indica que aquele número deve ser sempre associado a um sinal e de maneira oposta inteiros não assinados *(u)* não precisam ser associados a nenhum sinal, sendo assim, por padrão são positivos. É como escrever números no papel: quando o sinal é importante, um número é mostrado com um sinal de mais ou um sinal de menos, no entanto, quando é seguro assumir que o número é positivo, ele é exibido sem sinal. Os números assinados são armazenados usando a representação do complemento de dois . Os tamanhos de tipos de inteiros variam entre: 8, 16, 32, 64 e 128 bits. Podendo cada um deles ser acompanhado pelo i e u. Tipos literais numéricos: 1. Decimal - 98_222 2. Hex - 0xff 3. Octal - 0o77 4. Binário - 0b1111_0000 5. Byte (u8 apenas) - b'A' Quando não tiver certeza do qual tipo utilizar, os padrões do Rust geralmente são boas escolhas, e os tipos inteiros são padrão i32: esse tipo é geralmente o mais rápido. Exemplos: ```rust= fn main() { let i = 5; let d = 98_222; let h = 0xff; ``` #### Tipos flutuantes O Rust também possui dois tipos primitivos para números de ponto flutuante, que são números com pontos decimais. Os tipos de ponto flutuante do Rust são f32 e f64, que têm 32 bits e 64 bits, respectivamente. Exemplo que mostra números de ponto flutuante: ```rust= fn main() { let x = 2.0; // f64 let y: f32 = 3.0; // f32 } ``` ### Tipo booleano Um tipo booleano no Rust possui dois valores possíveis: true e false. Os booleanos têm um byte de tamanho e em Rust é especificado usando bool. Por exemplo: ```rust= fn main() { let t = true; let f: bool = false; //com anotação de tipo explícito } ``` A principal maneira de usar valores booleanos é por meio de condicionais, como um if, por exemplo. Que será abordado mais adiante. #### Char O tipo char de Rust é o tipo alfabético mais primitivo da linguagem. Observe que os char literais são especificados com aspas simples, ao contrário dos literais de string, que usam aspas duplas. Exemplo do uso de char: ```rust= fn main() { let c = 'z'; let z = 'ℤ'; let heart_eyed_cat = '😻'; } ``` #### Strings A String é armazenado como um vetor de bytes, mas é garantido que sempre seja uma seqüência UTF-8 válida. A string é um heap alocado, expansível e não terminado em null. O primeiro tipo de string é *&'static str*. É alocado estaticamente dentro do programa compilado. ```rust= fn main() { let hello = “Hello, this is Rust &‘static str”; } ``` O segundo tipo é o tipo String dinâmico, que é alocado para heap. ```rust= fn main() { let s = “Hello, this will be String type”.to_string(); let s = String::from(“Hello, this will be String type”); ``` Criar uma nova string: ```rust= fn main() { let s = String::new(); } ``` Concatenação de strings: ```rust= fn main() { let str1 = "Hello ".to_string(); let str2 = "world!"; let concat = str1 + str2; } ``` Substring: ```rust= fn main() { /* A segunda linha abaixo retorna os primeiros 5 bytes */ let hello_world = “Hello World”; let hello = &hello_world[0..5]; println!("{}",hello); } ``` Outros métodos; ```rust= fn main() { // push e pop char / string para e da string s.push ('a'); s.push_str ("adicionado"); s.pop (); // remove char na posição de byte s.remove (3); // comprimento da string em bytes vamos strlen = s.len (); // divide a string em dois let (primeiro, último) = s.split_at (3); } ``` #### Tupla Uma tupla é uma maneira geral de agrupar alguns outros valores com uma variedade de tipos em um tipo composto. As tuplas têm um comprimento fixo: uma vez declaradas, elas não podem crescer ou diminuir de tamanho. Criamos uma tupla escrevendo uma lista de valores separados por vírgulas entre parênteses. Cada posição na tupla tem um tipo e os tipos dos diferentes valores na tupla não precisam ser os mesmos. Exemplo: ```rust= fn main() { /* Variável tup representa a tupla */ let tup: (i32, f64, u8) = (500, 6.4, 1); } ``` É possível acessar diretamente um elemento da tupla a partir o período (.) seguido pelo índice do valor que se quer acessar. Conforme exemplo: ```rust= fn main() let x: (i32, f64, u8) = (500, 6.4, 1); let five_hundred = x.0; let six_point_four = x.1; let one = x.2; } ``` #### Matriz Outra maneira de ter uma coleção de vários valores é com uma matriz . Ao contrário de uma tupla, todos os elementos de uma matriz devem ter o mesmo tipo. Os arrays em Rust tem tamanho fixo. No Rust, os valores que entram em uma matriz são gravados como uma lista separada por vírgulas entre colchetes: ```rust= fn main() { let a = [1, 2, 3, 4, 5]; let months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; /* Aqui i32 define o tipo de cada elemento. Após o ponto e vírgula, o número 5 indica que o elemento contém cinco itens. */ let a: [i32; 5] = [1, 2, 3, 4, 5]; /* O array a aconterá 5 elementos que serão todos configurados para o valor 3 inicialmente. Isso é o mesmo que escrever, let a = [3, 3, 3, 3, 3]. */ let a = [3; 5]; } ``` Uma matriz é um único bloco de memória alocado na pilha. Você pode acessar elementos de um array usando indexação: ```rust= fn main() { let a = [1, 2, 3, 4, 5]; let first = a[0]; //recebe o valor 1 que está no índice 0 let second = a[1];// recebe o valor 2 que está no índice 1 } ``` ## Estrutura da linguagem ## Controle de fluxo e iterações Uma parte importante de uma linguagem é a capacidade de lidar com os fluxos que compõem uma aplicação complexa. ### if/else Rust utiliza condicionais de forma bem parecida com linguagens como Java e C++, utilizando blocos com chaves: ```rust fn main() { let n = 5; if n < 0 { print!("{} is negative", n); } else if n > 0 { print!("{} is positive", n); } else { print!("{} is zero", n); } } ``` Uma diferença é que o bloco _if_ pode retornar um valor, que pode ser atribuído à uma variável. Digamos que, se um número é pequeno, queremos aumentar ele em 1, mas se ele for grande, queremos diminuí-lo em um e atribuir isso à uma variável. ```rust= fn main() { let n = 5; let x = if n < 10 && n > -10 { n + 1 } else { n - 1 }; //Não esquecer do ponto-e-vírgula na atribuição! println!("Novo número = {}", x); //Resultado: Novo número = 6 } ``` ### loop A estrutura _loop_ simplesmente cria uma iteração infinita, como seria um `while(true)` de outras linguagens. Para encerrar, utiliza-se a palavra-chave `break`. ```rust= fn main(){ let count = 1; loop { if count == 5 { break; } print!("{}", count); } } /*Resultado: 12345*/ ``` É possível aninhar loops, porém a palavra-chave `break` sempre acaba parando todos os loops no qual ela está contida. Para evitar isso, é possível usar etiquetas, tanto na declaração do loop quando na hora de pará-lo. ```rust= fn main() { // Declara loop com o nome "fora" 'fora: loop { println!("Entrou no loop de fora"); // Declara loop com nome "dentro" 'dentro: loop { println!("Entrou no loop de dentro"); // Parando o loop de fora break 'fora; } println!("Nunca vai chegar aqui"); } println!("Saiu do loop de fora"); } ``` Finalmente, o loop ainda pode retornar um resultado: ```rust= fn main() { let mut x = 0; let result = loop { x += 1; if x == 5 { break x; } }; print!("{}", result); // Resultado: 5 } ``` ### while O bloco _while_ possui uma sintaxe bastante comum, executando iterações até que uma certa condição seja atingida. ```rust= fn main() { let mut n = 0; while n < 3 { print!("{} ", n); n += 1; } } // Resultado: 0 1 2 ``` ### for in Para trabalhar em cima de coleções, é possível utilizar a construção _for in_, que recebe uma lista pela qual fará a iteração. Para gerar uma lista de números, por exemplo, podemos usar um _range_, especificando um número inicial e um final entre dois pontos: ```rust= fn main() { for x in 1..5 { print!("{}", x); } } // Resulado: 1234 ``` ### match A estrutura de _match_ se assemelha ao _switch_ de linguagens como C, porém apresenta uma sintaxe diferente. ```rust= fn main() { let x = 5; match x { // Um comportamento para cada valor de x 0 => println!("Zero"), 1 => println!("Um"), 2 | 3 => println!("Dois ou Três"), 4...10 => println!("De quatro a dez"), _ => println!("Outro caso") } } //Resultado: De quatro a dez ``` ## Funções Funções são declaradas utilizando a palavra-chave `fn`. Seus argumentos e retorno são tipados na declaração e o valor de retorno é a última expressão do bloco. Caso seja necessário sair da função antes do fim, pode ser usada a expressão `return`. ```rust= fn main() { let a = somaNumeros(3, 5); println! ("Soma: {}", a); //Soma: 8 } /* i8 é o tipo integer de 8 bits; a parte '-> i8' é o que especifica o tipo do retorno */ fn somaNumeros(a: i8, b: i8) -> i8 { a + b } ``` Outra funcionalidade da linguagem, existente em outras linguagens modernas como o JavaScript, é a atribuição de função para uma variável, ou seja, tornar uma variável um ponteiro para uma função. Exemplo: ```rust= fn main() { let a = somaNumeros; //atribuição da função para variável println! ("Soma: {}", a(3, 10)); //chamada da função com passagem de parâmetros } fn somaNumeros(a: i8, b: i8) -> i8 { a + b } ``` É possível também, na assinatura e passagem de parâmetros, se ter funções, não somente variáveis. ```rust= fn main() { let a = somaNumeros; println! ("Soma duas vezes: {}", somaDuasVezesNumeros(a, 10, 5)); //Soma duas vezes: 30 } fn somaNumeros(a: i8, b: i8) -> i8 { a + b } fn somaDuasVezesNumeros (funcao: fn(i8, i8) -> i8, a: i8, b: i8) -> i8 { //o primeiro parâmetro indica que está sendo esperado uma função que tenha dois integer de 8 bits como entrada, e uma saída também sendo um integer de 8 bits funcao(funcao(a, b), funcao(a,b)) } ``` ### Métodos A relação objetos/métodos em Rust é representada com um elemento _struct_ como uma definição de classe e atributos e um elemento _impl_ que contém a implementação dos métodos. ```rust= struct Retangulo { altura: f64, largura: f64 } impl Retangulo { fn area(&self) -> f64 { self.altura * self.largura } } fn main() { let retangulo = Retangulo { altura: 2.5, largura: 2.5 }; print!("Área: {}", retangulo.area()); // Resultado: Área: 6.25 } ``` ### Closures Closures são definições de função anônimas, suportadas pela linguagem Rust, permitindo declarar execuções de funções, porém executá-las apenas no momento desejado. Essas funções possuem uma sintaxe diferente e podem capturar valores dos seus arredores. Esse tipo de função pode fazer inferência de tipos e então declarar operações com uma sintaxe menos verbosa. ```rust= fn main() { let x = 4; // Nesse caso, o valor passado entre pipes é o parâmetro da função, // É feita uma comparação com o valor de X, que não está declarado dentro da função, // mas sim nos seus "arredores". let igual_a_x = |z| z == x; let y = 4; println!("{}", igual_a_x(y)); } ``` ### Funções de ordem superior Rust, em seu caráter funcional, permite funções de ordem superior, que retornam outras funções ou recebem funções por parâmetro. Com isso, podemos utilizá-la de forma funcional para realizar diversas operações. ```rust= fn main() { let limite = 10; let soma_dos_quadrados_pares: u32 = (0..).map(|n| n * n) // Recebe uma sequência de números e coloca cada um ao quadrado .take_while(|&n_squared| n_squared < limite) // Seleciona apenas até o limite .filter(|&n_squared| n_squared % 2 == 1) // Filtra apenas os pares .fold(0, |acc, n_squared| acc + n_squared); // Soma println!("{}", soma_dos_quadrados_pares); } ``` ## Programação concorrente no Rust Para entender como a linguagem Rust oferece e facilita o desenvolvimento da programação concorrente, é necessário entender o conceito desse paradigma. Programação concorrente trata do cenário em que duas tarefas do sistema (thread) podem começar, rodar, e completar seu processamento numa mesma fatia de tempo. Isso não significa que elas irão rodar simultaneamente, nem que terminarão no mesmo tempo, mas que serão processadas pouco a pouco de forma que uma não esperará o término da outra pra começar o processamento. Rust oferece suporte a isso através de sua biblioteca padrão (std). ### Spawn O método spawn aceita um closure (explicado na seção anterior), e faz com que esse código seja executado numa nova thread: ```rust= use std::thread; fn main() { thread::spawn(|| { println!("Hello World de uma nova Thread!"); }); } ``` É possível passar valores de variáveis de uma thread para outra, através do closure move: ```rust= use std::thread; fn main() { let x = 5; thread::spawn(move || { //passando valor de x para a nova thread println!("Valor de x: {}", x); }); } ``` ### Consistência de dados entre Threads Um dos grandes problemas encontrados na programação concorrente, é a consistência de dados que estão compartilhados entre Threads. Para isso, a linguagem Rust fornece um conjunto de tipos para fazer o manuseio desses dados, garantindo a consistência entre eles. A linguagem por si só já oferece mecanismos de segurança, que previnem em tempo de compilação, a inconsistência de dados entre threads. Portanto, o código seguinte irá falhar logo no processo de compilação: ```rust= use std::thread; use std::time::Duration; fn main() { let mut data = vec![1, 2, 3]; for i in 0..3 { thread::spawn(move || { data[0] += i; }); } thread::sleep(Duration::from_millis(50)); } ``` O primeiro comando importante é o método clone, que retorna uma nova referência para um objeto. Entretanto, isso não garante a consistência, pois o valor original ainda pode ser alterado sem uma consistência entre as Threads. O seguinte código também irá falhar em compilação: ```rust= use std::thread; use std::time::Duration; use std::rc::Rc; fn main() { let mut data = Rc::new(vec![1, 2, 3]); for i in 0..3 { // Create a new owned reference: let data_ref = data.clone(); // Use it in a thread: thread::spawn(move || { data_ref[0] += i; }); } thread::sleep(Duration::from_millis(50)); } ``` O segundo passo importante, é a utilização do tipo Arc<T>, que garante a segurança de acesso por múltiplas Threads. Mas, isso também não é suficiente para garantir a consistência, pois o tipo Arc não permite a mutabilidade dos dados, apesar de permitir compartilhar. Portanto, o código irá falhar em sua compilação: ```rust= use std::thread; use std::sync::Arc; use std::time::Duration; fn main() { let mut data = Arc::new(vec![1, 2, 3]); for i in 0..3 { let data = data.clone(); thread::spawn(move || { data[0] += i; }); } thread::sleep(Duration::from_millis(50)); } ``` Por fim, para resolver o problema, o tipo de dados Mutex<T> contém uma abstração que garante que apenas uma thread por vez é capaz de mudar o valor de uma variável compartilhada. O código final, permitindo uma concorrência segura entre as threads: ```rust= use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; fn main() { let data = Arc::new(Mutex::new(vec![1, 2, 3])); for i in 0..3 { let data = data.clone(); thread::spawn(move || { let mut data = data.lock().unwrap(); data[0] += i; }); } thread::sleep(Duration::from_millis(50)); } ``` De uma forma simples, entendendo os tipos que a linguagem oferece, é possível extrair um grande poder de processamento dos computadores, solucionando um dos grandes problemas enfrentados na programação atualmente que é a programação concorrente. ## Bibliotecas ### Reqwest Essa biblioteca encapsula funções para comunicação pela web com o protocolo HTTP. A sua API é bastante simples e permite fazer requisições de forma pouco verbosa. ```rust= let body = reqwest::get("https://www.rust-lang.org")? .text()?; println!("body = {:?}", body); ``` ### Regex Biblioteca para utilização de expressões regulares em Rust, que não são suportadas nativamente. ```rust= use regex::Regex; fn main() { let re = Regex::new(r"(?x) (?P<year>\d{4}) # the year - (?P<month>\d{2}) # the month - (?P<day>\d{2}) # the day ").unwrap(); let caps = re.captures("2010-03-14").unwrap(); assert_eq!("2010", &caps["year"]); assert_eq!("03", &caps["month"]); assert_eq!("14", &caps["day"]); } ``` ## Conclusão Programar é difícil. Por mais que tenhamos um sistema completamente coberto por testes, sempre acabamos nos deparando com problemas que não estavam previstos, _edge_ cases, etc. Rust se tornou popular não só por possuir uma comunidade ativa e receptiva, mas por possuir um compilador extremamente "chato", que checa desde erros de sintaxe até gerenciamento de memória, evitando ao máximo problemas que acontecem apenas em tempo de execução. Em um mundo em que basicamente tudo passa por sistemas, evitar erros é a chave para o sucesso e Rust ajuda muito nesse aspecto. Se você deseja se aprofundar nessa linguagem, o site do Rust é a melhor porta de entrada: https://www.rust-lang.org/learn ## Referências https://medium.com/learning-rust/rust-basics-e73304ab35c7 https://doc.rust-lang.org/stable/rust-by-example/ https://doc.rust-lang.org/std/string/struct.String.html https://doc.rust-lang.org/1.30.0/book/first-edition/concurrency.html

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully