From 8bef9ce083c2aa68ed35d97d1ed5588e63e96119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matheus=20Catarino=20Fran=C3=A7a?= Date: Wed, 14 Feb 2024 13:30:29 -0300 Subject: [PATCH] Basics section full translated --- README.md | 15 +++ basics/alias-strings.md | 118 ++++++++++--------- basics/arrays.md | 151 +++++++++++++----------- basics/associative-arrays.md | 112 +++++++++--------- basics/classes.md | 77 +++++++----- basics/controlling-flow.md | 45 ++++--- basics/delegates.md | 68 +++++------ basics/exceptions.md | 78 +++++++------ basics/foreach.md | 84 ++++++++----- basics/functions.md | 51 ++++---- basics/further-reading.md | 30 +++-- basics/index.yml | 6 +- basics/interfaces.md | 76 ++++++------ basics/loops.md | 90 +++++++------- basics/memory.md | 75 ++++++++---- basics/ranges.md | 220 ++++++++++++++++++++++++++--------- basics/slices.md | 98 ++++++++-------- basics/storage-classes.md | 91 --------------- basics/structs.md | 136 +++++++++------------- basics/templates.md | 54 +++++---- basics/type-qualifiers.md | 126 ++++++++++++++++++++ 21 files changed, 1020 insertions(+), 781 deletions(-) delete mode 100644 basics/storage-classes.md create mode 100644 basics/type-qualifiers.md diff --git a/README.md b/README.md index 56aa30e..d8ab339 100644 --- a/README.md +++ b/README.md @@ -10,3 +10,18 @@ não hesite em abrir uma [issue](https://github.com/dlang-tour/brazilian-portugu Você também pode estar procurando pelo [repositório base](https://github.com/dlang-tour) que hospeda o conteúdo. + +Executar localmente +----------- + +Você precisará buscar o [repositório base](https://github.com/dlang-tour/core) via DUB uma vez: + +```sh +dub fetch dlang-tour +``` + +Agora você pode executar o `dlang-tour` no diretório principal desse repositório: + +```sh +dub run dlang-tour -- --lang-dir . +``` \ No newline at end of file diff --git a/basics/alias-strings.md b/basics/alias-strings.md index 6336369..eab9ae6 100644 --- a/basics/alias-strings.md +++ b/basics/alias-strings.md @@ -1,44 +1,46 @@ # Alias & Strings -Now that we know what arrays are, have gotten in touch with `immutable`, -and had a quick look at the basic types, it's time to introduce two -new constructs in one line: +Agora que sabemos o que são arrays, entramos em contato com `immutable`, +e demos uma olhada rápida nos tipos básicos, é hora de introduzir duas +novas construções em uma única linha: alias string = immutable(char)[]; -The term `string` is defined by an `alias` statement which defines it -as a slice of `immutable(char)`s. This means, once a `string` has been constructed -its content will never change again. And actually this is the second -introduction: welcome UTF-8 `string`! +O termo `string` é definido por uma instrução `alias` que o define +como uma slice de `immutable(char)`s. Isso significa que, uma vez que uma `string` +tenha sido construída seu conteúdo nunca mais será alterado. E, na verdade, +esta é a segunda introdução: bem-vindo ao `string` UTF-8! -Due to their immutablility, `string`s can be shared perfectly among -different threads. As `string` is a slice, parts can be taken out of it without -allocating memory. The standard function `std.algorithm.splitter` -for example, splits a string by newline without any memory allocations. +Devido à sua imutabilidade, as `string`s podem ser compartilhadas perfeitamente entre +diferentes threads. Como a `string` é uma slice, partes podem ser retiradas dela sem +alocar memória. A função padrão +[`std.algorithm.splitter`](https://dlang.org/phobos/std_algorithm_iteration.html#.splitter) +por exemplo, divide uma string por nova linha sem nenhuma alocação de memória. -Besides the UTF-8 `string`, there are two more types: +Além da `string` UTF-8, há mais dois tipos: alias wstring = immutable(wchar)[]; // UTF-16 alias dstring = immutable(dchar)[]; // UTF-32 -The variants are most easily converted between each other using -the `to` method from `std.conv`: +As variantes são mais facilmente convertidas entre si usando +o método `to` do `std.conv`: dstring myDstring = to!dstring(myString); string myString = to!string(myDstring); ### Unicode strings -This means that a plain `string` is defined as an array of 8-bit Unicode [code -units](http://unicode.org/glossary/#code_unit). All array operations can be -used on strings, but they will work on code unit level, and not character level. At -the same time, standard library algorithms will interpret `string`s as sequences -of [code points](http://unicode.org/glossary/#code_point), and there is also an -option to treat them as sequence of -[graphemes](http://unicode.org/glossary/#grapheme) by explicit usage of +Isso significa que uma `string` simples é definida como um array Unicode de 8 bits. +Todas as operações do array podem ser usadas em strings, mas elas funcionarão em +um nível de [unidade de código](http://unicode.org/glossary/#code_unit), +e não em um nível de caractere. +Ao mesmo tempo, os algoritmos da biblioteca padrão interpretarão `string`s como sequências +de [pontos de código](http://unicode.org/glossary/#code_point), e há também uma +opção para tratá-las como sequências de +[graphemes] (http://unicode.org/glossary/#grapheme) por meio do uso explícito de [`std.uni.byGrapheme`](https://dlang.org/library/std/uni/by_grapheme.html). -This small example illustrates the difference in interpretation: +Este pequeno exemplo ilustra essa diferença de interpretação: string s = "\u0041\u0308"; // Ä @@ -50,55 +52,65 @@ This small example illustrates the difference in interpretation: import std.uni : byGrapheme; writeln(s.byGrapheme.walkLength); // 1 -Here the actual array length of `s` is 3, because it contains 3 code units: -`0x41`, `0x03` and `0x08`. Of those latter two define single code point -(combining diacritics character) and +Aqui, o tamanho atual do array `s` é 3, porque ele contém 3 unidades de código: +`0x41`, `0x03` e `0x08`. Esses dois últimos definem um único ponto de código +(combinando caracteres diacríticos) e [`walkLength`](https://dlang.org/library/std/range/primitives/walk_length.html) -(standard library function to calculate arbitrary range length) counts two code -points total. Finally, `byGrapheme` performs rather expensive calculations -to recognize that these two code points combine into a single displayed -character. +(função da biblioteca padrão para calcular o comprimento de um range arbitrário) +conta dois pontos de código no total. Por fim, `byGrapheme` realiza cálculos bastante caros +para reconhecer que esses dois pontos de código se combinam em um único caractere exibido. +caractere. -Correct processing of Unicode can be very complicated, but most of the time, D -developers can simply consider `string` variables as magical byte arrays and -rely on standard library algorithms to do the right job. Most Unicode -functionality is provided by the -[`std.uni`](https://dlang.org/library/std/uni.html) module, with some more basic -primitives available in [`std.utf`](https://dlang.org/library/std/utf.html). +O processamento correto do Unicode pode ser muito complicado, mas, na maioria das vezes, os desenvolvedores de D +podem simplesmente considerar as variáveis `string` como arrays mágicas de bytes e +e confiar nos algoritmos da biblioteca padrão para fazer o trabalho correto. +Se a iteração por elemento (unidade de código) for desejada, é possível usar +[`byCodeUnit`](http://dlang.org/phobos/std_utf.html#.byCodeUnit). -### Multi-line strings +A decodificação automática em D é explicada em mais detalhes +no capítulo [Unicode gems](gems/unicode). -To create multi-line strings, use the `string str = q{ ... }` syntax. +### Strings de múltiplas linhas - string multiline = q{ This - may be a - long document - }; +As strings em D sempre podem se estender por várias linhas: -### Raw strings + string multiline = " + This + may be a + long document + "; -It is also possible to use raw strings to minimize laborious escaping -of reserved symbols. Raw strings can be declared using either backticks (`` ` -... ` ``) or the r(aw)-prefix (`r" ... "`). +Quando as aspas aparecem no documento, as strings Wysiwyg (veja abaixo) ou +[strings delimitadas](http://dlang.org/spec/lex.html#delimited_strings) podem ser usadas. + +### Strings Wysiwyg + +Também é possível usar strings brutas para minimizar o trabalho de escapar +de símbolos reservados. As cadeias de caracteres brutas podem ser declaradas com +o uso de backticks (`` `... ` ``) ou o prefixo r(aw) (`r" ... "`). string raw = `raw "string"`; // raw "string" - string raw2 = r"raw "string""; // raw "string" + string raw2 = r"raw `string`"; // raw `string` + +O D oferece ainda mais maneiras de representar strings - não hesite em +em [explorar](https://dlang.org/spec/lex.html#string_literals) essas formas. -### In-depth +### Maiores detalhes - [Unicode gem](gems/unicode) - [Characters in _Programming in D_](http://ddili.org/ders/d.en/characters.html) - [Strings in _Programming in D_](http://ddili.org/ders/d.en/strings.html) - [std.utf](http://dlang.org/phobos/std_utf.html) - UTF en-/decoding algorithms - [std.uni](http://dlang.org/phobos/std_uni.html) - Unicode algorithms +- [String Literals in the D spec](http://dlang.org/spec/lex.html#string_literals) ## {SourceCode} ```d -import std.stdio; -import std.range: walkLength; +import std.stdio : writeln, writefln; +import std.range : walkLength; import std.uni : byGrapheme; -import std.string: format; +import std.string : format; void main() { // format generates a string using a printf @@ -118,13 +130,13 @@ void main() { // Strings are just normal arrays, so any // operation that works on arrays works here // too! - import std.array: replace; + import std.array : replace; writeln(replace(str, "lö", "lo")); - import std.algorithm: endsWith; + import std.algorithm : endsWith; writefln("Does %s end with 'rld'? %s", str, endsWith(str, "rld")); - import std.conv: to; + import std.conv : to; // Convert to UTF-32 dstring dstr = to!dstring(str); // .. which of course looks the same! diff --git a/basics/arrays.md b/basics/arrays.md index ba05ec1..52a9b12 100644 --- a/basics/arrays.md +++ b/basics/arrays.md @@ -1,117 +1,134 @@ # Arrays -There are two types of Arrays in D: **static** and **dynamic**. -Access to arrays of any kind is always bounds checked - -a failed range check yields a `RangeError` which aborts the application. -The brave can disable this with the compiler flag `-boundschecks=off`, in order -to squeeze the last cycles out of their binary. +Há dois tipos de arrays em D: **estático** e **dinâmico**. +O acesso aos arrays de qualquer tipo é submetido à verificação de limites [_bounds-checked_] +(exceto quando o compilador consegue provar que as verificações não são necessárias). +Uma falha na verificação de limites gera um `RangeError` que interrompe o aplicativo. +O desenvolvedor pode desativar esse recurso de segurança com o sinalizador do compilador +sinalizador do compilador `-boundscheck=off` +para obter melhorias na velocidade ao custo da segurança. -#### Static arrays +### Arrays estáticos -Static arrays are stored on the stack if defined inside a function, -or in static memory otherwise. They have a fixed, -compile-time known length. A static array's type includes -the fixed size: +Arrays estáticos são armazenadas na pilha se forem definidas dentro de uma função, +ou na memória estática, caso contrário. Eles possuem tamanho fixo, +tamanho esse conhecido em tempo de compilação. O tipo de um array estático inclui +o tamanho fixo: int[8] arr; -`arr`'s type is `int[8]`. Note that the size of the array is denoted -next to the type, and not after the variable name like in C/C++. +O tipo de `arr` é `int[8]`. Observe que o tamanho do array é indicado +ao lado do tipo, e não após o nome da variável, como ocorre em C e C++. -#### Dynamic arrays +### Arrays dinâmicos -Dynamic arrays are stored on the heap and can be expanded -or shrunk at runtime. A dynamic array is created using a `new` expression -and its length: +As matrizes dinâmicas são armazenadas no heap e podem ser expandidas +ou encolhidos em tempo de execução. Um array dinâmico é criado usando +uma expressão `new` e seu tamanho: - int size = 8; // run-time variable + int size = 8; // variável em tempo de execução (run-time) int[] arr = new int[size]; -The type of `arr` is `int[]`, which is a **slice**. Slices -will be explained in more detail in the next section. Multi-dimensional -arrays can be created easily using the `auto arr = new int[3][3]` syntax. +O tipo de `arr` é `int[]`, que também é chamado de **slice**. Os slices +são pontos em um bloco contíguo de memória e serão explicadas +em mais detalhes na [próxima seção](basics/slices). +Os arrays multidimensionais podem ser criados facilmente +usando a sintaxe `auto arr = new int[3][3]`. -#### Array operations and properties +### Propriedades e operações do array -Arrays can be concatenated using the `~` operator, which -will create a new dynamic array. +Os arrays estáticos e dinâmicos fornecem a propriedade `.length`, +que é somente leitura para arrays estáticos, mas pode ser usada no caso de +matrizes dinâmicas para alterar seu tamanho dinamicamente. A propriedade +propriedade `.dup` cria uma cópia do array. -Mathematical operations can -be applied to whole arrays using a syntax like `c[] = a[] + b[]`, for example. -This adds all elements of `a` and `b` so that -`c[0] = a[0] + b[0]`, `c[1] = a[1] + b[1]`, etc. It is also possible -to perform operations on a whole array with a single -value: +A indexação de um array refere-se a um elemento desse array. +Ao indexar um array por meio da sintaxe `arr[idx]`, um símbolo especial +especial `$` indica o comprimento de um array. Por exemplo, `arr[$ - 1]` faz referência +o último elemento e é uma forma abreviada de `arr[arr.length - 1]`. - a[] *= 2; // multiple all elements by 2 - a[] %= 26; // calculate the modulo by 26 for all a's +Os arrays podem ser concatenados usando o operador `~`, que +criará um novo array dinâmico. -These operations might be optimized -by the compiler to use special processor instructions that -do the operations in one go. + int[] a = [1, 2]; + a ~= [3, 4]; + assert(a.length == 4); + a[0] = 10; + a.length--; + assert(a == [10, 2, 3]); -Both static and dynamic arrays provide the property `.length`, -which is read-only for static arrays, but can be used in the case of -dynamic arrays to change its size dynamically. The -property `.dup` creates a copy of the array. +#### Aritmética de vetores -When indexing an array through the `arr[idx]` syntax, a special -`$` symbol denotes an array's length. For example, `arr[$ - 1]` references -the last element and is a short form for `arr[arr.length - 1]`. +As operações matemáticas podem +ser aplicadas a matrizes inteiras usando uma sintaxe como `c[] = a[] + b[]`, por exemplo. +Isso adiciona todos os elementos de `a` e `b` de modo que +`c[0] = a[0] + b[0]`, `c[1] = a[1] + b[1]`, etc. Também é possível +realizar operações em um array inteiro com um único +valor: -### Exercise + a[] *= 2; // multiplica todos os elementos por 2 + a[] %= 26; // calcula o módulo 26 por todos os a's -Complete the function `encrypt` to decrypt the secret message. -The text should be encrypted using *Caesar encryption*, -which shifts the characters in the alphabet using a certain index. -The to-be-encrypted text only contains characters in the range `a-z`, -which should make things easier. +Essas operações podem ser otimizadas +pelo compilador para usar instruções especiais do processador que +realizam as operações de uma só vez. -### In-depth +### Exercício + +Complete a função `encrypt` para criptografar a mensagem secreta. +O texto deve ser criptografado usando a criptografia *Caesar*, +que desloca os caracteres no alfabeto usando um determinado índice. +O texto a ser criptografado contém apenas caracteres no intervalo `a-z`, +o que deve facilitar as coisas. + +Você pode procurar a solução [aqui](https://github.com/dlang-tour/core/issues/227). + +### Maiores detalhes - [Arrays in _Programming in D_](http://ddili.org/ders/d.en/arrays.html) +- [D Slices](https://dlang.org/d-array-article.html) - [Array specification](https://dlang.org/spec/arrays.html) ## {SourceCode:incomplete} ```d -import std.stdio; +import std.stdio : writeln; /** -Shifts every character in the -array `input` for `shift` characters. -The character range is limited to `a-z` -and the next character after z is a. - -Params: - input = array to shift - shift = shift length for each char -Returns: - Shifted char array +Desloque todos os caracteres do +array `input` para os caracteres `shift`. +O intervalo de caracteres é limitado a `a-z` +e o próximo caractere após z é a. + +Parâmetros: + input = array para deslocar + shift = tamanho do deslocamento +Retonará: + Array de caracteres deslocados */ char[] encrypt(char[] input, char shift) { auto result = input.dup; - // ... + // TODO: desloque cada caractere return result; } void main() { - // We will now encrypt the message with - // Caesar encryption and a - // shift factor of 16! + // Agora, criptografaremos a mensagem com + // criptografia Caesar e um + // fator de deslocamento é 16! char[] toBeEncrypted = [ 'w','e','l','c', 'o','m','e','t','o','d', - // The last , is okay and will just - // be ignored! + // O último , não tem problema + // e será simplesmente ignorado! ]; writeln("Before: ", toBeEncrypted); auto encrypted = encrypt(toBeEncrypted, 16); writeln("After: ", encrypted); - // Make sure we the algorithm works - // as expected + // Verifique se o algoritmo funciona + // como esperado assert(encrypted == [ 'm','u','b','s','e', 'c','u','j','e','t' ]); } diff --git a/basics/associative-arrays.md b/basics/associative-arrays.md index f2d37c2..fcd900b 100644 --- a/basics/associative-arrays.md +++ b/basics/associative-arrays.md @@ -1,38 +1,38 @@ -# Associative Arrays +# Arrays Associativos -D has built-in *associative arrays* also known as hash maps. -An associative array with a key type of `string` and a value type -of `int` is declared as follows: +O D tem *arrays associativos* incorporados, também conhecidos como mapas de hash. +Um array associativo com um tipo de chave `string` e um tipo de valor +de `int` é declarado da seguinte forma: int[string] arr; -The value can be accessed by its key and thus be set: +O valor pode ser acessado por sua chave e, assim, ser definido: arr["key1"] = 10; -To test whether a key is located in the associative array, the -`in` expression can be used: +Para testar se uma chave está localizada no array associativo, a expressão +expressão `in` pode ser usada: if ("key1" in arr) writeln("Yes"); -The `in` expression returns a pointer to the value if it -can be found or a `null` pointer otherwise. Thus existence check -and writes can be conveniently combined: +A expressão `in` retorna um ponteiro para o valor se ele +puder ser encontrado ou um ponteiro `null` caso contrário. Assim, a verificação de existência +e gravações podem ser convenientemente combinadas: if (auto val = "key1" in arr) *val = 20; -Access to a key which doesn't exist yields an `RangeError` -that immediately aborts the application. For a safe access -with a default value, `get(key, defaultValue)` can be used. +O acesso a uma chave que não existe gera um `RangeError` +que interrompe imediatamente o aplicativo. Para acesso seguro +com um valor padrão, `get(key, defaultValue)` pode ser usado. -AA's have the `.length` property like arrays and provide -a `.remove(val)` member to remove entries by their key. -It is left as an exercise to the reader to explore -the special `.byKey` and `.byValue` ranges. +Os AAs têm a propriedade `.length` como os arrays e fornecem +um membro `.remove(key)` para remover entradas por sua chave. +Deixamos como exercício para o leitor explorar +os intervalos especiais `.byKey` e `.byValue`. -### In-depth +### Maiores detalhes - [Associative arrays in _Programming in D_](http://ddili.org/ders/d.en/aa.html) - [Associative arrays specification](https://dlang.org/spec/hash-map.html) @@ -41,47 +41,47 @@ the special `.byKey` and `.byValue` ranges. ## {SourceCode} ```d -import std.stdio; - -/** -Splits the given text into words and returns -an associative array that maps words to their -respective word counts. - -Params: - text = text to be splitted -*/ -int[string] wordCount(string text) -{ - // The function splitter lazily splits the - // input into a range - import std.algorithm.iteration: splitter; - import std.string: toLower; - - // Indexed by words and returning the count - int[string] words; - - foreach(word; splitter(text.toLower(), " ")) - { - // Increment word count if word - // has been found. - // Integers are by default 0. - words[word]++; - } - - return words; -} +import std.array : assocArray; +import std.algorithm.iteration: each, group, + splitter, sum; +import std.string: toLower; +import std.stdio : writefln, writeln; void main() { - string text = "D is a lot of fun"; + string text = "Rock D with D"; - auto wc = wordCount(text); - writeln("Word counts: ", wc); - - // possible iterations: - // byKey, byValue, byKeyValue - foreach (word; wc.byValue) - writeln(word); + // Iterar sobre todas as palavras e contar + // cada palavra uma vez + int[string] words; + text.toLower() + .splitter(" ") + .each!(w => words[w]++); + + foreach (key, value; words) + writefln("key: %s, value: %d", + key, value); + + // `.keys` e `.values` retornam arrays + writeln("Words: ", words.keys); + + // `.byKey`, `.byValue` e `.byKeyValue` + // return lazy, iteratable ranges + writeln("# Words: ", words.byValue.sum); + + // Um novo array associativo pode ser criado + // com `assocArray` passando um + // intervalo de tuplas de chave/valor; + auto array = ['a', 'a', 'a', 'b', 'b', + 'c', 'd', 'e', 'e']; + + // `.group` agrupa elementos + // consecutivamente equivalentes + // em uma única tupla do elemento + // elemento e o número de suas repetições + auto keyValue = array.group; + writeln("Key/Value range: ", keyValue); + writeln("Associative array: ", + keyValue.assocArray); } ``` diff --git a/basics/classes.md b/basics/classes.md index 0ef0c32..cdf67df 100644 --- a/basics/classes.md +++ b/basics/classes.md @@ -1,45 +1,64 @@ # Classes -D provides support for classes and interfaces like in Java or C++. +O D oferece suporte a classes e interfaces como em Java ou C++. -Any `class` type inherits from [`Object`](https://dlang.org/phobos/object.html) implicitly. +Qualquer tipo de `class` herda implicitamente do [`Object`](https://dlang.org/phobos/object.html) (objeto). - class Foo { } // inherits from Object - class Bar: Foo { } // Bar is a Foo too + class Foo { } // herda de Object + class Bar : Foo { } // Bar é imcorporado ao Foo -Classes in D are generally instantiated on the heap using `new`: +As classes em D geralmente são instanciadas no heap usando `new`: auto bar = new Bar; -Class objects are always references types and unlike `struct` aren't -copied by value. +Os objetos de classe são sempre tipos de referência e, ao contrário do `struct`, não são +copiados por valor. - Bar bar = foo; // bar points to foo + Bar bar = foo; // bar aponta para foo -The garbage collector will make sure the memory is freed -when no references to an object exist anymore. +O coletor de lixo garantirá que a memória seja liberada +quando não houver mais referências a um objeto. -#### Inheritance +#### Herança -If a member function of a base class is overridden, the keyword -`override` must be used to indicate that. This prevents unintentional -overriding of functions. +Se uma função de membro de uma classe base for substituída, a palavra-chave +`override` deve ser usada para indicar isso. Isso evita a substituição não intencional +sobreposição não intencional de funções. - class Bar: Foo { + class Bar : Foo { override functionFromFoo() {} } -In D, classes can only inherit from one class. +Em D, as classes só podem herdar de uma classe. -#### Final and abstract member functions +### Funções de membro Final e abstract -A function can be marked `final` in a base class to disallow overriding -it. A function can be declared as `abstract` to force base classes to override -it. A whole class can be declared as `abstract` to make sure -that it isn't instantiated. To access the base class, -use the special keyword `super`. +- Uma função pode ser declarada como `final` em uma classe base para não permitir +a sobreposição dela +- Uma função pode ser declarada como `abstract` para forçar as classes derivadas +a sobrepor ela +- Uma classe inteira pode ser declarada como `abstract` para garantir que +que ela não seja instanciada +- `super(...)` pode ser usado para chamar explicitamente o construtor da base -### In-depth +### Verificação de equivalência + +Para objetos de classe, os operadores `==` e `!=` comparam o conteúdo dos objetos. +Portanto, a comparação com `null` é inválida, pois `null` não tem conteúdo. +O `is` compara a equivalência. Para comparar a não-equivalência, use `e1 !is e2`. + +```d +MyClass c; +if (c == null) // erro + ... +if (c is null) // ok + ... +``` + +Para objetos `struct`, todos os bits são comparados, +para outros tipos de operandos, equivalência é o mesmo que igualdade. + +### Maiores detalhes - [Classes in _Programming in D_](http://ddili.org/ders/d.en/class.html) - [Inheritance in _Programming in D_](http://ddili.org/ders/d.en/inheritance.html) @@ -49,7 +68,7 @@ use the special keyword `super`. ## {SourceCode} ```d -import std.stdio; +import std.stdio : writeln; /* Fancy type which can be used for @@ -73,7 +92,7 @@ class Any { abstract string convertToString(); } -class Integer: Any { +class Integer : Any { // just seen by Integer private { int number; @@ -91,13 +110,13 @@ class Integer: Any { public: override string convertToString() { - import std.conv: to; + import std.conv : to; // The swiss army knife of conversion. return to!string(number); } } -class Float: Any { +class Float : Any { private float number; this(float number) { @@ -106,7 +125,7 @@ class Float: Any { } override string convertToString() { - import std.string: format; + import std.string : format; // We want to control precision return format("%.1f", number); } @@ -117,7 +136,7 @@ void main() Any[] anys = [ new Integer(10), new Float(3.1415f) - ]; + ]; foreach (any; anys) { writeln("any's type = ", any.getType()); diff --git a/basics/controlling-flow.md b/basics/controlling-flow.md index 2450c81..9bd53e5 100644 --- a/basics/controlling-flow.md +++ b/basics/controlling-flow.md @@ -1,7 +1,6 @@ -# Control flow +# Fluxo de controle -An application's flow can be controlled conditionally with `if` and `else` -statements: +O fluxo de um aplicativo pode ser controlado condicionalmente com declarações `if` e `else`: if (a == 5) { writeln("Condition is met"); @@ -11,35 +10,35 @@ statements: writeln("Nothing is met!"); } -When an `if` or `else` block only contains one statement, -the braces can be omitted. +Quando um bloco `if` ou `else` contém apenas uma instrução, +as chaves podem ser omitidas. -D provides the same operators as C/C++ and Java to test -variables for equality or compare them: +O D fornece os mesmos operadores que o C, C++ e o Java para testar +variáveis quanto à equivalência ou compará-las: -* `==` and `!=` for testing equality and inequality -* `<`, `<=`, `>` and `>=` for testing less than (or equal to) and greater than (or equal to) +* `==` e `!=` para testar a equivalência ou diferença +* `<`, `<=`, `>` e `>=` para testar se são menores (ou iguais) e maiores (ou iguais) -For combining multiple conditions, the `||` operator represents -the logical *OR*, and `&&` the logical *AND*. +Para combinar várias condições, o operador `||` representa +o operador lógico *OR*, e `&&` o operador lógico *AND*. -D also defines a `switch`..`case` statement which executes one case -depending on the value of *one* variable. `switch` -works with all basic types as well as strings! -It's even possible to define ranges for integral types -using the `case START: .. case END:` syntax. Make sure to -take a look at the source code example. +D também define uma instrução `switch`..`case` que executa um caso +dependendo do valor de *uma* variável. `switch` +funciona com todos os tipos básicos e também com strings! +É possível até mesmo definir intervalos para tipos integrais +usando a sintaxe `case START: ... case END:`. Não deixe de +dar uma olhada no exemplo do código-fonte. -### In-depth +### Maiores detalhes -#### Basic references +#### Referências básicas - [Logical expressions in _Programming in D_](http://ddili.org/ders/d.en/logical_expressions.html) - [If statement in _Programming in D_](http://ddili.org/ders/d.en/if.html) - [Ternary expressions in _Programming in D_](http://ddili.org/ders/d.en/ternary.html) - [`switch` and `case` in _Programming in D_](http://ddili.org/ders/d.en/switch_case.html) -#### Advanced references +#### Referências avançadas - [Expressions in detail](https://dlang.org/spec/expression.html) - [If Statement specification](https://dlang.org/spec/statement.html#if-statement) @@ -47,7 +46,7 @@ take a look at the source code example. ## {SourceCode} ```d -import std.stdio; +import std.stdio : writeln; void main() { @@ -58,11 +57,11 @@ void main() switch(c) { case 0: .. case 9: writeln(c, " is within 0-9"); - break; // necessary! + break; // interrupção necessária! case 10: writeln("A Ten!"); break; - default: // if nothing else matches + default: // não encontrou nenhum caso, writeln("Nothing"); break; } diff --git a/basics/delegates.md b/basics/delegates.md index 11bc45c..1ae753a 100644 --- a/basics/delegates.md +++ b/basics/delegates.md @@ -1,44 +1,44 @@ # Delegates -### Functions as arguments +### Funções como argumentos -A function can also be a parameter to another function: +Uma função também pode ser um parâmetro para outra função: void doSomething(int function(int, int) doer) { // call passed function doer(5,5); } - doSomething(add); // use global function `add` here - // add must have 2 int parameters + doSomething(&add); // use a função global `add` aqui + // add deve ter 2 parâmetros int -`doer` can then be called like any other normal function. +`doer` pode então ser chamado como qualquer outra função normal. -### Local functions with context +### Funções locais com contexto -The above example uses the `function` type which is -a pointer to a global function. As soon as a member -function or a local function is referenced, `delegate`'s -have to be used. It's a function pointer -that additionally contains information about its -context - or *enclosure*, thus also called **closure** -in other languages. For example a `delegate` -that points to a member function of a class also includes -the pointer to the class object. A `delegate` created by -a nested function includes a link to the enclosing context -instead. However, the D compiler may automatically make a copy of -the context on the heap if it is necessary for memory safety - -then a delegate will link to this heap area. +O exemplo acima usa o tipo `function` que é +um ponteiro para uma função global. Assim que uma função membro +ou uma função local é referenciada, os `delegate` +devem ser usados. Trata-se de um ponteiro de função +que, além disso, contém informações sobre seu +contexto - ou *enclosure*, portanto também chamado de **closure** +em outras linguagens. Por exemplo, um `delegate` +que aponta para uma função membro de uma classe também inclui +o ponteiro para o objeto da classe. Um `delegate` criado por +uma função aninhada inclui um link para o contexto +em vez disso. No entanto, o compilador D pode fazer automaticamente uma cópia do +do contexto no heap se isso for necessário para a segurança da memória. +então um delegate será vinculado a essa área de heap. void foo() { void local() { writeln("local"); } - auto f = &local; // f is of type delegate() + auto f = &local; // f é do tipo delegate() } -The same function `doSomething` taking a `delegate` -would look like this: +A mesma função `doSomething` que recebe um `delegate` +teria a seguinte aparência: void doSomething(int delegate(int,int) doer); @@ -47,34 +47,34 @@ standard function [`std.functional.toDelegate`](https://dlang.org/phobos/std_functional.html#.toDelegate) converts a `function` to a `delegate`. -### Anonymous functions & Lambdas +### Funções anônimas & Lambdas -As functions can be saved as variables and passed to other functions, -it is laborious to give them an own name and to define them. Hence D allows -nameless functions and one-line _lambdas_. +Como as funções podem ser salvas como variáveis e passadas para outras funções, +é trabalhoso dar a elas seu próprio nome e defini-las. Por isso, o D permite +funções sem nome e _lambdas_ de uma linha. auto f = (int lhs, int rhs) { return lhs + rhs; }; - auto f = (int lhs, int rhs) => lhs + rhs; // Lambda - internally converted to the above + auto f = (int lhs, int rhs) => lhs + rhs; // Lambda - convertido internamente para o valor acima -It is also possible to pass-in strings as template argument to functional parts -of D's standard library. For example they offer a convenient way -to define a folding (aka reducer): +Também é possível passar strings como argumentos de template para partes funcionais +da biblioteca padrão do D. Por exemplo, elas oferecem uma maneira conveniente +de definir um *folding* (também conhecido como *reducer*): [1, 2, 3].reduce!`a + b`; // 6 -String functions are only possible for _one or two_ arguments and then use `a` -as first and `b` as second argument. +As funções de strings só são possíveis para _um ou dois_ argumentos e usam `a` +como o primeiro e `b` como o segundo argumento. -### In-depth +### Maiores detalhes - [Delegate specification](https://dlang.org/spec/function.html#closures) ## {SourceCode} ```d -import std.stdio; +import std.stdio : writeln; enum IntOps { add = 0, diff --git a/basics/exceptions.md b/basics/exceptions.md index 5c39bd5..c0dfd9a 100644 --- a/basics/exceptions.md +++ b/basics/exceptions.md @@ -1,13 +1,13 @@ -# Exceptions +# Exceções -This guide is only about User-`Exceptions` - System-`Errors` are usually fatal -and should __never__ be catched. +Este guia trata apenas de User-`Exceptions` - System-`Errors` geralmente são fatais +e _nunca_ devem ser capturados. -### Catching Exception +### Captura de exceções -A common case for exceptions is to validate potentially invalid user input. -Once an exception is thrown, the stack will be unwound until the first matching exception -handler is found. +Um caso comum de exceções é a validação de entradas do usuário potencialmente inválidas. +Quando uma exceção for lançada, a pilha será deslocada até que o primeiro manipulador de exceção +correspondente seja encontrado. ```d try @@ -20,8 +20,8 @@ catch (FileException e) } ``` -You can also have multiple `catch` blocks and a `finally` block that is executed -regardless of whether an error occurred. Exceptions are thrown with `throw`. +É possível ter vários blocos `catch` e um bloco `finally` que é executado +independentemente da ocorrência de um erro. As exceções são lançadas com `throw`. ```d try @@ -42,12 +42,11 @@ finally } ``` -Remember that the scope guard is usually a better solution to the `try-finally` -pattern. +Lembre-se de que o [scope guard](gems/scope-guards) geralmente é uma solução melhor para o padrão `try-finally`. -### Custom exceptions +### Exceções personalizadas -One can easily inherit from `Exception` and create custom exceptions: +É possível herdar facilmente de `Exception` e criar exceções personalizadas: ```d class UserNotFoundException : Exception @@ -59,11 +58,11 @@ class UserNotFoundException : Exception throw new UserNotFoundException("D-Man is on vacation"); ``` -### Enter a safe world with `nothrow` +### Entre em um mundo seguro com o `nothrow` -The D compiler can ensure that a function can't cause catastrophic side-effects. -Such functions can be annotated with the `nothrow` keyword. The D compiler -statically forbids throwing exceptions in `nothrow` functions. +O compilador D pode garantir que uma função não cause efeitos colaterais catastróficos. +Essas funções podem ser anotadas com a palavra-chave `nothrow`. O compilador D +proíbe estaticamente o lançamento de exceções em funções `nothrow`. ```d bool lessThan(int a, int b) nothrow @@ -73,18 +72,22 @@ bool lessThan(int a, int b) nothrow } ``` -Please note that the compiler is able to infer attributes for templated code -automatically. +Observe que o compilador é capaz de inferir atributos para o código de modelo +automaticamente. ### std.exception -It is important to avoid contract programming for user-input as the contracts -are removed when compiled in release mode. For convenience `std.exception` provides -`enforce` that can be used like `assert`, but throws `Exceptions` -instead of an `AssertError`. +É importante evitar o `assert` e o que será introduzido em breve +[contract programming](gems/contract-programming) +para a entrada do usuário, pois o `assert` e os contratos +são removidos quando compilados no modo de lançamento. Por conveniência +[`std.exception`](https://dlang.org/phobos/std_exception.html) fornece +[`enforce`](https://dlang.org/phobos/std_exception.html#enforce) +que pode ser usado como o `assert`, mas lança `Exception`s +em vez de um `AssertError`. ```d -import std.exception: enforce; +import std.exception : enforce; float magic = 1_000_000_000; enforce(magic + 42 - magic == 42, "Floating-point math is fun"); @@ -92,19 +95,20 @@ enforce(magic + 42 - magic == 42, "Floating-point math is fun"); enforce!StringException('a' != 'A', "Case-sensitive algorithm"); ``` -However there's more in `std.exception`. For example when the error might not be -fatal, one can opt-in to `collect` it: +No entanto, há mais em `std.exception`. Por exemplo, quando o erro pode não ser +fatal, é possível optar por +[collect](https://dlang.org/phobos/std_exception.html#collectException): ```d -import std.exception: collectException; +import std.exception : collectException; auto e = collectException(aDangerousOperation()); if (e) writeln("The dangerous operation failed with ", e); ``` -To test whether an exception is thrown in tests, use `assertThrown`. +Para verificar se uma exceção foi lançada nos testes, use [`assertThrown`](https://dlang.org/phobos/std_exception.html#assertThrown). -### In-depth +### Maiores detalhes - [Exception Safety in D](https://dlang.org/exception-safe.html) - [std.exception](https://dlang.org/phobos/std_exception.html) @@ -114,8 +118,8 @@ To test whether an exception is thrown in tests, use `assertThrown`. ## {SourceCode} ```d -import std.file; -import std.stdio; +import std.file : FileException, readText; +import std.stdio : writeln; void main() { @@ -125,13 +129,13 @@ void main() } catch (FileException e) { - writeln("Message:\n", e.msg); - writeln("File: ", e.file); - writeln("Line: ", e.line); - writeln("Stack trace:\n", e.info); + writeln("Message:\n", e.msg); + writeln("File: ", e.file); + writeln("Line: ", e.line); + writeln("Stack trace:\n", e.info); - // Default formatting could be used too - // writeln(e); + // Default formatting could be used too + // writeln(e); } } ``` diff --git a/basics/foreach.md b/basics/foreach.md index 45079b9..64b0a35 100644 --- a/basics/foreach.md +++ b/basics/foreach.md @@ -2,43 +2,65 @@ {{#img-right}}dman-teacher-foreach.jpg{{/img-right}} -D features a `foreach` loop which allows -less error-prone and better readable iterations. +D apresenta um loop `foreach` que permite +iteração menos propensa a erros e mais legível. -### Element iteration +### Iteração dos elementos -Given an array `arr` of type `int[]` it is possible to -iterate through the elements using a `foreach` loop: +Dado um array `arr` do tipo `int[]`, é possível +iterar sobre os elementos usando um loop `foreach`: foreach (int e; arr) { writeln(e); } -The first field in the `foreach` definition is the variable -name used in the loop iteration. Its type is induced automatically: +O primeiro parâmetro em um loop `foreach` é o nome da variável +usada para cada iteração. Seu tipo pode ser inferido automaticamente da seguinte forma: foreach (e; arr) { - // typeof(e) is int + // typeof(e) é int writeln(e); } -The second field must be an array - or a special iterable -object called a **range** which will be introduced in the next section. +O segundo campo deve ser um array - ou um objeto iterável especial +chamado **range**, que será apresentado na [próxima seção](basics/ranges). -### Access by reference +### Acessando por referência -Elements will be copied from the array or range during iteration. -This is acceptable for basic types, but might be a problem for -large types. To prevent copying or to enable *in-place -*mutation, `ref` can be used: +Os elementos serão copiados do array ou range durante a iteração. +Isso é aceitável para tipos básicos, mas pode ser um problema para tipos +tipos grandes. Para evitar a cópia e permitir a mutabilidade do dado +pode ser usado o `ref`: foreach (ref e; arr) { - e = 10; // overwrite value + e = 10; // sobrescrevendo o valor } -### Reverse iteration with `foreach_reverse` +### Iterar `n` vezes -A collection can be iterated in reverse order with +D nos permite escrever iterações que devem ser executadas +`n` vezes, de forma mais concisa com a sintaxe `..`: + + foreach (i; 0 .. 3) { + writeln(i); + } + // 0 1 2 + +O último número em `a ... b` é excluído do intervalo, +portanto, o corpo do loop é executado `3` vezes. + +### Iteração com contador de índice + +Para arrays, também é possível acessar uma variável de índice separada. + + foreach (i, e; [4, 5, 6]) { + writeln(i, ":", e); + } + // 0:4 1:5 2:6 + +### Iteração reversa com `foreach_reverse` + +Um array pode ser iterada na ordem inversa com `foreach_reverse`: foreach_reverse (e; [1, 2, 3]) { @@ -46,7 +68,7 @@ A collection can be iterated in reverse order with } // 3 2 1 -### In-depth +### Maiores detalhes - [`foreach` in _Programming in D_](http://ddili.org/ders/d.en/foreach.html) - [`foreach` with Structs and Classes _Programming in D_](http://ddili.org/ders/d.en/foreach_opapply.html) @@ -55,23 +77,23 @@ A collection can be iterated in reverse order with ## {SourceCode} ```d -import std.stdio; +import std.stdio : writefln; void main() { - auto arr = [ [5, 15], // 20 - [2, 3, 2, 3], // 10 - [3, 6, 2, 9] ]; // 20 + auto arr = [ + [5, 15], // 20 + [2, 3, 2, 3], // 10 + [3, 6, 2, 9], // 20 + ]; - // Iterate through array in reverse order - import std.range: retro; - foreach (row; retro(arr)) + foreach (i, row; arr) { - double accumulator = 0.0; - foreach (c; row) - accumulator += c; + double total = 0.0; + foreach (e; row) + total += e; - writeln("The average of ", row, - " = ", accumulator / row.length); + auto avg = total / row.length; + writefln("AVG [row=%d]: %.2f", i, avg); } } ``` diff --git a/basics/functions.md b/basics/functions.md index da798d4..dbf09f4 100644 --- a/basics/functions.md +++ b/basics/functions.md @@ -1,35 +1,34 @@ -# Functions +# Funções -One function has already been introduced: `main()` - the starting point of every -D program. A function may return a value (or be declared with -`void` if nothing is returned) and accept an arbitrary number of arguments: +Uma função já foi introduzida: `main()` - o ponto de partida de todo programa +programa D. Uma função pode retornar um valor (ou ser declarada com `void` +se nada for retornado) e aceitar um número arbitrário de argumentos: int add(int lhs, int rhs) { return lhs + rhs; } -### `auto` return types +### Retornar tipo `auto` -If the return type is defined as `auto`, the D compiler infers the return -type automatically. Hence multiple `return` statements must return values with -compatible types. +Se o tipo de retorno for definido como `auto`, o compilador D infere o tipo de retorno +automaticamente. Portanto, várias instruções `return` devem retornar valores com +tipos compatíveis. - auto add(int lhs, int rhs) { // returns `int` + auto add(int lhs, int rhs) { // retorna `int` return lhs + rhs; } - auto lessOrEqual(int lhs, int rhs) { // returns `double` + auto lessOrEqual(int lhs, int rhs) { // retorna `double` if (lhs <= rhs) return 0; else return 1.0; } -### Default arguments +### Argumentos pré-atribuidos -Functions may optionally define default arguments. -This avoids the tedious work of declaring redundant -overloads. +As funções podem, opcionalmente, definir argumentos padrão. +Isso evita o trabalho tedioso de declarar sobrecargas redundantes. void plot(string msg, string color = "red") { ... @@ -37,15 +36,15 @@ overloads. plot("D rocks"); plot("D rocks", "blue"); -Once a default argument has been specified, all following arguments -must be default arguments too. +Uma vez que um argumento padrão tenha sido especificado, todos os argumentos seguintes +também devem ser argumentos padrão. -### Local functions +### Funções locais -Functions may even be declared inside other functions, where they may be -used locally and aren't visible to the outside world. -These functions can even have access to objects that are local to -the parent's scope: +As funções podem até ser declaradas dentro de outras funções, onde podem ser +usadas localmente e não são visíveis para o mundo externo. +Essas funções podem até mesmo ter acesso a objetos que são locais para +escopo da função principal: void fun() { int local = 10; @@ -54,10 +53,10 @@ the parent's scope: } ... -Such nested functions are called delegates, and they will be explained in more depth -[soon](basics/delegates). +Essas funções aninhadas são chamadas de delegates e serão explicadas com mais detalhes +[em breve](basics/delegates). -### In-depth +### Maiores detalhes - [Functions in _Programming in D_](http://ddili.org/ders/d.en/functions.html) - [Function parameters in _Programming in D_](http://ddili.org/ders/d.en/function_parameters.html) @@ -66,8 +65,8 @@ Such nested functions are called delegates, and they will be explained in more d ## {SourceCode} ```d -import std.stdio; -import std.random; +import std.stdio : writeln; +import std.random : uniform; void randomCalculator() { diff --git a/basics/further-reading.md b/basics/further-reading.md index c22c51c..18cc55f 100644 --- a/basics/further-reading.md +++ b/basics/further-reading.md @@ -1,22 +1,24 @@ -# Further Reading +# Leitura adicional -Now that you've finished the basics, you can move on to some more advanced sections of this tour. Or, you can check out some of the following resources: +Agora que você concluiu o básico, pode passar para algumas seções mais avançadas deste tour. Ou, você pode conferir alguns dos recursos a seguir: -### Basic resources +**Nota:** Todos os materiais citados abaixo estão escritos em inglês! -* [Learn D as a beginner](http://ddili.org/ders/d.en/index.html) -* [Learn D as an experienced programmers](http://wiki.dlang.org/Coming_From) coming from other languages -* Quickstart with [D Tutorials](https://wiki.dlang.org/Tutorials) +### Materiais básicos + +* New to programming? [This book](http://ddili.org/ders/d.en/index.html) is a great starting place for beginners +* [Coming from another language?](http://wiki.dlang.org/Coming_From) +* Looking for a book to read? [Discover books about D](https://wiki.dlang.org/Books) +* Read [articles about D](http://dlang.org/articles.html) +* Explore more [D Tutorials](https://wiki.dlang.org/Tutorials) * Browse the [D Wiki](https://wiki.dlang.org/), which contains a lot of information and links -* Explore [articles about D](http://dlang.org/articles.html) -* Discover [books about D](https://wiki.dlang.org/Books), for an in-depth view -* See [common questions about D](http://dlang.org/faq.html) +* See [frequently asked questions about D](http://dlang.org/faq.html) -### In-depth resources +### Materiais aprofundados * Get familiar with the API of the standard library [Phobos](https://dlang.org/phobos) * Read the [language reference](https://dlang.org/spec/) -* Watch [_d.announce_](http://forum.dlang.org/group/announce) for new annoucements +* Watch [_d.announce_](http://forum.dlang.org/group/announce) for new announcements * Share your ideas in the [Forum](https://forum.dlang.org/) or scan very active discussions * Browse the [Dub Repository](https://code.dlang.org), hosting an ever growing list of 3rd-party D programs and libraries. * Dive into the source code on github ([dmd compiler](https://github.com/dlang/dmd), [Phobos standard library](https://github.com/dlang/phobos), [druntime](https://github.com/dlang/druntime)) @@ -24,3 +26,9 @@ Now that you've finished the basics, you can move on to some more advanced secti * See the D Language on [Rosetta code](http://rosettacode.org/wiki/Category:D) * Explore [awesome-d](https://github.com/zhaopuming/awesome-d/blob/master/README.md) - A curated list of awesome D frameworks, libraries and software * Get inspired by [Idioms for the D Programming Language](https://p0nce.github.io/d-idioms/) + +### Ajuda para a comunidade + +* Ask questions in the [#d](irc://irc.freenode.net/d) IRC channel on freenode ([web interface](https://kiwiirc.com/client/irc.freenode.net/d)) +* Get help at [D.learn](http://forum.dlang.org/group/learn) +* Open an issue [at the D bugtracker](https://issues.dlang.org) diff --git a/basics/index.yml b/basics/index.yml index 4b958bf..bca2278 100644 --- a/basics/index.yml +++ b/basics/index.yml @@ -1,9 +1,9 @@ -title: D's Basics +title: Fundamentos de D ordering: - imports-and-modules - basic-types - memory -- storage-classes +- type-qualifiers - controlling-flow - functions - structs @@ -19,4 +19,4 @@ ordering: - templates - delegates - exceptions -- further-reading +- further-reading \ No newline at end of file diff --git a/basics/interfaces.md b/basics/interfaces.md index 0efbffe..76eaa9a 100644 --- a/basics/interfaces.md +++ b/basics/interfaces.md @@ -1,43 +1,41 @@ # Interfaces -D allows defining `interface`s which are technically like -`class` types, but whose member functions must be implemented -by any class inheriting from the `interface`. +O D permite definir `interface`s que são tecnicamente como os tipos `class`, +mas cujas funções membros devem ser implementadas +por qualquer classe que herde da `interface`. - interface Animal { + interface IAnimal { void makeNoise(); } -The `makeNoise` member function has to be implemented -by `Dog` because it inherits from the `Animal` interface. -Essentially `makeNoise` behaves like an `abstract` member -function in a base class. +A função membro `makeNoise` deve ser implementada +por `Dog` porque ela herda da interface `Animal`. +Essencialmente, `makeNoise` se comporta como uma função membro `abstract` +em uma classe base. - class Dog: Animal { - override makeNoise() { + class Dog : IAnimal { + void makeNoise() { ... } } - auto dog = new Animal; - Animal animal = dog; // implicit cast to interface - dog.makeNoise(); + IAnimal animal = new Dog(); // conversão implícita a interface + animal.makeNoise(); -The number of `interface`s a `class` can implement isn't limited, -but it can inherit from only *one* base class. +Embora uma classe só possa herdar diretamente de *uma* classe base, +ela pode implementar *qualquer número* de interfaces. ### NVI (non virtual interface) pattern -The [NVI pattern](https://en.wikipedia.org/wiki/Non-virtual_interface_pattern) -prevents the violation of a common execution pattern by allowing _non virtual_ methods -for a common interface. -D easily enables the NVI pattern by -allowing the definition of `final` functions in an `interface` -that aren't allowed to be overridden. This enforces specific -behaviours customized by overriding the other `interface` -functions. +O [NVI pattern](https://en.wikipedia.org/wiki/Non-virtual_interface_pattern) +permite métodos _não virtuais_ para uma interface comum. +Portanto, esse padrão impede a violação de um padrão de execução comum. +D ativa o padrão NVI ao +permitir funções `final` (ou seja, não substituíveis) em uma `interface`. +Isso impõe comportamentos específicos personalizados por meio da substituição de +outras funções abstratas de `interface`. - interface Animal { + interface IAnimal { void makeNoise(); final doubleNoise() // NVI pattern { @@ -46,7 +44,7 @@ functions. } } -### In-depth +### Maiores detalhes - [Interfaces in _Programming in D_](http://ddili.org/ders/d.en/interface.html) - [Interfaces in D](https://dlang.org/spec/interface.html) @@ -54,21 +52,17 @@ functions. ## {SourceCode} ```d -import std.stdio; +import std.stdio : writeln; -interface Animal { - /* - Virtual function - which needs to be overridden! - */ +interface IAnimal { void makeNoise(); /* NVI pattern. Uses makeNoise internally to customize behaviour inheriting classes. - - Params: + + Params: n = number of repetitions */ final void multipleNoise(int n) { @@ -78,22 +72,22 @@ interface Animal { } } -class Dog: Animal { - override void makeNoise() { - writeln("Bark!"); +class Dog: IAnimal { + void makeNoise() { + writeln("Woof!"); } } -class Cat: Animal { - override void makeNoise() { +class Cat: IAnimal { + void makeNoise() { writeln("Meeoauw!"); } } void main() { - Animal dog = new Dog; - Animal cat = new Cat; - Animal[] animals = [dog, cat]; + IAnimal dog = new Dog; + IAnimal cat = new Cat; + IAnimal[] animals = [dog, cat]; foreach(animal; animals) { animal.multipleNoise(5); } diff --git a/basics/loops.md b/basics/loops.md index dad2501..a3a56eb 100644 --- a/basics/loops.md +++ b/basics/loops.md @@ -1,53 +1,63 @@ # Loops -D provides four loop constructs. +D oferece quatro construções de loop. -### 1) Classical `for` loop +### 1) `while` -The classical `for` loop known from C/C++ or Java -with _initializer_, _loop condition_ and _loop statement_: +`while` executa o bloco de código fornecido +enquanto uma determinada condição é atendida: - for (int i = 0; i < arr.length; ++i) { - ... - -### 2) `while` - -`while` loops execute the given code block -while a certain condition is met: - - while (condition) { + while (condition) + { foo(); } -### 3) `do ... while` +### 2) `do ... while` -The `do .. while` loops execute the given code block -while a certain condition is met, but in contrast to `while` -the _loop block_ is executed before the loop condition is -evaluated for the first time. +`do ... while` executa o bloco de código fornecido +enquanto uma determinada condição é atendida, mas, ao contrário do `while` +o _bloco do loop_ é executado antes que a condição do loop seja +avaliada pela primeira vez. - do { + do + { foo(); } while (condition); -#### 4) `foreach` +### 3) O clássico `for` loop -The [`foreach` loop](basics/foreach) which will be introduced in the -next section. +O clássico `for` loop conhecido em C, C++ ou Java +com _initializer_, _loop condition_ e _loop statement_: -#### Special keywords and labels + for (int i = 0; i < arr.length; i++) + { + ... + +### 4) `foreach` -The special keyword `break` will immediately abort the current loop. -In a nested loop a _label_ can be used to break of any outer loop: +[`foreach`](basics/foreach), será apresentado em mais detalhes +na próxima seção: - outer: for (int i = 0; i < 10; ++i) { - for (int j = 0; j < 5; ++j) { + foreach (el; arr) + { + ... + } + +#### Palavra-chave especial e labels + +A palavra-chave especial `break` interromperá imediatamente o loop atual. +Em um loop aninhado, um _label_ pode ser usado para sair de qualquer loop externo: + + outer: for (int i = 0; i < 10; ++i) + { + for (int j = 0; j < 5; ++j) + { ... break outer; -The keyword `continue` starts with the next loop iteration. +A palavra-chave `continue` inicia a próxima iteração do loop. -### In-depth +### Maiores detalhes - `for` loop in [_Programming in D_](http://ddili.org/ders/d.en/for.html), [specification](https://dlang.org/spec/statement.html#ForStatement) - `while` loop in [_Programming in D_](http://ddili.org/ders/d.en/while.html), [specification](https://dlang.org/spec/statement.html#WhileStatement) @@ -56,28 +66,25 @@ The keyword `continue` starts with the next loop iteration. ## {SourceCode} ```d -import std.stdio; +import std.stdio : writeln; /* Computes the average of the elements of an array. */ -double average(int[] array) { - // The property .empty for arrays isn't - // native in D but has to be made accessible - // by importing the function from std.array - import std.array: empty, front; - +double average(int[] array) +{ + immutable initialLength = array.length; double accumulator = 0.0; - auto length = array.length; - while (!array.empty) { + while (array.length) + { // this could be also done with .front - // with import std.array: front; + // with import std.array : front; accumulator += array[0]; array = array[1 .. $]; } - return accumulator / length; + return accumulator / initialLength; } void main() @@ -86,7 +93,8 @@ void main() [2, 3, 2, 3], // 10 [3, 6, 2, 9] ]; // 20 - for (auto i = 0; i < testers.length; ++i) { + for (auto i = 0; i < testers.length; ++i) + { writeln("The average of ", testers[i], " = ", average(testers[i])); } diff --git a/basics/memory.md b/basics/memory.md index 4464486..542d2a7 100644 --- a/basics/memory.md +++ b/basics/memory.md @@ -1,52 +1,75 @@ -# Memory +# Memória -D is a system programming language and thus allows you to manually -manage memory. However, manual memory management is very error-prone and thus -D uses a *garbage collector* by default to free unused memory. +D é uma linguagem de programação de sistema e, portanto, permite o gerenciamento manual da memória. +Entretanto, o gerenciamento manual de memória está sujeito a erros de segurança de memória +e, portanto, o D usa um *coletor de lixo* por padrão para gerenciar a alocação de memória. -D provides pointer types `T*` like in C: +D fornece tipos de ponteiro `T*` como em C: - int a; - int* b = &a; // b contains address of a - auto c = &a; // c is int* and contains address of a + int a; // a declarado na pilha + int* b = &a; // b contém o endereço de a + auto c = &a; // c é int* e contém o endereço de a -A new memory block on the heap is allocated using the -`new` expression, which returns a pointer to the managed -memory: +Um novo bloco de memória no heap é alocado usando uma expressão +expressão [`new T`](https://dlang.org/spec/expression.html#new_expressions), +que retorna um ponteiro para a memória gerenciada (quando T é um tipo de valor): int* a = new int; -As soon as the memory referenced by `a` isn't referenced anymore -through any variable in the program, the garbage collector -will free its memory. +Quando a memória referenciada por `a` não for referenciada em nenhum lugar +por meio de qualquer variável no programa, o próximo ciclo de coleta de lixo +liberará sua memória. Por padrão, o coletor de lixo só pode ser +executado ao alocar memória com o GC - por exemplo, ao utilizar +a expressão `new`. -D has three different security levels for functions: `@system`, `@trusted`, and `@safe`. -Unless specified otherwise, the default is `@system`. -`@safe` is a subset of D that prevents memory bugs by design. -`@safe` code can only call other `@safe` or `@trusted` functions. -Moreover, explicit pointer arithmetic is forbidden in `@safe` code: +* Um ciclo do GC pode ser chamado manualmente com `GC.collect` (a partir de + [`core.memory`](https://dlang.org/phobos/core_memory.html#.GC)) +* As coletas podem ser desativadas com `GC.disable` (e reativadas com `GC.enable`) + +### Segurança de memória + +As violações de segurança de memória podem: + +* Dificultar a reprodução de bugs +* Permitir acesso não autorizado a dados sensíveis +* Corrupção de memória + +Para evitar isso, D tem um subconjunto para segurança de memória. + +O D tem três níveis de segurança diferentes para as funções: `@system`, `@trusted` e `@safe`. +A menos que especificado de outra forma, o padrão é `@system`, que não verifica a segurança da memória. + +O `@safe` impõe um subconjunto de D que impede a ocorrência de bugs de memória por design. +O código `@safe` só pode chamar outras funções `@safe` ou `@trusted`. +Além disso, a aritmética explícita de ponteiros é proibida no código `@safe`: void main() @safe { int a = 5; int* p = &a; - int* c = p + 5; // error + int* c = p + 5; // erro } -`@trusted` functions are manually verified functions that allow a bridge between SafeD and the underlying dirty low-level world. +As funções `@trusted` são funções verificadas manualmente, que devem ter +uma interface segura para a memória. +Internamente, elas podem executar operações `@system`. +Elas permitem uma ponte entre o SafeD e o acesso de baixo nível subjacente. -### In-depth +### Maiores detalhes -* [SafeD](https://dlang.org/safed.html) +* [Garbage Collection](https://dlang.org/spec/garbage.html) +* [SafeD article](https://dlang.org/safed.html) +* [Memory-safe spec](https://dlang.org/spec/memory-safe-d.html) ## {SourceCode} ```d -import std.stdio; +import std.stdio : writeln; void safeFun() @safe { writeln("Hello World"); - // allocating memory with the GC is safe too + // A alocação de memória com + // o GC também é segura int* p = new int; } @@ -56,6 +79,8 @@ void unsafeFun() int* fiddling = p + 5; } +// tente declarar isso como +// @safe para obter um erro void main() { safeFun(); diff --git a/basics/ranges.md b/basics/ranges.md index 3503901..c6ee141 100644 --- a/basics/ranges.md +++ b/basics/ranges.md @@ -1,87 +1,201 @@ # Ranges -If a `foreach` is encountered by the compiler +Se um `foreach` for encontrado pelo compilador - foreach(element; range) { +``` +foreach (element; range) +{ +   // corpo do Loop... +} +``` -it's internally rewritten similar to the following: +ele é reescrito internamente de forma semelhante à seguinte: - for (; !range.empty; range.popFront()) { - auto element = range.front; - ... +``` +for (auto __rangeCopy = range; +     !__rangeCopy.empty; +     __rangeCopy.popFront()) + { +    auto element = __rangeCopy.front; +    // Loop body... +} +``` -Any object which fulfills the above interface is called a **range** -and is thus a type that can be iterated over: +Qualquer objeto que atenda à seguinte interface é chamado de **range** +(ou, mais especificamente, `InputRange`) e, portanto, é um tipo que pode ser iterado: - struct Range { - @property empty() const; +``` +    interface InputRange(E) + { + bool empty(); + E front(); void popFront(); - T front(); } +``` + +Dê uma olhada no exemplo à direita para inspecionar a implementação e o uso +de um intervalo de entrada mais próximo. + +## Laziness (preguiçoso) + +Os ranges são __lazy__. Eles não serão avaliados até que sejam solicitados. +Portanto, um range de um range infinito pode ser obtido: + +```d +42.repeat.take(3).writeln; // [42, 42, 42] +``` + +## Tipos: Valor vs. Referência + +Se o objeto range for um tipo de valor, então o range será copiado e somente a cópia +será utilizada: + +```d +auto r = 5.iota; +r.drop(5).writeln; // [] +r.writeln; // [0, 1, 2, 3, 4] +``` + +Se o objeto range for um tipo de referência (por exemplo, `class` ou [`std.range.refRange`](https://dlang.org/phobos/std_range.html#refRange)), +então o range será utilizado e não será redefinido: + +```d +auto r = 5.iota; +auto r2 = refRange(&r); +r2.drop(5).writeln; // [] +r2.writeln; // [] +``` + +### `InputRanges` copiáveis são `ForwardRanges` + +A maioria dos ranges na biblioteca padrão são structs e, portanto, a iteração `foreach` +geralmente não é destrutiva, embora não seja garantida. Se essa +garantia for importante, uma especialização de um `InputRange` pode ser usada +**forward** ranges com um método `.save`: + +``` +interface ForwardRange(E) : InputRange!E +{ + typeof(this) save(); +} +``` + +```d +// by value (Structs) +auto r = 5.iota; +auto r2 = refRange(&r); +r2.save.drop(5).writeln; // [] +r2.writeln; // [0, 1, 2, 3, 4] +``` -The functions in `std.range` and `std.algorithm` provide -building blocks that make use of this interface. Ranges allow -to compose complex algorithms behind an object that -can be iterated with ease. Furthermore ranges allow to create **lazy** -objects that only perform a calculation when it's really needed -in an iteration e.g. when the next range's element is accessed. -Special range algorithm will be presented later in the -[D's Gems](gems/range-algorithms) section. +### `ForwardRanges` pode ser estendido por ranges bidirecionais + ranges de acesso aleatório -### Exercise +Há duas extensões do `ForwardRange` copiável: (1) um range bidirecional +e (2) um range de acesso aleatório. +Um range bidirecional permite a iteração de trás para frente: -Complete the source code to create the `FibonacciRange` range -that returns numbers of the -[Fibonacci sequence](https://en.wikipedia.org/wiki/Fibonacci_number). -Don't fool yourself into deleting the `assert`ions! +```d +interface BidirectionalRange(E) : ForwardRange!E +{ + E back(); + void popBack(); +} +``` + +```d +5.iota.retro.writeln; // [4, 3, 2, 1, 0] +``` -### In-depth +Um range de acesso aleatório tem um `length` (comprimento) conhecido e cada elemento pode ser acessado diretamente. + +```d +interface RandomAccessRange(E) : ForwardRange!E +{ + E opIndex(size_t i); + size_t length(); +} +``` + +Em termos práticos, o range de acesso aleatório mais conhecido é o array de D: + +```d +auto r = [4, 5, 6]; +r[1].writeln; // 5 +``` + +### Algoritmos lazy range + +As funções em [`std.range`](http://dlang.org/phobos/std_range.html) e +[`std.algorithm`](http://dlang.org/phobos/std_algorithm.html) fornecem +blocos de construção que fazem uso dessa interface. Os ranges permitem a +composição de algoritmos complexos por trás de um objeto que +pode ser iterado com facilidade. Além disso, os ranges permitem a criação de objetos **lazy** +que só executam um cálculo quando ele é realmente necessário +em uma iteração, por exemplo, quando o próximo elemento do range é acessado. +Algoritmos especiais do range serão apresentados mais adiante na seção +[D's Gems](gems/range-algorithms). + +### Maiores detalhes - [`std.algorithm`](http://dlang.org/phobos/std_algorithm.html) - [`std.range`](http://dlang.org/phobos/std_range.html) -## {SourceCode:incomplete} +## {SourceCode} ```d -import std.stdio; +import std.stdio : writeln; struct FibonacciRange { - bool empty() const @property - { - // So when does the Fibonacci sequence - // end?! - } + // States of the Fibonacci generator + int a = 1, b = 1; - void popFront() + // The fibonacci range never ends + enum empty = false; + + // Peek at the first element + int front() const @property { + return a; } - int front() @property + // Remove the first element + void popFront() { + auto t = a; + a = b; + b = t + b; } } -void main() { - import std.range: take; - import std.array: array; - +void main() +{ FibonacciRange fib; - // `take` creates another range which - // will return N elements at maximum. - // This range is _lazy_ and just - // touches the original range - // if actually needed - auto fib10 = take(fib, 10); - - // But we do want to touch all elements and - // convert the range to array of integers. - int[] the10Fibs = array(fib10); - - writeln("The 10 first Fibonacci numbers: ", - the10Fibs); - assert(the10Fibs == - [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]); + import std.range : drop, take; + import std.algorithm.iteration : + filter, sum; + + // Select the first 10 fibonacci numbers + auto fib10 = fib.take(10); + writeln("Fib 10: ", fib10); + + // Except the first five + auto fib5 = fib10.drop(5); + writeln("Fib 5: ", fib5); + + // Select the even subset + auto even = fib5.filter!(x => x % 2 == 0); + writeln("FibEven : ", even); + + // Sum of all elements + writeln("Sum of FibEven: ", even.sum); + + // Usually this is summarized as: + fib.take(10) + .drop(5) + .filter!(x => x % 2 == 0) + .sum + .writeln; } ``` diff --git a/basics/slices.md b/basics/slices.md index 390c163..f16b7b3 100644 --- a/basics/slices.md +++ b/basics/slices.md @@ -1,53 +1,51 @@ # Slices -Slices are objects from type `T[]` for any given type `T`. -Slices provide a view on a subset of an array -of `T` values - or just point to the whole array. -**Slices and dynamic arrays are the same.** +Slices são objetos do tipo `T[]` para qualquer tipo `T`. +Os slices fornecem uma visualização em um subconjunto de uma matriz +de valores `T` ou simplesmente apontam para todo o array. -A slice consists of two members - a pointer to the starting element and the -length of the slice: +**Slices e arrays dinâmicos são a mesma coisa.** + +Um slice consiste em dois membros - um ponteiro para o elemento inicial e o +tamanho do slice: T* ptr; - size_t length; // unsigned 32 bit on 32bit, unsigned 64 bit on 64bit + size_t length; // unsigned 32 bit em 32bit, unsigned 64 bit em 64bit -### Getting a slice via new allocation +### Obtendo um slice por meio de uma nova alocação -If a new dynamic array is created, a slice to this freshly -allocated memory is returned: +Se um novo array dinâmico for criado, será retornado um slice para essa +memória recém-alocada: auto arr = new int[5]; - assert(arr.length == 5); // memory referenced in arr.ptr + assert(arr.length == 5); // referenciando memória em arr.ptr -Actual allocated memory in this case is completely managed by garbage -collector, returned slice acts as a "view" on underlying elements. +A memória real alocada, nesse caso, é totalmente gerenciada pelo coletor de lixo. +O slice retornado funciona como um ponto entre dois elementos subjacentes. -### Getting a slice to existing memory +### Obtendo um slice numa memória existente -Using a slicing operator one can also get a slice pointing to some already -existing memory. Slicing operator can be applied to another slice, static -arrays, structs/classes implementing `opSlice` and few other entities. +Usando um operador de slicing, também é possível obter um slice apontando para alguma memória já existente. +O operador de slicing pode ser aplicado a outro slice, arrays estáticos, structs/classes que implementam `opSlice` e algumas outras entidades. -In an example expression `origin[start .. end]` slicing operator is used to get -a slice of all elements of `origin` from `start` to the element _before_ `end`: +Em uma expressão de exemplo `origin[start .. end]`, o operador de divisão é usado para obter +um slice de todos os elementos de `origin` de `start` até o elemento _before_ `end`: - auto newArr = arr[1 .. 4]; // index 4 ist NOT included + auto newArr = arr[1 .. 4]; // O índice 4 NÃO está incluso assert(newArr.length == 3); - newArr[0] = 10; // changes newArr[0] aka arr[1] + newArr[0] = 10; // altera newArr[0] também conhecido como arr[1] -Such slices generate a new view on existing memory. They *don't* create -a new copy. If no slice holds a reference to that memory anymore - or a *sliced* -part of it - it will be freed by the garbage collector. +Esses slices geram um novo ponto de extremidade numa memória existente. Eles *não* criam +uma nova cópia. Se nenhum slice tiver mais uma referência a essa memória - ou uma parte *cortada* dela - ela será liberada pelo coletor de lixo. -Using slices, it's possible to write very efficient code for things (like parsers, for example) -that only operate on one memory block, and slice only the parts they really need -to work on. In this way, there's no need to allocate new memory blocks. +Usando slices, é possível escrever um código muito eficiente para coisas (como parsers, por exemplo) +que operam somente em um bloco de memória e separam somente as partes que realmente precisam +trabalhar. Dessa forma, não há necessidade de alocar novos blocos de memória. -As seen in the previous section, the `[$]` expression is a shorthand form for -`arr.length`. Hence `arr[$]` indexes the element one past the slice's end, and -thus would generate a `RangeError` (if bounds-checking hasn't been disabled). +Como visto na [seção anterior](basics/arrays), a expressão `[$]` é uma forma abreviação de +`arr.length`. Portanto, `arr[$]` indexa o elemento após o final do slice e, portanto, geraria um `RangeError` (se a verificação de limites não tiver sido desativada). -### In-depth +### Maiores detalhes - [Introduction to Slices in D](http://dlang.org/d-array-article.html) - [Slices in _Programming in D_](http://ddili.org/ders/d.en/slices.html) @@ -55,30 +53,26 @@ thus would generate a `RangeError` (if bounds-checking hasn't been disabled). ## {SourceCode} ```d -import std.stdio; - -/** -Calculates the minimum of all values -in a slice recursively. For every recursive -call a sub-slice is taken thus we don't -create a copy and don't do any allocations. -*/ -int minimum(int[] slice) -{ - assert(slice.length > 0); - if (slice.length == 1) - return slice[0]; - auto otherMin = minimum(slice[1 .. $]); - return slice[0] < otherMin ? - slice[0] : otherMin; -} +import std.stdio : writeln; void main() { int[] test = [ 3, 9, 11, 7, 2, 76, 90, 6 ]; - auto min = minimum(test); - writefln("The minimum of %s is %d", - test, min); - assert(min == 2); + test.writeln; + writeln("First element: ", test[0]); + writeln("Last element: ", test[$ - 1]); + writeln("Exclude the first two elements: ", + test[2 .. $]); + + writeln("Slices are views on the memory:"); + auto test2 = test; + auto subView = test[3 .. $]; + test[] += 1; // increment each element by 1 + test.writeln; + test2.writeln; + subView.writeln; + + // Create an empty slice + assert(test[2 .. 2].length == 0); } ``` diff --git a/basics/storage-classes.md b/basics/storage-classes.md deleted file mode 100644 index 907acac..0000000 --- a/basics/storage-classes.md +++ /dev/null @@ -1,91 +0,0 @@ -# Storage classes - -D is a statically typed language: once a variable has been declared, -its type can't be changed from that point onwards. This allows -the compiler to prevent bugs early and enforce restrictions -at compile time. Good type-safety provides the support one needs -to make large programs safer and more maintainable. - -### `immutable` - -In addition to a static type system, D provides -storage classes that enforce additional -constraints on certain objects. For example, an -`immutable` object can only -be initialized once and then isn't -allowed to change. - - immutable int err = 5; - // or: immutable err = 5 and int is inferred. - err = 5; // won't compile - -`immutable` objects can thus be safely shared among different threads -because they never change by design. This implies that `immutable` -objects can be cached perfectly. - -### `const` - -`const` objects can't be modified either. This -restriction is only valid for the current scope. A `const` -pointer can be created from either a *mutable* or -`immutable` object. This means that the object -is `const` for your current scope, but someone -else might modify it in the future. Only with an `immutable` -can you be certain that an object's value will never -change. It is common for APIs to accept `const` objects -to ensure they don't modify the input. - - immutable a = 10; - int b = 5; - const int* pa = &a; - const int* pb = &b; - *pa = 7; // disallowed - -Both `immutable` and `const` are _transitive_ which ensures that once -`const` is applied to a type, it applies recursively to every sub-component of that type. - -### In-depth - -#### Basic references - -- [Immutable in _Programming in D_](http://ddili.org/ders/d.en/const_and_immutable.html) -- [Scopes in _Programming in D_](http://ddili.org/ders/d.en/name_space.html) - -#### Advanced references - -- [const(FAQ)](https://dlang.org/const-faq.html) -- [Type qualifiers D](https://dlang.org/spec/const3.html) - -## {SourceCode} - -```d -import std.stdio; - -void main() -{ - immutable forever = 100; - // ERROR: - // forever = 5; - writeln("forever: ", - typeof(forever).stringof); - - const int* cForever = &forever; - // ERROR: - // *cForever = 10; - writeln("const* forever: ", - typeof(cForever).stringof); - - int mutable = 100; - writeln("mutable: ", - typeof(mutable).stringof); - mutable = 10; // Fine - const int* cMutable = &mutable; // Fine - // ERROR: - // *cMutable = 100; - writeln("cMutable: ", - typeof(cMutable).stringof); - - // ERROR: - // immutable int* imMutable = &mutable; -} -``` diff --git a/basics/structs.md b/basics/structs.md index 3344b77..3bc1ce9 100644 --- a/basics/structs.md +++ b/basics/structs.md @@ -1,7 +1,7 @@ # Structs -One way to define compound or custom types in D is to -define them through a `struct`: +Uma maneira de definir tipos compostos ou personalizados em D é +usar um `struct`: struct Person { int age; @@ -9,17 +9,17 @@ define them through a `struct`: float ageXHeight; } -`struct`s are always constructed on the stack (unless created -with `new`) and are copied **by value** in assignments or -as parameters to function calls. +Por padrão, os `struct`s são construídos na pilha (a menos que sejam criados +com `new`) e são copiados **por valor** em atribuições ou +como parâmetros para chamadas de função. auto p = Person(30, 180, 3.1415); - auto t = p; // copy + auto t = p; // cópia -When a new object of a `struct` type is created, its members can be initialized -in the order they are defined in the `struct`. A custom constructor can be defined through -a `this(...)` member function. If needed to avoid name conflicts, the current instance -can be explicitly accessed with `this`: +Quando um novo objeto de um tipo `struct` é criado, seus membros podem ser inicializados +na ordem em que são definidos no `struct`. Um construtor personalizado pode ser definido por meio de +uma função membro chamado `this(...)`. Se necessário, para evitar conflitos de nomes, a instância atual +pode ser acessada explicitamente com `this`: struct Person { this(int age, int height) { @@ -29,14 +29,14 @@ can be explicitly accessed with `this`: } ... - Person p(30, 180); // initialization - p = Person(30, 180); // assignment to new instance + Person p = Person(30, 180); // inicialização + p = Person(30, 180); // atribuiu nova instância -A `struct` might contain any number of member functions. These -are by default `public` and accessible from the outside. They could -also be `private` and thus only be callable by other -member functions of the same `struct`, or other code in the same -module. +Um `struct` pode conter qualquer número de funções-membro. Por padrão +elas são `public` e acessíveis do lado de fora. Elas podem +também podem ser `private` e, portanto, só podem ser chamadas por outras +funções-membro do mesmo `struct`, ou outro código no mesmo +módulo. struct Person { void doStuff() { @@ -44,53 +44,53 @@ module. private void privateStuff() { ... - p.doStuff(); // call method doStuff - p.privateStuff(); // forbidden + // Em outro módulo: + p.doStuff(); // chamando o método doStuff + p.privateStuff(); // proibido -### Const member functions +### Função membro `const` -If a member function is declared with `const`, it won't be allowed -to modify any of its members. This is enforced by the compiler. -Making a member function `const` makes it callable on any `const` -or `immutable` object, but also guarantees to callers that -the member function will never change the state of the object. +Se uma função membro for declarada com `const`, não será permitido +modificar nenhum de seus membros. Isso é imposto pelo compilador. +Tornar uma função membro `const` faz com que ela possa ser chamada em qualquer objeto `const` +ou objeto `immutable`, mas também garante aos chamadores que +a função de membro nunca alterará o estado do objeto. -### Static member functions +### Função membro `static` -If a member function is declared as `static`, it will be callable -without an instantiated object (e.g. `Person.myStatic()`) but -won't be allowed to access any non-`static` members. A `static` -member function can be used to give access to all instances of a -`struct`, rather than the current instance, or when the -member function must be usable by callers that don't have an instance -available. For example, Singletons (where only one instance is allowed) -use `static`. +Se uma função membro for declarada como `static`, ela poderá ser chamada +sem um objeto instanciado (por exemplo, `Person.myStatic()`), mas ela +não poderá acessar nenhum membro que não seja `static`. Ele pode ser usado se um método +não precisar acessar nenhum dos campos de membro do objeto, mas logicamente +pertence à mesma classe. Também pode ser usado para fornecer alguma funcionalidade +sem criar uma instância explícita, por exemplo, algumas implementações do padrão de design Singleton +usam `static`. -### Inheritance +### Herança -Note that a `struct` can't inherit from another `struct`. -Hierachies of types can only be built using classes, -which we will see in a future section. -However, with `alias this` or `mixins` one can easily achieve -polymorphic inheritance. +Observe que um `struct` não pode herdar de outro `struct`. +As hierarquias de tipos só podem ser construídas usando classes, +que veremos em uma seção posterior. +Entretanto, com `alias this` ou `mixins` é possível obter facilmente +herança polimórfica. -### In-depth +### Maiores detalhes - [Structs in _Programming in D_](http://ddili.org/ders/d.en/struct.html) - [Struct specification](https://dlang.org/spec/struct.html) -### Exercise +### Exercício -Given the `struct Vector3`, implement the following functions and make -the example application run successfully: +Dado o `struct Vector3`, implemente as seguintes funções e faça com que +o aplicativo de exemplo seja executado com êxito: -* `length()` - returns the vector's length -* `dot(Vector3)` - returns the dot product of two vectors -* `toString()` - returns a string representation of this vector. - The function [`std.string.format`](https://dlang.org/phobos/std_format.html) - returns a string using `printf`-like syntax: - `format("MyInt = %d", myInt)`. Strings will be explained in detailed in a later - section. +* `length()` - retorna o tamanho do vetor +* `dot(Vector3)` - retorna o ponto do produto de dois vetores +* `toString()` - retorna uma representação de string desse vetor. + A função [`std.string.format`](https://dlang.org/phobos/std_format.html) + retorna uma string usando a sintáxe parecido com `printf`: + `format("MyInt = %d", myInt)`. As strings serão explicadas em detalhes em uma + seção posterior. ## {SourceCode:incomplete} @@ -101,28 +101,16 @@ struct Vector3 { double z; double length() const { - import std.math: sqrt; + import std.math : sqrt; + // TODO: implement the length of Vector3 return 0.0; } // rhs will be copied double dot(Vector3 rhs) const { + // TODO: implement the dot product return 0.0; } - - /** - Returns: representation of the string in the - special format. The output is restricted to - a precision of one! - "x: 0.0 y: 0.0 z: 0.0" - */ - string toString() const { - import std.string: format; - // Hint: refer to the documentation of - // std.format to see how to influence - // output for floating point numbers. - return format(""); - } } void main() { @@ -142,21 +130,9 @@ void main() { // 1 * 1 + 2 * 1 + 3 * 1 auto vec3 = Vector3(1, 2, 3); - assert(vec3.dot(Vector3(1, 1, 1) == 6); + assert(vec3.dot(Vector3(1, 1, 1)) == 6); // 1 * 3 + 2 * 2 + 3 * 1 - assert(vec3.dot(Vector3(3, 2, 1) == 10); - - // Thanks to toString() we can now just - // output our vector's with writeln - import std.stdio: writeln, writefln; - writeln("vec1 = ", vec1); - writefln("vec2 = %s", vec2); - - // Check the string representation - assert(vec1.toString() == - "x: 10.0 y: 0.0 z: 0.0"); - assert(vec2.toString() == - "x: 0.0 y: 20.0 z: 0.0"); + assert(vec3.dot(Vector3(3, 2, 1)) == 10); } ``` diff --git a/basics/templates.md b/basics/templates.md index 7be092b..b8d2d0d 100644 --- a/basics/templates.md +++ b/basics/templates.md @@ -1,54 +1,52 @@ # Templates -**D** allows defining templated functions similar to C++ and Java -which is a mean to define **generic** functions or objects which work -for any type that compiles with the statements within the function's body: +**D** permite definir funções com template semelhantes a C++ e Java +que é um meio de definir funções ou objetos **genéricos** que funcionam +para qualquer tipo que seja compilado com as instruções no corpo da função: auto add(T)(T lhs, T rhs) { return lhs + rhs; } -The template parameter `T` is defined in a set of parentheses -in front of the actual function parameters. `T` is a placeholder -which is replaced by the compiler when actually *instantiating* -the function using the `!` operator: +O parâmetro com template `T` é definido em um conjunto de parênteses +na frente dos parâmetros reais da função. `T` é um espaço reservado +que é substituído pelo compilador ao *instanciar* a função usando o operador `!`: add!int(5, 10); add!float(5.0f, 10.0f); - add!Animal(dog, cat); // won't compile; Animal doesn't implement + + add!Animal(dog, cat); // não será compilado; o tipo Animal não implementou `+` -If no template parameter is given for a templated function the compiler -tries to deduce the type using the input parameters with which the function -is called: +### Parâmetros com template implícitos + +As funções de tipos genéricos utilizando template, têm dois conjuntos de parâmetros: +o primeiro é para argumentos de argumentos em tempo de compilação e o segundo para +argumentos em tempo de execução. +(As funções sem template podem aceitar apenas argumentos em tempo de execução). +Se um ou mais argumentos em tempo de compilação não forem especificados quando a função for chamada, +o compilador tentará deduzi-los da lista de argumentos de tempo de execução como os tipos desses argumentos. int a = 5; int b = 10; - add(a, b); // T is to deduced to `int` - float c = 5.0f; - add(a, c); // ERROR: conflict because compiler - // doesn't know what T should be + add(a, b); // T é deduzido como `int` + float c = 5.0; + add(a, c); // T é deduzido como `float` -A function can have any number of template parameters which -are specified during instantiation using the `func!(T1, T2 ..)` -syntax. Template parameters can be of any basic type -including `string`s and floating point numbers. +### Propriedades do template -Unlike generics in Java, templates in D are compile-time only, and yield -highly optimized code tailored to the specific set of types -used when actually calling the function +Diferentemente dos genéricos em Java, os templates em D funcionam apenas em tempo de compilação e produzem código altamente otimizado, adaptado ao conjunto específico de tipos +usados ao chamar a função de fato -Of course, `struct`, `class` and `interface` types can be defined as template -types too. +Obviamente, os tipos `struct`, `class` e `interface` também podem ser definidos como tipos genéricos usando templates também. struct S(T) { // ... } -### In-depth +### Maiores detalhes - [Tutorial to D Templates](https://github.com/PhilippeSigaud/D-templates-tutorial) - [Templates in _Programming in D_](http://ddili.org/ders/d.en/templates.html) -#### Advanced +#### Referências avançadas - [D Templates spec](https://dlang.org/spec/template.html) - [Templates Revisited](http://dlang.org/templates-revisited.html): Walter Bright writes about how D improves upon C++ templates. @@ -57,7 +55,7 @@ types too. ## {SourceCode} ```d -import std.stdio; +import std.stdio : writeln; /** Template class that allows @@ -71,7 +69,7 @@ class Animal(string noise) { } } -class Dog: Animal!("Bark") { +class Dog: Animal!("Woof") { } class Cat: Animal!("Meeoauw") { diff --git a/basics/type-qualifiers.md b/basics/type-qualifiers.md new file mode 100644 index 0000000..0e242b3 --- /dev/null +++ b/basics/type-qualifiers.md @@ -0,0 +1,126 @@ +# Mutabilidade + +D é uma linguagem estaticamente tipada: depois que uma variável é declarada, +seu tipo não pode ser alterado daquele ponto em diante. Isso permite que o +que o compilador evite bugs desde o início e imponha restrições +em tempo de compilação. Uma boa segurança de tipo oferece o suporte necessário +para tornar os programas grandes mais seguros e mais fáceis de manter. + +Há vários qualificadores de tipo em D, mas os mais comumente usados são +`const` e `immutable`. + +### `immutable` + +Além de um sistema de tipos estáticos, o D fornece qualificadores de tipos (às vezes também +chamados de "construtores de tipos") que impõem restrições adicionais a determinados +objetos. Por exemplo, um objeto `immutable` só pode ser inicializado uma vez e +depois disso, não pode ser alterado. + + immutable int err = 5; + // ou: immutable err = 5 e int será inferido. + err = 5; // não compila + +Os objetos `imutáveis` podem, portanto, ser compartilhados com segurança entre diferentes threads sem +sincronização, pois, por definição, eles nunca mudam. Isso também implica que os objetos +os objetos `immutable` podem ser armazenados em cache perfeitamente. + +### `const` + +Os objetos não podem ser modificados por meio de uma referência const. +Uma referência mutável para o mesmo objeto ainda pode modificá-lo. +Um ponteiro `const` pode ser criado a partir de um objeto *mutável* ou +objeto `immutable`. É comum que as APIs aceitem argumentos `const` +para garantir que não modifiquem a entrada, pois isso permite que a mesma +função processe dados mutáveis e imutáveis. + + void foo(const char[] s) + { + // se não for comentada, a próxima linha + // resultará em erro (não é possível modificar const): + // s[0] = 'x'; + + import std.stdio : writeln; + writeln(s); + } + + // graças ao `const`, ambas as chamadas serão compiladas: + foo("abcd"); // string é um array imutável + foo("abcd".dup); // .dup returna uma cópia mutável + +## Transitividade + +Tanto `immutable` quanto `const` são qualificadores de tipo _transitivos_, garantindo assim que, uma vez que `const` seja aplicado a um tipo, ele se aplica recursivamente a cada subcomponente desse tipo. + + immutable int* p = new int; + p = null; // erro + *p = 5; // erro + +O tipo de elemento de um ponteiro (ou array) pode ser qualificado separadamente: + + immutable p = new int; // immutable(int*) + immutable(int)* q = p; // OK, ponteiro mutável + q = null; // OK + *q = 5; // erro + +O tipo [`string`] (basics/alias-strings) é definido como `immutable(char)[]`: + + string s = "hi"; + s ~= " world"; // OK, acrescenta novos caracteres + s[0] = 'c'; // erro, não é possível alterar dados existentes + +### Maiores detalhes + +#### Referências básicas + +- [Immutable in _Programming in D_](http://ddili.org/ders/d.en/const_and_immutable.html) +- [Scopes in _Programming in D_](http://ddili.org/ders/d.en/name_space.html) + +#### Referências avançadas + +- [const(FAQ)](https://dlang.org/const-faq.html) +- [Type qualifiers in D](https://dlang.org/spec/const3.html) + +## {SourceCode} + +```d +import std.stdio : writeln; + +void main() +{ + /** + * Variables are mutable by default and + * editing them is allowed: + */ + int m = 100; // mutable + writeln("m: ", typeof(m).stringof); + m = 10; // fine + + /** + * Pointing to mutable memory: + */ + // A const pointer to mutable memory is + // allowed + const int* cm = &m; + writeln("cm: ", typeof(cm).stringof); + // By defintion `const` can't be modified: + // *cm = 100; // error! + + // As `immutable` is guaranteed to stay + // unchanged, it can't point to + // mutable memory + // immutable int* im = &m; // error! + + /** + * Pointing to read-only memory: + */ + immutable v = 100; + writeln("v: ", typeof(v).stringof); + // v = 5; // error! + + // `const` may point to read-only memory, + // but it is read-only as well + const int* cv = &v; + writeln("cv: ", typeof(cv).stringof); + // *cv = 10; // error! +} +```