Browse Source

Merge branch 'release/20190415'

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

538
porque-rust.html

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

Loading…
Cancel
Save