Uma introdução ao sistema de tipos de Rust
Python Brasil - 2016 - #pybr12
Olá!
- Engenheira da Computação
- Programação
- Eletrônica
- Matemática
- Física
- Lego
- Meetups
- Bichinhos
- Café
- Pokémon
- GIFs
#pybr12 @hannelita
Atenção
Isso não é um tutorial de introdução ao Rust
Teoria
Alguns tópicos podem gerar discussões. Opiniões pessoais nos slides
GIFs :)
Atenção
Ao final dos slides há um material de referência para introdução à linguagem
Agenda
- Escolhendo uma linguagem de programação
- Introdução aos tipos
- Por que Rust é interessante
- Visão geral da estrutura de Rust
- Borrow
- Lifetime
- Sobre segurança de tipos em Rust
- Os pontos fracos de Rust
#pybr12 @hannelita
Como você escolhe uma linguagem de programação?
#pybr12 @hannelita
- Por causa da empresa
- Por ser popular
- Por causa do seu time
- Por causa da data para entregar o projeto
- Objetivo do projeto
- Ferramentas disponíveis
- Única linguagem que aprendi na faculdade
- Alguém me recomendou esta linguagem
- Sei lá :P
#pybr12 @hannelita
Com que frequência você considera os itens a seguir para escolher uma linguagem?
- Sistema de Tipos
- Imutabilidade
- Evitar erros em tempo de execução
- Paradigma
- Verbosidade
- Gerenciamento de memória
#pybr12 @hannelita
Péra - O que é um sistema de tipos?
De acordo com a Wikipedia:
"In programming languages, a type system is a collection of rules that assign a property called type to various constructs a computer program consists of"
#pybr12 @hannelita
Agenda
#pybr12 @hannelita
- Escolhendo uma linguagem de programação
- Introdução aos tipos
- Por que Rust é interessante
- Visão geral da estrutura de Rust
- Borrow
- Lifetime
- Sobre segurança de tipos em Rust
- Os pontos fracos de Rust
Péra - O que é um sistema de tipos?
#pybr12 @hannelita
Em todas as linguagens de programação, até mesmo em Assembly, possuímos dois componentes:
Dados
Operações
Nem todas as operações disponíveis fazem sentido para todos os tipos de dados
#pybr12 @hannelita
Se você usar partes incompatíveis de dados em uma operação, você terá um erro de representação.
#pybr12 @hannelita
Linguagens de programação usam um sistema de tipos para analisar um programa e determinar se um erro de representação ocorrerá ou não.
#pybr12 @hannelita
Quais são as estratégias possíveis que um sistema de tipos pode usar para tratar esses erros de representação?
#pybr12 @hannelita
Strategies
- Gerar um erro de compilação
- Checar os tipos antes de executar o código
- Definir um conjunto fechado de erros que podem ser lançados
- Erros de execução imprevisíveis
- Conversão implícita para ajustar os tipos
- O compilador rotula trechos de código e tenta inferir se o comportamento será válido ou não (antes da execução do programa)
- O compilador ou interpretador gera código para rastrear os dados
#pybr12 @hannelita
Strategies
- Gerar um erro de compilação
- Checar os tipos antes de executar o código
- Definir um conjunto fechado de erros que podem ser lançados
- Erros de execução imprevisíveis
- Conversão implícita para ajustar os tipos
- O compilador rotula trechos de código e tenta inferir se o comportamento será válido ou não (antes da execução do programa)
- O compilador ou interpretador gera código para rastrear os dados
"Strong"
"Weak"
"Static"
"Dynamic"
*As definições não são exatas na literatura
Strategies
- Generate a compile error
- Perform a type check before run the code
- Well defined error set
- Erros de execução imprevisíveis
- Conversão implícita para ajustar os tipos
- O compilador rotula trechos de código e tenta inferir se o comportamento será válido ou não (antes da execução do programa)
- O compilador ou interpretador gera código para rastrear os dados
"Strong"
"Weak"
"Static"
"Dynamic"
- Não tratar/ não fazer nada
"Untyped"
Você não precisa escolher uma única alternativa.
Python: strong (os tipos não são alterados pelo interpretador) e dynamic (O interpretador rastreia os dados)
#pybr12 @hannelita
Uma estratégia para reduzir os erros é adotar um sistema de tipos static e strong
#pybr12 @hannelita
Java se encaixa em partes nessa descrição
Java pode causar problemas por conta do GC (coletor de lixo)
#pybr12 @hannelita
Usar C ou C++
Não há consenso se é weak ou strong
#pybr12 @hannelita
Rust vem para o resgate!
#pybr12 @hannelita
Agenda
#pybr12 @hannelita
- Escolhendo uma linguagem de programação
- Introdução aos tipos
- Por que Rust é interessante
- Visão geral da estrutura de Rust
- Borrow
- Lifetime
- Sobre segurança de tipos em Rust
- Os pontos fracos de Rust
Rust - funcionalidades
- Memory safe, data race free
- O compilador previne diversos erros em tempo de execução
- Interface com C/C++
- Generics
- Polimorfismo
- Mantido pela Mozilla e por uma grande comunidade
#pybr12 @hannelita
Rust - funcionalidades
- Sem GC
- Sem alocação manual de memória (malloc/free)
- Sem seg faults
#pybr12 @hannelita
Agenda
#pybr12 @hannelita
- Escolhendo uma linguagem de programação
- Introdução aos tipos
- Por que Rust é interessante
- Visão geral da estrutura de Rust
- Borrow
- Lifetime
- Sobre segurança de tipos em Rust
- Os pontos fracos de Rust
Visão geral de Rust
fn main() {
fizzbuzz_to(100);
}
fn is_divisible_by(lhs: u32, rhs: u32) -> bool {
if rhs == 0 {
return false;
}
lhs % rhs == 0
}
fn fizzbuzz(n: u32) -> () {
if is_divisible_by(n, 15) {
println!("fizzbuzz");
} else if is_divisible_by(n, 3) {
println!("fizz");
} else if is_divisible_by(n, 5) {
println!("buzz");
} else {
println!("{}", n);
}
}
fn fizzbuzz_to(n: u32) {
for n in 1..n + 1 {
fizzbuzz(n);
}
}
source: http://rustbyexample.com/fn.html
Inferência de tipos limitada. Declaração de tipos explícita para parâmetros e tipo de retorno de uma função.
Macros
Visão geral de Rust
fn main() {
let _immutable_binding = 1;
let mut mutable_binding = 1;
println!("Before mutation: {}", mutable_binding);
// Ok
mutable_binding += 1;
println!("After mutation: {}", mutable_binding);
// Error!
_immutable_binding += 1;
// FIXME ^ Comment out this line
}
source: http://rustbyexample.com/variable_bindings/mut.html
Imutabilidade por padrão
Visão Geral de Rust
fn is_odd(n: u32) -> bool {
n % 2 == 1
}
fn main() {
println!("Find the sum of all the squared odd numbers under 1000");
let upper = 1000;
let mut acc = 0;
for n in 0.. {
let n_squared = n * n;
if n_squared >= upper {
break;
} else if is_odd(n_squared) {
acc += n_squared;
}
}
println!("imperative style: {}", acc);
let sum_of_squared_odd_numbers: u32 =
(0..).map(|n| n * n) // All natural numbers squared
.take_while(|&n| n < upper) // Below upper limit
.filter(|n| is_odd(*n)) // That are odd
.fold(0, |sum, i| sum + i); // Sum them
println!("functional style: {}", sum_of_squared_odd_numbers);
}
source: http://rustbyexample.com/fn/hof.html
High
Order
Functions
Outras funcionalidades - Tuples, Enums, Structures, Traits.
#pybr12 @hannelita
Como se livrar de seg faults?
#pybr12 @hannelita
Agenda
#pybr12 @hannelita
- Escolhendo uma linguagem de programação
- Introdução aos tipos
- Por que Rust é interessante
- Visão geral da estrutura de Rust
- Borrow
- Lifetime
- Sobre segurança de tipos em Rust
- Os pontos fracos de Rust
Variable bindings possuem (own) os valores em Rust
fn foo() {
let v = vec![1, 2, 3];
let v2 = v;
println!("v[0] is: {}", v[0]);
}
#pybr12 @hannelita
Variable bindings possuem (own) os valores em Rust
fn foo() {
let v = vec![1, 2, 3];
let v2 = v;
println!("v[0] is: {}", v[0]);
}
O compilador de Rust reclama: "error: use of moved value: `v` println!("v[0] is: {}", v[0]);"
O quê?
#pybr12 @hannelita
Isso pode soar pouco prático, mas ajuda a previnir diversos erros em tempo de execução.
#pybr12 @hannelita
Rust permite que alguns valores sejam partilhados através de uma funcionalidade chamada 'borrowing'
#pybr12 @hannelita
fn main() {
fn sum_vec(v: &Vec<i32>) -> i32 {
return v.iter().fold(0, |a, &b| a + b);
}
fn foo(v1: &Vec<i32>, v2: &Vec<i32>) -> i32 {
let s1 = sum_vec(v1);
let s2 = sum_vec(v2);
s1 + s2
}
let v1 = vec![1, 2, 3];
let v2 = vec![4, 5, 6];
let answer = foo(&v1, &v2);
println!("{}", answer);
}
Borrowing
&
#pybr12 @hannelita
Muito similar a estratégia de "Read-Writers Lock"
- Muitos readers de uma vez OU um único writer com acesso exclusivo
- Read only não requer acesso exclusivo
- Acesso exclusivo não permite outros readers
(More info: https://users.cs.duke.edu/~chase/cps210-archive/slides/moresync6.pdf )
Rust usa um modelo similar em tempo de compilação.
Muito similar a estratégia de "Read-Writers Lock"
- Muitos readers de uma vez OU um único writer com acesso exclusivo
- Read only não requer acesso exclusivo
- Acesso exclusivo não permite outros readers
Rust usa um modelo similar em tempo de compilação.
T: Base type; possui um valor
&T: Reader compartilhado
&mut T: Writer exclusivo
(Note: Não estou considerando a feature de Copy nesses slides!)
Muito similar a estratégia de "Read-Writers Lock"
- Muitos readers de uma vez OU um único writer com acesso exclusivo
- Read only não requer acesso exclusivo
- Acesso exclusivo não permite outros readers
Rust usa um modelo similar em tempo de compilação.
T: Base type; possui um valor
&T: Reader compartilhado
&mut T: Writer exclusivo
(Note: Não estou considerando a feature de Copy nesses slides!)
Referência imutável
Referência mutável
Alguns problemas que o borrowing previne:
- Iteradores inválidos
- Problemas com Data race
- Utilizar um valor após o free
#pybr12 @hannelita
Falando nisso, como performar um free em uma variável em Rust? Não há GC; como limpo a memória?
#pybr12 @hannelita
Péra, eu também não poderia bagunçar a técnica de borrowing se eu liberasse uma variável que está emprestada?
#pybr12 @hannelita
#pybr12 @hannelita
Não precisamos lidar com isso manualmente. Pelo menos não de forma explícita :)
#pybr12 @hannelita
#pybr12 @hannelita
Agenda
#pybr12 @hannelita
- Escolhendo uma linguagem de programação
- Introdução aos tipos
- Por que Rust é interessante
- Visão geral da estrutura de Rust
- Borrow
- Lifetime
- Sobre segurança de tipos em Rust
- Os pontos fracos de Rust
Em Rust, cada referência possui um lifetime (tempo de vida) associado.
fn lifetimes() {
let a1 = vec![1, 2, 3]; // +
let a2 = vec![4, 5, 6]; // + |
// | |
let b1 = &a1; // + | |
let b2 = &a2; // + | | |
foo(b1); // | | | |
foo(b2); // 'b2 'b1 'a2 'a1
// | | | |
}
#pybr12 @hannelita
Você pode explicitar os lifetimes em Rust
fn explicit_lifetime<'a>(x: &'a i32) {
}
Ou até mesmo múltiplos lifetimes
fn multiple_lifetimes<'a, 'b>(x: &'a str, y: &'b str) -> &'a str {
}
#pybr12 @hannelita
Ao final de um lifetime, ocorrerá um free.
#pybr12 @hannelita
- GC não é necessário
- Mecanismo para evitar dangling pointers
- malloc e free não são necessários manualmente
Alguns problemas que o sistema de lifetime ajuda a prevenir:
#pybr12 @hannelita
Ok, então Rust é sempre seguro em termos de memória?
#pybr12 @hannelita
Agenda
#pybr12 @hannelita
- Escolhendo uma linguagem de programação
- Introdução aos tipos
- Por que Rust é interessante
- Visão geral da estrutura de Rust
- Borrow
- Lifetime
- Sobre segurança de tipos em Rust
- Os pontos fracos de Rust
Rust é seguro não somente devido ao borrowing e ao lifetime
#pybr12 @hannelita
Rust possui um bom sistema de tipos genéricos, Traits e Closures
http://huonw.github.io/blog/2015/05/finding-closure-in-rust/
#pybr12 @hannelita
É possível invocar código C/C++ a partir do Rust. Mas C/C++ não garante a mesma segurança de alocação de memória.
#pybr12 @hannelita
unsafe
fn main() {
let u: &[u8] = &[49, 50, 51];
unsafe {
assert!(u == std::mem::transmute::<&str, &[u8]>("123"));
}
}
#pybr12 @hannelita
Chamadas explícitas com unsafe.
#pybr12 @hannelita
Rust é perfeito?
#pybr12 @hannelita
Agenda
#pybr12 @hannelita
- Escolhendo uma linguagem de programação
- Introdução aos tipos
- Por que Rust é interessante
- Visão geral da estrutura de Rust
- Borrow
- Lifetime
- Sobre segurança de tipos em Rust
- Os pontos fracos de Rust
Reclamações sobre Rust
- Curva de aprendizado é um pocuo lenta
- Muitos conceitos novos
- Linguagem relativamente nova no mercado
#pybr12 @hannelita
Reclamações sobre Rust
- Curva de aprendizado é um pocuo lenta
- Muitos conceitos novos
- Linguagem relativamente nova no mercado
Respostas de Rust para resolver os problemas
- Documentação rica e recusros de aprendizagem
- A comunidade é ativa e amigável
- A comunidade tem construído diversas ferramentas e bibliotecas para enriquecer os recursos disponíveis.
#pybr12 @hannelita
Bônus #1: Pergunta final - qual é o sistema de tipos de Rust?
#pybr12 @hannelita
Resposta: Aproximamos para e strong. Há um projeto de pesquisa para descrever o sistema de tipos de Rust:
https://www.ralfj.de/blog/2015/10/12/formalizing-rust.html
#pybr12 @hannelita
Bônus #2
O tópico sobre sistema de tipos é interessante! Quais são os próximos passos para se aprofundar?
Resposta: Lambda Calculus e Type Theory :)
#pybr12 @hannelita
http://slides.com/hannelitavante-hannelita/type-theory-101-35#/
Bônus #3
Free GIF!
Referências
- https://www.youtube.com/watch?v=Q7lQCgnNWU0
- https://www.quora.com/Why-do-programming-languages-use-type-systems
- http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html
- http://lucacardelli.name/papers/typesystems.pdf
- https://www.ralfj.de/blog/2015/10/12/formalizing-rust.html
- http://jadpole.github.io/rust/type-system
- https://wiki.haskell.org/Typing
- https://gist.github.com/Kimundi/8391398
- https://www.smashingmagazine.com/2013/04/introduction-to-programming-type-systems/
(Alguns desses links não são muito científicos)
Referências - Introdução ao Rust
- https://doc.rust-lang.org/book/
- https://doc.rust-lang.org/reference.html
- https://doc.rust-lang.org/nomicon/
-
Rust e Pokémons - http://slides.com/hannelitavante-hannelita/rust-and-pokmons#/
Agradecimentos especiais
- Comunidade de Rust e Rust SP - https://www.meetup.com/Rust-Sao-Paulo-Meetup/ e @bltavares
- B.C., pela revisão constante
- @ramalhoorg
- Time da Python Brasil
Obrigada :)
Perguntas?
hannelita@gmail.com
@hannelita
Python Brasil 12 - Rust Type system (PT-BR)
By Hanneli Tavante (hannelita)
Python Brasil 12 - Rust Type system (PT-BR)
- 2,071