summaryrefslogtreecommitdiffhomepage
path: root/pt-br/d-pt.html.markdown
blob: e01eae77b3a6723b319b77bb46e9c6cdce74dbe8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
---
language: D
filename: learnd-pt.d
contributors:
    - ["Nick Papanastasiou", "www.nickpapanastasiou.github.io"]
translators:
    - ["Julio Vanzelli", "https://github.com/JulioVanzelli"]
lang: pt-br
---

```d
// Você sabe o que está por vir...
module hello;

import std.stdio;

// args é opcional
void main(string[] args) {
    writeln("Hello, World!");
}
```

Se você é como eu e passa muito tempo na Internet, é provável que tenha ouvido
sobre [D](http://dlang.org/). A linguagem de programação D é moderna, de uso geral,
linguagem multiparadigma com suporte para tudo, desde recursos de baixo nível até
abstrações expressivas de alto nível.

D é desenvolvido ativamente por um grande grupo de pessoas super-inteligentes e é liderado por
[Walter Bright](https://en.wikipedia.org/wiki/Walter_Bright) e
[Andrei Alexandrescu](https://en.wikipedia.org/wiki/Andrei_Alexandrescu).
Com tudo isso fora do caminho, vamos dar uma olhada em alguns exemplos!

```d
import std.stdio;

void main() {

    // Condicionais e loops funcionam como esperado.
    for(int i = 0; i < 10000; i++) {
        writeln(i);
    }

    // 'auto' pode ser usado para inferir tipos.
    auto n = 1;

    // literais numéricos podem usar '_' como um separador de dígitos para maior clareza.
    while(n < 10_000) {
        n += n;
    }

    do {
        n -= (n / 2);
    } while(n > 0);

    // Por e enquanto são bons, mas em D-land preferimos loops 'foreach'.
    // O '..' cria um intervalo contínuo, incluindo o primeiro valor
    // mas excluindo o último.
    foreach(n; 1..1_000_000) {
        if(n % 2 == 0)
            writeln(n);
    }

    // Há também 'foreach_reverse' quando você deseja fazer um loop para trás.
    foreach_reverse(n; 1..int.max) {
        if(n % 2 == 1) {
            writeln(n);
        } else {
            writeln("No!");
        }
    }
}
```

Podemos definir novos tipos com `struct`, `class`, `union` e `enum`. Estruturas e uniões
são passados para funções por valor(ou seja, copiados) e as classes são passadas por referência. Além disso,
podemos usar modelos para parametrizar tudo isso em tipos e valores!

```d
// Aqui, 'T' é um parâmetro de tipo. Pense '<T>' em C++/C#/Java.
struct LinkedList(T) {
    T data = null;

    // Usar '!' para instanciar um tipo parametrizado. Mais uma vez, pense '<T>'.
    LinkedList!(T)* next;
}

class BinTree(T) {
    T data = null;

    // Se houver apenas um parâmetro de modelo, podemos omitir os parênteses.
    BinTree!T left;
    BinTree!T right;
}

enum Day {
    Sunday,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
}

// Use o alias para criar abreviações para tipos.
alias IntList = LinkedList!int;
alias NumTree = BinTree!double;

// Também podemos criar modelos de funções!
T max(T)(T a, T b) {
    if(a < b)
        return b;

    return a;
}

// Use a palavra-chave ref para garantir a passagem por referência. Ou seja, mesmo que 'a'
// e 'b' sejam tipos de valor, eles sempre serão passados por referência a 'swap ()'.
void swap(T)(ref T a, ref T b) {
    auto temp = a;

    a = b;
    b = temp;
}

// Com os modelos, também podemos parametrizar valores, não apenas tipos.
class Matrix(uint m, uint n, T = int) {
    T[m] rows;
    T[n] columns;
}

auto mat = new Matrix!(3, 3); // O tipo 'T' foi padronizado como 'int'.
```

Falando em aulas, vamos falar sobre propriedades por um segundo. Uma propriedade
é aproximadamente uma função que pode agir como um valor I, para que possamos
ter a sintaxe das estruturas POD (`structure.x = 7`) com a semântica de
métodos getter e setter (`object.setX (7)`)!

```d
// Considere uma classe parametrizada nos tipos 'T' e 'U'.
class MyClass(T, U) {
    T _data;
    U _other;
}

// E os métodos "getter" e "setter", assim:
class MyClass(T, U) {
    T _data;
    U _other;

    // Os construtores sempre são chamados de 'this'.
    this(T t, U u) {
        // This will call the setter methods below.
        data = t;
        other = u;
    }

    // getters
    @property T data() {
        return _data;
    }

    @property U other() {
        return _other;
    }

    // setters
    @property void data(T t) {
        _data = t;
    }

    @property void other(U u) {
        _other = u;
    }
}

// E nós os usamos desta maneira:
void main() {
    auto mc = new MyClass!(int, string)(7, "seven");

    // Importe o módulo 'stdio' da biblioteca padrão para gravar no
    // console (as importações podem ser locais para um escopo).
    import std.stdio;

    // Ligue para os getters para buscar os valores.
    writefln("Earlier: data = %d, str = %s", mc.data, mc.other);

    // Ligue para os setters para atribuir novos valores.
    mc.data = 8;
    mc.other = "eight";

    // Ligue para os getters novamente para buscar os novos valores.
    writefln("Later: data = %d, str = %s", mc.data, mc.other);
}
```

Com propriedades, podemos adicionar qualquer quantidade de lógica para
nossos métodos getter e setter, e mantenha a sintaxe limpa de
acessando membros diretamente!

Outras guloseimas orientadas a objetos à nossa disposição,
incluem interfaces, classes abstratas,
e métodos de substituição. D faz herança como Java:
Estenda uma classe, implemente quantas interfaces você desejar.

Vimos as instalações OOP de D, mas vamos mudar de marcha. D oferece
programação funcional com funções de primeira classe, `pura`
funções e dados imutáveis. Além disso, todos os seus favoritos
algoritmos funcionais (mapear, filtrar, reduzir e amigos) podem ser
encontrado no maravilhoso módulo `std.algorithm`!

```d
import std.algorithm : map, filter, reduce;
import std.range : iota; // cria uma gama exclusiva de final

void main() {
    // Queremos imprimir a soma de uma lista de quadrados de ints pares
    // de 1 a 100. Fácil!

    // Basta passar expressões lambda como parâmetros de modelo!
    // Você pode passar qualquer função que desejar, mas as lambdas são convenientes aqui.
    auto num = iota(1, 101).filter!(x => x % 2 == 0)
                           .map!(y => y ^^ 2)
                           .reduce!((a, b) => a + b);

    writeln(num);
}
```

Observe como conseguimos construir um bom pipeline haskelliano para calcular num?
Isso se deve a uma inovação em D, conhecida como Uniform Function Call Syntax (UFCS).
Com o UFCS, podemos optar por escrever uma chamada de função como método
ou chamada de função grátis! Walter escreveu um bom artigo sobre isso
[aqui](http://www.drdobbs.com/cpp/uniform-function-call-syntax/232700394).
Em resumo, você pode chamar funções cujo primeiro parâmetro
é de algum tipo A em qualquer expressão do tipo A como método.

Eu gosto de paralelismo. Alguém mais gosta de paralelismo? Com certeza. Vamos fazer um pouco!

```d
// Digamos que queremos preencher uma matriz grande com a raiz quadrada de todos
// os números inteiros consecutivos começando de 1 (até o tamanho da matriz), e queremos
// fazer isso simultaneamente, aproveitando o número de núcleos que temos
// disponível.

import std.stdio;
import std.parallelism : parallel;
import std.math : sqrt;

void main() {
    // Crie sua grande variedade
    auto arr = new double[1_000_000];

    // Use um índice, acesse todos os elementos da matriz por referência (porque vamos
    // mudar cada elemento) e apenas chame paralelo na matriz!
    foreach(i, ref elem; parallel(arr)) {
        elem = sqrt(i + 1.0);
    }
}
```