Browse Source

Merge branch 'release/20190415'

master
Julio Biason 5 years ago
parent
commit
fef7acb79c
  1. 538
      porque-rust.html

538
porque-rust.html

@ -74,7 +74,7 @@
<div class="slides">
<section>
<section data-background="_images/rust-ferris.png" data-header>
<h1 class="semi-opaque">Porque Rust</h1>
<h2 class="semi-opaque">Porque Rust</h2>
</section>
</section>
@ -103,69 +103,69 @@
<p class="fragment">... pelo 4⁰ ano seguido.</p>
<aside class="notes">
O resultado do StackOverflow é sobre qual
linguagem os programadores realmente gostam de
programar (e quais eles tem pavor de usar).
<aside class="notes">
O resultado do StackOverflow é sobre qual
linguagem os programadores realmente gostam de
programar (e quais eles tem pavor de usar).
Pessoalmente, depois de 30 anos programando,
quando começei a brincar com Rust, eu
finalmente me diverti enquanto programava.
</aside>
Pessoalmente, depois de 30 anos programando,
quando começei a brincar com Rust, eu
finalmente me diverti enquanto programava.
</aside>
</p>
</section>
</section>
<section>
<section>
<h2>"Low Level Language with High Level Abstractions"</h2>
</section>
<section>
<p>Resultado final com performance semelhante ao C...</p>
<img src="_images/rust-energy.png" alt="">
<aside class="notes">
Num estudo sobre quais linguagens consomem mais
energia, Rust chegou bem próximo de C.
Parte do trabalho de otimização do Rust vem da LLVM
(parte do pacote do Clang), mas a árvore de
abstração ainda é gerada pela linguagem -- o que
significa que o compilador Rust consegue "ajudar" o
LLVM a otimizar o código.
</aside>
</section>
<section>
<p>... mas com abstrações em algo nível</p>
<ul>
<li>Strings sem tamanho fixo</li>
<li>Listas</li>
<li>Mapas</li>
</ul>
<aside class="notes">
Ao contrário de C, em que só se mexe com ponteiros
pra cima e pra baixo, Rust tem todas as abstrações
de alto nível que estamos acostumados com outras
linguagens.
</aside>
</section>
</section>
<section>
<section>
<h2>"Low Level Language with High Level Abstractions"</h2>
</section>
<section>
<p>Resultado final com performance semelhante ao C...</p>
<img src="_images/rust-energy.png" alt="">
<aside class="notes">
Num estudo sobre quais linguagens consomem mais
energia, Rust chegou bem próximo de C.
Parte do trabalho de otimização do Rust vem da LLVM
(parte do pacote do Clang), mas a árvore de
abstração ainda é gerada pela linguagem -- o que
significa que o compilador Rust consegue "ajudar" o
LLVM a otimizar o código.
</aside>
</section>
<section>
<p>... mas com abstrações em algo nível</p>
<ul>
<li>Strings sem tamanho fixo</li>
<li>Listas</li>
<li>Mapas</li>
</ul>
<aside class="notes">
Ao contrário de C, em que só se mexe com ponteiros
pra cima e pra baixo, Rust tem todas as abstrações
de alto nível que estamos acostumados com outras
linguagens.
</aside>
</section>
</section>
<section>
<section>
<h2>Imutabilidade por Default</h2>
<aside class="notes">
Por que "imutabilidade" seria algo importante?
Imutabilidade muda a forma como pensamos nos dados,
e evita que o estado fique mudando quando não
queremos.
</aside>
<aside class="notes">
Por que "imutabilidade" seria algo importante?
Imutabilidade muda a forma como pensamos nos dados,
e evita que o estado fique mudando quando não
queremos.
</aside>
</section>
<section>
@ -189,10 +189,10 @@ fn main() {
| ^^^^^ cannot assign twice to immutable variable
</code></pre>
<aside class="notes">
Se você tentar mudar um dado depois de criado, o
compilador Rust não vai deixar.
</aside>
<aside class="notes">
Se você tentar mudar um dado depois de criado, o
compilador Rust não vai deixar.
</aside>
</section>
<section>
@ -204,13 +204,13 @@ fn main() {
}
</code></pre>
<aside class="notes">
... a não ser que você transforme sua variável em mutável.
<aside class="notes">
... a não ser que você transforme sua variável em mutável.
Ainda, Rust tem funcionalidades para facilitar
copiar dados de um lado para o outro (como o
"spread operator" em structs).
</aside>
Ainda, Rust tem funcionalidades para facilitar
copiar dados de um lado para o outro (como o
"spread operator" em structs).
</aside>
</section>
</section>
@ -218,14 +218,14 @@ fn main() {
<section>
<h2>Borrow Checker</h2>
<aside class="notes">
O "Borrow Checker" é uma das principais novidades
do Rust em comparação com outras linguagens.
<aside class="notes">
O "Borrow Checker" é uma das principais novidades
do Rust em comparação com outras linguagens.
Ele basicamente controla como as variáveis vão ser
alocadas, quando serão desalocadas, quem pode
acessar o conteúdo da mesma e assim por diante.
</aside>
Ele basicamente controla como as variáveis vão ser
alocadas, quando serão desalocadas, quem pode
acessar o conteúdo da mesma e assim por diante.
</aside>
</section>
<section>
@ -237,11 +237,11 @@ a = String::from("hello");
<section>
"Variável <code>a</code> tem o valor <code>"hello"</code>"
<aside class="notes">
Em todas as linguagens que eu usei, sempre que via
uma atribuição, eu pensava "a variável X tem o
valor Y" -- mesmo em C.
</aside>
<aside class="notes">
Em todas as linguagens que eu usei, sempre que via
uma atribuição, eu pensava "a variável X tem o
valor Y" -- mesmo em C.
</aside>
</section>
<section>
@ -255,24 +255,24 @@ a = String::from("hello");
</code></pre>
</div>
<aside class="notes">
Nunca uma linguagem me fez "despensar" no nome da
variável pra pensar que ela representa, na verdade,
uma posição de memória.
</aside>
</section>
<aside class="notes">
Nunca uma linguagem me fez "despensar" no nome da
variável pra pensar que ela representa, na verdade,
uma posição de memória.
</aside>
</section>
<section>
<section>
<img src="_images/rust-memory.png" alt="" class="stretch">
<aside class="notes">
É mais ou menos isso que Rust "pensa" internamente
quando vê uma variável: uma posição de memória, de
um tamanho já definido, de um tipo definido.
<aside class="notes">
É mais ou menos isso que Rust "pensa" internamente
quando vê uma variável: uma posição de memória, de
um tamanho já definido, de um tipo definido.
E essa posição de memória *pertence* apenas à
variável indicada.
</aside>
E essa posição de memória *pertence* apenas à
variável indicada.
</aside>
</section>
<section>
@ -306,16 +306,18 @@ error[E0382]: borrow of moved value: `a`
5 | println!("{}", a)
| ^ value borrowed here after move
|
= note: move occurs because `a` has type `std::string::String`, which does not implement the `Copy` trait
= note: move occurs because `a` has type
`std::string::String`, which does not
implement the `Copy` trait
</code></pre>
<aside class="notes">
O borrow checked não deixa a variável "a" ser
utilizada: quando a atribuímos "_b" o valor de "a",
o que estamos fazendo é indicando que aquela
posição de memória agora é controlada por "_b" e
não mais por "a".
</aside>
<aside class="notes">
O borrow checked não deixa a variável "a" ser
utilizada: quando a atribuímos "_b" o valor de "a",
o que estamos fazendo é indicando que aquela
posição de memória agora é controlada por "_b" e
não mais por "a".
</aside>
</section>
<section>
@ -323,9 +325,9 @@ error[E0382]: borrow of moved value: `a`
<h3 class="fragment">References</h3>
<aside class="notes">
Assim como C++, Rust tem o conceito de "referências".
</aside>
<aside class="notes">
Assim como C++, Rust tem o conceito de "referências".
</aside>
</section>
<section>
@ -341,10 +343,10 @@ fn main() {
<section>
<img src="_images/rust-reference.png" alt="" class="stretch">
<aside class="notes">
Uma referência nada mais é que um ponteiro para um
"controlador" de uma região de memória.
</aside>
<aside class="notes">
Uma referência nada mais é que um ponteiro para um
"controlador" de uma região de memória.
</aside>
</section>
<section>
@ -354,39 +356,44 @@ fn main() {
Uma região de memória tem apenas um dono.
</p>
<p class="fragment">
Passar um valor (região de memória) de uma variável
para outra, troca o dono.
</p>
<p class="fragment">
A região é desalocada quando o dono sair de escopo.
</p>
<aside class="notes">
Uma coisa engraçada sobre "quando sair de escopo" é
que existe uma função semelhante ao "free()" do C,
chamada "drop". Essa função não tem nada no corpo,
e recebe um parâmetro (sem ser por referência), se
tornando a dona da memória; assim, como ela termina
exatamente naquele ponto, a região de memória é
liberada.
</aside>
<aside class="notes">
Uma coisa engraçada sobre "quando sair de escopo" é
que existe uma função semelhante ao "free()" do C,
chamada "drop". Essa função não tem nada no corpo,
e recebe um parâmetro (sem ser por referência), se
tornando a dona da memória; assim, como ela termina
exatamente naquele ponto, a região de memória é
liberada.
</aside>
</section>
<section>
<h3>Regras do Borrow Checker</h3>
<p class="fragment">
Uma região de memória pode ter inifitas referências.
Uma região de memória pode ter infinitas referências.
</p>
<p class="fragment">
... desde que elas não durem mais do que o dono.
</p>
<aside class="notes">
Não é possível ter uma função que cria uma variável
e retorna apenas uma referência para essa variável:
no momento que a função for encerrada, ela irá
levar todas as variáveis com ela e as referências
se tornaram inválidas.
</aside>
<aside class="notes">
Não é possível ter uma função que cria uma variável
e retorna apenas uma referência para essa variável:
no momento que a função for encerrada, ela irá
levar todas as variáveis com ela e as referências
se tornaram inválidas.
</aside>
</section>
<section>
@ -405,9 +412,9 @@ fn main() {
<section>
<img src="_images/dunno.jpg" alt="">
<aside class="notes">
E o que isso ajuda, no final das contas?
</aside>
<aside class="notes">
E o que isso ajuda, no final das contas?
</aside>
</section>
<section data-transition="fade">
@ -415,11 +422,11 @@ fn main() {
canal &lt;- presente
&nbsp;</code></pre>
<aside class="notes">
Num exemplo em Go, criamos uma estrutura e passamos
essa estrutura para outra thread através de um
canal.
</aside>
<aside class="notes">
Num exemplo em Go, criamos uma estrutura e passamos
essa estrutura para outra thread através de um
canal.
</aside>
</section>
<section data-transition="fade">
@ -427,129 +434,112 @@ canal &lt;- presente
canal &lt;- presente
presente.abrir()</code></pre>
<aside class="notes">
... e depois de passar o presente pra outra pessoa,
nós abrimos o presente.
<aside class="notes">
... e depois de passar o presente pra outra pessoa,
nós abrimos o presente.
Mas se estamos entregando um presente pra alguém,
como é que estamos abrindo o presente?
Mas se estamos entregando um presente pra alguém,
como é que estamos abrindo o presente?
O borrow checker não permite esse tipo de coisa:
Ele irá barrar a função atual de continuar
utilizando a variável porque, afinal de contas,
agora a região de memória pertence à outra função
(uma função que está rodando em outra thread).
</aside>
O borrow checker não permite esse tipo de coisa:
Ele irá barrar a função atual de continuar
utilizando a variável porque, afinal de contas,
agora a região de memória pertence à outra função
(uma função que está rodando em outra thread).
</aside>
</section>
<section>
<h2>E GC?</h2>
<section>
<h2>E GC?</h2>
<p class="fragment">GC não é determinístico.</p>
<p class="fragment">GC não é determinístico.</p>
<aside class="notes">
Um problema com GC é que ele é não determinístico:
uma hora o teu código roda rápido e outro momento
ele fica lento, sem que tu consiga entender o
porque.
<aside class="notes">
Um problema com GC é que ele é não determinístico:
uma hora o teu código roda rápido e outro momento
ele fica lento, sem que tu consiga entender o
porque.
Sem GC, a execução do código torna-se determinística e
tu pode ter certeza da velocidade de execução.
</aside>
</section>
Sem GC, a execução do código torna-se determinística e
tu pode ter certeza da velocidade de execução.
</aside>
</section>
<section>
<a href="https://swift.org/blog/swift-5-exclusivity/">Swift 5 Exclusivity Enforcement</a>
<aside class="notes">
A ideia do borrow checker é tão interessante que
até o Swift 5 agora tem o seu próprio borrow
checker (com outro nome, mas o princípio da coisa é
basicamente o mesmo, apesar de ser um pouco mais
leve no Swift).
</aside>
<aside class="notes">
A ideia do borrow checker é tão interessante que
até o Swift 5 agora tem o seu próprio borrow
checker (com outro nome, mas o princípio da coisa é
basicamente o mesmo, apesar de ser um pouco mais
leve no Swift).
</aside>
</section>
</section>
<section>
<section>
<h2>Hora da anedota!</h2>
<img class="stretch" src="_images/senta-que-la-vem-historia.gif" alt="">
</section>
<section>
<p>localtime</p>
<p class="fragment">SimpleDateFormatter</p>
<aside class="notes">
A muito tempo atrás, eu estava ajudando uma colega
a resolver um problema com processamento de eventos
num projeto em C. Aparentemente, quando um evento
era processado, acontecia do tempo de processamento
ficar errado (algo como ficar negativo ou levar
menos de 10ms pra fazer uma query num banco
oracle). Quando perguntei como ela estava
calculando o tempo, ela me falou que estava usando
o "localtime". Foi quando me lembrei que
"localtime" não é thread-safe e, por isso, quando
uma thread passava pela chamada da função, o valor
era "resetado".
Outra situação aconteceu recentemente: Num projeto
Java, começou a acontecer de, em alguns casos, a
função que convertia strings para Date começou a
dar resultados completamente errados.
Estranhamente, eu lembrei da questão do localtime e
perguntei se o projeto usava threads: sim; fui
direto no DuckDuckGo e procurei por
"simpledateformatter thread safe" e o primeiro
resultado foi uma pergunta do StackOverflow: "Why
isn't SimpleDateFormatter thread-safe?"
</aside>
</section>
<section>
<h3>Rust resolveria isso?</h3>
<h2 class="fragment">Não</h2>
<h4 class="fragment">... na verdade, nem ia compilar.</h4>
<aside class="notes">
Uma questão importante para o Rust são "Zero Cost
Abstractions", segundo a definição do Bjarne
Stroustrup, criado do C++: para que algo seja
aceito no compilador, é preciso que o custo de não
usar algo não acarrete nada; ou seja, tornar uma
função thread-safe simplesmente inserindo um mutex,
não é zero cost porque, se tu não estiver usando
threads, não faz sentido o mutex.
</aside>
</section>
</section>
<section>
<section>
<h2>Tipos Algébricos</h2>
<h2>Hora da anedota!</h2>
<p class="fragment">(structs)</p>
<img class="stretch" src="_images/senta-que-la-vem-historia.gif" alt="">
</section>
<section>
<h3>struct</h3>
<p>localtime</p>
<pre><code class="hljs rust" data-trim>
struct Present {
package_color: String,
content: String
}
</code></pre>
<p class="fragment">SimpleDateFormatter</p>
<aside class="notes">
A muito tempo atrás, eu estava ajudando uma colega
a resolver um problema com processamento de eventos
num projeto em C. Aparentemente, quando um evento
era processado, acontecia do tempo de processamento
ficar errado (algo como ficar negativo ou levar
menos de 10ms pra fazer uma query num banco
oracle). Quando perguntei como ela estava
calculando o tempo, ela me falou que estava usando
o "localtime". Foi quando me lembrei que
"localtime" não é thread-safe e, por isso, quando
uma thread passava pela chamada da função, o valor
era "resetado".
<aside class="notes">
</aside>
Outra situação aconteceu recentemente: Num projeto
Java, começou a acontecer de, em alguns casos, a
função que convertia strings para Date começou a
dar resultados completamente errados.
Estranhamente, eu lembrei da questão do localtime e
perguntei se o projeto usava threads: sim; fui
direto no DuckDuckGo e procurei por
"simpledateformatter thread safe" e o primeiro
resultado foi uma pergunta do StackOverflow: "Why
isn't SimpleDateFormatter thread-safe?"
</aside>
</section>
<section>
<h3>Rust resolveria isso?</h3>
<h2 class="fragment">Não</h2>
<h4 class="fragment">... na verdade, nem ia compilar.</h4>
<aside class="notes">
Uma questão importante para o Rust são "Zero Cost
Abstractions", segundo a definição do Bjarne
Stroustrup, criado do C++: para que algo seja
aceito no compilador, é preciso que o custo de não
usar algo não acarrete nada; ou seja, tornar uma
função thread-safe simplesmente inserindo um mutex,
não é zero cost porque, se tu não estiver usando
threads, não faz sentido o mutex.
</aside>
</section>
</section>
<section>
<section>
<h2>Tipos Algébricos</h2>
</section>
<section>
@ -680,34 +670,51 @@ OK(())
<section>
<h2>Macros</h2>
<small class="fragment">?</small>
<small class="fragment">?</small>
</section>
</section>
<section>
<h2>Structs</h2>
<section>
<pre><code class="hljs rust" data-trim>
struct Present {
package_color: String,
content: String
}
</code></pre>
<aside class="notes">
Structs em Rust são basicamente o mesmo que em C.
</aside>
</section>
</section>
<section>
<section>
<h2>Traits/Generics</h2>
</section>
<section>
<section>
<h2>Traits/Generics</h2>
</section>
<section>
<section>
<pre><code class="hljs rust" data-trim>
enum Result&lt;T, E&gt; {
Ok(T),
Err(E),
}
</code></pre>
</section>
</section>
<section>
<pre><code class="hljs rust" data-trim>
<section>
<pre><code class="hljs rust" data-trim>
trait Summary {
fn summarize(&amp;self) -&gt; String;
}
</code></pre>
</section>
</code></pre>
</section>
<section>
<pre><code class="hljs rust" data-trim>
<section>
<pre><code class="hljs rust" data-trim>
struct Super {
phrase: String
}
@ -721,7 +728,7 @@ impl Summary for Super {
}
}
</code></pre>
</section>
</section>
<section>
<pre><code class="hljs rust" data-trim>
@ -732,7 +739,18 @@ fn get_summary(summarizable: T) -&gt; String
}
</code></pre>
</section>
</section>
<section>
<h2>Structs genéricas</h2>
<pre><code class="hljs rust" data-trim>
struct Point<T> {
x: T,
y: T
}
</code></pre>
</section>
</section>
<section>
<section>
@ -768,23 +786,23 @@ fn get_summary(summarizable: T) -&gt; String
</section>
</section>
<section>
<section>
<h2>Falando em WASM...</h2>
</section>
<section>
<section>
<h2>Falando em WASM...</h2>
</section>
<section>
<h2>WASM</h2>
<section>
<h2>WASM</h2>
<p><a href="https://rustwasm.github.io/wasm-pack/installer/">wasm-pack</a></p>
</section>
<p><a href="https://rustwasm.github.io/wasm-pack/installer/">wasm-pack</a></p>
</section>
<section>
<h2><a href="https://wasi.dev/">WASI</a></h2>
<section>
<h2><a href="https://wasi.dev/">WASI</a></h2>
<p>The WebAssembly System Interface</p>
</section>
</section>
<p>The WebAssembly System Interface</p>
</section>
</section>
<section>
<section>

Loading…
Cancel
Save