|
|
|
|
|
msgid ""
|
|
|
msgstr ""
|
|
|
"Project-Id-Version: Rust Design Patterns\n"
|
|
|
"POT-Creation-Date: \n"
|
|
|
"PO-Revision-Date: 2023-04-08 21:51+0200\n"
|
|
|
"Last-Translator: <EMAIL@ADDRESS>\n"
|
|
|
"Language-Team: Italian\n"
|
|
|
"MIME-Version: 1.0\n"
|
|
|
"Content-Type: text/plain; charset=UTF-8\n"
|
|
|
"Content-Transfer-Encoding: 8bit\n"
|
|
|
"Language: it\n"
|
|
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
|
|
|
|
#: src\SUMMARY.md:3
|
|
|
#, fuzzy
|
|
|
msgid "Introduction"
|
|
|
msgstr "introduzione"
|
|
|
|
|
|
#: src\SUMMARY.md:4
|
|
|
#, fuzzy
|
|
|
msgid "Translations"
|
|
|
msgstr "Traduzioni"
|
|
|
|
|
|
#: src\SUMMARY.md:5
|
|
|
#, fuzzy
|
|
|
msgid "Idioms"
|
|
|
msgstr "Idiomi"
|
|
|
|
|
|
#: src\SUMMARY.md:6
|
|
|
#, fuzzy
|
|
|
msgid "Use borrowed types for arguments"
|
|
|
msgstr "Usa i tipi presi in prestito per gli argomenti"
|
|
|
|
|
|
#: src\SUMMARY.md:7
|
|
|
#, fuzzy
|
|
|
msgid "Concatenating Strings with format!"
|
|
|
msgstr "Concatenare le stringhe con il formato!"
|
|
|
|
|
|
#: src\SUMMARY.md:8
|
|
|
#, fuzzy
|
|
|
msgid "Constructor"
|
|
|
msgstr "Costruttore"
|
|
|
|
|
|
#: src\SUMMARY.md:9
|
|
|
#, fuzzy
|
|
|
msgid "The Default Trait"
|
|
|
msgstr "Il tratto predefinito"
|
|
|
|
|
|
#: src\SUMMARY.md:10
|
|
|
#, fuzzy
|
|
|
msgid "Collections Are Smart Pointers"
|
|
|
msgstr "Le raccolte sono puntatori intelligenti"
|
|
|
|
|
|
#: src\SUMMARY.md:11
|
|
|
#, fuzzy
|
|
|
msgid "Finalisation in Destructors"
|
|
|
msgstr "Finalizzazione in Distruttori"
|
|
|
|
|
|
#: src\SUMMARY.md:12
|
|
|
#, fuzzy
|
|
|
msgid "mem::{take(_), replace(_)}"
|
|
|
msgstr "mem::{prendi(_), sostituisci(_)}"
|
|
|
|
|
|
#: src\SUMMARY.md:13
|
|
|
#, fuzzy
|
|
|
msgid "On-Stack Dynamic Dispatch"
|
|
|
msgstr "Invio dinamico in pila"
|
|
|
|
|
|
#: src\SUMMARY.md:14 src\SUMMARY.md:40
|
|
|
#, fuzzy
|
|
|
msgid "Foreign function interface (FFI)"
|
|
|
msgstr "Interfaccia per funzioni estere (FFI)"
|
|
|
|
|
|
#: src\SUMMARY.md:15
|
|
|
#, fuzzy
|
|
|
msgid "Idiomatic Errors"
|
|
|
msgstr "Errori idiomatici"
|
|
|
|
|
|
#: src\SUMMARY.md:16
|
|
|
#, fuzzy
|
|
|
msgid "Accepting Strings"
|
|
|
msgstr "Accettare stringhe"
|
|
|
|
|
|
#: src\SUMMARY.md:17
|
|
|
#, fuzzy
|
|
|
msgid "Passing Strings"
|
|
|
msgstr "Passare le stringhe"
|
|
|
|
|
|
#: src\SUMMARY.md:18
|
|
|
#, fuzzy
|
|
|
msgid "Iterating over an Option"
|
|
|
msgstr "Iterare su un'opzione"
|
|
|
|
|
|
#: src\SUMMARY.md:19
|
|
|
#, fuzzy
|
|
|
msgid "Pass Variables to Closure"
|
|
|
msgstr "Passa le variabili alla chiusura"
|
|
|
|
|
|
#: src\SUMMARY.md:20
|
|
|
#, fuzzy
|
|
|
msgid "Privacy For Extensibility"
|
|
|
msgstr "Privacy per l'estensibilità"
|
|
|
|
|
|
#: src\SUMMARY.md:21
|
|
|
#, fuzzy
|
|
|
msgid "Easy doc initialization"
|
|
|
msgstr "Facile inizializzazione dei documenti"
|
|
|
|
|
|
#: src\SUMMARY.md:22
|
|
|
#, fuzzy
|
|
|
msgid "Temporary mutability"
|
|
|
msgstr "Mutabilità temporanea"
|
|
|
|
|
|
#: src\SUMMARY.md:23
|
|
|
#, fuzzy
|
|
|
msgid "Return consumed arg on error"
|
|
|
msgstr "Restituisce l'argomento consumato in caso di errore"
|
|
|
|
|
|
#: src\SUMMARY.md:25
|
|
|
#, fuzzy
|
|
|
msgid "Design Patterns"
|
|
|
msgstr "Modelli di progettazione"
|
|
|
|
|
|
#: src\SUMMARY.md:26
|
|
|
#, fuzzy
|
|
|
msgid "Behavioural"
|
|
|
msgstr "Comportamentale"
|
|
|
|
|
|
#: src\SUMMARY.md:27
|
|
|
#, fuzzy
|
|
|
msgid "Command"
|
|
|
msgstr "Comando"
|
|
|
|
|
|
#: src\SUMMARY.md:28
|
|
|
#, fuzzy
|
|
|
msgid "Interpreter"
|
|
|
msgstr "Interprete"
|
|
|
|
|
|
#: src\SUMMARY.md:29
|
|
|
#, fuzzy
|
|
|
msgid "Newtype"
|
|
|
msgstr "Nuovo tipo"
|
|
|
|
|
|
#: src\SUMMARY.md:30
|
|
|
#, fuzzy
|
|
|
msgid "RAII Guards"
|
|
|
msgstr "Guardie Rai"
|
|
|
|
|
|
#: src\SUMMARY.md:31
|
|
|
#, fuzzy
|
|
|
msgid "Strategy"
|
|
|
msgstr "Strategia"
|
|
|
|
|
|
#: src\SUMMARY.md:32
|
|
|
#, fuzzy
|
|
|
msgid "Visitor"
|
|
|
msgstr "Visitatore"
|
|
|
|
|
|
#: src\SUMMARY.md:33
|
|
|
#, fuzzy
|
|
|
msgid "Creational"
|
|
|
msgstr "Creativo"
|
|
|
|
|
|
#: src\SUMMARY.md:34
|
|
|
#, fuzzy
|
|
|
msgid "Builder"
|
|
|
msgstr "Costruttore"
|
|
|
|
|
|
#: src\SUMMARY.md:35
|
|
|
#, fuzzy
|
|
|
msgid "Fold"
|
|
|
msgstr "Piega"
|
|
|
|
|
|
#: src\SUMMARY.md:36
|
|
|
#, fuzzy
|
|
|
msgid "Structural"
|
|
|
msgstr "Strutturale"
|
|
|
|
|
|
#: src\SUMMARY.md:37
|
|
|
#, fuzzy
|
|
|
msgid "Compose Structs"
|
|
|
msgstr "Componi strutture"
|
|
|
|
|
|
#: src\SUMMARY.md:38
|
|
|
#, fuzzy
|
|
|
msgid "Prefer Small Crates"
|
|
|
msgstr "Preferisci casse piccole"
|
|
|
|
|
|
#: src\SUMMARY.md:39
|
|
|
#, fuzzy
|
|
|
msgid "Contain unsafety in small modules"
|
|
|
msgstr "Contenere l'insicurezza in piccoli moduli"
|
|
|
|
|
|
#: src\SUMMARY.md:41
|
|
|
#, fuzzy
|
|
|
msgid "Object-Based APIs"
|
|
|
msgstr "API basate su oggetti"
|
|
|
|
|
|
#: src\SUMMARY.md:42
|
|
|
#, fuzzy
|
|
|
msgid "Type Consolidation into Wrappers"
|
|
|
msgstr "Digitare Consolidamento in wrapper"
|
|
|
|
|
|
#: src\SUMMARY.md:44
|
|
|
#, fuzzy
|
|
|
msgid "Anti-patterns"
|
|
|
msgstr "Anti-modelli"
|
|
|
|
|
|
#: src\SUMMARY.md:45
|
|
|
#, fuzzy
|
|
|
msgid "Clone to satisfy the borrow checker"
|
|
|
msgstr "Clona per soddisfare il controllore del prestito"
|
|
|
|
|
|
#: src\SUMMARY.md:46
|
|
|
#, fuzzy
|
|
|
msgid "#[deny(warnings)]"
|
|
|
msgstr "#[nega(avvisi)]"
|
|
|
|
|
|
#: src\SUMMARY.md:47
|
|
|
#, fuzzy
|
|
|
msgid "Deref Polymorphism"
|
|
|
msgstr "Polimorfismo di Deref"
|
|
|
|
|
|
#: src\SUMMARY.md:49
|
|
|
#, fuzzy
|
|
|
msgid "Functional Programming"
|
|
|
msgstr "Programmazione funzionale"
|
|
|
|
|
|
#: src\SUMMARY.md:50
|
|
|
#, fuzzy
|
|
|
msgid "Programming paradigms"
|
|
|
msgstr "Paradigmi di programmazione"
|
|
|
|
|
|
#: src\SUMMARY.md:51
|
|
|
#, fuzzy
|
|
|
msgid "Generics as Type Classes"
|
|
|
msgstr "Generici come classi di tipo"
|
|
|
|
|
|
#: src\SUMMARY.md:52
|
|
|
#, fuzzy
|
|
|
msgid "Lenses and Prisms"
|
|
|
msgstr "Lenti e prismi"
|
|
|
|
|
|
#: src\SUMMARY.md:54
|
|
|
#, fuzzy
|
|
|
msgid "Additional Resources"
|
|
|
msgstr "Risorse addizionali"
|
|
|
|
|
|
#: src\SUMMARY.md:55
|
|
|
#, fuzzy
|
|
|
msgid "Design principles"
|
|
|
msgstr "Principi di progettazione"
|
|
|
|
|
|
#: src\intro.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Introduction"
|
|
|
msgstr "# Introduzione"
|
|
|
|
|
|
#: src\intro.md:3
|
|
|
#, fuzzy
|
|
|
msgid "## Participation"
|
|
|
msgstr "## Partecipazione"
|
|
|
|
|
|
#: src\intro.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"If you are interested in contributing to this book, check out the\n"
|
|
|
"[contribution "
|
|
|
"guidelines](https://github.com/rust-unofficial/patterns/blob/master/CONTRIBUTING.md)."
|
|
|
msgstr ""
|
|
|
"Se sei interessato a contribuire a questo libro, dai un'occhiata al\n"
|
|
|
"[linee guida per il "
|
|
|
"contributo](https://github.com/rust-unofficial/patterns/blob/master/CONTRIBUTING.md)."
|
|
|
|
|
|
#: src\intro.md:8
|
|
|
#, fuzzy
|
|
|
msgid "## Design patterns"
|
|
|
msgstr "## Modelli di progettazione"
|
|
|
|
|
|
#: src\intro.md:10
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"In software development, we often come across problems that share\n"
|
|
|
"similarities regardless of the environment they appear in. Although the\n"
|
|
|
"implementation details are crucial to solve the task at hand, we may\n"
|
|
|
"abstract from these particularities to find the common practices that\n"
|
|
|
"are generically applicable."
|
|
|
msgstr ""
|
|
|
"Nello sviluppo del software, spesso incontriamo problemi che condividono\n"
|
|
|
"somiglianze indipendentemente dall'ambiente in cui appaiono\n"
|
|
|
"i dettagli di implementazione sono cruciali per risolvere il compito a "
|
|
|
"portata di mano, potremmo\n"
|
|
|
"astratto da queste particolarità per trovare le pratiche comuni che\n"
|
|
|
"sono genericamente applicabili."
|
|
|
|
|
|
#: src\intro.md:16
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Design patterns are a collection of reusable and tested solutions to\n"
|
|
|
"recurring problems in engineering. They make our software more modular,\n"
|
|
|
"maintainable, and extensible. Moreover, these patterns provide a common\n"
|
|
|
"language for developers, making them an excellent tool for effective\n"
|
|
|
"communication when problem-solving in teams."
|
|
|
msgstr ""
|
|
|
"I modelli di progettazione sono una raccolta di soluzioni riutilizzabili e "
|
|
|
"testate per\n"
|
|
|
"problemi ricorrenti in ingegneria. Rendono il nostro software più modulare,\n"
|
|
|
"manutenibile ed estensibile. Inoltre, questi modelli forniscono un comune\n"
|
|
|
"linguaggio per sviluppatori, rendendoli uno strumento eccellente per "
|
|
|
"efficaci\n"
|
|
|
"comunicazione durante la risoluzione dei problemi in team."
|
|
|
|
|
|
#: src\intro.md:22 src\patterns/index.md:14
|
|
|
#, fuzzy
|
|
|
msgid "## Design patterns in Rust"
|
|
|
msgstr "## Modelli di design in Rust"
|
|
|
|
|
|
#: src\intro.md:24
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Rust is not object-oriented, and the combination of all its "
|
|
|
"characteristics,\n"
|
|
|
"such as functional elements, a strong type system, and the borrow checker,\n"
|
|
|
"makes it unique.\n"
|
|
|
"Because of this, Rust design patterns vary with respect to other\n"
|
|
|
"traditional object-oriented programming languages.\n"
|
|
|
"That's why we decided to write this book. We hope you enjoy reading it!\n"
|
|
|
"The book is divided in three main chapters:"
|
|
|
msgstr ""
|
|
|
"Rust non è orientato agli oggetti e la combinazione di tutte le sue "
|
|
|
"caratteristiche,\n"
|
|
|
"come elementi funzionali, un forte sistema di tipi e il controllo del "
|
|
|
"prestito,\n"
|
|
|
"lo rende unico.\n"
|
|
|
"Per questo motivo, i modelli di design di Rust variano rispetto ad altri\n"
|
|
|
"linguaggi di programmazione tradizionali orientati agli oggetti.\n"
|
|
|
"Ecco perché abbiamo deciso di scrivere questo libro. Ci auguriamo che ti "
|
|
|
"piaccia leggerlo!\n"
|
|
|
"Il libro è diviso in tre capitoli principali:"
|
|
|
|
|
|
#: src\intro.md:32
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [Idioms](./idioms/index.md): guidelines to follow when coding.\n"
|
|
|
" They are the social norms of the community.\n"
|
|
|
" You should break them only if you have a good reason for it.\n"
|
|
|
"- [Design patterns](./patterns/index.md): methods to solve common problems\n"
|
|
|
" when coding.\n"
|
|
|
"- [Anti-patterns](./anti_patterns/index.md): methods to solve common "
|
|
|
"problems\n"
|
|
|
" when coding.\n"
|
|
|
" However, while design patterns give us benefits,\n"
|
|
|
" anti-patterns create more problems."
|
|
|
msgstr ""
|
|
|
"- [Idioms](./idioms/index.md): linee guida da seguire durante la codifica.\n"
|
|
|
" Sono le norme sociali della comunità.\n"
|
|
|
" Dovresti romperli solo se hai una buona ragione per farlo.\n"
|
|
|
"- [Design patterns](./patterns/index.md): metodi per risolvere problemi "
|
|
|
"comuni\n"
|
|
|
" durante la codifica.\n"
|
|
|
"- [Anti-patterns](./anti_patterns/index.md): metodi per risolvere problemi "
|
|
|
"comuni\n"
|
|
|
" durante la codifica.\n"
|
|
|
" Tuttavia, mentre i design pattern ci danno dei vantaggi,\n"
|
|
|
" gli anti-pattern creano più problemi."
|
|
|
|
|
|
#: src\translations.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Translations"
|
|
|
msgstr "# Traduzioni"
|
|
|
|
|
|
#: src\translations.md:3
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"We are utilizing "
|
|
|
"[mdbook-i18n-helper](https://github.com/google/mdbook-i18n-helpers).\n"
|
|
|
"Please read up on how to _add_ and _update_ translations in [their "
|
|
|
"repository](https://github.com/google/mdbook-i18n-helpers#creating-and-updating-translations)"
|
|
|
msgstr ""
|
|
|
"Stiamo utilizzando "
|
|
|
"[mdbook-i18n-helper](https://github.com/google/mdbook-i18n-helpers).\n"
|
|
|
"Leggi come _aggiungere_ e _aggiornare_ le traduzioni nel [loro "
|
|
|
"repository](https://github.com/google/mdbook-i18n-helpers#creating-and-updating-translations)"
|
|
|
|
|
|
#: src\translations.md:6
|
|
|
#, fuzzy
|
|
|
msgid "## External translations"
|
|
|
msgstr "## Traduzioni esterne"
|
|
|
|
|
|
#: src\translations.md:8
|
|
|
#, fuzzy
|
|
|
msgid "- [简体中文](https://fomalhauthmj.github.io/patterns/)"
|
|
|
msgstr "- [简体中文](https://fomalhauthmj.github.io/patterns/)"
|
|
|
|
|
|
#: src\translations.md:10
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"If you want to add a translation, please open an issue in the\n"
|
|
|
"[main repository](https://github.com/rust-unofficial/patterns)."
|
|
|
msgstr ""
|
|
|
"Se desideri aggiungere una traduzione, apri un problema nel file\n"
|
|
|
"[repository principale](https://github.com/rust-unofficial/patterns)."
|
|
|
|
|
|
#: src\idioms/index.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Idioms"
|
|
|
msgstr "# Idiomi"
|
|
|
|
|
|
#: src\idioms/index.md:3
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"[Idioms](https://en.wikipedia.org/wiki/Programming_idiom) are commonly used\n"
|
|
|
"styles, guidelines and patterns largely agreed upon by a community.\n"
|
|
|
"Writing idiomatic code allows other developers to understand better what is\n"
|
|
|
"happening."
|
|
|
msgstr ""
|
|
|
"[Idioms](https://en.wikipedia.org/wiki/Programming_idiom) sono comunemente "
|
|
|
"usati\n"
|
|
|
"stili, linee guida e modelli ampiamente concordati da una comunità.\n"
|
|
|
"Scrivere codice idiomatico consente ad altri sviluppatori di capire meglio "
|
|
|
"cos'è\n"
|
|
|
"accadendo."
|
|
|
|
|
|
#: src\idioms/index.md:8
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"After all, the computer only cares about the machine code that is generated\n"
|
|
|
"by the compiler.\n"
|
|
|
"Instead, the source code is mainly beneficial to the developer.\n"
|
|
|
"So, since we have this abstraction layer, why not make it more readable?"
|
|
|
msgstr ""
|
|
|
"Dopotutto, al computer interessa solo il codice macchina che viene generato\n"
|
|
|
"dal compilatore.\n"
|
|
|
"Invece, il codice sorgente è principalmente vantaggioso per lo "
|
|
|
"sviluppatore.\n"
|
|
|
"Quindi, visto che abbiamo questo livello di astrazione, perché non renderlo "
|
|
|
"più leggibile?"
|
|
|
|
|
|
#: src\idioms/index.md:13
|
|
|
msgid ""
|
|
|
"Remember the [KISS "
|
|
|
"principle](https://en.wikipedia.org/wiki/KISS_principle):\n"
|
|
|
"\"Keep It Simple, Stupid\". It claims that \"most systems work best if they "
|
|
|
"are\n"
|
|
|
"kept simple rather than made complicated; therefore, simplicity should be a "
|
|
|
"key\n"
|
|
|
"goal in design, and unnecessary complexity should be avoided\"."
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/index.md:18
|
|
|
#, fuzzy
|
|
|
msgid "> Code is there for humans, not computers, to understand."
|
|
|
msgstr "> Il codice è lì per essere compreso dagli umani, non dai computer."
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Use borrowed types for arguments"
|
|
|
msgstr "# Usa i tipi presi in prestito per gli argomenti"
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:3 src\idioms/concat-format.md:3
|
|
|
#: src\idioms/default.md:3 src\idioms/deref.md:3 src\idioms/dtor-finally.md:3
|
|
|
#: src\idioms/mem-replace.md:3 src\idioms/on-stack-dyn-dispatch.md:3
|
|
|
#: src\idioms/ffi/errors.md:3 src\idioms/ffi/accepting-strings.md:3
|
|
|
#: src\idioms/ffi/passing-strings.md:3 src\idioms/option-iter.md:3
|
|
|
#: src\idioms/pass-var-to-closure.md:3 src\idioms/priv-extend.md:3
|
|
|
#: src\idioms/temporary-mutability.md:3
|
|
|
#: src\idioms/return-consumed-arg-on-error.md:3
|
|
|
#: src\patterns/behavioural/command.md:3
|
|
|
#: src\patterns/behavioural/interpreter.md:3
|
|
|
#: src\patterns/behavioural/newtype.md:13 src\patterns/behavioural/RAII.md:3
|
|
|
#: src\patterns/behavioural/strategy.md:3 src\patterns/behavioural/visitor.md:3
|
|
|
#: src\patterns/creational/builder.md:3 src\patterns/creational/fold.md:3
|
|
|
#: src\patterns/structural/compose-structs.md:5
|
|
|
#: src\patterns/structural/small-crates.md:3
|
|
|
#: src\patterns/structural/unsafe-mods.md:3 src\patterns/ffi/export.md:3
|
|
|
#: src\patterns/ffi/wrappers.md:3 src\anti_patterns/borrow_clone.md:3
|
|
|
#: src\anti_patterns/deny-warnings.md:3 src\anti_patterns/deref.md:3
|
|
|
#: src\functional/generics-type-classes.md:3
|
|
|
#, fuzzy
|
|
|
msgid "## Description"
|
|
|
msgstr "## Descrizione"
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Using a target of a deref coercion can increase the flexibility of your "
|
|
|
"code\n"
|
|
|
"when you are deciding which argument type to use for a function argument.\n"
|
|
|
"In this way, the function will accept more input types."
|
|
|
msgstr ""
|
|
|
"L'utilizzo di un obiettivo di una coercizione deref può aumentare la "
|
|
|
"flessibilità del codice\n"
|
|
|
"quando si decide quale tipo di argomento utilizzare per un argomento di "
|
|
|
"funzione.\n"
|
|
|
"In questo modo, la funzione accetterà più tipi di input."
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:9
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This is not limited to slice-able or fat pointer types.\n"
|
|
|
"In fact, you should always prefer using the **borrowed type** over\n"
|
|
|
"**borrowing the owned type**.\n"
|
|
|
"Such as `&str` over `&String`, `&[T]` over `&Vec<T>`, or `&T` over `&Box<T>`."
|
|
|
msgstr ""
|
|
|
"Questo non è limitato ai tipi di puntatore slice-able o fat.\n"
|
|
|
"In effetti, dovresti sempre preferire l'utilizzo del **tipo preso in "
|
|
|
"prestito**\n"
|
|
|
"**prendendo in prestito il tipo di proprietà**.\n"
|
|
|
"Ad esempio `&str` su `&String`, `&[T]` su `&Vec<T>` o `&T` su `&Box<T>`."
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:14
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Using borrowed types you can avoid layers of indirection for those "
|
|
|
"instances\n"
|
|
|
"where the owned type already provides a layer of indirection. For instance, "
|
|
|
"a\n"
|
|
|
"`String` has a layer of indirection, so a `&String` will have two layers of\n"
|
|
|
"indirection. We can avoid this by using `&str` instead, and letting "
|
|
|
"`&String`\n"
|
|
|
"coerce to a `&str` whenever the function is invoked."
|
|
|
msgstr ""
|
|
|
"Utilizzando i tipi presi in prestito è possibile evitare livelli di "
|
|
|
"riferimento indiretto per tali istanze\n"
|
|
|
"dove il tipo di proprietà fornisce già uno strato di riferimento indiretto. "
|
|
|
"Ad esempio, a\n"
|
|
|
"\"Stringa\" ha uno strato di riferimento indiretto, quindi una \"&Stringa\" "
|
|
|
"avrà due strati di\n"
|
|
|
"indiretto. Possiamo evitarlo usando invece `&str` e lasciando `&String`\n"
|
|
|
"forzare a un `&str` ogni volta che la funzione viene invocata."
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:20 src\idioms/concat-format.md:10
|
|
|
#: src\idioms/default.md:20 src\idioms/deref.md:9 src\idioms/dtor-finally.md:9
|
|
|
#: src\idioms/mem-replace.md:11 src\idioms/on-stack-dyn-dispatch.md:10
|
|
|
#: src\idioms/pass-var-to-closure.md:12 src\idioms/priv-extend.md:18
|
|
|
#: src\idioms/temporary-mutability.md:12
|
|
|
#: src\idioms/return-consumed-arg-on-error.md:8
|
|
|
#: src\patterns/behavioural/command.md:18
|
|
|
#: src\patterns/behavioural/newtype.md:18 src\patterns/behavioural/RAII.md:11
|
|
|
#: src\patterns/behavioural/strategy.md:28
|
|
|
#: src\patterns/behavioural/visitor.md:13 src\patterns/creational/builder.md:7
|
|
|
#: src\patterns/creational/fold.md:12
|
|
|
#: src\patterns/structural/compose-structs.md:17
|
|
|
#: src\anti_patterns/borrow_clone.md:11 src\anti_patterns/deny-warnings.md:8
|
|
|
#: src\anti_patterns/deref.md:8 src\functional/generics-type-classes.md:38
|
|
|
#, fuzzy
|
|
|
msgid "## Example"
|
|
|
msgstr "## Esempio"
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:22
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"For this example, we will illustrate some differences for using `&String` as "
|
|
|
"a\n"
|
|
|
"function argument versus using a `&str`, but the ideas apply as well to "
|
|
|
"using\n"
|
|
|
"`&Vec<T>` versus using a `&[T]` or using a `&Box<T>` versus a `&T`."
|
|
|
msgstr ""
|
|
|
"Per questo esempio, illustreremo alcune differenze per l'utilizzo di "
|
|
|
"`&String` come a\n"
|
|
|
"argomento della funzione rispetto all'utilizzo di un `&str`, ma le idee si "
|
|
|
"applicano anche all'utilizzo\n"
|
|
|
"`&Vec<T>` rispetto all'utilizzo di un `&[T]` o all'utilizzo di un `&Box<T>` "
|
|
|
"rispetto a un `&T`."
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:26
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Consider an example where we wish to determine if a word contains three\n"
|
|
|
"consecutive vowels. We don't need to own the string to determine this, so "
|
|
|
"we\n"
|
|
|
"will take a reference."
|
|
|
msgstr ""
|
|
|
"Considera un esempio in cui desideriamo determinare se una parola ne "
|
|
|
"contiene tre\n"
|
|
|
"vocali consecutive. Non abbiamo bisogno di possedere la stringa per "
|
|
|
"determinarlo, quindi noi\n"
|
|
|
"prenderà un riferimento."
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:30
|
|
|
#, fuzzy
|
|
|
msgid "The code might look something like this:"
|
|
|
msgstr "Il codice potrebbe essere simile a questo:"
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:32
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"fn three_vowels(word: &String) -> bool {\n"
|
|
|
" let mut vowel_count = 0;\n"
|
|
|
" for c in word.chars() {\n"
|
|
|
" match c {\n"
|
|
|
" 'a' | 'e' | 'i' | 'o' | 'u' => {\n"
|
|
|
" vowel_count += 1;\n"
|
|
|
" if vowel_count >= 3 {\n"
|
|
|
" return true\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
" _ => vowel_count = 0\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
" false\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn main() {\n"
|
|
|
" let ferris = \"Ferris\".to_string();\n"
|
|
|
" let curious = \"Curious\".to_string();\n"
|
|
|
" println!(\"{}: {}\", ferris, three_vowels(&ferris));\n"
|
|
|
" println!(\"{}: {}\", curious, three_vowels(&curious));\n"
|
|
|
"\n"
|
|
|
" // This works fine, but the following two lines would fail:\n"
|
|
|
" // println!(\"Ferris: {}\", three_vowels(\"Ferris\"));\n"
|
|
|
" // println!(\"Curious: {}\", three_vowels(\"Curious\"));\n"
|
|
|
"\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:62
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This works fine because we are passing a `&String` type as a parameter.\n"
|
|
|
"If we remove the comments on the last two lines, the example will fail. "
|
|
|
"This\n"
|
|
|
"is because a `&str` type will not coerce to a `&String` type. We can fix "
|
|
|
"this\n"
|
|
|
"by simply modifying the type for our argument."
|
|
|
msgstr ""
|
|
|
"Funziona bene perché stiamo passando un tipo `&String` come parametro.\n"
|
|
|
"Se rimuoviamo i commenti sulle ultime due righe, l'esempio fallirà. Questo\n"
|
|
|
"è perché un tipo `&str` non costringerà a un tipo `&String`. Possiamo "
|
|
|
"risolvere questo problema\n"
|
|
|
"semplicemente modificando il tipo per il nostro argomento."
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:67
|
|
|
#, fuzzy
|
|
|
msgid "For instance, if we change our function declaration to:"
|
|
|
msgstr "Ad esempio, se cambiamo la nostra dichiarazione di funzione in:"
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:69
|
|
|
msgid ""
|
|
|
"```rust, ignore\n"
|
|
|
"fn three_vowels(word: &str) -> bool {\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:73
|
|
|
#, fuzzy
|
|
|
msgid "then both versions will compile and print the same output."
|
|
|
msgstr "quindi entrambe le versioni compileranno e stamperanno lo stesso output."
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:75
|
|
|
msgid ""
|
|
|
"```bash\n"
|
|
|
"Ferris: false\n"
|
|
|
"Curious: true\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:80
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"But wait, that's not all! There is more to this story.\n"
|
|
|
"It's likely that you may say to yourself: that doesn't matter, I will never "
|
|
|
"be\n"
|
|
|
"using a `&'static str` as an input anyways (as we did when we used "
|
|
|
"`\"Ferris\"`).\n"
|
|
|
"Even ignoring this special example, you may still find that using `&str` "
|
|
|
"will\n"
|
|
|
"give you more flexibility than using a `&String`."
|
|
|
msgstr ""
|
|
|
"Ma aspetta, non è tutto! C'è di più su questa storia.\n"
|
|
|
"È probabile che tu possa dire a te stesso: non importa, non lo sarò mai\n"
|
|
|
"usando comunque una `&'static str` come input (come abbiamo fatto quando "
|
|
|
"abbiamo usato `\"Ferris\"`).\n"
|
|
|
"Anche ignorando questo esempio speciale, potresti comunque scoprire che "
|
|
|
"l'uso di `&str` lo farà\n"
|
|
|
"ti offre maggiore flessibilità rispetto all'utilizzo di una `&Stringa`."
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:86
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Let's now take an example where someone gives us a sentence, and we want to\n"
|
|
|
"determine if any of the words in the sentence contain three consecutive "
|
|
|
"vowels.\n"
|
|
|
"We probably should make use of the function we have already defined and "
|
|
|
"simply\n"
|
|
|
"feed in each word from the sentence."
|
|
|
msgstr ""
|
|
|
"Facciamo ora un esempio in cui qualcuno ci dà una frase, e noi vogliamo\n"
|
|
|
"determinare se una qualsiasi delle parole nella frase contiene tre vocali "
|
|
|
"consecutive.\n"
|
|
|
"Probabilmente dovremmo utilizzare la funzione che abbiamo già definito e "
|
|
|
"semplicemente\n"
|
|
|
"inserire ogni parola della frase."
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:91
|
|
|
#, fuzzy
|
|
|
msgid "An example of this could look like this:"
|
|
|
msgstr "Un esempio di questo potrebbe assomigliare a questo:"
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:93
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"fn three_vowels(word: &str) -> bool {\n"
|
|
|
" let mut vowel_count = 0;\n"
|
|
|
" for c in word.chars() {\n"
|
|
|
" match c {\n"
|
|
|
" 'a' | 'e' | 'i' | 'o' | 'u' => {\n"
|
|
|
" vowel_count += 1;\n"
|
|
|
" if vowel_count >= 3 {\n"
|
|
|
" return true\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
" _ => vowel_count = 0\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
" false\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn main() {\n"
|
|
|
" let sentence_string =\n"
|
|
|
" \"Once upon a time, there was a friendly curious crab named "
|
|
|
"Ferris\".to_string();\n"
|
|
|
" for word in sentence_string.split(' ') {\n"
|
|
|
" if three_vowels(word) {\n"
|
|
|
" println!(\"{} has three consecutive vowels!\", word);\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:121
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Running this example using our function declared with an argument type "
|
|
|
"`&str`\n"
|
|
|
"will yield"
|
|
|
msgstr ""
|
|
|
"Eseguire questo esempio usando la nostra funzione dichiarata con un tipo di "
|
|
|
"argomento `&str`\n"
|
|
|
"cederà"
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:124
|
|
|
msgid ""
|
|
|
"```bash\n"
|
|
|
"curious has three consecutive vowels!\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:128
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"However, this example will not run when our function is declared with an\n"
|
|
|
"argument type `&String`. This is because string slices are a `&str` and not "
|
|
|
"a\n"
|
|
|
"`&String` which would require an allocation to be converted to `&String` "
|
|
|
"which\n"
|
|
|
"is not implicit, whereas converting from `String` to `&str` is cheap and "
|
|
|
"implicit."
|
|
|
msgstr ""
|
|
|
"Tuttavia, questo esempio non verrà eseguito quando la nostra funzione viene "
|
|
|
"dichiarata con an\n"
|
|
|
"tipo di argomento `&Stringa`. Questo perché le sezioni di stringa sono un "
|
|
|
"`&str` e non un\n"
|
|
|
"`&String` che richiederebbe la conversione di un'allocazione in `&String` "
|
|
|
"which\n"
|
|
|
"non è implicito, mentre la conversione da `String` a `&str` è economica e "
|
|
|
"implicita."
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:133 src\idioms/default.md:58
|
|
|
#: src\idioms/deref.md:76 src\idioms/dtor-finally.md:88
|
|
|
#: src\idioms/mem-replace.md:108 src\idioms/on-stack-dyn-dispatch.md:83
|
|
|
#: src\idioms/option-iter.md:46 src\idioms/priv-extend.md:120
|
|
|
#: src\patterns/behavioural/command.md:218
|
|
|
#: src\patterns/behavioural/interpreter.md:142
|
|
|
#: src\patterns/behavioural/newtype.md:104 src\patterns/behavioural/RAII.md:111
|
|
|
#: src\patterns/behavioural/strategy.md:174
|
|
|
#: src\patterns/behavioural/visitor.md:106
|
|
|
#: src\patterns/creational/builder.md:108 src\patterns/creational/fold.md:109
|
|
|
#: src\patterns/structural/small-crates.md:45
|
|
|
#: src\patterns/structural/unsafe-mods.md:32
|
|
|
#: src\anti_patterns/borrow_clone.md:68 src\anti_patterns/deny-warnings.md:96
|
|
|
#: src\anti_patterns/deref.md:123 src\functional/generics-type-classes.md:237
|
|
|
#, fuzzy
|
|
|
msgid "## See also"
|
|
|
msgstr "## Guarda anche"
|
|
|
|
|
|
#: src\idioms/coercion-arguments.md:135
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [Rust Language Reference on Type "
|
|
|
"Coercions](https://doc.rust-lang.org/reference/type-coercions.html)\n"
|
|
|
"- For more discussion on how to handle `String` and `&str` see\n"
|
|
|
" [this blog series "
|
|
|
"(2015)](https://web.archive.org/web/20201112023149/https://hermanradtke.com/2015/05/03/string-vs-str-in-rust-functions.html)\n"
|
|
|
" by Herman J. Radtke III"
|
|
|
msgstr ""
|
|
|
"- [Riferimento al linguaggio Rust sulle coercizioni di "
|
|
|
"tipo](https://doc.rust-lang.org/reference/type-coercions.html)\n"
|
|
|
"- Per ulteriori discussioni su come gestire `String` e `&str` vedere\n"
|
|
|
" [questa serie di blog "
|
|
|
"(2015)](https://web.archive.org/web/20201112023149/https://hermanradtke.com/2015/05/03/string-vs-str-in-rust-functions.html "
|
|
|
")\n"
|
|
|
" di Hermann J. Radtke III"
|
|
|
|
|
|
#: src\idioms/concat-format.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Concatenating strings with `format!`"
|
|
|
msgstr "# Concatenazione di stringhe con `format!`"
|
|
|
|
|
|
#: src\idioms/concat-format.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"It is possible to build up strings using the `push` and `push_str` methods "
|
|
|
"on a\n"
|
|
|
"mutable `String`, or using its `+` operator. However, it is often more\n"
|
|
|
"convenient to use `format!`, especially where there is a mix of literal and\n"
|
|
|
"non-literal strings."
|
|
|
msgstr ""
|
|
|
"È possibile creare stringhe usando i metodi `push` e `push_str` su a\n"
|
|
|
"mutabile `Stringa`, o usando il suo operatore `+`. Tuttavia, spesso è di "
|
|
|
"più\n"
|
|
|
"conveniente usare `format!`, specialmente dove c'è un misto di letterale e\n"
|
|
|
"stringhe non letterali."
|
|
|
|
|
|
#: src\idioms/concat-format.md:12
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"fn say_hello(name: &str) -> String {\n"
|
|
|
" // We could construct the result string manually.\n"
|
|
|
" // let mut result = \"Hello \".to_owned();\n"
|
|
|
" // result.push_str(name);\n"
|
|
|
" // result.push('!');\n"
|
|
|
" // result\n"
|
|
|
"\n"
|
|
|
" // But using format! is better.\n"
|
|
|
" format!(\"Hello {}!\", name)\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/concat-format.md:25 src\idioms/deref.md:43
|
|
|
#: src\idioms/dtor-finally.md:42 src\idioms/mem-replace.md:83
|
|
|
#: src\idioms/on-stack-dyn-dispatch.md:48 src\idioms/ffi/errors.md:131
|
|
|
#: src\idioms/ffi/accepting-strings.md:68 src\idioms/ffi/passing-strings.md:68
|
|
|
#: src\idioms/pass-var-to-closure.md:48 src\idioms/temporary-mutability.md:38
|
|
|
#: src\idioms/return-consumed-arg-on-error.md:55
|
|
|
#: src\patterns/behavioural/newtype.md:66 src\patterns/behavioural/RAII.md:78
|
|
|
#: src\patterns/behavioural/strategy.md:96
|
|
|
#: src\patterns/creational/builder.md:68
|
|
|
#: src\patterns/structural/compose-structs.md:75
|
|
|
#: src\patterns/structural/small-crates.md:12
|
|
|
#: src\patterns/structural/unsafe-mods.md:11 src\patterns/ffi/export.md:111
|
|
|
#: src\patterns/ffi/wrappers.md:63 src\anti_patterns/deny-warnings.md:16
|
|
|
#: src\anti_patterns/deref.md:69 src\functional/generics-type-classes.md:210
|
|
|
#, fuzzy
|
|
|
msgid "## Advantages"
|
|
|
msgstr "## Vantaggi"
|
|
|
|
|
|
#: src\idioms/concat-format.md:27
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Using `format!` is usually the most succinct and readable way to combine "
|
|
|
"strings."
|
|
|
msgstr ""
|
|
|
"Usare `format!` è di solito il modo più succinto e leggibile per combinare "
|
|
|
"le stringhe."
|
|
|
|
|
|
#: src\idioms/concat-format.md:29 src\idioms/deref.md:50
|
|
|
#: src\idioms/dtor-finally.md:47 src\idioms/mem-replace.md:87
|
|
|
#: src\idioms/on-stack-dyn-dispatch.md:54 src\idioms/ffi/errors.md:136
|
|
|
#: src\idioms/ffi/accepting-strings.md:141
|
|
|
#: src\idioms/ffi/passing-strings.md:103 src\idioms/pass-var-to-closure.md:57
|
|
|
#: src\idioms/temporary-mutability.md:42
|
|
|
#: src\idioms/return-consumed-arg-on-error.md:59
|
|
|
#: src\patterns/behavioural/newtype.md:77
|
|
|
#: src\patterns/behavioural/strategy.md:104
|
|
|
#: src\patterns/creational/builder.md:76
|
|
|
#: src\patterns/structural/compose-structs.md:81
|
|
|
#: src\patterns/structural/small-crates.md:22
|
|
|
#: src\patterns/structural/unsafe-mods.md:17 src\patterns/ffi/export.md:234
|
|
|
#: src\patterns/ffi/wrappers.md:69 src\anti_patterns/deref.md:81
|
|
|
#: src\functional/generics-type-classes.md:221
|
|
|
#, fuzzy
|
|
|
msgid "## Disadvantages"
|
|
|
msgstr "## Svantaggi"
|
|
|
|
|
|
#: src\idioms/concat-format.md:31
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"It is usually not the most efficient way to combine strings - a series of "
|
|
|
"`push`\n"
|
|
|
"operations on a mutable string is usually the most efficient (especially if "
|
|
|
"the\n"
|
|
|
"string has been pre-allocated to the expected size)."
|
|
|
msgstr ""
|
|
|
"Di solito non è il modo più efficiente per combinare le stringhe: una serie "
|
|
|
"di \"push\".\n"
|
|
|
"operazioni su una stringa mutabile è solitamente la più efficiente "
|
|
|
"(specialmente se il\n"
|
|
|
"la stringa è stata preallocata alla dimensione prevista)."
|
|
|
|
|
|
#: src\idioms/ctor.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Constructors\r"
|
|
|
msgstr "# Costruttori\r"
|
|
|
|
|
|
#: src\idioms/ctor.md:3 src\idioms/rustdoc-init.md:3
|
|
|
#, fuzzy
|
|
|
msgid "## Description\r"
|
|
|
msgstr "## Descrizione\r"
|
|
|
|
|
|
#: src\idioms/ctor.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Rust does not have constructors as a language construct. Instead, the\r\n"
|
|
|
"convention is to use an [associated function][associated function] `new` to "
|
|
|
"create an object:"
|
|
|
msgstr ""
|
|
|
"Rust non ha costruttori come costrutto del linguaggio. Invece il\r\n"
|
|
|
"convenzione è usare una [funzione associata][funzione associata] `new` per "
|
|
|
"creare un oggetto:"
|
|
|
|
|
|
#: src\idioms/ctor.md:8
|
|
|
msgid ""
|
|
|
"````rust\r\n"
|
|
|
"/// Time in seconds.\r\n"
|
|
|
"///\r\n"
|
|
|
"/// # Example\r\n"
|
|
|
"///\r\n"
|
|
|
"/// ```\r\n"
|
|
|
"/// let s = Second::new(42);\r\n"
|
|
|
"/// assert_eq!(42, s.value());\r\n"
|
|
|
"/// ```\r\n"
|
|
|
"pub struct Second {\r\n"
|
|
|
" value: u64\r\n"
|
|
|
"}\r\n"
|
|
|
"\r\n"
|
|
|
"impl Second {\r\n"
|
|
|
" // Constructs a new instance of [`Second`].\r\n"
|
|
|
" // Note this is an associated function - no self.\r\n"
|
|
|
" pub fn new(value: u64) -> Self {\r\n"
|
|
|
" Self { value }\r\n"
|
|
|
" }\r\n"
|
|
|
"\r\n"
|
|
|
" /// Returns the value in seconds.\r\n"
|
|
|
" pub fn value(&self) -> u64 {\r\n"
|
|
|
" self.value\r\n"
|
|
|
" }\r\n"
|
|
|
"}\r\n"
|
|
|
"````"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/ctor.md:35
|
|
|
#, fuzzy
|
|
|
msgid "## Default Constructors\r"
|
|
|
msgstr "## Costruttori predefiniti\r"
|
|
|
|
|
|
#: src\idioms/ctor.md:37
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Rust supports default constructors with the [`Default`][std-default] trait:"
|
|
|
msgstr ""
|
|
|
"Rust supporta i costruttori predefiniti con il tratto "
|
|
|
"[`Default`][std-default]:"
|
|
|
|
|
|
#: src\idioms/ctor.md:39
|
|
|
msgid ""
|
|
|
"````rust\r\n"
|
|
|
"/// Time in seconds.\r\n"
|
|
|
"///\r\n"
|
|
|
"/// # Example\r\n"
|
|
|
"///\r\n"
|
|
|
"/// ```\r\n"
|
|
|
"/// let s = Second::default();\r\n"
|
|
|
"/// assert_eq!(0, s.value());\r\n"
|
|
|
"/// ```\r\n"
|
|
|
"pub struct Second {\r\n"
|
|
|
" value: u64\r\n"
|
|
|
"}\r\n"
|
|
|
"\r\n"
|
|
|
"impl Second {\r\n"
|
|
|
" /// Returns the value in seconds.\r\n"
|
|
|
" pub fn value(&self) -> u64 {\r\n"
|
|
|
" self.value\r\n"
|
|
|
" }\r\n"
|
|
|
"}\r\n"
|
|
|
"\r\n"
|
|
|
"impl Default for Second {\r\n"
|
|
|
" fn default() -> Self {\r\n"
|
|
|
" Self { value: 0 }\r\n"
|
|
|
" }\r\n"
|
|
|
"}\r\n"
|
|
|
"````"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/ctor.md:66
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"`Default` can also be derived if all types of all fields implement "
|
|
|
"`Default`,\r\n"
|
|
|
"like they do with `Second`:"
|
|
|
msgstr ""
|
|
|
"`Default` può anche essere derivato se tutti i tipi di tutti i campi "
|
|
|
"implementano `Default`,\r\n"
|
|
|
"come fanno con `Secondo`:"
|
|
|
|
|
|
#: src\idioms/ctor.md:69
|
|
|
msgid ""
|
|
|
"````rust\r\n"
|
|
|
"/// Time in seconds.\r\n"
|
|
|
"///\r\n"
|
|
|
"/// # Example\r\n"
|
|
|
"///\r\n"
|
|
|
"/// ```\r\n"
|
|
|
"/// let s = Second::default();\r\n"
|
|
|
"/// assert_eq!(0, s.value());\r\n"
|
|
|
"/// ```\r\n"
|
|
|
"#[derive(Default)]\r\n"
|
|
|
"pub struct Second {\r\n"
|
|
|
" value: u64\r\n"
|
|
|
"}\r\n"
|
|
|
"\r\n"
|
|
|
"impl Second {\r\n"
|
|
|
" /// Returns the value in seconds.\r\n"
|
|
|
" pub fn value(&self) -> u64 {\r\n"
|
|
|
" self.value\r\n"
|
|
|
" }\r\n"
|
|
|
"}\r\n"
|
|
|
"````"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/ctor.md:91
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"**Note:** It is common and expected for types to implement both\r\n"
|
|
|
"`Default` and an empty `new` constructor. `new` is the constructor\r\n"
|
|
|
"convention in Rust, and users expect it to exist, so if it is\r\n"
|
|
|
"reasonable for the basic constructor to take no arguments, then it\r\n"
|
|
|
"should, even if it is functionally identical to default."
|
|
|
msgstr ""
|
|
|
"**Nota:** è comune e previsto che i tipi implementino entrambi\r\n"
|
|
|
"`Default` e un costruttore `new` vuoto. `new` è il costruttore\r\n"
|
|
|
"convenzione in Rust e gli utenti si aspettano che esista, quindi se lo è\r\n"
|
|
|
"ragionevole che il costruttore di base non accetti argomenti, allora it\r\n"
|
|
|
"dovrebbe, anche se è funzionalmente identico a default."
|
|
|
|
|
|
#: src\idioms/ctor.md:97
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"**Hint:** The advantage of implementing or deriving `Default` is that your "
|
|
|
"type\r\n"
|
|
|
"can now be used where a `Default` implementation is required, most "
|
|
|
"prominently,\r\n"
|
|
|
"any of the [`*or_default` functions in the standard library][std-or-default]."
|
|
|
msgstr ""
|
|
|
"**Suggerimento:** il vantaggio di implementare o derivare `Default` è che il "
|
|
|
"tuo tipo\r\n"
|
|
|
"ora può essere utilizzato dove è richiesta un'implementazione `Default`, "
|
|
|
"soprattutto,\r\n"
|
|
|
"qualsiasi delle [funzioni `*or_default` nella libreria "
|
|
|
"standard][std-or-default]."
|
|
|
|
|
|
#: src\idioms/ctor.md:101
|
|
|
#, fuzzy
|
|
|
msgid "## See also\r"
|
|
|
msgstr "## Guarda anche\r"
|
|
|
|
|
|
#: src\idioms/ctor.md:103
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- The [default idiom](default.md) for a more in-depth description of the\r\n"
|
|
|
" `Default` trait.\r\n"
|
|
|
"\r\n"
|
|
|
"- The [builder pattern](../patterns/creational/builder.md) for "
|
|
|
"constructing\r\n"
|
|
|
" objects where there are multiple configurations.\r\n"
|
|
|
"\r\n"
|
|
|
"- [API Guidelines/C-COMMON-TRAITS][API Guidelines/C-COMMON-TRAITS] for\r\n"
|
|
|
" implementing both, `Default` and `new`.\r\n"
|
|
|
"\r"
|
|
|
msgstr ""
|
|
|
"- L'[idioma predefinito](default.md) per una descrizione più approfondita "
|
|
|
"del file\r\n"
|
|
|
" Tratto `Predefinito`.\r\n"
|
|
|
"\r\n"
|
|
|
"- Il [modello builder](../patterns/creational/builder.md) per la "
|
|
|
"costruzione\r\n"
|
|
|
" oggetti in cui sono presenti più configurazioni.\r\n"
|
|
|
"\r\n"
|
|
|
"- [Linee guida API/C-COMMON-TRAITS][Linee guida API/C-COMMON-TRAITS] per\r\n"
|
|
|
" implementando entrambi, `Default` e `new`.\r\n"
|
|
|
"\r"
|
|
|
|
|
|
#: src\idioms/default.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# The `Default` Trait"
|
|
|
msgstr "# Il tratto `Predefinito`"
|
|
|
|
|
|
#: src\idioms/default.md:5
|
|
|
msgid ""
|
|
|
"Many types in Rust have a [constructor]. However, this is _specific_ to the\n"
|
|
|
"type; Rust cannot abstract over \"everything that has a `new()` method\". "
|
|
|
"To\n"
|
|
|
"allow this, the [`Default`] trait was conceived, which can be used with\n"
|
|
|
"containers and other generic types (e.g. see "
|
|
|
"[`Option::unwrap_or_default()`]).\n"
|
|
|
"Notably, some containers already implement it where applicable."
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/default.md:11
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Not only do one-element containers like `Cow`, `Box` or `Arc` implement\n"
|
|
|
"`Default` for contained `Default` types, one can automatically\n"
|
|
|
"`#[derive(Default)]` for structs whose fields all implement it, so the more\n"
|
|
|
"types implement `Default`, the more useful it becomes."
|
|
|
msgstr ""
|
|
|
"Non solo i contenitori a un elemento come `Cow`, `Box` o `Arc` implementano\n"
|
|
|
"`Default` per i tipi `Default` contenuti, si può automaticamente\n"
|
|
|
"`#[derive(Default)]` per struct i cui campi lo implementano tutti, quindi "
|
|
|
"more\n"
|
|
|
"i tipi implementano `Default`, più diventa utile."
|
|
|
|
|
|
#: src\idioms/default.md:16
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"On the other hand, constructors can take multiple arguments, while the\n"
|
|
|
"`default()` method does not. There can even be multiple constructors with\n"
|
|
|
"different names, but there can only be one `Default` implementation per type."
|
|
|
msgstr ""
|
|
|
"D'altra parte, i costruttori possono prendere più argomenti, mentre il\n"
|
|
|
"Il metodo `default()` no. Possono anche esserci più costruttori con\n"
|
|
|
"nomi diversi, ma può esserci solo un'implementazione `Default` per tipo."
|
|
|
|
|
|
#: src\idioms/default.md:22
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"use std::{path::PathBuf, time::Duration};\n"
|
|
|
"\n"
|
|
|
"// note that we can simply auto-derive Default here.\n"
|
|
|
"#[derive(Default, Debug, PartialEq)]\n"
|
|
|
"struct MyConfiguration {\n"
|
|
|
" // Option defaults to None\n"
|
|
|
" output: Option<PathBuf>,\n"
|
|
|
" // Vecs default to empty vector\n"
|
|
|
" search_path: Vec<PathBuf>,\n"
|
|
|
" // Duration defaults to zero time\n"
|
|
|
" timeout: Duration,\n"
|
|
|
" // bool defaults to false\n"
|
|
|
" check: bool,\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"impl MyConfiguration {\n"
|
|
|
" // add setters here\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn main() {\n"
|
|
|
" // construct a new instance with default values\n"
|
|
|
" let mut conf = MyConfiguration::default();\n"
|
|
|
" // do something with conf here\n"
|
|
|
" conf.check = true;\n"
|
|
|
" println!(\"conf = {:#?}\", conf);\n"
|
|
|
" \n"
|
|
|
" // partial initialization with default values, creates the same "
|
|
|
"instance\n"
|
|
|
" let conf1 = MyConfiguration {\n"
|
|
|
" check: true,\n"
|
|
|
" ..Default::default()\n"
|
|
|
" };\n"
|
|
|
" assert_eq!(conf, conf1);\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/default.md:60
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- The [constructor] idiom is another way to generate instances that may or "
|
|
|
"may\n"
|
|
|
" not be \"default\"\n"
|
|
|
"- The [`Default`] documentation (scroll down for the list of implementors)\n"
|
|
|
"- [`Option::unwrap_or_default()`]\n"
|
|
|
"- [`derive(new)`]"
|
|
|
msgstr ""
|
|
|
"- L'idioma [costruttore] è un altro modo per generare istanze che possono o "
|
|
|
"possono\n"
|
|
|
" non essere \"predefinito\"\n"
|
|
|
"- La documentazione [`Default`] (scorrere verso il basso per l'elenco degli "
|
|
|
"implementatori)\n"
|
|
|
"- [`Opzione::unwrap_or_default()`]\n"
|
|
|
"- [`deriva(nuovo)`]"
|
|
|
|
|
|
#: src\idioms/deref.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Collections are smart pointers"
|
|
|
msgstr "# Le raccolte sono puntatori intelligenti"
|
|
|
|
|
|
#: src\idioms/deref.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Use the [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html)\n"
|
|
|
"trait to treat collections like smart pointers, offering owning\n"
|
|
|
"and borrowed views of data."
|
|
|
msgstr ""
|
|
|
"Usa [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html)\n"
|
|
|
"tratto per trattare le raccolte come puntatori intelligenti, offrendo la "
|
|
|
"proprietà\n"
|
|
|
"e viste prese in prestito dei dati."
|
|
|
|
|
|
#: src\idioms/deref.md:11
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"use std::ops::Deref;\n"
|
|
|
"\n"
|
|
|
"struct Vec<T> {\n"
|
|
|
" data: RawVec<T>,\n"
|
|
|
" //..\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"impl<T> Deref for Vec<T> {\n"
|
|
|
" type Target = [T];\n"
|
|
|
"\n"
|
|
|
" fn deref(&self) -> &[T] {\n"
|
|
|
" //..\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/deref.md:28
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"A `Vec<T>` is an owning collection of `T`s, while a slice (`&[T]`) is a "
|
|
|
"borrowed\n"
|
|
|
"collection of `T`s. Implementing `Deref` for `Vec` allows implicit "
|
|
|
"dereferencing\n"
|
|
|
"from `&Vec<T>` to `&[T]` and includes the relationship in auto-derefencing\n"
|
|
|
"searches. Most methods you might expect to be implemented for `Vec`s are "
|
|
|
"instead\n"
|
|
|
"implemented for slices."
|
|
|
msgstr ""
|
|
|
"Un `Vec<T>` è una raccolta proprietaria di `T`, mentre una slice (`&[T]`) è "
|
|
|
"un oggetto preso in prestito\n"
|
|
|
"raccolta di `T`s. L'implementazione di \"Deref\" per \"Vec\" consente la "
|
|
|
"dereferenziazione implicita\n"
|
|
|
"da `&Vec<T>` a `&[T]` e include la relazione nell'auto-derefencing\n"
|
|
|
"ricerche. La maggior parte dei metodi che potresti aspettarti di essere "
|
|
|
"implementati per `Vec`s lo sono invece\n"
|
|
|
"implementato per le fette."
|
|
|
|
|
|
#: src\idioms/deref.md:34
|
|
|
#, fuzzy
|
|
|
msgid "Also `String` and `&str` have a similar relation."
|
|
|
msgstr "Anche `String` e `&str` hanno una relazione simile."
|
|
|
|
|
|
#: src\idioms/deref.md:36 src\idioms/dtor-finally.md:32
|
|
|
#: src\idioms/mem-replace.md:57 src\idioms/on-stack-dyn-dispatch.md:37
|
|
|
#: src\idioms/ffi/accepting-strings.md:12 src\idioms/ffi/passing-strings.md:14
|
|
|
#: src\idioms/return-consumed-arg-on-error.md:43
|
|
|
#: src\patterns/behavioural/command.md:8
|
|
|
#: src\patterns/behavioural/interpreter.md:16
|
|
|
#: src\patterns/behavioural/newtype.md:56 src\patterns/behavioural/RAII.md:72
|
|
|
#: src\patterns/behavioural/strategy.md:19
|
|
|
#: src\patterns/behavioural/visitor.md:72 src\patterns/creational/builder.md:63
|
|
|
#: src\patterns/creational/fold.md:73
|
|
|
#: src\patterns/structural/compose-structs.md:71 src\patterns/ffi/export.md:15
|
|
|
#: src\anti_patterns/borrow_clone.md:30
|
|
|
#, fuzzy
|
|
|
msgid "## Motivation"
|
|
|
msgstr "## Motivazione"
|
|
|
|
|
|
#: src\idioms/deref.md:38
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Ownership and borrowing are key aspects of the Rust language. Data "
|
|
|
"structures\n"
|
|
|
"must account for these semantics properly to give a good user\n"
|
|
|
"experience. When implementing a data structure that owns its data, offering "
|
|
|
"a\n"
|
|
|
"borrowed view of that data allows for more flexible APIs."
|
|
|
msgstr ""
|
|
|
"La proprietà e il prestito sono aspetti chiave del linguaggio Rust. "
|
|
|
"Strutture dati\n"
|
|
|
"deve tenere conto di queste semantiche correttamente per dare un buon "
|
|
|
"utente\n"
|
|
|
"esperienza. Quando si implementa una struttura dati che possiede i suoi "
|
|
|
"dati, offrendo a\n"
|
|
|
"vista presa in prestito di tali dati consente API più flessibili."
|
|
|
|
|
|
#: src\idioms/deref.md:45
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Most methods can be implemented only for the borrowed view, they are then\n"
|
|
|
"implicitly available for the owning view."
|
|
|
msgstr ""
|
|
|
"La maggior parte dei metodi può essere implementata solo per la vista presa "
|
|
|
"in prestito, allora lo sono\n"
|
|
|
"implicitamente disponibile per la vista proprietaria."
|
|
|
|
|
|
#: src\idioms/deref.md:48
|
|
|
#, fuzzy
|
|
|
msgid "Gives clients a choice between borrowing or taking ownership of data."
|
|
|
msgstr ""
|
|
|
"Offre ai clienti la scelta tra prendere in prestito o assumere la proprietà "
|
|
|
"dei dati."
|
|
|
|
|
|
#: src\idioms/deref.md:52
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Methods and traits only available via dereferencing are not taken into "
|
|
|
"account\n"
|
|
|
"when bounds checking, so generic programming with data structures using "
|
|
|
"this\n"
|
|
|
"pattern can get complex (see the `Borrow` and `AsRef` traits, etc.)."
|
|
|
msgstr ""
|
|
|
"I metodi e i tratti disponibili solo tramite dereferenziazione non vengono "
|
|
|
"presi in considerazione\n"
|
|
|
"durante il controllo dei limiti, quindi programmazione generica con "
|
|
|
"strutture di dati che utilizzano this\n"
|
|
|
"pattern può diventare complesso (vedi i tratti `Borrow` e `AsRef`, ecc.)."
|
|
|
|
|
|
#: src\idioms/deref.md:56 src\idioms/dtor-finally.md:61
|
|
|
#: src\idioms/mem-replace.md:97 src\idioms/on-stack-dyn-dispatch.md:68
|
|
|
#: src\idioms/priv-extend.md:85 src\patterns/behavioural/command.md:203
|
|
|
#: src\patterns/behavioural/interpreter.md:103
|
|
|
#: src\patterns/behavioural/newtype.md:85 src\patterns/behavioural/RAII.md:83
|
|
|
#: src\patterns/behavioural/strategy.md:110
|
|
|
#: src\patterns/behavioural/visitor.md:79 src\patterns/creational/builder.md:81
|
|
|
#: src\patterns/creational/fold.md:85
|
|
|
#: src\patterns/structural/compose-structs.md:89 src\anti_patterns/deref.md:102
|
|
|
#, fuzzy
|
|
|
msgid "## Discussion"
|
|
|
msgstr "## Discussione"
|
|
|
|
|
|
#: src\idioms/deref.md:58
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Smart pointers and collections are analogous: a smart pointer points to a "
|
|
|
"single\n"
|
|
|
"object, whereas a collection points to many objects. From the point of view "
|
|
|
"of\n"
|
|
|
"the type system, there is little difference between the two. A collection "
|
|
|
"owns\n"
|
|
|
"its data if the only way to access each datum is via the collection and the\n"
|
|
|
"collection is responsible for deleting the data (even in cases of shared\n"
|
|
|
"ownership, some kind of borrowed view may be appropriate). If a collection "
|
|
|
"owns\n"
|
|
|
"its data, it is usually useful to provide a view of the data as borrowed so "
|
|
|
"that\n"
|
|
|
"it can be referenced multiple times."
|
|
|
msgstr ""
|
|
|
"I puntatori intelligenti e le raccolte sono analoghi: un puntatore "
|
|
|
"intelligente punta a un singolo\n"
|
|
|
"oggetto, mentre una raccolta punta a molti oggetti. Dal punto di vista di\n"
|
|
|
"il sistema di tipo, c'è poca differenza tra i due. Una collezione possiede\n"
|
|
|
"i suoi dati se l'unico modo per accedere a ciascun dato è attraverso la "
|
|
|
"raccolta e il\n"
|
|
|
"collection è responsabile della cancellazione dei dati (anche in caso di "
|
|
|
"shared\n"
|
|
|
"proprietà, potrebbe essere appropriato un qualche tipo di visione presa in "
|
|
|
"prestito). Se una collezione possiede\n"
|
|
|
"suoi dati, di solito è utile fornire una vista dei dati presi in prestito in "
|
|
|
"modo che\n"
|
|
|
"può essere referenziato più volte."
|
|
|
|
|
|
#: src\idioms/deref.md:67
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Most smart pointers (e.g., `Foo<T>`) implement `Deref<Target=T>`. However,\n"
|
|
|
"collections will usually dereference to a custom type. `[T]` and `str` have "
|
|
|
"some\n"
|
|
|
"language support, but in the general case, this is not necessary. `Foo<T>` "
|
|
|
"can\n"
|
|
|
"implement `Deref<Target=Bar<T>>` where `Bar` is a dynamically sized type "
|
|
|
"and\n"
|
|
|
"`&Bar<T>` is a borrowed view of the data in `Foo<T>`."
|
|
|
msgstr ""
|
|
|
"La maggior parte dei puntatori intelligenti (ad esempio, `Foo<T>`) "
|
|
|
"implementano `Deref<Target=T>`. Tuttavia,\n"
|
|
|
"le collezioni di solito fanno riferimento a un tipo personalizzato. `[T]` e "
|
|
|
"`str` ne hanno alcuni\n"
|
|
|
"supporto linguistico, ma nel caso generale questo non è necessario. `Foo<T>` "
|
|
|
"può\n"
|
|
|
"implementa `Deref<Target=Bar<T>>` dove `Bar` è un tipo dimensionato "
|
|
|
"dinamicamente e\n"
|
|
|
"`&Bar<T>` è una vista presa in prestito dei dati in `Foo<T>`."
|
|
|
|
|
|
#: src\idioms/deref.md:73
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Commonly, ordered collections will implement `Index` for `Range`s to "
|
|
|
"provide\n"
|
|
|
"slicing syntax. The target will be the borrowed view."
|
|
|
msgstr ""
|
|
|
"Comunemente, le raccolte ordinate implementeranno `Index` per `Range`s da "
|
|
|
"fornire\n"
|
|
|
"sintassi per affettare. L'obiettivo sarà la vista presa in prestito."
|
|
|
|
|
|
#: src\idioms/deref.md:78
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [Deref polymorphism anti-pattern](../anti_patterns/deref.md).\n"
|
|
|
"- [Documentation for `Deref` "
|
|
|
"trait](https://doc.rust-lang.org/std/ops/trait.Deref.html)."
|
|
|
msgstr ""
|
|
|
"- [Deref polimorfismo anti-pattern](../anti_patterns/deref.md).\n"
|
|
|
"- [Documentazione per il tratto "
|
|
|
"`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html)."
|
|
|
|
|
|
#: src\idioms/dtor-finally.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Finalisation in destructors"
|
|
|
msgstr "# Finalizzazione nei distruttori"
|
|
|
|
|
|
#: src\idioms/dtor-finally.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Rust does not provide the equivalent to `finally` blocks - code that will "
|
|
|
"be\n"
|
|
|
"executed no matter how a function is exited. Instead, an object's destructor "
|
|
|
"can\n"
|
|
|
"be used to run code that must be run before exit."
|
|
|
msgstr ""
|
|
|
"Rust non fornisce l'equivalente dei blocchi `finally` - codice che sarà\n"
|
|
|
"eseguito indipendentemente da come si esce da una funzione. Invece, il "
|
|
|
"distruttore di un oggetto può farlo\n"
|
|
|
"essere utilizzato per eseguire il codice che deve essere eseguito prima "
|
|
|
"dell'uscita."
|
|
|
|
|
|
#: src\idioms/dtor-finally.md:11
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"fn bar() -> Result<(), ()> {\n"
|
|
|
" // These don't need to be defined inside the function.\n"
|
|
|
" struct Foo;\n"
|
|
|
"\n"
|
|
|
" // Implement a destructor for Foo.\n"
|
|
|
" impl Drop for Foo {\n"
|
|
|
" fn drop(&mut self) {\n"
|
|
|
" println!(\"exit\");\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" // The dtor of _exit will run however the function `bar` is exited.\n"
|
|
|
" let _exit = Foo;\n"
|
|
|
" // Implicit return with `?` operator.\n"
|
|
|
" baz()?;\n"
|
|
|
" // Normal return.\n"
|
|
|
" Ok(())\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/dtor-finally.md:34
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"If a function has multiple return points, then executing code on exit "
|
|
|
"becomes\n"
|
|
|
"difficult and repetitive (and thus bug-prone). This is especially the case "
|
|
|
"where\n"
|
|
|
"return is implicit due to a macro. A common case is the `?` operator which\n"
|
|
|
"returns if the result is an `Err`, but continues if it is `Ok`. `?` is used "
|
|
|
"as\n"
|
|
|
"an exception handling mechanism, but unlike Java (which has `finally`), "
|
|
|
"there is\n"
|
|
|
"no way to schedule code to run in both the normal and exceptional cases.\n"
|
|
|
"Panicking will also exit a function early."
|
|
|
msgstr ""
|
|
|
"Se una funzione ha più punti di ritorno, l'esecuzione del codice all'uscita "
|
|
|
"diventa\n"
|
|
|
"difficile e ripetitivo (e quindi soggetto a bug). Questo è particolarmente "
|
|
|
"vero dove\n"
|
|
|
"return è implicito a causa di una macro. Un caso comune è l'operatore `?` "
|
|
|
"which\n"
|
|
|
"restituisce se il risultato è \"Err\", ma continua se è \"Ok\". `?` è usato "
|
|
|
"come\n"
|
|
|
"un meccanismo di gestione delle eccezioni, ma a differenza di Java (che ha "
|
|
|
"\"finalmente\"), c'è\n"
|
|
|
"non c'è modo di programmare l'esecuzione del codice sia nei casi normali che "
|
|
|
"in quelli eccezionali.\n"
|
|
|
"Anche il panico uscirà presto da una funzione."
|
|
|
|
|
|
#: src\idioms/dtor-finally.md:44
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Code in destructors will (nearly) always be run - copes with panics, early\n"
|
|
|
"returns, etc."
|
|
|
msgstr ""
|
|
|
"Il codice nei distruttori verrà (quasi) sempre eseguito - affronta il "
|
|
|
"panico, presto\n"
|
|
|
"ritorni, ecc."
|
|
|
|
|
|
#: src\idioms/dtor-finally.md:49
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"It is not guaranteed that destructors will run. For example, if there is an\n"
|
|
|
"infinite loop in a function or if running a function crashes before exit.\n"
|
|
|
"Destructors are also not run in the case of a panic in an already panicking\n"
|
|
|
"thread. Therefore, destructors cannot be relied on as finalizers where it "
|
|
|
"is\n"
|
|
|
"absolutely essential that finalisation happens."
|
|
|
msgstr ""
|
|
|
"Non è garantito che i distruttori vengano eseguiti. Ad esempio, se esiste "
|
|
|
"un\n"
|
|
|
"ciclo infinito in una funzione o se l'esecuzione di una funzione si arresta "
|
|
|
"in modo anomalo prima dell'uscita.\n"
|
|
|
"Anche i distruttori non vengono eseguiti in caso di panico in una situazione "
|
|
|
"già in preda al panico\n"
|
|
|
"filo. Pertanto, non è possibile fare affidamento sui distruttori come "
|
|
|
"finalizzatori dove si trovano\n"
|
|
|
"assolutamente essenziale che avvenga la finalizzazione."
|
|
|
|
|
|
#: src\idioms/dtor-finally.md:55
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This pattern introduces some hard to notice, implicit code. Reading a "
|
|
|
"function\n"
|
|
|
"gives no clear indication of destructors to be run on exit. This can make\n"
|
|
|
"debugging tricky."
|
|
|
msgstr ""
|
|
|
"Questo modello introduce un codice implicito difficile da notare. Lettura di "
|
|
|
"una funzione\n"
|
|
|
"non fornisce alcuna chiara indicazione dei distruttori da eseguire "
|
|
|
"all'uscita. Questo può fare\n"
|
|
|
"debug complicato."
|
|
|
|
|
|
#: src\idioms/dtor-finally.md:59
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Requiring an object and `Drop` impl just for finalisation is heavy on "
|
|
|
"boilerplate."
|
|
|
msgstr ""
|
|
|
"Richiedere un oggetto e \"Drop\" impl solo per la finalizzazione è pesante "
|
|
|
"sul boilerplate."
|
|
|
|
|
|
#: src\idioms/dtor-finally.md:63
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"There is some subtlety about how exactly to store the object used as a\n"
|
|
|
"finalizer. It must be kept alive until the end of the function and must then "
|
|
|
"be\n"
|
|
|
"destroyed. The object must always be a value or uniquely owned pointer "
|
|
|
"(e.g.,\n"
|
|
|
"`Box<Foo>`). If a shared pointer (such as `Rc`) is used, then the finalizer "
|
|
|
"can\n"
|
|
|
"be kept alive beyond the lifetime of the function. For similar reasons, the\n"
|
|
|
"finalizer should not be moved or returned."
|
|
|
msgstr ""
|
|
|
"C'è una certa sottigliezza su come memorizzare esattamente l'oggetto usato "
|
|
|
"come a\n"
|
|
|
"finalizzatore. Deve essere mantenuto in vita fino alla fine della funzione e "
|
|
|
"deve esserlo\n"
|
|
|
"distrutto. L'oggetto deve sempre essere un valore o un puntatore di "
|
|
|
"proprietà univoca (ad esempio,\n"
|
|
|
"`Box<Foo>`). Se viene utilizzato un puntatore condiviso (come `Rc`), il "
|
|
|
"finalizzatore può farlo\n"
|
|
|
"essere mantenuto in vita oltre la durata della funzione. Per ragioni simili, "
|
|
|
"il\n"
|
|
|
"finalizzatore non deve essere spostato o restituito."
|
|
|
|
|
|
#: src\idioms/dtor-finally.md:70
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The finalizer must be assigned into a variable, otherwise it will be "
|
|
|
"destroyed\n"
|
|
|
"immediately, rather than when it goes out of scope. The variable name must "
|
|
|
"start\n"
|
|
|
"with `_` if the variable is only used as a finalizer, otherwise the "
|
|
|
"compiler\n"
|
|
|
"will warn that the finalizer is never used. However, do not call the "
|
|
|
"variable\n"
|
|
|
"`_` with no suffix - in that case it will be destroyed immediately."
|
|
|
msgstr ""
|
|
|
"Il finalizzatore deve essere assegnato in una variabile, altrimenti verrà "
|
|
|
"distrutto\n"
|
|
|
"immediatamente, piuttosto che quando esce dal campo di applicazione. Il nome "
|
|
|
"della variabile deve iniziare\n"
|
|
|
"con `_` se la variabile è usata solo come finalizzatore, altrimenti il "
|
|
|
"compilatore\n"
|
|
|
"avviserà che il finalizzatore non viene mai utilizzato. Tuttavia, non "
|
|
|
"chiamare la variabile\n"
|
|
|
"`_` senza suffisso - in tal caso verrà distrutto immediatamente."
|
|
|
|
|
|
#: src\idioms/dtor-finally.md:76
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"In Rust, destructors are run when an object goes out of scope. This happens\n"
|
|
|
"whether we reach the end of block, there is an early return, or the program\n"
|
|
|
"panics. When panicking, Rust unwinds the stack running destructors for each\n"
|
|
|
"object in each stack frame. So, destructors get called even if the panic "
|
|
|
"happens\n"
|
|
|
"in a function being called."
|
|
|
msgstr ""
|
|
|
"In Rust, i distruttori vengono eseguiti quando un oggetto esce dall'ambito. "
|
|
|
"Questo succede\n"
|
|
|
"se raggiungiamo la fine del blocco, c'è un ritorno anticipato o il "
|
|
|
"programma\n"
|
|
|
"panico. In preda al panico, Rust rimuove lo stack eseguendo i distruttori "
|
|
|
"per ciascuno\n"
|
|
|
"oggetto in ogni stack frame. Quindi, i distruttori vengono chiamati anche se "
|
|
|
"si verifica il panico\n"
|
|
|
"in una funzione che viene chiamata."
|
|
|
|
|
|
#: src\idioms/dtor-finally.md:82
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"If a destructor panics while unwinding, there is no good action to take, so "
|
|
|
"Rust\n"
|
|
|
"aborts the thread immediately, without running further destructors. This "
|
|
|
"means\n"
|
|
|
"that destructors are not absolutely guaranteed to run. It also means that "
|
|
|
"you\n"
|
|
|
"must take extra care in your destructors not to panic, since it could leave\n"
|
|
|
"resources in an unexpected state."
|
|
|
msgstr ""
|
|
|
"Se un distruttore va nel panico mentre si rilassa, non c'è nessuna buona "
|
|
|
"azione da intraprendere, quindi Rust\n"
|
|
|
"interrompe immediatamente il thread, senza eseguire ulteriori distruttori. "
|
|
|
"Questo significa\n"
|
|
|
"che non è assolutamente garantito che i distruttori funzionino. Significa "
|
|
|
"anche che tu\n"
|
|
|
"devi prestare particolare attenzione ai tuoi distruttori per non farti "
|
|
|
"prendere dal panico, poiché potrebbe andarsene\n"
|
|
|
"risorse in uno stato imprevisto."
|
|
|
|
|
|
#: src\idioms/dtor-finally.md:90
|
|
|
#, fuzzy
|
|
|
msgid "[RAII guards](../patterns/behavioural/RAII.md)."
|
|
|
msgstr "[Guardie RAII](../patterns/behavioural/RAII.md)."
|
|
|
|
|
|
#: src\idioms/mem-replace.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# `mem::{take(_), replace(_)}` to keep owned values in changed enums"
|
|
|
msgstr ""
|
|
|
"# `mem::{take(_), replace(_)}` per mantenere i valori posseduti nelle enum "
|
|
|
"modificate"
|
|
|
|
|
|
#: src\idioms/mem-replace.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Say we have a `&mut MyEnum` which has (at least) two variants,\n"
|
|
|
"`A { name: String, x: u8 }` and `B { name: String }`. Now we want to change\n"
|
|
|
"`MyEnum::A` to a `B` if `x` is zero, while keeping `MyEnum::B` intact."
|
|
|
msgstr ""
|
|
|
"Supponiamo di avere un `&mut MyEnum` che ha (almeno) due varianti,\n"
|
|
|
"`A { nome: String, x: u8 }` e `B { nome: String }`. Ora vogliamo cambiare\n"
|
|
|
"`MyEnum::A` in una `B` se `x` è zero, mantenendo intatto `MyEnum::B`."
|
|
|
|
|
|
#: src\idioms/mem-replace.md:9
|
|
|
#, fuzzy
|
|
|
msgid "We can do this without cloning the `name`."
|
|
|
msgstr "Possiamo farlo senza clonare il `nome`."
|
|
|
|
|
|
#: src\idioms/mem-replace.md:13
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"use std::mem;\n"
|
|
|
"\n"
|
|
|
"enum MyEnum {\n"
|
|
|
" A { name: String, x: u8 },\n"
|
|
|
" B { name: String }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn a_to_b(e: &mut MyEnum) {\n"
|
|
|
" if let MyEnum::A { name, x: 0 } = e {\n"
|
|
|
" // this takes out our `name` and put in an empty String instead\n"
|
|
|
" // (note that empty strings don't allocate).\n"
|
|
|
" // Then, construct the new enum variant (which will\n"
|
|
|
" // be assigned to `*e`).\n"
|
|
|
" *e = MyEnum::B { name: mem::take(name) }\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/mem-replace.md:32
|
|
|
#, fuzzy
|
|
|
msgid "This also works with more variants:"
|
|
|
msgstr "Questo funziona anche con più varianti:"
|
|
|
|
|
|
#: src\idioms/mem-replace.md:34
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"use std::mem;\n"
|
|
|
"\n"
|
|
|
"enum MultiVariateEnum {\n"
|
|
|
" A { name: String },\n"
|
|
|
" B { name: String },\n"
|
|
|
" C,\n"
|
|
|
" D\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn swizzle(e: &mut MultiVariateEnum) {\n"
|
|
|
" use MultiVariateEnum::*;\n"
|
|
|
" *e = match e {\n"
|
|
|
" // Ownership rules do not allow taking `name` by value, but we "
|
|
|
"cannot\n"
|
|
|
" // take the value out of a mutable reference, unless we replace it:\n"
|
|
|
" A { name } => B { name: mem::take(name) },\n"
|
|
|
" B { name } => A { name: mem::take(name) },\n"
|
|
|
" C => D,\n"
|
|
|
" D => C\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/mem-replace.md:59
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"When working with enums, we may want to change an enum value in place, "
|
|
|
"perhaps\n"
|
|
|
"to another variant. This is usually done in two phases to keep the borrow\n"
|
|
|
"checker happy. In the first phase, we observe the existing value and look "
|
|
|
"at\n"
|
|
|
"its parts to decide what to do next. In the second phase we may "
|
|
|
"conditionally\n"
|
|
|
"change the value (as in the example above)."
|
|
|
msgstr ""
|
|
|
"Quando lavoriamo con gli enum, potremmo voler cambiare un valore enum sul "
|
|
|
"posto, forse\n"
|
|
|
"ad un'altra variante. Questo di solito viene fatto in due fasi per mantenere "
|
|
|
"il prestito\n"
|
|
|
"correttore felice. Nella prima fase, osserviamo il valore esistente e "
|
|
|
"guardiamo\n"
|
|
|
"sue parti per decidere cosa fare dopo. Nella seconda fase possiamo "
|
|
|
"condizionalmente\n"
|
|
|
"modificare il valore (come nell'esempio precedente)."
|
|
|
|
|
|
#: src\idioms/mem-replace.md:65
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The borrow checker won't allow us to take out `name` of the enum (because\n"
|
|
|
"_something_ must be there.) We could of course `.clone()` name and put the "
|
|
|
"clone\n"
|
|
|
"into our `MyEnum::B`, but that would be an instance of the [Clone to satisfy "
|
|
|
"the borrow checker](../anti_patterns/borrow_clone.md) anti-pattern. Anyway, "
|
|
|
"we\n"
|
|
|
"can avoid the extra allocation by changing `e` with only a mutable borrow."
|
|
|
msgstr ""
|
|
|
"Il controllo del prestito non ci consentirà di eliminare il \"nome\" "
|
|
|
"dell'enumerazione (perché\n"
|
|
|
"_qualcosa_ deve esserci.) Potremmo ovviamente nominare `.clone()` e inserire "
|
|
|
"il clone\n"
|
|
|
"nel nostro `MyEnum::B`, ma sarebbe un'istanza dell'anti-pattern [Clone per "
|
|
|
"soddisfare il controllo del prestito](../anti_patterns/borrow_clone.md). "
|
|
|
"Comunque, noi\n"
|
|
|
"può evitare l'allocazione extra cambiando `e` solo con un prestito mutabile."
|
|
|
|
|
|
#: src\idioms/mem-replace.md:70
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"`mem::take` lets us swap out the value, replacing it with it's default "
|
|
|
"value,\n"
|
|
|
"and returning the previous value. For `String`, the default value is an "
|
|
|
"empty\n"
|
|
|
"`String`, which does not need to allocate. As a result, we get the original\n"
|
|
|
"`name` _as an owned value_. We can then wrap this in another enum."
|
|
|
msgstr ""
|
|
|
"`mem::take` ci permette di scambiare il valore, sostituendolo con il suo "
|
|
|
"valore predefinito,\n"
|
|
|
"e restituendo il valore precedente. Per \"Stringa\", il valore predefinito è "
|
|
|
"vuoto\n"
|
|
|
"`String`, che non deve essere allocato. Di conseguenza, otteniamo "
|
|
|
"l'originale\n"
|
|
|
"`nome` _come valore di proprietà_. Possiamo quindi avvolgerlo in un altro "
|
|
|
"enum."
|
|
|
|
|
|
#: src\idioms/mem-replace.md:75
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"**NOTE:** `mem::replace` is very similar, but allows us to specify what to\n"
|
|
|
"replace the value with. An equivalent to our `mem::take` line would be\n"
|
|
|
"`mem::replace(name, String::new())`."
|
|
|
msgstr ""
|
|
|
"**NOTA:** `mem::replace` è molto simile, ma ci permette di specificare cosa\n"
|
|
|
"sostituisci il valore con Un equivalente alla nostra riga `mem::take` "
|
|
|
"sarebbe\n"
|
|
|
"`mem::replace(name, String::new())`."
|
|
|
|
|
|
#: src\idioms/mem-replace.md:79
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Note, however, that if we are using an `Option` and want to replace its\n"
|
|
|
"value with a `None`, `Option`’s `take()` method provides a shorter and\n"
|
|
|
"more idiomatic alternative."
|
|
|
msgstr ""
|
|
|
"Nota, tuttavia, che se stiamo usando un'opzione `e vogliamo sostituirla\n"
|
|
|
"value con `None`, il metodo `take()` di `Option` fornisce un and\n"
|
|
|
"alternativa più idiomatica."
|
|
|
|
|
|
#: src\idioms/mem-replace.md:85
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Look ma, no allocation! Also you may feel like Indiana Jones while doing it."
|
|
|
msgstr ""
|
|
|
"Guarda mamma, nessuna allocazione! Inoltre potresti sentirti come Indiana "
|
|
|
"Jones mentre lo fai."
|
|
|
|
|
|
#: src\idioms/mem-replace.md:89
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This gets a bit wordy. Getting it wrong repeatedly will make you hate the\n"
|
|
|
"borrow checker. The compiler may fail to optimize away the double store,\n"
|
|
|
"resulting in reduced performance as opposed to what you'd do in unsafe\n"
|
|
|
"languages."
|
|
|
msgstr ""
|
|
|
"Questo diventa un po' prolisso. Sbagliare ripetutamente ti farà odiare il\n"
|
|
|
"controllore in prestito. Il compilatore potrebbe non riuscire a ottimizzare "
|
|
|
"il doppio archivio,\n"
|
|
|
"con conseguente riduzione delle prestazioni rispetto a ciò che faresti in "
|
|
|
"condizioni non sicure\n"
|
|
|
"le lingue."
|
|
|
|
|
|
#: src\idioms/mem-replace.md:94
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Furthermore, the type you are taking needs to implement the [`Default` "
|
|
|
"trait](./default.md). However, if the type you're working with doesn't\n"
|
|
|
"implement this, you can instead use `mem::replace`."
|
|
|
msgstr ""
|
|
|
"Inoltre, il tipo che stai prendendo deve implementare il [tratto "
|
|
|
"`Default`](./default.md). Tuttavia, se il tipo con cui stai lavorando non lo "
|
|
|
"fa\n"
|
|
|
"implementarlo, puoi invece usare `mem::replace`."
|
|
|
|
|
|
#: src\idioms/mem-replace.md:99
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This pattern is only of interest in Rust. In GC'd languages, you'd take the\n"
|
|
|
"reference to the value by default (and the GC would keep track of refs), and "
|
|
|
"in\n"
|
|
|
"other low-level languages like C you'd simply alias the pointer and fix "
|
|
|
"things\n"
|
|
|
"later."
|
|
|
msgstr ""
|
|
|
"Questo schema interessa solo Rust. Nelle lingue GC, prenderesti il\n"
|
|
|
"riferimento al valore per impostazione predefinita (e il GC terrà traccia "
|
|
|
"dei riferimenti), e in\n"
|
|
|
"altri linguaggi di basso livello come C avresti semplicemente alias il "
|
|
|
"puntatore e aggiustato le cose\n"
|
|
|
"Dopo."
|
|
|
|
|
|
#: src\idioms/mem-replace.md:104
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"However, in Rust, we have to do a little more work to do this. An owned "
|
|
|
"value\n"
|
|
|
"may only have one owner, so to take it out, we need to put something back in "
|
|
|
"–\n"
|
|
|
"like Indiana Jones, replacing the artifact with a bag of sand."
|
|
|
msgstr ""
|
|
|
"Tuttavia, in Rust, dobbiamo fare un po' più di lavoro per farlo. Un valore "
|
|
|
"posseduto\n"
|
|
|
"potrebbe avere un solo proprietario, quindi per toglierlo dobbiamo "
|
|
|
"rimetterci qualcosa...\n"
|
|
|
"come Indiana Jones, sostituendo il manufatto con un sacco di sabbia."
|
|
|
|
|
|
#: src\idioms/mem-replace.md:110
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This gets rid of the [Clone to satisfy the borrow "
|
|
|
"checker](../anti_patterns/borrow_clone.md)\n"
|
|
|
"anti-pattern in a specific case."
|
|
|
msgstr ""
|
|
|
"Questo elimina [Clone per soddisfare il controllo del "
|
|
|
"prestito](../anti_patterns/borrow_clone.md)\n"
|
|
|
"anti-pattern in un caso specifico."
|
|
|
|
|
|
#: src\idioms/on-stack-dyn-dispatch.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# On-Stack Dynamic Dispatch"
|
|
|
msgstr "# Invio dinamico in pila"
|
|
|
|
|
|
#: src\idioms/on-stack-dyn-dispatch.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"We can dynamically dispatch over multiple values, however, to do so, we "
|
|
|
"need\n"
|
|
|
"to declare multiple variables to bind differently-typed objects. To extend "
|
|
|
"the\n"
|
|
|
"lifetime as necessary, we can use deferred conditional initialization, as "
|
|
|
"seen\n"
|
|
|
"below:"
|
|
|
msgstr ""
|
|
|
"Possiamo spedire dinamicamente su più valori, tuttavia, per farlo, abbiamo "
|
|
|
"bisogno\n"
|
|
|
"per dichiarare più variabili per associare oggetti tipizzati in modo "
|
|
|
"diverso. Per estendere il\n"
|
|
|
"lifetime se necessario, possiamo usare l'inizializzazione condizionale "
|
|
|
"differita, come visto\n"
|
|
|
"sotto:"
|
|
|
|
|
|
#: src\idioms/on-stack-dyn-dispatch.md:12
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"use std::io;\n"
|
|
|
"use std::fs;\n"
|
|
|
"\n"
|
|
|
"# fn main() -> Result<(), Box<dyn std::error::Error>> {\n"
|
|
|
"# let arg = \"-\";\n"
|
|
|
"\n"
|
|
|
"// These must live longer than `readable`, and thus are declared first:\n"
|
|
|
"let (mut stdin_read, mut file_read);\n"
|
|
|
"\n"
|
|
|
"// We need to ascribe the type to get dynamic dispatch.\n"
|
|
|
"let readable: &mut dyn io::Read = if arg == \"-\" {\n"
|
|
|
" stdin_read = io::stdin();\n"
|
|
|
" &mut stdin_read\n"
|
|
|
"} else {\n"
|
|
|
" file_read = fs::File::open(arg)?;\n"
|
|
|
" &mut file_read\n"
|
|
|
"};\n"
|
|
|
"\n"
|
|
|
"// Read from `readable` here.\n"
|
|
|
"\n"
|
|
|
"# Ok(())\n"
|
|
|
"# }\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/on-stack-dyn-dispatch.md:39
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Rust monomorphises code by default. This means a copy of the code will be\n"
|
|
|
"generated for each type it is used with and optimized independently. While "
|
|
|
"this\n"
|
|
|
"allows for very fast code on the hot path, it also bloats the code in "
|
|
|
"places\n"
|
|
|
"where performance is not of the essence, thus costing compile time and "
|
|
|
"cache\n"
|
|
|
"usage."
|
|
|
msgstr ""
|
|
|
"Rust monomorfizza il codice per impostazione predefinita. Ciò significa che "
|
|
|
"una copia del codice sarà\n"
|
|
|
"generato per ogni tipo con cui viene utilizzato e ottimizzato in modo "
|
|
|
"indipendente. Mentre questo\n"
|
|
|
"consente un codice molto veloce sul percorso caldo, inoltre gonfia il codice "
|
|
|
"in alcuni punti\n"
|
|
|
"dove le prestazioni non sono essenziali, costando così tempo di compilazione "
|
|
|
"e cache\n"
|
|
|
"utilizzo."
|
|
|
|
|
|
#: src\idioms/on-stack-dyn-dispatch.md:45
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Luckily, Rust allows us to use dynamic dispatch, but we have to explicitly "
|
|
|
"ask\n"
|
|
|
"for it."
|
|
|
msgstr ""
|
|
|
"Fortunatamente, Rust ci consente di utilizzare l'invio dinamico, ma dobbiamo "
|
|
|
"chiedere esplicitamente\n"
|
|
|
"per questo."
|
|
|
|
|
|
#: src\idioms/on-stack-dyn-dispatch.md:50
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"We do not need to allocate anything on the heap. Neither do we need to\n"
|
|
|
"initialize something we won't use later, nor do we need to monomorphize the\n"
|
|
|
"whole code that follows to work with both `File` or `Stdin`."
|
|
|
msgstr ""
|
|
|
"Non è necessario allocare nulla nell'heap. Nemmeno noi ne abbiamo bisogno\n"
|
|
|
"inizializzare qualcosa che non useremo in seguito, né abbiamo bisogno di "
|
|
|
"monomorfizzare il\n"
|
|
|
"tutto il codice che segue per funzionare sia con `File` che con `Stdin`."
|
|
|
|
|
|
#: src\idioms/on-stack-dyn-dispatch.md:56
|
|
|
#, fuzzy
|
|
|
msgid "The code needs more moving parts than the `Box`-based version:"
|
|
|
msgstr ""
|
|
|
"Il codice richiede più parti mobili rispetto alla versione basata su `Box`:"
|
|
|
|
|
|
#: src\idioms/on-stack-dyn-dispatch.md:58
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"// We still need to ascribe the type for dynamic dispatch.\n"
|
|
|
"let readable: Box<dyn io::Read> = if arg == \"-\" {\n"
|
|
|
" Box::new(io::stdin())\n"
|
|
|
"} else {\n"
|
|
|
" Box::new(fs::File::open(arg)?)\n"
|
|
|
"};\n"
|
|
|
"// Read from `readable` here.\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/on-stack-dyn-dispatch.md:70
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Rust newcomers will usually learn that Rust requires all variables to be\n"
|
|
|
"initialized _before use_, so it's easy to overlook the fact that _unused_\n"
|
|
|
"variables may well be uninitialized. Rust works quite hard to ensure that "
|
|
|
"this\n"
|
|
|
"works out fine and only the initialized values are dropped at the end of "
|
|
|
"their\n"
|
|
|
"scope."
|
|
|
msgstr ""
|
|
|
"I nuovi arrivati di Rust di solito impareranno che Rust richiede che tutte "
|
|
|
"le variabili siano\n"
|
|
|
"inizializzato _prima dell'uso_, quindi è facile trascurare il fatto che _non "
|
|
|
"utilizzato_\n"
|
|
|
"le variabili potrebbero essere non inizializzate. Rust lavora molto "
|
|
|
"duramente per garantire che ciò avvenga\n"
|
|
|
"funziona bene e solo i valori inizializzati vengono eliminati alla fine del "
|
|
|
"loro\n"
|
|
|
"scopo."
|
|
|
|
|
|
#: src\idioms/on-stack-dyn-dispatch.md:76
|
|
|
#, fuzzy
|
|
|
msgid "The example meets all the constraints Rust places on us:"
|
|
|
msgstr "L'esempio soddisfa tutti i vincoli che Rust ci impone:"
|
|
|
|
|
|
#: src\idioms/on-stack-dyn-dispatch.md:78
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- All variables are initialized before using (in this case borrowing) them\n"
|
|
|
"- Each variable only holds values of a single type. In our example, `stdin` "
|
|
|
"is\n"
|
|
|
" of type `Stdin`, `file` is of type `File` and `readable` is of type `&mut "
|
|
|
"dyn Read`\n"
|
|
|
"- Each borrowed value outlives all the references borrowed from it"
|
|
|
msgstr ""
|
|
|
"- Tutte le variabili vengono inizializzate prima di utilizzarle (in questo "
|
|
|
"caso prendendole in prestito).\n"
|
|
|
"- Ogni variabile contiene solo valori di un singolo tipo. Nel nostro "
|
|
|
"esempio, `stdin` è\n"
|
|
|
" di tipo `Stdin`, `file` è di tipo `File` e `readable` è di tipo `&mut dyn "
|
|
|
"Read`\n"
|
|
|
"- Ogni valore preso in prestito sopravvive a tutti i riferimenti presi in "
|
|
|
"prestito da esso"
|
|
|
|
|
|
#: src\idioms/on-stack-dyn-dispatch.md:85
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [Finalisation in destructors](dtor-finally.md) and\n"
|
|
|
" [RAII guards](../patterns/behavioural/RAII.md) can benefit from tight "
|
|
|
"control over\n"
|
|
|
" lifetimes.\n"
|
|
|
"- For conditionally filled `Option<&T>`s of (mutable) references, one can\n"
|
|
|
" initialize an `Option<T>` directly and use its [`.as_ref()`] method to get "
|
|
|
"an\n"
|
|
|
" optional reference."
|
|
|
msgstr ""
|
|
|
"- [Finalizzazione nei distruttori](dtor-finally.md) e\n"
|
|
|
" [Le guardie RAII](../patterns/behavioural/RAII.md) possono beneficiare di "
|
|
|
"uno stretto controllo su\n"
|
|
|
" vite.\n"
|
|
|
"- Per i riferimenti `Option<&T>` riempiti in modo condizionale di "
|
|
|
"riferimenti (mutabili), si può\n"
|
|
|
" inizializzare un `Option<T>` direttamente e utilizzare il suo metodo "
|
|
|
"[`.as_ref()`] per ottenere un\n"
|
|
|
" riferimento facoltativo."
|
|
|
|
|
|
#: src\idioms/ffi/intro.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# FFI Idioms"
|
|
|
msgstr "# Idiomi FFI"
|
|
|
|
|
|
#: src\idioms/ffi/intro.md:3
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Writing FFI code is an entire course in itself.\n"
|
|
|
"However, there are several idioms here that can act as pointers, and avoid\n"
|
|
|
"traps for inexperienced users of `unsafe` Rust."
|
|
|
msgstr ""
|
|
|
"Scrivere il codice FFI è un intero corso in sé.\n"
|
|
|
"Tuttavia, ci sono diversi idiomi qui che possono fungere da puntatori ed "
|
|
|
"evitare\n"
|
|
|
"trappole per utenti inesperti di \"non sicuro\" Rust."
|
|
|
|
|
|
#: src\idioms/ffi/intro.md:7
|
|
|
#, fuzzy
|
|
|
msgid "This section contains idioms that may be useful when doing FFI."
|
|
|
msgstr ""
|
|
|
"Questa sezione contiene espressioni idiomatiche che possono essere utili "
|
|
|
"quando si fa FFI."
|
|
|
|
|
|
#: src\idioms/ffi/intro.md:9
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"1. [Idiomatic Errors](./errors.md) - Error handling with integer codes and\n"
|
|
|
" sentinel return values (such as `NULL` pointers)\n"
|
|
|
"\n"
|
|
|
"2. [Accepting Strings](./accepting-strings.md) with minimal unsafe code\n"
|
|
|
"\n"
|
|
|
"3. [Passing Strings](./passing-strings.md) to FFI functions"
|
|
|
msgstr ""
|
|
|
"1. [Errori idiomatici](./errors.md) - Gestione degli errori con codici "
|
|
|
"interi e\n"
|
|
|
" valori di ritorno sentinella (come i puntatori `NULL`)\n"
|
|
|
"\n"
|
|
|
"2. [Accepting Strings](./accepting-strings.md) con codice non sicuro minimo\n"
|
|
|
"\n"
|
|
|
"3. [Passing Strings](./passing-strings.md) alle funzioni FFI"
|
|
|
|
|
|
#: src\idioms/ffi/errors.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Error Handling in FFI"
|
|
|
msgstr "# Gestione degli errori in FFI"
|
|
|
|
|
|
#: src\idioms/ffi/errors.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"In foreign languages like C, errors are represented by return codes.\n"
|
|
|
"However, Rust's type system allows much more rich error information to be\n"
|
|
|
"captured and propogated through a full type."
|
|
|
msgstr ""
|
|
|
"In lingue straniere come il C, gli errori sono rappresentati da codici di "
|
|
|
"ritorno.\n"
|
|
|
"Tuttavia, il sistema di tipi di Rust consente di avere informazioni sugli "
|
|
|
"errori molto più ricche\n"
|
|
|
"catturato e propagato attraverso un tipo completo."
|
|
|
|
|
|
#: src\idioms/ffi/errors.md:9
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This best practice shows different kinds of error codes, and how to expose "
|
|
|
"them\n"
|
|
|
"in a usable way:"
|
|
|
msgstr ""
|
|
|
"Questa procedura consigliata mostra diversi tipi di codici di errore e come "
|
|
|
"esporli\n"
|
|
|
"in modo utilizzabile:"
|
|
|
|
|
|
#: src\idioms/ffi/errors.md:12
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"1. Flat Enums should be converted to integers and returned as codes.\n"
|
|
|
"2. Structured Enums should be converted to an integer code with a string "
|
|
|
"error\n"
|
|
|
" message for detail.\n"
|
|
|
"3. Custom Error Types should become \"transparent\", with a C representation."
|
|
|
msgstr ""
|
|
|
"1. Gli enum flat devono essere convertiti in numeri interi e restituiti come "
|
|
|
"codici.\n"
|
|
|
"2. Gli enum strutturati devono essere convertiti in un codice intero con un "
|
|
|
"errore di stringa\n"
|
|
|
" messaggio per i dettagli.\n"
|
|
|
"3. I tipi di errore personalizzati dovrebbero diventare \"trasparenti\", con "
|
|
|
"una rappresentazione C."
|
|
|
|
|
|
#: src\idioms/ffi/errors.md:17 src\idioms/ffi/accepting-strings.md:29
|
|
|
#: src\idioms/ffi/passing-strings.md:26 src\patterns/ffi/export.md:40
|
|
|
#: src\patterns/ffi/wrappers.md:23
|
|
|
#, fuzzy
|
|
|
msgid "## Code Example"
|
|
|
msgstr "## Esempio di codice"
|
|
|
|
|
|
#: src\idioms/ffi/errors.md:19
|
|
|
#, fuzzy
|
|
|
msgid "### Flat Enums"
|
|
|
msgstr "### Enumerazioni piatte"
|
|
|
|
|
|
#: src\idioms/ffi/errors.md:21
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"enum DatabaseError {\n"
|
|
|
" IsReadOnly = 1, // user attempted a write operation\n"
|
|
|
" IOError = 2, // user should read the C errno() for what it was\n"
|
|
|
" FileCorrupted = 3, // user should run a repair tool to recover it\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"impl From<DatabaseError> for libc::c_int {\n"
|
|
|
" fn from(e: DatabaseError) -> libc::c_int {\n"
|
|
|
" (e as i8).into()\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/ffi/errors.md:35
|
|
|
#, fuzzy
|
|
|
msgid "### Structured Enums"
|
|
|
msgstr "### Enumerazioni strutturate"
|
|
|
|
|
|
#: src\idioms/ffi/errors.md:37
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"pub mod errors {\n"
|
|
|
" enum DatabaseError {\n"
|
|
|
" IsReadOnly,\n"
|
|
|
" IOError(std::io::Error),\n"
|
|
|
" FileCorrupted(String), // message describing the issue\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" impl From<DatabaseError> for libc::c_int {\n"
|
|
|
" fn from(e: DatabaseError) -> libc::c_int {\n"
|
|
|
" match e {\n"
|
|
|
" DatabaseError::IsReadOnly => 1,\n"
|
|
|
" DatabaseError::IOError(_) => 2,\n"
|
|
|
" DatabaseError::FileCorrupted(_) => 3,\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"pub mod c_api {\n"
|
|
|
" use super::errors::DatabaseError;\n"
|
|
|
"\n"
|
|
|
" #[no_mangle]\n"
|
|
|
" pub extern \"C\" fn db_error_description(\n"
|
|
|
" e: *const DatabaseError\n"
|
|
|
" ) -> *mut libc::c_char {\n"
|
|
|
"\n"
|
|
|
" let error: &DatabaseError = unsafe {\n"
|
|
|
" // SAFETY: pointer lifetime is greater than the current stack "
|
|
|
"frame\n"
|
|
|
" &*e\n"
|
|
|
" };\n"
|
|
|
"\n"
|
|
|
" let error_str: String = match error {\n"
|
|
|
" DatabaseError::IsReadOnly => {\n"
|
|
|
" format!(\"cannot write to read-only database\");\n"
|
|
|
" }\n"
|
|
|
" DatabaseError::IOError(e) => {\n"
|
|
|
" format!(\"I/O Error: {}\", e);\n"
|
|
|
" }\n"
|
|
|
" DatabaseError::FileCorrupted(s) => {\n"
|
|
|
" format!(\"File corrupted, run repair: {}\", &s);\n"
|
|
|
" }\n"
|
|
|
" };\n"
|
|
|
"\n"
|
|
|
" let c_error = unsafe {\n"
|
|
|
" // SAFETY: copying error_str to an allocated buffer with a NUL\n"
|
|
|
" // character at the end\n"
|
|
|
" let mut malloc: *mut u8 = libc::malloc(error_str.len() + 1) as "
|
|
|
"*mut _;\n"
|
|
|
"\n"
|
|
|
" if malloc.is_null() {\n"
|
|
|
" return std::ptr::null_mut();\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" let src = error_str.as_bytes().as_ptr();\n"
|
|
|
"\n"
|
|
|
" std::ptr::copy_nonoverlapping(src, malloc, error_str.len());\n"
|
|
|
"\n"
|
|
|
" std::ptr::write(malloc.add(error_str.len()), 0);\n"
|
|
|
"\n"
|
|
|
" malloc as *mut libc::c_char\n"
|
|
|
" };\n"
|
|
|
"\n"
|
|
|
" c_error\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/ffi/errors.md:104
|
|
|
#, fuzzy
|
|
|
msgid "### Custom Error Types"
|
|
|
msgstr "### Tipi di errore personalizzati"
|
|
|
|
|
|
#: src\idioms/ffi/errors.md:106
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"struct ParseError {\n"
|
|
|
" expected: char,\n"
|
|
|
" line: u32,\n"
|
|
|
" ch: u16\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"impl ParseError { /* ... */ }\n"
|
|
|
"\n"
|
|
|
"/* Create a second version which is exposed as a C structure */\n"
|
|
|
"#[repr(C)]\n"
|
|
|
"pub struct parse_error {\n"
|
|
|
" pub expected: libc::c_char,\n"
|
|
|
" pub line: u32,\n"
|
|
|
" pub ch: u16\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"impl From<ParseError> for parse_error {\n"
|
|
|
" fn from(e: ParseError) -> parse_error {\n"
|
|
|
" let ParseError { expected, line, ch } = e;\n"
|
|
|
" parse_error { expected, line, ch }\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/ffi/errors.md:133
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This ensures that the foreign language has clear access to error "
|
|
|
"information\n"
|
|
|
"while not compromising the Rust code's API at all."
|
|
|
msgstr ""
|
|
|
"Ciò garantisce che la lingua straniera abbia un chiaro accesso alle "
|
|
|
"informazioni sugli errori\n"
|
|
|
"pur non compromettendo affatto l'API del codice Rust."
|
|
|
|
|
|
#: src\idioms/ffi/errors.md:138
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"It's a lot of typing, and some types may not be able to be converted easily\n"
|
|
|
"to C."
|
|
|
msgstr ""
|
|
|
"È un sacco di digitazione e alcuni tipi potrebbero non essere convertiti "
|
|
|
"facilmente\n"
|
|
|
"a c."
|
|
|
|
|
|
#: src\idioms/ffi/accepting-strings.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Accepting Strings"
|
|
|
msgstr "# Accettazione di stringhe"
|
|
|
|
|
|
#: src\idioms/ffi/accepting-strings.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"When accepting strings via FFI through pointers, there are two principles "
|
|
|
"that\n"
|
|
|
"should be followed:"
|
|
|
msgstr ""
|
|
|
"Quando si accettano stringhe tramite FFI tramite puntatori, esistono due "
|
|
|
"principi che\n"
|
|
|
"dovrebbe essere seguito:"
|
|
|
|
|
|
#: src\idioms/ffi/accepting-strings.md:8
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"1. Keep foreign strings \"borrowed\", rather than copying them directly.\n"
|
|
|
"2. Minimize the amount of complexity and `unsafe` code involved in "
|
|
|
"converting\n"
|
|
|
" from a C-style string to native Rust strings."
|
|
|
msgstr ""
|
|
|
"1. Mantieni le stringhe straniere \"prese in prestito\", piuttosto che "
|
|
|
"copiarle direttamente.\n"
|
|
|
"2. Ridurre al minimo la complessità e il codice \"non sicuro\" coinvolti "
|
|
|
"nella conversione\n"
|
|
|
" da una stringa in stile C alle stringhe Rust native."
|
|
|
|
|
|
#: src\idioms/ffi/accepting-strings.md:14
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The strings used in C have different behaviours to those used in Rust, "
|
|
|
"namely:"
|
|
|
msgstr ""
|
|
|
"Le stringhe usate in C hanno comportamenti diversi da quelle usate in Rust, "
|
|
|
"ovvero:"
|
|
|
|
|
|
#: src\idioms/ffi/accepting-strings.md:16
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- C strings are null-terminated while Rust strings store their length\n"
|
|
|
"- C strings can contain any arbitrary non-zero byte while Rust strings must "
|
|
|
"be\n"
|
|
|
" UTF-8\n"
|
|
|
"- C strings are accessed and manipulated using `unsafe` pointer operations\n"
|
|
|
" while interactions with Rust strings go through safe methods"
|
|
|
msgstr ""
|
|
|
"- Le stringhe C hanno terminazione null mentre le stringhe Rust memorizzano "
|
|
|
"la loro lunghezza\n"
|
|
|
"- Le stringhe C possono contenere qualsiasi byte arbitrario diverso da zero "
|
|
|
"mentre le stringhe Rust devono esserlo\n"
|
|
|
" UTF-8\n"
|
|
|
"- Le stringhe C sono accessibili e manipolate usando operazioni di puntatore "
|
|
|
"`unsafe`\n"
|
|
|
" mentre le interazioni con le stringhe Rust passano attraverso metodi sicuri"
|
|
|
|
|
|
#: src\idioms/ffi/accepting-strings.md:22
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The Rust standard library comes with C equivalents of Rust's `String` and "
|
|
|
"`&str`\n"
|
|
|
"called `CString` and `&CStr`, that allow us to avoid a lot of the "
|
|
|
"complexity\n"
|
|
|
"and `unsafe` code involved in converting between C strings and Rust strings."
|
|
|
msgstr ""
|
|
|
"La libreria standard di Rust viene fornita con gli equivalenti C di `String` "
|
|
|
"e `&str` di Rust\n"
|
|
|
"chiamate `CString` e `&CStr`, che ci permettono di evitare gran parte della "
|
|
|
"complessità\n"
|
|
|
"e il codice \"non sicuro\" coinvolto nella conversione tra stringhe C e "
|
|
|
"stringhe Rust."
|
|
|
|
|
|
#: src\idioms/ffi/accepting-strings.md:26
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The `&CStr` type also allows us to work with borrowed data, meaning passing\n"
|
|
|
"strings between Rust and C is a zero-cost operation."
|
|
|
msgstr ""
|
|
|
"Il tipo `&CStr` ci permette anche di lavorare con dati presi in prestito, "
|
|
|
"ovvero di passaggio\n"
|
|
|
"stringhe tra Rust e C è un'operazione a costo zero."
|
|
|
|
|
|
#: src\idioms/ffi/accepting-strings.md:31
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"pub mod unsafe_module {\n"
|
|
|
"\n"
|
|
|
" // other module content\n"
|
|
|
"\n"
|
|
|
" /// Log a message at the specified level.\n"
|
|
|
" ///\n"
|
|
|
" /// # Safety\n"
|
|
|
" ///\n"
|
|
|
" /// It is the caller's guarantee to ensure `msg`:\n"
|
|
|
" ///\n"
|
|
|
" /// - is not a null pointer\n"
|
|
|
" /// - points to valid, initialized data\n"
|
|
|
" /// - points to memory ending in a null byte\n"
|
|
|
" /// - won't be mutated for the duration of this function call\n"
|
|
|
" #[no_mangle]\n"
|
|
|
" pub unsafe extern \"C\" fn mylib_log(\n"
|
|
|
" msg: *const libc::c_char,\n"
|
|
|
" level: libc::c_int\n"
|
|
|
" ) {\n"
|
|
|
" let level: crate::LogLevel = match level { /* ... */ };\n"
|
|
|
"\n"
|
|
|
" // SAFETY: The caller has already guaranteed this is okay (see the\n"
|
|
|
" // `# Safety` section of the doc-comment).\n"
|
|
|
" let msg_str: &str = match std::ffi::CStr::from_ptr(msg).to_str() {\n"
|
|
|
" Ok(s) => s,\n"
|
|
|
" Err(e) => {\n"
|
|
|
" crate::log_error(\"FFI string conversion failed\");\n"
|
|
|
" return;\n"
|
|
|
" }\n"
|
|
|
" };\n"
|
|
|
"\n"
|
|
|
" crate::log(msg_str, level);\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/ffi/accepting-strings.md:70
|
|
|
#, fuzzy
|
|
|
msgid "The example is is written to ensure that:"
|
|
|
msgstr "L'esempio è scritto per garantire che:"
|
|
|
|
|
|
#: src\idioms/ffi/accepting-strings.md:72
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"1. The `unsafe` block is as small as possible.\n"
|
|
|
"2. The pointer with an \"untracked\" lifetime becomes a \"tracked\" shared\n"
|
|
|
" reference"
|
|
|
msgstr ""
|
|
|
"1. Il blocco \"non sicuro\" è il più piccolo possibile.\n"
|
|
|
"2. Il puntatore con una durata \"non tracciata\" diventa un condiviso "
|
|
|
"\"tracciato\".\n"
|
|
|
" riferimento"
|
|
|
|
|
|
#: src\idioms/ffi/accepting-strings.md:76
|
|
|
#, fuzzy
|
|
|
msgid "Consider an alternative, where the string is actually copied:"
|
|
|
msgstr ""
|
|
|
"Considera un'alternativa, in cui la stringa viene effettivamente copiata:"
|
|
|
|
|
|
#: src\idioms/ffi/accepting-strings.md:78
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"pub mod unsafe_module {\n"
|
|
|
"\n"
|
|
|
" // other module content\n"
|
|
|
"\n"
|
|
|
" pub extern \"C\" fn mylib_log(msg: *const libc::c_char, level: "
|
|
|
"libc::c_int) {\n"
|
|
|
" // DO NOT USE THIS CODE.\n"
|
|
|
" // IT IS UGLY, VERBOSE, AND CONTAINS A SUBTLE BUG.\n"
|
|
|
"\n"
|
|
|
" let level: crate::LogLevel = match level { /* ... */ };\n"
|
|
|
"\n"
|
|
|
" let msg_len = unsafe { /* SAFETY: strlen is what it is, I guess? */\n"
|
|
|
" libc::strlen(msg)\n"
|
|
|
" };\n"
|
|
|
"\n"
|
|
|
" let mut msg_data = Vec::with_capacity(msg_len + 1);\n"
|
|
|
"\n"
|
|
|
" let msg_cstr: std::ffi::CString = unsafe {\n"
|
|
|
" // SAFETY: copying from a foreign pointer expected to live\n"
|
|
|
" // for the entire stack frame into owned memory\n"
|
|
|
" std::ptr::copy_nonoverlapping(msg, msg_data.as_mut(), msg_len);\n"
|
|
|
"\n"
|
|
|
" msg_data.set_len(msg_len + 1);\n"
|
|
|
"\n"
|
|
|
" std::ffi::CString::from_vec_with_nul(msg_data).unwrap()\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" let msg_str: String = unsafe {\n"
|
|
|
" match msg_cstr.into_string() {\n"
|
|
|
" Ok(s) => s,\n"
|
|
|
" Err(e) => {\n"
|
|
|
" crate::log_error(\"FFI string conversion failed\");\n"
|
|
|
" return;\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
" };\n"
|
|
|
"\n"
|
|
|
" crate::log(&msg_str, level);\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/ffi/accepting-strings.md:120
|
|
|
#, fuzzy
|
|
|
msgid "This code in inferior to the original in two respects:"
|
|
|
msgstr "Questo codice è inferiore all'originale sotto due aspetti:"
|
|
|
|
|
|
#: src\idioms/ffi/accepting-strings.md:122
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"1. There is much more `unsafe` code, and more importantly, more invariants "
|
|
|
"it\n"
|
|
|
" must uphold.\n"
|
|
|
"2. Due to the extensive arithmetic required, there is a bug in this version\n"
|
|
|
" that cases Rust `undefined behaviour`."
|
|
|
msgstr ""
|
|
|
"1. C'è molto più codice \"non sicuro\" e, cosa più importante, più "
|
|
|
"invarianti\n"
|
|
|
" deve sostenere.\n"
|
|
|
"2. A causa dell'ampia aritmetica richiesta, c'è un bug in questa versione\n"
|
|
|
" che causa il \"comportamento indefinito\" di Rust."
|
|
|
|
|
|
#: src\idioms/ffi/accepting-strings.md:127
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The bug here is a simple mistake in pointer arithmetic: the string was "
|
|
|
"copied,\n"
|
|
|
"all `msg_len` bytes of it. However, the `NUL` terminator at the end was not."
|
|
|
msgstr ""
|
|
|
"Il bug qui è un semplice errore nell'aritmetica del puntatore: la stringa è "
|
|
|
"stata copiata,\n"
|
|
|
"tutti i byte `msg_len` di esso. Tuttavia, il terminatore \"NUL\" alla fine "
|
|
|
"non lo era."
|
|
|
|
|
|
#: src\idioms/ffi/accepting-strings.md:130
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The Vector then had its size _set_ to the length of the _zero padded string_ "
|
|
|
"--\n"
|
|
|
"rather than _resized_ to it, which could have added a zero at the end.\n"
|
|
|
"As a result, the last byte in the Vector is uninitialized memory.\n"
|
|
|
"When the `CString` is created at the bottom of the block, its read of the\n"
|
|
|
"Vector will cause `undefined behaviour`!"
|
|
|
msgstr ""
|
|
|
"Il vettore aveva quindi la sua dimensione _impostata_ sulla lunghezza della "
|
|
|
"_stringa imbottita zero_ --\n"
|
|
|
"piuttosto che _ridimensionato_ ad esso, che avrebbe potuto aggiungere uno "
|
|
|
"zero alla fine.\n"
|
|
|
"Di conseguenza, l'ultimo byte nel vettore è memoria non inizializzata.\n"
|
|
|
"Quando \"CString\" viene creato nella parte inferiore del blocco, viene "
|
|
|
"letto il file\n"
|
|
|
"Il vettore causerà un `comportamento indefinito`!"
|
|
|
|
|
|
#: src\idioms/ffi/accepting-strings.md:136
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Like many such issues, this would be difficult issue to track down.\n"
|
|
|
"Sometimes it would panic because the string was not `UTF-8`, sometimes it "
|
|
|
"would\n"
|
|
|
"put a weird character at the end of the string, sometimes it would just\n"
|
|
|
"completely crash."
|
|
|
msgstr ""
|
|
|
"Come molti di questi problemi, questo sarebbe un problema difficile da "
|
|
|
"rintracciare.\n"
|
|
|
"A volte andava nel panico perché la stringa non era \"UTF-8\", a volte sì\n"
|
|
|
"metti un carattere strano alla fine della stringa, a volte sarebbe solo\n"
|
|
|
"crollare completamente."
|
|
|
|
|
|
#: src\idioms/ffi/accepting-strings.md:143
|
|
|
#: src\idioms/ffi/passing-strings.md:105
|
|
|
#, fuzzy
|
|
|
msgid "None?"
|
|
|
msgstr "Nessuno?"
|
|
|
|
|
|
#: src\idioms/ffi/passing-strings.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Passing Strings"
|
|
|
msgstr "# Passaggio di stringhe"
|
|
|
|
|
|
#: src\idioms/ffi/passing-strings.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"When passing strings to FFI functions, there are four principles that should "
|
|
|
"be\n"
|
|
|
"followed:"
|
|
|
msgstr ""
|
|
|
"Quando si passano stringhe alle funzioni FFI, ci sono quattro principi che "
|
|
|
"dovrebbero essere\n"
|
|
|
"seguito:"
|
|
|
|
|
|
#: src\idioms/ffi/passing-strings.md:8
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"1. Make the lifetime of owned strings as long as possible.\n"
|
|
|
"2. Minimize `unsafe` code during the conversion.\n"
|
|
|
"3. If the C code can modify the string data, use `Vec` instead of "
|
|
|
"`CString`.\n"
|
|
|
"4. Unless the Foreign Function API requires it, the ownership of the string\n"
|
|
|
" should not transfer to the callee."
|
|
|
msgstr ""
|
|
|
"1. Aumentare il più possibile la durata delle stringhe possedute.\n"
|
|
|
"2. Ridurre al minimo il codice \"non sicuro\" durante la conversione.\n"
|
|
|
"3. Se il codice C può modificare i dati della stringa, utilizzare \"Vec\" "
|
|
|
"invece di \"CString\".\n"
|
|
|
"4. A meno che l'API della funzione esterna non lo richieda, la proprietà "
|
|
|
"della stringa\n"
|
|
|
" non deve essere trasferito al chiamato."
|
|
|
|
|
|
#: src\idioms/ffi/passing-strings.md:16
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Rust has built-in support for C-style strings with its `CString` and `CStr`\n"
|
|
|
"types. However, there are different approaches one can take with strings "
|
|
|
"that\n"
|
|
|
"are being sent to a foreign function call from a Rust function."
|
|
|
msgstr ""
|
|
|
"Rust ha il supporto integrato per le stringhe in stile C con i suoi "
|
|
|
"`CString` e `CStr`\n"
|
|
|
"tipi. Tuttavia, ci sono diversi approcci che si possono adottare con "
|
|
|
"stringhe che\n"
|
|
|
"vengono inviati a una chiamata di funzione esterna da una funzione Rust."
|
|
|
|
|
|
#: src\idioms/ffi/passing-strings.md:20
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The best practice is simple: use `CString` in such a way as to minimize\n"
|
|
|
"`unsafe` code. However, a secondary caveat is that\n"
|
|
|
"_the object must live long enough_, meaning the lifetime should be "
|
|
|
"maximized.\n"
|
|
|
"In addition, the documentation explains that \"round-tripping\" a `CString` "
|
|
|
"after\n"
|
|
|
"modification is UB, so additional work is necessary in that case."
|
|
|
msgstr ""
|
|
|
"La migliore pratica è semplice: usa `CString` in modo tale da minimizzare\n"
|
|
|
"codice \"non sicuro\". Tuttavia, un avvertimento secondario è quello\n"
|
|
|
"_l'oggetto deve vivere abbastanza a lungo_, il che significa che la durata "
|
|
|
"dovrebbe essere massimizzata.\n"
|
|
|
"Inoltre, la documentazione spiega che \"round-tripping\" a `CString` after\n"
|
|
|
"la modifica è UB, quindi in tal caso è necessario ulteriore lavoro."
|
|
|
|
|
|
#: src\idioms/ffi/passing-strings.md:28
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"pub mod unsafe_module {\n"
|
|
|
"\n"
|
|
|
" // other module content\n"
|
|
|
"\n"
|
|
|
" extern \"C\" {\n"
|
|
|
" fn seterr(message: *const libc::c_char);\n"
|
|
|
" fn geterr(buffer: *mut libc::c_char, size: libc::c_int) -> "
|
|
|
"libc::c_int;\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" fn report_error_to_ffi<S: Into<String>>(\n"
|
|
|
" err: S\n"
|
|
|
" ) -> Result<(), std::ffi::NulError>{\n"
|
|
|
" let c_err = std::ffi::CString::new(err.into())?;\n"
|
|
|
"\n"
|
|
|
" unsafe {\n"
|
|
|
" // SAFETY: calling an FFI whose documentation says the pointer "
|
|
|
"is\n"
|
|
|
" // const, so no modification should occur\n"
|
|
|
" seterr(c_err.as_ptr());\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" Ok(())\n"
|
|
|
" // The lifetime of c_err continues until here\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" fn get_error_from_ffi() -> Result<String, std::ffi::IntoStringError> {\n"
|
|
|
" let mut buffer = vec![0u8; 1024];\n"
|
|
|
" unsafe {\n"
|
|
|
" // SAFETY: calling an FFI whose documentation implies\n"
|
|
|
" // that the input need only live as long as the call\n"
|
|
|
" let written: usize = geterr(buffer.as_mut_ptr(), 1023).into();\n"
|
|
|
"\n"
|
|
|
" buffer.truncate(written + 1);\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" std::ffi::CString::new(buffer).unwrap().into_string()\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/ffi/passing-strings.md:70
|
|
|
#, fuzzy
|
|
|
msgid "The example is written in a way to ensure that:"
|
|
|
msgstr "L'esempio è scritto in modo da garantire che:"
|
|
|
|
|
|
#: src\idioms/ffi/passing-strings.md:72
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"1. The `unsafe` block is as small as possible.\n"
|
|
|
"2. The `CString` lives long enough.\n"
|
|
|
"3. Errors with typecasts are always propagated when possible."
|
|
|
msgstr ""
|
|
|
"1. Il blocco \"non sicuro\" è il più piccolo possibile.\n"
|
|
|
"2. Il `CString` vive abbastanza a lungo.\n"
|
|
|
"3. Gli errori con i typecast vengono sempre propagati quando possibile."
|
|
|
|
|
|
#: src\idioms/ffi/passing-strings.md:76
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"A common mistake (so common it's in the documentation) is to not use the\n"
|
|
|
"variable in the first block:"
|
|
|
msgstr ""
|
|
|
"Un errore comune (così comune è nella documentazione) è non usare il file\n"
|
|
|
"variabile nel primo blocco:"
|
|
|
|
|
|
#: src\idioms/ffi/passing-strings.md:79
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"pub mod unsafe_module {\n"
|
|
|
"\n"
|
|
|
" // other module content\n"
|
|
|
"\n"
|
|
|
" fn report_error<S: Into<String>>(err: S) -> Result<(), "
|
|
|
"std::ffi::NulError> {\n"
|
|
|
" unsafe {\n"
|
|
|
" // SAFETY: whoops, this contains a dangling pointer!\n"
|
|
|
" seterr(std::ffi::CString::new(err.into())?.as_ptr());\n"
|
|
|
" }\n"
|
|
|
" Ok(())\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/ffi/passing-strings.md:94
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This code will result in a dangling pointer, because the lifetime of the\n"
|
|
|
"`CString` is not extended by the pointer creation, unlike if a reference "
|
|
|
"were\n"
|
|
|
"created."
|
|
|
msgstr ""
|
|
|
"Questo codice si tradurrà in un puntatore penzolante, perché la durata del "
|
|
|
"file\n"
|
|
|
"`CString` non viene esteso dalla creazione del puntatore, a differenza di un "
|
|
|
"riferimento\n"
|
|
|
"creato."
|
|
|
|
|
|
#: src\idioms/ffi/passing-strings.md:98
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Another issue frequently raised is that the initialization of a 1k vector "
|
|
|
"of\n"
|
|
|
"zeroes is \"slow\". However, recent versions of Rust actually optimize that\n"
|
|
|
"particular macro to a call to `zmalloc`, meaning it is as fast as the "
|
|
|
"operating\n"
|
|
|
"system's ability to return zeroed memory (which is quite fast)."
|
|
|
msgstr ""
|
|
|
"Un altro problema spesso sollevato è che l'inizializzazione di un vettore 1k "
|
|
|
"di\n"
|
|
|
"zeri è \"lento\". Tuttavia, le versioni recenti di Rust lo ottimizzano "
|
|
|
"effettivamente\n"
|
|
|
"particolare macro a una chiamata a `zmalloc`, il che significa che è veloce "
|
|
|
"quanto l'operazione\n"
|
|
|
"la capacità del sistema di restituire la memoria azzerata (che è abbastanza "
|
|
|
"veloce)."
|
|
|
|
|
|
#: src\idioms/option-iter.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Iterating over an `Option`"
|
|
|
msgstr "# Iterazione su una `Opzione`"
|
|
|
|
|
|
#: src\idioms/option-iter.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"`Option` can be viewed as a container that contains either zero or one\n"
|
|
|
"element. In particular, it implements the `IntoIterator` trait, and as such\n"
|
|
|
"can be used with generic code that needs such a type."
|
|
|
msgstr ""
|
|
|
"`Option` può essere visto come un contenitore che contiene zero o uno\n"
|
|
|
"elemento. In particolare, implementa il tratto `IntoIterator`, e come tale\n"
|
|
|
"può essere utilizzato con codice generico che necessita di tale tipo."
|
|
|
|
|
|
#: src\idioms/option-iter.md:9 src\patterns/structural/small-crates.md:34
|
|
|
#: src\patterns/structural/unsafe-mods.md:22
|
|
|
#, fuzzy
|
|
|
msgid "## Examples"
|
|
|
msgstr "## Esempi"
|
|
|
|
|
|
#: src\idioms/option-iter.md:11
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Since `Option` implements `IntoIterator`, it can be used as an argument to\n"
|
|
|
"[`.extend()`](https://doc.rust-lang.org/std/iter/trait.Extend.html#tymethod.extend):"
|
|
|
msgstr ""
|
|
|
"Poiché `Option` implementa `IntoIterator`, può essere utilizzato come "
|
|
|
"argomento per\n"
|
|
|
"[`.extend()`](https://doc.rust-lang.org/std/iter/trait.Extend.html#tymethod.extend):"
|
|
|
|
|
|
#: src\idioms/option-iter.md:14
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"let turing = Some(\"Turing\");\n"
|
|
|
"let mut logicians = vec![\"Curry\", \"Kleene\", \"Markov\"];\n"
|
|
|
"\n"
|
|
|
"logicians.extend(turing);\n"
|
|
|
"\n"
|
|
|
"// equivalent to\n"
|
|
|
"if let Some(turing_inner) = turing {\n"
|
|
|
" logicians.push(turing_inner);\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/option-iter.md:26
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"If you need to tack an `Option` to the end of an existing iterator, you can\n"
|
|
|
"pass it to "
|
|
|
"[`.chain()`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.chain):"
|
|
|
msgstr ""
|
|
|
"Se devi aggiungere un'opzione alla fine di un iteratore esistente, puoi "
|
|
|
"farlo\n"
|
|
|
"passalo a "
|
|
|
"[`.chain()`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.chain):"
|
|
|
|
|
|
#: src\idioms/option-iter.md:29
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"let turing = Some(\"Turing\");\n"
|
|
|
"let logicians = vec![\"Curry\", \"Kleene\", \"Markov\"];\n"
|
|
|
"\n"
|
|
|
"for logician in logicians.iter().chain(turing.iter()) {\n"
|
|
|
" println!(\"{} is a logician\", logician);\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/option-iter.md:38
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Note that if the `Option` is always `Some`, then it is more idiomatic to "
|
|
|
"use\n"
|
|
|
"[`std::iter::once`](https://doc.rust-lang.org/std/iter/fn.once.html) on the\n"
|
|
|
"element instead."
|
|
|
msgstr ""
|
|
|
"Nota che se \"Option\" è sempre \"Some\", allora è più idiomatico da usare\n"
|
|
|
"[`std::iter::once`](https://doc.rust-lang.org/std/iter/fn.once.html) sul\n"
|
|
|
"elemento invece."
|
|
|
|
|
|
#: src\idioms/option-iter.md:42
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Also, since `Option` implements `IntoIterator`, it's possible to iterate "
|
|
|
"over\n"
|
|
|
"it using a `for` loop. This is equivalent to matching it with `if let "
|
|
|
"Some(..)`,\n"
|
|
|
"and in most cases you should prefer the latter."
|
|
|
msgstr ""
|
|
|
"Inoltre, poiché `Option` implementa `IntoIterator`, è possibile iterare\n"
|
|
|
"usando un ciclo `for`. Ciò equivale a confrontarlo con `if let Some(..)`,\n"
|
|
|
"e nella maggior parte dei casi dovresti preferire quest'ultimo."
|
|
|
|
|
|
#: src\idioms/option-iter.md:48
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [`std::iter::once`](https://doc.rust-lang.org/std/iter/fn.once.html) is "
|
|
|
"an\n"
|
|
|
" iterator which yields exactly one element. It's a more readable "
|
|
|
"alternative to\n"
|
|
|
" `Some(foo).into_iter()`.\n"
|
|
|
"\n"
|
|
|
"- "
|
|
|
"[`Iterator::filter_map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter_map)\n"
|
|
|
" is a version of "
|
|
|
"[`Iterator::map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map),\n"
|
|
|
" specialized to mapping functions which return `Option`.\n"
|
|
|
"\n"
|
|
|
"- The [`ref_slice`](https://crates.io/crates/ref_slice) crate provides "
|
|
|
"functions\n"
|
|
|
" for converting an `Option` to a zero- or one-element slice.\n"
|
|
|
"\n"
|
|
|
"- [Documentation for "
|
|
|
"`Option<T>`](https://doc.rust-lang.org/std/option/enum.Option.html)"
|
|
|
msgstr ""
|
|
|
"- [`std::iter::once`](https://doc.rust-lang.org/std/iter/fn.once.html) è un\n"
|
|
|
" iteratore che restituisce esattamente un elemento. È un'alternativa più "
|
|
|
"leggibile a\n"
|
|
|
" `Alcuni(foo).into_iter()`.\n"
|
|
|
"\n"
|
|
|
"- "
|
|
|
"[`Iterator::filter_map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter_map)\n"
|
|
|
" è una versione di "
|
|
|
"[`Iterator::map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map),\n"
|
|
|
" specializzato per mappare funzioni che restituiscono `Opzione`.\n"
|
|
|
"\n"
|
|
|
"- Il crate [`ref_slice`](https://crates.io/crates/ref_slice) fornisce "
|
|
|
"funzioni\n"
|
|
|
" per convertire una `Opzione` in una fetta con zero o un elemento.\n"
|
|
|
"\n"
|
|
|
"- [Documentazione per "
|
|
|
"`Option<T>`](https://doc.rust-lang.org/std/option/enum.Option.html)"
|
|
|
|
|
|
#: src\idioms/pass-var-to-closure.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Pass variables to closure"
|
|
|
msgstr "# Passa le variabili alla chiusura"
|
|
|
|
|
|
#: src\idioms/pass-var-to-closure.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"By default, closures capture their environment by borrowing. Or you can use\n"
|
|
|
"`move`-closure to move whole environment. However, often you want to move "
|
|
|
"just\n"
|
|
|
"some variables to closure, give it copy of some data, pass it by reference, "
|
|
|
"or\n"
|
|
|
"perform some other transformation."
|
|
|
msgstr ""
|
|
|
"Per impostazione predefinita, le chiusure catturano il loro ambiente "
|
|
|
"prendendo in prestito. Oppure puoi usare\n"
|
|
|
"`move`-chiusura per spostare l'intero ambiente. Tuttavia, spesso vuoi "
|
|
|
"muoverti solo\n"
|
|
|
"alcune variabili alla chiusura, dagli una copia di alcuni dati, passalo per "
|
|
|
"riferimento o\n"
|
|
|
"eseguire qualche altra trasformazione."
|
|
|
|
|
|
#: src\idioms/pass-var-to-closure.md:10
|
|
|
#, fuzzy
|
|
|
msgid "Use variable rebinding in separate scope for that."
|
|
|
msgstr "Usa il rebinding variabile in un ambito separato per questo."
|
|
|
|
|
|
#: src\idioms/pass-var-to-closure.md:14
|
|
|
#, fuzzy
|
|
|
msgid "Use"
|
|
|
msgstr "Utilizzo"
|
|
|
|
|
|
#: src\idioms/pass-var-to-closure.md:16
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"use std::rc::Rc;\n"
|
|
|
"\n"
|
|
|
"let num1 = Rc::new(1);\n"
|
|
|
"let num2 = Rc::new(2);\n"
|
|
|
"let num3 = Rc::new(3);\n"
|
|
|
"let closure = {\n"
|
|
|
" // `num1` is moved\n"
|
|
|
" let num2 = num2.clone(); // `num2` is cloned\n"
|
|
|
" let num3 = num3.as_ref(); // `num3` is borrowed\n"
|
|
|
" move || {\n"
|
|
|
" *num1 + *num2 + *num3;\n"
|
|
|
" }\n"
|
|
|
"};\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/pass-var-to-closure.md:32
|
|
|
#, fuzzy
|
|
|
msgid "instead of"
|
|
|
msgstr "invece di"
|
|
|
|
|
|
#: src\idioms/pass-var-to-closure.md:34
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"use std::rc::Rc;\n"
|
|
|
"\n"
|
|
|
"let num1 = Rc::new(1);\n"
|
|
|
"let num2 = Rc::new(2);\n"
|
|
|
"let num3 = Rc::new(3);\n"
|
|
|
"\n"
|
|
|
"let num2_cloned = num2.clone();\n"
|
|
|
"let num3_borrowed = num3.as_ref();\n"
|
|
|
"let closure = move || {\n"
|
|
|
" *num1 + *num2_cloned + *num3_borrowed;\n"
|
|
|
"};\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/pass-var-to-closure.md:50
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Copied data are grouped together with closure definition, so their purpose "
|
|
|
"is\n"
|
|
|
"more clear, and they will be dropped immediately even if they are not "
|
|
|
"consumed\n"
|
|
|
"by closure."
|
|
|
msgstr ""
|
|
|
"I dati copiati sono raggruppati insieme alla definizione di chiusura, quindi "
|
|
|
"il loro scopo è\n"
|
|
|
"più chiari, e verranno immediatamente eliminati anche se non vengono "
|
|
|
"consumati\n"
|
|
|
"per chiusura."
|
|
|
|
|
|
#: src\idioms/pass-var-to-closure.md:54
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Closure uses same variable names as surrounding code whether data are copied "
|
|
|
"or\n"
|
|
|
"moved."
|
|
|
msgstr ""
|
|
|
"La chiusura utilizza gli stessi nomi di variabile del codice circostante "
|
|
|
"indipendentemente dal fatto che i dati vengano copiati o\n"
|
|
|
"mosso."
|
|
|
|
|
|
#: src\idioms/pass-var-to-closure.md:59
|
|
|
#, fuzzy
|
|
|
msgid "Additional indentation of closure body."
|
|
|
msgstr "Rientro aggiuntivo del corpo della chiusura."
|
|
|
|
|
|
#: src\idioms/priv-extend.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# `#[non_exhaustive]` and private fields for extensibility"
|
|
|
msgstr "# `#[non_esaustivo]` e campi privati per l'estensibilità"
|
|
|
|
|
|
#: src\idioms/priv-extend.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"A small set of scenarios exist where a library author may want to add "
|
|
|
"public\n"
|
|
|
"fields to a public struct or new variants to an enum without breaking "
|
|
|
"backwards\n"
|
|
|
"compatibility."
|
|
|
msgstr ""
|
|
|
"Esiste un piccolo insieme di scenari in cui un autore di libreria potrebbe "
|
|
|
"voler aggiungere public\n"
|
|
|
"campi a una struttura pubblica o nuove varianti a un'enumerazione senza "
|
|
|
"andare all'indietro\n"
|
|
|
"Compatibilità."
|
|
|
|
|
|
#: src\idioms/priv-extend.md:9
|
|
|
#, fuzzy
|
|
|
msgid "Rust offers two solutions to this problem:"
|
|
|
msgstr "Rust offre due soluzioni a questo problema:"
|
|
|
|
|
|
#: src\idioms/priv-extend.md:11
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- Use `#[non_exhaustive]` on `struct`s, `enum`s, and `enum` variants.\n"
|
|
|
" For extensive documentation on all the places where `#[non_exhaustive]` "
|
|
|
"can be\n"
|
|
|
" used, see [the "
|
|
|
"docs](https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute).\n"
|
|
|
"\n"
|
|
|
"- You may add a private field to a struct to prevent it from being directly\n"
|
|
|
" instantiated or matched against (see Alternative)"
|
|
|
msgstr ""
|
|
|
"- Usa `#[non_exhaustive]` sulle varianti `struct`s, `enum`s e `enum`.\n"
|
|
|
" Per un'ampia documentazione su tutti i luoghi in cui può essere "
|
|
|
"`#[non_esauriente]`\n"
|
|
|
" utilizzato, vedere [la "
|
|
|
"documentazione](https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute).\n"
|
|
|
"\n"
|
|
|
"- Puoi aggiungere un campo privato a una struttura per evitare che sia "
|
|
|
"diretta\n"
|
|
|
" istanziato o confrontato (vedi Alternativa)"
|
|
|
|
|
|
#: src\idioms/priv-extend.md:20
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"mod a {\n"
|
|
|
" // Public struct.\n"
|
|
|
" #[non_exhaustive]\n"
|
|
|
" pub struct S {\n"
|
|
|
" pub foo: i32,\n"
|
|
|
" }\n"
|
|
|
" \n"
|
|
|
" #[non_exhaustive]\n"
|
|
|
" pub enum AdmitMoreVariants {\n"
|
|
|
" VariantA,\n"
|
|
|
" VariantB,\n"
|
|
|
" #[non_exhaustive]\n"
|
|
|
" VariantC { a: String }\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn print_matched_variants(s: a::S) {\n"
|
|
|
" // Because S is `#[non_exhaustive]`, it cannot be named here and\n"
|
|
|
" // we must use `..` in the pattern.\n"
|
|
|
" let a::S { foo: _, ..} = s;\n"
|
|
|
" \n"
|
|
|
" let some_enum = a::AdmitMoreVariants::VariantA;\n"
|
|
|
" match some_enum {\n"
|
|
|
" a::AdmitMoreVariants::VariantA => println!(\"it's an A\"),\n"
|
|
|
" a::AdmitMoreVariants::VariantB => println!(\"it's a b\"),\n"
|
|
|
"\n"
|
|
|
" // .. required because this variant is non-exhaustive as well\n"
|
|
|
" a::AdmitMoreVariants::VariantC { a, .. } => println!(\"it's a c\"),\n"
|
|
|
"\n"
|
|
|
" // The wildcard match is required because more variants may be\n"
|
|
|
" // added in the future\n"
|
|
|
" _ => println!(\"it's a new variant\")\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/priv-extend.md:57
|
|
|
#, fuzzy
|
|
|
msgid "## Alternative: `Private fields` for structs"
|
|
|
msgstr "## Alternativa: `Campi privati` per le strutture"
|
|
|
|
|
|
#: src\idioms/priv-extend.md:59
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"`#[non_exhaustive]` only works across crate boundaries.\n"
|
|
|
"Within a crate, the private field method may be used."
|
|
|
msgstr ""
|
|
|
"\"#[non_exhaustive]\" funziona solo oltre i confini della cassa.\n"
|
|
|
"All'interno di una cassa, può essere utilizzato il metodo del campo privato."
|
|
|
|
|
|
#: src\idioms/priv-extend.md:62
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Adding a field to a struct is a mostly backwards compatible change.\n"
|
|
|
"However, if a client uses a pattern to deconstruct a struct instance, they\n"
|
|
|
"might name all the fields in the struct and adding a new one would break "
|
|
|
"that\n"
|
|
|
"pattern.\n"
|
|
|
"The client could name some fields and use `..` in the pattern, in which case "
|
|
|
"adding\n"
|
|
|
"another field is backwards compatible.\n"
|
|
|
"Making at least one of the struct's fields private forces clients to use the "
|
|
|
"latter\n"
|
|
|
"form of patterns, ensuring that the struct is future-proof."
|
|
|
msgstr ""
|
|
|
"L'aggiunta di un campo a una struttura è una modifica per lo più compatibile "
|
|
|
"con le versioni precedenti.\n"
|
|
|
"Tuttavia, se un client utilizza un modello per decostruire un'istanza "
|
|
|
"struct, essi\n"
|
|
|
"potrebbe nominare tutti i campi nella struttura e aggiungerne uno nuovo lo "
|
|
|
"interromperebbe\n"
|
|
|
"modello.\n"
|
|
|
"Il client potrebbe nominare alcuni campi e utilizzare `..` nel pattern, nel "
|
|
|
"qual caso aggiungendo\n"
|
|
|
"un altro campo è retrocompatibile.\n"
|
|
|
"Rendere privato almeno uno dei campi della struttura obbliga i client a "
|
|
|
"utilizzare quest'ultimo\n"
|
|
|
"forma di modelli, assicurando che la struttura sia a prova di futuro."
|
|
|
|
|
|
#: src\idioms/priv-extend.md:71
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The downside of this approach is that you might need to add an otherwise "
|
|
|
"unneeded\n"
|
|
|
"field to the struct.\n"
|
|
|
"You can use the `()` type so that there is no runtime overhead and prepend "
|
|
|
"`_` to\n"
|
|
|
"the field name to avoid the unused field warning."
|
|
|
msgstr ""
|
|
|
"Lo svantaggio di questo approccio è che potrebbe essere necessario "
|
|
|
"aggiungere un file altrimenti non necessario\n"
|
|
|
"campo alla struttura.\n"
|
|
|
"Puoi usare il tipo `()` in modo che non ci sia sovraccarico di runtime e "
|
|
|
"anteporre `_` a\n"
|
|
|
"il nome del campo per evitare l'avviso di campo inutilizzato."
|
|
|
|
|
|
#: src\idioms/priv-extend.md:76
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"pub struct S {\n"
|
|
|
" pub a: i32,\n"
|
|
|
" // Because `b` is private, you cannot match on `S` without using `..` "
|
|
|
"and `S`\n"
|
|
|
" // cannot be directly instantiated or matched against\n"
|
|
|
" _b: ()\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/priv-extend.md:87
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"On `struct`s, `#[non_exhaustive]` allows adding additional fields in a "
|
|
|
"backwards\n"
|
|
|
"compatible way.\n"
|
|
|
"It will also prevent clients from using the struct constructor, even if all "
|
|
|
"the\n"
|
|
|
"fields are public.\n"
|
|
|
"This may be helpful, but it's worth considering if you _want_ an additional "
|
|
|
"field\n"
|
|
|
"to be found by clients as a compiler error rather than something that may be "
|
|
|
"silently\n"
|
|
|
"undiscovered."
|
|
|
msgstr ""
|
|
|
"Su `struct`s, `#[non_exhaustive]` consente di aggiungere ulteriori campi in "
|
|
|
"un modo all'indietro\n"
|
|
|
"modo compatibile.\n"
|
|
|
"Impedirà inoltre ai client di utilizzare il costruttore struct, anche se "
|
|
|
"tutti i file\n"
|
|
|
"i campi sono pubblici\n"
|
|
|
"Questo può essere utile, ma vale la pena considerare se _vuoi_ un campo "
|
|
|
"aggiuntivo\n"
|
|
|
"essere trovato dai client come un errore del compilatore piuttosto che "
|
|
|
"qualcosa che potrebbe essere nascosto\n"
|
|
|
"non scoperto."
|
|
|
|
|
|
#: src\idioms/priv-extend.md:95
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"`#[non_exhaustive]` can be applied to enum variants as well.\n"
|
|
|
"A `#[non_exhaustive]` variant behaves in the same way as a "
|
|
|
"`#[non_exhaustive]` struct."
|
|
|
msgstr ""
|
|
|
"`#[non_exhaustive]` può essere applicato anche alle varianti enum.\n"
|
|
|
"Una variante `#[non_exhaustive]` si comporta allo stesso modo di una "
|
|
|
"struttura `#[non_exhaustive]`."
|
|
|
|
|
|
#: src\idioms/priv-extend.md:98
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Use this deliberately and with caution: incrementing the major version when "
|
|
|
"adding\n"
|
|
|
"fields or variants is often a better option.\n"
|
|
|
"`#[non_exhaustive]` may be appropriate in scenarios where you're modeling an "
|
|
|
"external\n"
|
|
|
"resource that may change out-of-sync with your library, but is not a general "
|
|
|
"purpose\n"
|
|
|
"tool."
|
|
|
msgstr ""
|
|
|
"Usalo deliberatamente e con cautela: incrementare la versione principale "
|
|
|
"durante l'aggiunta\n"
|
|
|
"campi o varianti è spesso un'opzione migliore.\n"
|
|
|
"\"#[non_exhaustive]\" può essere appropriato in scenari in cui stai "
|
|
|
"modellando un esterno\n"
|
|
|
"risorsa che potrebbe cambiare in modo non sincronizzato con la tua libreria, "
|
|
|
"ma non è uno scopo generale\n"
|
|
|
"attrezzo."
|
|
|
|
|
|
#: src\idioms/priv-extend.md:104
|
|
|
#, fuzzy
|
|
|
msgid "### Disadvantages"
|
|
|
msgstr "### Svantaggi"
|
|
|
|
|
|
#: src\idioms/priv-extend.md:106
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"`#[non_exhaustive]` can make your code much less ergonomic to use, "
|
|
|
"especially when\n"
|
|
|
"forced to handle unknown enum variants.\n"
|
|
|
"It should only be used when these sorts of evolutions are required "
|
|
|
"**without**\n"
|
|
|
"incrementing the major version."
|
|
|
msgstr ""
|
|
|
"`#[non_exhaustive]` può rendere il tuo codice molto meno ergonomico da "
|
|
|
"usare, specialmente quando\n"
|
|
|
"costretto a gestire varianti enum sconosciute.\n"
|
|
|
"Dovrebbe essere usato solo quando sono richiesti questi tipi di evoluzioni "
|
|
|
"**senza**\n"
|
|
|
"incrementando la versione principale."
|
|
|
|
|
|
#: src\idioms/priv-extend.md:111
|
|
|
msgid ""
|
|
|
"When `#[non_exhaustive]` is applied to `enum`s, it forces clients to handle "
|
|
|
"a\n"
|
|
|
"wildcard variant.\n"
|
|
|
"If there is no sensible action to take in this case, this may lead to "
|
|
|
"awkward\n"
|
|
|
"code and code paths that are only executed in extremely rare circumstances.\n"
|
|
|
"If a client decides to `panic!()` in this scenario, it may have been better "
|
|
|
"to\n"
|
|
|
"expose this error at compile time.\n"
|
|
|
"In fact, `#[non_exhaustive]` forces clients to handle the \"Something else\" "
|
|
|
"case;\n"
|
|
|
"there is rarely a sensible action to take in this scenario."
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/priv-extend.md:122
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [RFC introducing #[non_exhaustive] attribute for enums and "
|
|
|
"structs](https://github.com/rust-lang/rfcs/blob/master/text/2008-non-exhaustive.md)"
|
|
|
msgstr ""
|
|
|
"- [RFC introduce l'attributo #[non_exhaustive] per enum e "
|
|
|
"struct](https://github.com/rust-lang/rfcs/blob/master/text/2008-non-exhaustive.md)"
|
|
|
|
|
|
#: src\idioms/rustdoc-init.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Easy doc initialization\r"
|
|
|
msgstr "# Facile inizializzazione dei documenti\r"
|
|
|
|
|
|
#: src\idioms/rustdoc-init.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"If a struct takes significant effort to initialize when writing docs, it can "
|
|
|
"be\r\n"
|
|
|
"quicker to wrap your example with a helper function which takes the struct "
|
|
|
"as an\r\n"
|
|
|
"argument."
|
|
|
msgstr ""
|
|
|
"Se una struttura richiede uno sforzo significativo per l'inizializzazione "
|
|
|
"durante la scrittura di documenti, può esserlo\r\n"
|
|
|
"più veloce per avvolgere il tuo esempio con una funzione di supporto che "
|
|
|
"prende la struttura come un\r\n"
|
|
|
"discussione."
|
|
|
|
|
|
#: src\idioms/rustdoc-init.md:9
|
|
|
#, fuzzy
|
|
|
msgid "## Motivation\r"
|
|
|
msgstr "## Motivazione\r"
|
|
|
|
|
|
#: src\idioms/rustdoc-init.md:11
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Sometimes there is a struct with multiple or complicated parameters and "
|
|
|
"several\r\n"
|
|
|
"methods. Each of these methods should have examples."
|
|
|
msgstr ""
|
|
|
"A volte c'è una struttura con parametri multipli o complicati e diversi\r\n"
|
|
|
"metodi. Ognuno di questi metodi dovrebbe avere degli esempi."
|
|
|
|
|
|
#: src\idioms/rustdoc-init.md:14
|
|
|
#, fuzzy
|
|
|
msgid "For example:"
|
|
|
msgstr "Per esempio:"
|
|
|
|
|
|
#: src\idioms/rustdoc-init.md:16
|
|
|
msgid ""
|
|
|
"````rust,ignore\r\n"
|
|
|
"struct Connection {\r\n"
|
|
|
" name: String,\r\n"
|
|
|
" stream: TcpStream,\r\n"
|
|
|
"}\r\n"
|
|
|
"\r\n"
|
|
|
"impl Connection {\r\n"
|
|
|
" /// Sends a request over the connection.\r\n"
|
|
|
" ///\r\n"
|
|
|
" /// # Example\r\n"
|
|
|
" /// ```no_run\r\n"
|
|
|
" /// # // Boilerplate are required to get an example working.\r\n"
|
|
|
" /// # let stream = TcpStream::connect(\"127.0.0.1:34254\");\r\n"
|
|
|
" /// # let connection = Connection { name: \"foo\".to_owned(), stream "
|
|
|
"};\r\n"
|
|
|
" /// # let request = Request::new(\"RequestId\", RequestType::Get, "
|
|
|
"\"payload\");\r\n"
|
|
|
" /// let response = connection.send_request(request);\r\n"
|
|
|
" /// assert!(response.is_ok());\r\n"
|
|
|
" /// ```\r\n"
|
|
|
" fn send_request(&self, request: Request) -> Result<Status, SendErr> {\r\n"
|
|
|
" // ...\r\n"
|
|
|
" }\r\n"
|
|
|
"\r\n"
|
|
|
" /// Oh no, all that boilerplate needs to be repeated here!\r\n"
|
|
|
" fn check_status(&self) -> Status {\r\n"
|
|
|
" // ...\r\n"
|
|
|
" }\r\n"
|
|
|
"}\r\n"
|
|
|
"````"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/rustdoc-init.md:45
|
|
|
#, fuzzy
|
|
|
msgid "## Example\r"
|
|
|
msgstr "## Esempio\r"
|
|
|
|
|
|
#: src\idioms/rustdoc-init.md:47
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Instead of typing all of this boilerplate to create a `Connection` and\r\n"
|
|
|
"`Request`, it is easier to just create a wrapping helper function which "
|
|
|
"takes\r\n"
|
|
|
"them as arguments:"
|
|
|
msgstr ""
|
|
|
"Invece di digitare tutto questo boilerplate per creare una \"Connessione\" "
|
|
|
"e\r\n"
|
|
|
"`Request`, è più facile creare semplicemente una funzione di supporto per il "
|
|
|
"wrapping che accetta\r\n"
|
|
|
"loro come argomenti:"
|
|
|
|
|
|
#: src\idioms/rustdoc-init.md:51
|
|
|
msgid ""
|
|
|
"````rust,ignore\r\n"
|
|
|
"struct Connection {\r\n"
|
|
|
" name: String,\r\n"
|
|
|
" stream: TcpStream,\r\n"
|
|
|
"}\r\n"
|
|
|
"\r\n"
|
|
|
"impl Connection {\r\n"
|
|
|
" /// Sends a request over the connection.\r\n"
|
|
|
" ///\r\n"
|
|
|
" /// # Example\r\n"
|
|
|
" /// ```\r\n"
|
|
|
" /// # fn call_send(connection: Connection, request: Request) {\r\n"
|
|
|
" /// let response = connection.send_request(request);\r\n"
|
|
|
" /// assert!(response.is_ok());\r\n"
|
|
|
" /// # }\r\n"
|
|
|
" /// ```\r\n"
|
|
|
" fn send_request(&self, request: Request) {\r\n"
|
|
|
" // ...\r\n"
|
|
|
" }\r\n"
|
|
|
"}\r\n"
|
|
|
"````"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/rustdoc-init.md:73
|
|
|
msgid ""
|
|
|
"**Note** in the above example the line `assert!(response.is_ok());` will "
|
|
|
"not\r\n"
|
|
|
"actually run while testing because it is inside a function which is never\r\n"
|
|
|
"invoked."
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/rustdoc-init.md:77
|
|
|
#, fuzzy
|
|
|
msgid "## Advantages\r"
|
|
|
msgstr "## Vantaggi\r"
|
|
|
|
|
|
#: src\idioms/rustdoc-init.md:79
|
|
|
#, fuzzy
|
|
|
msgid "This is much more concise and avoids repetitive code in examples."
|
|
|
msgstr "Questo è molto più conciso ed evita il codice ripetitivo negli esempi."
|
|
|
|
|
|
#: src\idioms/rustdoc-init.md:81
|
|
|
#, fuzzy
|
|
|
msgid "## Disadvantages\r"
|
|
|
msgstr "## Svantaggi\r"
|
|
|
|
|
|
#: src\idioms/rustdoc-init.md:83
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"As example is in a function, the code will not be tested. Though it will "
|
|
|
"still be\r\n"
|
|
|
"checked to make sure it compiles when running a `cargo test`. So this "
|
|
|
"pattern is\r\n"
|
|
|
"most useful when you need `no_run`. With this, you do not need to add "
|
|
|
"`no_run`."
|
|
|
msgstr ""
|
|
|
"Poiché l'esempio è in una funzione, il codice non verrà testato. Anche se lo "
|
|
|
"sarà ancora\r\n"
|
|
|
"controllato per assicurarsi che venga compilato durante l'esecuzione di un "
|
|
|
"`cargo test`. Quindi questo modello è\r\n"
|
|
|
"molto utile quando hai bisogno di `no_run`. Con questo, non è necessario "
|
|
|
"aggiungere `no_run`."
|
|
|
|
|
|
#: src\idioms/rustdoc-init.md:87
|
|
|
#, fuzzy
|
|
|
msgid "## Discussion\r"
|
|
|
msgstr "## Discussione\r"
|
|
|
|
|
|
#: src\idioms/rustdoc-init.md:89
|
|
|
#, fuzzy
|
|
|
msgid "If assertions are not required this pattern works well."
|
|
|
msgstr "Se le asserzioni non sono richieste, questo modello funziona bene."
|
|
|
|
|
|
#: src\idioms/rustdoc-init.md:91
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"If they are, an alternative can be to create a public method to create a "
|
|
|
"helper\r\n"
|
|
|
"instance which is annotated with `#[doc(hidden)]` (so that users won't see "
|
|
|
"it).\r\n"
|
|
|
"Then this method can be called inside of rustdoc because it is part of "
|
|
|
"the\r\n"
|
|
|
"crate's public API."
|
|
|
msgstr ""
|
|
|
"Se lo sono, un'alternativa può essere quella di creare un metodo pubblico "
|
|
|
"per creare un helper\r\n"
|
|
|
"istanza che è annotata con `#[doc(hidden)]` (in modo che gli utenti non la "
|
|
|
"vedano).\r\n"
|
|
|
"Quindi questo metodo può essere chiamato all'interno di rustdoc perché fa "
|
|
|
"parte del file\r\n"
|
|
|
"API pubblica di crate."
|
|
|
|
|
|
#: src\idioms/temporary-mutability.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Temporary mutability"
|
|
|
msgstr "# Mutabilità temporanea"
|
|
|
|
|
|
#: src\idioms/temporary-mutability.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Often it is necessary to prepare and process some data, but after that data "
|
|
|
"are\n"
|
|
|
"only inspected and never modified. The intention can be made explicit by "
|
|
|
"redefining\n"
|
|
|
"the mutable variable as immutable."
|
|
|
msgstr ""
|
|
|
"Spesso è necessario preparare ed elaborare alcuni dati, ma poi i dati lo "
|
|
|
"sono\n"
|
|
|
"solo revisionata e mai modificata. L'intenzione può essere resa esplicita "
|
|
|
"ridefinendo\n"
|
|
|
"la variabile mutabile come immutabile."
|
|
|
|
|
|
#: src\idioms/temporary-mutability.md:9
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"It can be done either by processing data within a nested block or by "
|
|
|
"redefining\n"
|
|
|
"the variable."
|
|
|
msgstr ""
|
|
|
"Può essere fatto elaborando i dati all'interno di un blocco nidificato o "
|
|
|
"ridefinendo\n"
|
|
|
"la variabile."
|
|
|
|
|
|
#: src\idioms/temporary-mutability.md:14
|
|
|
#, fuzzy
|
|
|
msgid "Say, vector must be sorted before usage."
|
|
|
msgstr "Supponiamo che il vettore debba essere ordinato prima dell'uso."
|
|
|
|
|
|
#: src\idioms/temporary-mutability.md:16
|
|
|
#, fuzzy
|
|
|
msgid "Using nested block:"
|
|
|
msgstr "Utilizzando il blocco annidato:"
|
|
|
|
|
|
#: src\idioms/temporary-mutability.md:18
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"let data = {\n"
|
|
|
" let mut data = get_vec();\n"
|
|
|
" data.sort();\n"
|
|
|
" data\n"
|
|
|
"};\n"
|
|
|
"\n"
|
|
|
"// Here `data` is immutable.\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/temporary-mutability.md:28
|
|
|
#, fuzzy
|
|
|
msgid "Using variable rebinding:"
|
|
|
msgstr "Utilizzo del rebinding variabile:"
|
|
|
|
|
|
#: src\idioms/temporary-mutability.md:30
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"let mut data = get_vec();\n"
|
|
|
"data.sort();\n"
|
|
|
"let data = data;\n"
|
|
|
"\n"
|
|
|
"// Here `data` is immutable.\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/temporary-mutability.md:40
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Compiler ensures that you don't accidentally mutate data after some point."
|
|
|
msgstr ""
|
|
|
"Il compilatore garantisce di non modificare accidentalmente i dati dopo un "
|
|
|
"certo punto."
|
|
|
|
|
|
#: src\idioms/temporary-mutability.md:44
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Nested block requires additional indentation of block body.\n"
|
|
|
"One more line to return data from block or redefine variable."
|
|
|
msgstr ""
|
|
|
"Il blocco annidato richiede un rientro aggiuntivo del corpo del blocco.\n"
|
|
|
"Un'altra riga per restituire i dati dal blocco o ridefinire la variabile."
|
|
|
|
|
|
#: src\idioms/return-consumed-arg-on-error.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Return consumed argument on error"
|
|
|
msgstr "# Restituisce l'argomento consumato in caso di errore"
|
|
|
|
|
|
#: src\idioms/return-consumed-arg-on-error.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"If a fallible function consumes (moves) an argument, return that argument "
|
|
|
"back inside\n"
|
|
|
"an error."
|
|
|
msgstr ""
|
|
|
"Se una funzione fallibile consuma (sposta) un argomento, riporta "
|
|
|
"quell'argomento all'interno\n"
|
|
|
"un errore."
|
|
|
|
|
|
#: src\idioms/return-consumed-arg-on-error.md:10
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"pub fn send(value: String) -> Result<(), SendError> {\n"
|
|
|
" println!(\"using {value} in a meaningful way\");\n"
|
|
|
" // Simulate non-deterministic fallible action.\n"
|
|
|
" use std::time::SystemTime;\n"
|
|
|
" let period = "
|
|
|
"SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();\n"
|
|
|
" if period.subsec_nanos() % 2 == 1 {\n"
|
|
|
" Ok(())\n"
|
|
|
" } else {\n"
|
|
|
" Err(SendError(value))\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"pub struct SendError(String);\n"
|
|
|
"\n"
|
|
|
"fn main() {\n"
|
|
|
" let mut value = \"imagine this is very long string\".to_string();\n"
|
|
|
"\n"
|
|
|
" let success = 's: {\n"
|
|
|
" // Try to send value two times.\n"
|
|
|
" for _ in 0..2 {\n"
|
|
|
" value = match send(value) {\n"
|
|
|
" Ok(()) => break 's true,\n"
|
|
|
" Err(SendError(value)) => value,\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
" false\n"
|
|
|
" };\n"
|
|
|
"\n"
|
|
|
" println!(\"success: {}\", success);\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\idioms/return-consumed-arg-on-error.md:45
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"In case of error you may want to try some alternative way or to\n"
|
|
|
"retry action in case of non-deterministic function. But if the argument\n"
|
|
|
"is always consumed, you are forced to clone it on every call, which\n"
|
|
|
"is not very efficient."
|
|
|
msgstr ""
|
|
|
"In caso di errore potresti voler provare un modo alternativo o per\n"
|
|
|
"riprovare l'azione in caso di funzione non deterministica. Ma se "
|
|
|
"l'argomento\n"
|
|
|
"è sempre consumato, sei costretto a clonarlo ad ogni chiamata, quale\n"
|
|
|
"non è molto efficiente."
|
|
|
|
|
|
#: src\idioms/return-consumed-arg-on-error.md:50
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The standard library uses this approach in e.g. `String::from_utf8` method.\n"
|
|
|
"When given a vector that doesn't contain valid UTF-8, a `FromUtf8Error`\n"
|
|
|
"is returned.\n"
|
|
|
"You can get original vector back using `FromUtf8Error::into_bytes` method."
|
|
|
msgstr ""
|
|
|
"La libreria standard utilizza questo approccio ad es. Metodo "
|
|
|
"`String::from_utf8`.\n"
|
|
|
"Quando viene fornito un vettore che non contiene UTF-8 valido, viene "
|
|
|
"visualizzato un `FromUtf8Error`\n"
|
|
|
"viene restituito.\n"
|
|
|
"Puoi recuperare il vettore originale usando il metodo "
|
|
|
"`FromUtf8Error::into_bytes`."
|
|
|
|
|
|
#: src\idioms/return-consumed-arg-on-error.md:57
|
|
|
#, fuzzy
|
|
|
msgid "Better performance because of moving arguments whenever possible."
|
|
|
msgstr ""
|
|
|
"Migliori prestazioni grazie allo spostamento degli argomenti quando "
|
|
|
"possibile."
|
|
|
|
|
|
#: src\idioms/return-consumed-arg-on-error.md:61
|
|
|
#, fuzzy
|
|
|
msgid "Slightly more complex error types."
|
|
|
msgstr "Tipi di errore leggermente più complessi."
|
|
|
|
|
|
#: src\patterns/index.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Design Patterns"
|
|
|
msgstr "# Modelli di progettazione"
|
|
|
|
|
|
#: src\patterns/index.md:3
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"[Design patterns](https://en.wikipedia.org/wiki/Software_design_pattern) "
|
|
|
"are\n"
|
|
|
"\"general reusable solutions to a commonly occurring problem within a given\n"
|
|
|
"context in software design\". Design patterns are a great way to describe "
|
|
|
"the\n"
|
|
|
"culture of a programming language. Design patterns are very "
|
|
|
"language-specific -\n"
|
|
|
"what is a pattern in one language may be unnecessary in another due to a\n"
|
|
|
"language feature, or impossible to express due to a missing feature."
|
|
|
msgstr ""
|
|
|
"[Modelli di "
|
|
|
"progettazione](https://en.wikipedia.org/wiki/Software_design_pattern) lo "
|
|
|
"sono\n"
|
|
|
"\"soluzioni generali riutilizzabili a un problema che si verifica "
|
|
|
"comunemente all'interno di un dato\n"
|
|
|
"contesto nella progettazione del software\". I modelli di progettazione sono "
|
|
|
"un ottimo modo per descrivere il\n"
|
|
|
"cultura di un linguaggio di programmazione. I modelli di progettazione sono "
|
|
|
"molto specifici della lingua -\n"
|
|
|
"quello che è uno schema in una lingua potrebbe non essere necessario in "
|
|
|
"un'altra a causa di a\n"
|
|
|
"caratteristica della lingua, o impossibile da esprimere a causa di una "
|
|
|
"caratteristica mancante."
|
|
|
|
|
|
#: src\patterns/index.md:10
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"If overused, design patterns can add unnecessary complexity to programs.\n"
|
|
|
"However, they are a great way to share intermediate and advanced level "
|
|
|
"knowledge\n"
|
|
|
"about a programming language."
|
|
|
msgstr ""
|
|
|
"Se abusati, i design pattern possono aggiungere inutili complessità ai "
|
|
|
"programmi.\n"
|
|
|
"Tuttavia, sono un ottimo modo per condividere conoscenze di livello "
|
|
|
"intermedio e avanzato\n"
|
|
|
"su un linguaggio di programmazione."
|
|
|
|
|
|
#: src\patterns/index.md:16
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Rust has many unique features. These features give us great benefit by "
|
|
|
"removing\n"
|
|
|
"whole classes of problems. Some of them are also patterns that are _unique_ "
|
|
|
"to Rust."
|
|
|
msgstr ""
|
|
|
"Rust ha molte caratteristiche uniche. Queste funzionalità ci danno un grande "
|
|
|
"vantaggio rimuovendo\n"
|
|
|
"intere classi di problemi. Alcuni di essi sono anche modelli _unici_ di Rust."
|
|
|
|
|
|
#: src\patterns/index.md:19
|
|
|
#, fuzzy
|
|
|
msgid "## YAGNI"
|
|
|
msgstr "## YAGNI"
|
|
|
|
|
|
#: src\patterns/index.md:21
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"YAGNI is an acronym that stands for `You Aren't Going to Need It`.\n"
|
|
|
"It's a vital software design principle to apply as you write code."
|
|
|
msgstr ""
|
|
|
"YAGNI è un acronimo che sta per `You Are not Going to Need It`.\n"
|
|
|
"È un principio di progettazione software fondamentale da applicare durante "
|
|
|
"la scrittura del codice."
|
|
|
|
|
|
#: src\patterns/index.md:24
|
|
|
#, fuzzy
|
|
|
msgid "> The best code I ever wrote was code I never wrote."
|
|
|
msgstr ""
|
|
|
"> Il miglior codice che abbia mai scritto è stato un codice che non ho mai "
|
|
|
"scritto."
|
|
|
|
|
|
#: src\patterns/index.md:26
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"If we apply YAGNI to design patterns, we see that the features of Rust allow "
|
|
|
"us to\n"
|
|
|
"throw out many patterns. For instance, there is no need for the [strategy "
|
|
|
"pattern](https://en.wikipedia.org/wiki/Strategy_pattern)\n"
|
|
|
"in Rust because we can just use "
|
|
|
"[traits](https://doc.rust-lang.org/book/traits.html)."
|
|
|
msgstr ""
|
|
|
"Se applichiamo YAGNI ai modelli di design, vediamo che le caratteristiche di "
|
|
|
"Rust ce lo consentono\n"
|
|
|
"buttare via molti modelli. Ad esempio, non è necessario il [modello "
|
|
|
"strategico](https://en.wikipedia.org/wiki/Strategy_pattern)\n"
|
|
|
"in Rust perché possiamo semplicemente usare "
|
|
|
"[traits](https://doc.rust-lang.org/book/traits.html)."
|
|
|
|
|
|
#: src\patterns/behavioural/intro.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Behavioural Patterns"
|
|
|
msgstr "# Modelli comportamentali"
|
|
|
|
|
|
#: src\patterns/behavioural/intro.md:3
|
|
|
#, fuzzy
|
|
|
msgid "From [Wikipedia](https://en.wikipedia.org/wiki/Behavioral_pattern):"
|
|
|
msgstr "Da [Wikipedia](https://en.wikipedia.org/wiki/Behavioral_pattern):"
|
|
|
|
|
|
#: src\patterns/behavioural/intro.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"> Design patterns that identify common communication patterns among "
|
|
|
"objects.\n"
|
|
|
"> By doing so, these patterns increase flexibility in carrying out "
|
|
|
"communication."
|
|
|
msgstr ""
|
|
|
"> Modelli di design che identificano modelli di comunicazione comuni tra gli "
|
|
|
"oggetti.\n"
|
|
|
"> In tal modo, questi modelli aumentano la flessibilità nell'effettuare la "
|
|
|
"comunicazione."
|
|
|
|
|
|
#: src\patterns/behavioural/command.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Command"
|
|
|
msgstr "# Comando"
|
|
|
|
|
|
#: src\patterns/behavioural/command.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The basic idea of the Command pattern is to separate out actions into its "
|
|
|
"own\n"
|
|
|
"objects and pass them as parameters."
|
|
|
msgstr ""
|
|
|
"L'idea di base del modello di comando è separare le azioni nelle proprie\n"
|
|
|
"oggetti e passarli come parametri."
|
|
|
|
|
|
#: src\patterns/behavioural/command.md:10
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Suppose we have a sequence of actions or transactions encapsulated as "
|
|
|
"objects.\n"
|
|
|
"We want these actions or commands to be executed or invoked in some order "
|
|
|
"later\n"
|
|
|
"at different time. These commands may also be triggered as a result of some "
|
|
|
"event.\n"
|
|
|
"For example, when a user pushes a button, or on arrival of a data packet.\n"
|
|
|
"In addition, these commands might be undoable. This may come in useful for\n"
|
|
|
"operations of an editor. We might want to store logs of executed commands so "
|
|
|
"that\n"
|
|
|
"we could reapply the changes later if the system crashes."
|
|
|
msgstr ""
|
|
|
"Supponiamo di avere una sequenza di azioni o transazioni incapsulate come "
|
|
|
"oggetti.\n"
|
|
|
"Vogliamo che queste azioni o comandi vengano eseguiti o richiamati in un "
|
|
|
"certo ordine in un secondo momento\n"
|
|
|
"in tempi diversi. Questi comandi possono anche essere attivati a seguito di "
|
|
|
"qualche evento.\n"
|
|
|
"Ad esempio, quando un utente preme un pulsante o all'arrivo di un pacchetto "
|
|
|
"di dati.\n"
|
|
|
"Inoltre, questi comandi potrebbero essere annullabili. Questo può tornare "
|
|
|
"utile per\n"
|
|
|
"operazioni di un editore. Potremmo voler memorizzare i log dei comandi "
|
|
|
"eseguiti in modo che\n"
|
|
|
"potremmo riapplicare le modifiche in un secondo momento se il sistema va in "
|
|
|
"crash."
|
|
|
|
|
|
#: src\patterns/behavioural/command.md:20
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Define two database operations `create table` and `add field`. Each of "
|
|
|
"these\n"
|
|
|
"operations is a command which knows how to undo the command, e.g., `drop "
|
|
|
"table`\n"
|
|
|
"and `remove field`. When a user invokes a database migration operation then "
|
|
|
"each\n"
|
|
|
"command is executed in the defined order, and when the user invokes the "
|
|
|
"rollback\n"
|
|
|
"operation then the whole set of commands is invoked in reverse order."
|
|
|
msgstr ""
|
|
|
"Definisci due operazioni di database \"crea tabella\" e \"aggiungi campo\". "
|
|
|
"Ognuno di questi\n"
|
|
|
"operations è un comando che sa come annullare il comando, ad esempio `drop "
|
|
|
"table`\n"
|
|
|
"e `rimuovi campo`. Quando un utente richiama un'operazione di migrazione del "
|
|
|
"database, each\n"
|
|
|
"Il comando viene eseguito nell'ordine definito e quando l'utente richiama il "
|
|
|
"rollback\n"
|
|
|
"operazione allora l'intera serie di comandi viene richiamata in ordine "
|
|
|
"inverso."
|
|
|
|
|
|
#: src\patterns/behavioural/command.md:26
|
|
|
#, fuzzy
|
|
|
msgid "## Approach: Using trait objects"
|
|
|
msgstr "## Approccio: utilizzo di oggetti tratto"
|
|
|
|
|
|
#: src\patterns/behavioural/command.md:28
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"We define a common trait which encapsulates our command with two operations\n"
|
|
|
"`execute` and `rollback`. All command `structs` must implement this trait."
|
|
|
msgstr ""
|
|
|
"Definiamo un tratto comune che incapsula il nostro comando con due "
|
|
|
"operazioni\n"
|
|
|
"`esegui` e `rollback`. Tutti i comandi `structs` devono implementare questa "
|
|
|
"caratteristica."
|
|
|
|
|
|
#: src\patterns/behavioural/command.md:31
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"pub trait Migration {\n"
|
|
|
" fn execute(&self) -> &str;\n"
|
|
|
" fn rollback(&self) -> &str;\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"pub struct CreateTable;\n"
|
|
|
"impl Migration for CreateTable {\n"
|
|
|
" fn execute(&self) -> &str {\n"
|
|
|
" \"create table\"\n"
|
|
|
" }\n"
|
|
|
" fn rollback(&self) -> &str {\n"
|
|
|
" \"drop table\"\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"pub struct AddField;\n"
|
|
|
"impl Migration for AddField {\n"
|
|
|
" fn execute(&self) -> &str {\n"
|
|
|
" \"add field\"\n"
|
|
|
" }\n"
|
|
|
" fn rollback(&self) -> &str {\n"
|
|
|
" \"remove field\"\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"struct Schema {\n"
|
|
|
" commands: Vec<Box<dyn Migration>>,\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"impl Schema {\n"
|
|
|
" fn new() -> Self {\n"
|
|
|
" Self { commands: vec![] }\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" fn add_migration(&mut self, cmd: Box<dyn Migration>) {\n"
|
|
|
" self.commands.push(cmd);\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" fn execute(&self) -> Vec<&str> {\n"
|
|
|
" self.commands.iter().map(|cmd| cmd.execute()).collect()\n"
|
|
|
" }\n"
|
|
|
" fn rollback(&self) -> Vec<&str> {\n"
|
|
|
" self.commands\n"
|
|
|
" .iter()\n"
|
|
|
" .rev() // reverse iterator's direction\n"
|
|
|
" .map(|cmd| cmd.rollback())\n"
|
|
|
" .collect()\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn main() {\n"
|
|
|
" let mut schema = Schema::new();\n"
|
|
|
"\n"
|
|
|
" let cmd = Box::new(CreateTable);\n"
|
|
|
" schema.add_migration(cmd);\n"
|
|
|
" let cmd = Box::new(AddField);\n"
|
|
|
" schema.add_migration(cmd);\n"
|
|
|
"\n"
|
|
|
" assert_eq!(vec![\"create table\", \"add field\"], schema.execute());\n"
|
|
|
" assert_eq!(vec![\"remove field\", \"drop table\"], schema.rollback());\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/behavioural/command.md:95
|
|
|
#, fuzzy
|
|
|
msgid "## Approach: Using function pointers"
|
|
|
msgstr "## Approccio: utilizzo dei puntatori di funzione"
|
|
|
|
|
|
#: src\patterns/behavioural/command.md:97
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"We could follow another approach by creating each individual command as\n"
|
|
|
"a different function and store function pointers to invoke these functions "
|
|
|
"later\n"
|
|
|
"at a different time. Since function pointers implement all three traits "
|
|
|
"`Fn`,\n"
|
|
|
"`FnMut`, and `FnOnce` we could as well pass and store closures instead of\n"
|
|
|
"function pointers."
|
|
|
msgstr ""
|
|
|
"Potremmo seguire un altro approccio creando ogni singolo comando come\n"
|
|
|
"una funzione diversa e memorizza i puntatori a funzione per richiamare "
|
|
|
"queste funzioni in un secondo momento\n"
|
|
|
"in un momento diverso. Poiché i puntatori di funzione implementano tutti e "
|
|
|
"tre i tratti `Fn`,\n"
|
|
|
"`FnMut` e `FnOnce` potremmo anche passare e memorizzare le chiusure invece "
|
|
|
"di\n"
|
|
|
"puntatori di funzione."
|
|
|
|
|
|
#: src\patterns/behavioural/command.md:103
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"type FnPtr = fn() -> String;\n"
|
|
|
"struct Command {\n"
|
|
|
" execute: FnPtr,\n"
|
|
|
" rollback: FnPtr,\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"struct Schema {\n"
|
|
|
" commands: Vec<Command>,\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"impl Schema {\n"
|
|
|
" fn new() -> Self {\n"
|
|
|
" Self { commands: vec![] }\n"
|
|
|
" }\n"
|
|
|
" fn add_migration(&mut self, execute: FnPtr, rollback: FnPtr) {\n"
|
|
|
" self.commands.push(Command { execute, rollback });\n"
|
|
|
" }\n"
|
|
|
" fn execute(&self) -> Vec<String> {\n"
|
|
|
" self.commands.iter().map(|cmd| (cmd.execute)()).collect()\n"
|
|
|
" }\n"
|
|
|
" fn rollback(&self) -> Vec<String> {\n"
|
|
|
" self.commands\n"
|
|
|
" .iter()\n"
|
|
|
" .rev()\n"
|
|
|
" .map(|cmd| (cmd.rollback)())\n"
|
|
|
" .collect()\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn add_field() -> String {\n"
|
|
|
" \"add field\".to_string()\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn remove_field() -> String {\n"
|
|
|
" \"remove field\".to_string()\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn main() {\n"
|
|
|
" let mut schema = Schema::new();\n"
|
|
|
" schema.add_migration(|| \"create table\".to_string(), || \"drop "
|
|
|
"table\".to_string());\n"
|
|
|
" schema.add_migration(add_field, remove_field);\n"
|
|
|
" assert_eq!(vec![\"create table\", \"add field\"], schema.execute());\n"
|
|
|
" assert_eq!(vec![\"remove field\", \"drop table\"], schema.rollback());\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/behavioural/command.md:150
|
|
|
#, fuzzy
|
|
|
msgid "## Approach: Using `Fn` trait objects"
|
|
|
msgstr "## Approccio: utilizzo di oggetti tratto `Fn`"
|
|
|
|
|
|
#: src\patterns/behavioural/command.md:152
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Finally, instead of defining a common command trait we could store\n"
|
|
|
"each command implementing the `Fn` trait separately in vectors."
|
|
|
msgstr ""
|
|
|
"Infine, invece di definire un tratto di comando comune, potremmo "
|
|
|
"memorizzare\n"
|
|
|
"ogni comando implementa il tratto `Fn` separatamente nei vettori."
|
|
|
|
|
|
#: src\patterns/behavioural/command.md:155
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"type Migration<'a> = Box<dyn Fn() -> &'a str>;\n"
|
|
|
"\n"
|
|
|
"struct Schema<'a> {\n"
|
|
|
" executes: Vec<Migration<'a>>,\n"
|
|
|
" rollbacks: Vec<Migration<'a>>,\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"impl<'a> Schema<'a> {\n"
|
|
|
" fn new() -> Self {\n"
|
|
|
" Self {\n"
|
|
|
" executes: vec![],\n"
|
|
|
" rollbacks: vec![],\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
" fn add_migration<E, R>(&mut self, execute: E, rollback: R)\n"
|
|
|
" where\n"
|
|
|
" E: Fn() -> &'a str + 'static,\n"
|
|
|
" R: Fn() -> &'a str + 'static,\n"
|
|
|
" {\n"
|
|
|
" self.executes.push(Box::new(execute));\n"
|
|
|
" self.rollbacks.push(Box::new(rollback));\n"
|
|
|
" }\n"
|
|
|
" fn execute(&self) -> Vec<&str> {\n"
|
|
|
" self.executes.iter().map(|cmd| cmd()).collect()\n"
|
|
|
" }\n"
|
|
|
" fn rollback(&self) -> Vec<&str> {\n"
|
|
|
" self.rollbacks.iter().rev().map(|cmd| cmd()).collect()\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn add_field() -> &'static str {\n"
|
|
|
" \"add field\"\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn remove_field() -> &'static str {\n"
|
|
|
" \"remove field\"\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn main() {\n"
|
|
|
" let mut schema = Schema::new();\n"
|
|
|
" schema.add_migration(|| \"create table\", || \"drop table\");\n"
|
|
|
" schema.add_migration(add_field, remove_field);\n"
|
|
|
" assert_eq!(vec![\"create table\", \"add field\"], schema.execute());\n"
|
|
|
" assert_eq!(vec![\"remove field\", \"drop table\"], schema.rollback());\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/behavioural/command.md:205
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"If our commands are small and may be defined as functions or passed as a "
|
|
|
"closure\n"
|
|
|
"then using function pointers might be preferable since it does not exploit\n"
|
|
|
"dynamic dispatch. But if our command is a whole struct with a bunch of "
|
|
|
"functions\n"
|
|
|
"and variables defined as seperated module then using trait objects would be\n"
|
|
|
"more suitable. A case of application can be found in "
|
|
|
"[`actix`](https://actix.rs/),\n"
|
|
|
"which uses trait objects when it registers a handler function for routes.\n"
|
|
|
"In case of using `Fn` trait objects we can create and use commands in the "
|
|
|
"same\n"
|
|
|
"way as we used in case of function pointers."
|
|
|
msgstr ""
|
|
|
"Se i nostri comandi sono piccoli e possono essere definiti come funzioni o "
|
|
|
"passati come chiusura\n"
|
|
|
"quindi l'utilizzo di puntatori a funzione potrebbe essere preferibile poiché "
|
|
|
"non sfrutta\n"
|
|
|
"invio dinamico. Ma se il nostro comando è un'intera struttura con un mucchio "
|
|
|
"di funzioni\n"
|
|
|
"e le variabili definite come modulo separato sarebbero allora utilizzando "
|
|
|
"gli oggetti tratto\n"
|
|
|
"più adatto. Un caso di applicazione può essere trovato in "
|
|
|
"[`actix`](https://actix.rs/),\n"
|
|
|
"che utilizza oggetti tratto quando registra una funzione di gestione per le "
|
|
|
"rotte.\n"
|
|
|
"In caso di utilizzo di oggetti tratto `Fn` possiamo creare e utilizzare "
|
|
|
"comandi nello stesso\n"
|
|
|
"modo come abbiamo usato in caso di puntatori a funzione."
|
|
|
|
|
|
#: src\patterns/behavioural/command.md:214
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"As performance, there is always a trade-off between performance and code\n"
|
|
|
"simplicity and organisation. Static dispatch gives faster performance, "
|
|
|
"while\n"
|
|
|
"dynamic dispatch provides flexibility when we structure our application."
|
|
|
msgstr ""
|
|
|
"Come prestazioni, c'è sempre un compromesso tra prestazioni e codice\n"
|
|
|
"semplicità e organizzazione. L'invio statico offre prestazioni più veloci, "
|
|
|
"mentre\n"
|
|
|
"l'invio dinamico fornisce flessibilità quando strutturiamo la nostra "
|
|
|
"applicazione."
|
|
|
|
|
|
#: src\patterns/behavioural/command.md:220
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [Command pattern](https://en.wikipedia.org/wiki/Command_pattern)\n"
|
|
|
"\n"
|
|
|
"- [Another example for the `command` "
|
|
|
"pattern](https://web.archive.org/web/20210223131236/https://chercher.tech/rust/command-design-pattern-rust)"
|
|
|
msgstr ""
|
|
|
"- [Modello di comando](https://en.wikipedia.org/wiki/Command_pattern)\n"
|
|
|
"\n"
|
|
|
"- [Un altro esempio per il pattern "
|
|
|
"`command`](https://web.archive.org/web/20210223131236/https://chercher.tech/rust/command-design-pattern-rust)"
|
|
|
|
|
|
#: src\patterns/behavioural/interpreter.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Interpreter"
|
|
|
msgstr "# Interprete"
|
|
|
|
|
|
#: src\patterns/behavioural/interpreter.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"If a problem occurs very often and requires long and repetitive steps to "
|
|
|
"solve\n"
|
|
|
"it, then the problem instances might be expressed in a simple language and "
|
|
|
"an\n"
|
|
|
"interpreter object could solve it by interpreting the sentences written in "
|
|
|
"this\n"
|
|
|
"simple language."
|
|
|
msgstr ""
|
|
|
"Se un problema si verifica molto spesso e richiede passaggi lunghi e "
|
|
|
"ripetitivi per essere risolto\n"
|
|
|
"it, allora le istanze del problema potrebbero essere espresse in un "
|
|
|
"linguaggio semplice e un\n"
|
|
|
"oggetto interprete potrebbe risolverlo interpretando le frasi scritte in "
|
|
|
"questo\n"
|
|
|
"linguaggio semplice."
|
|
|
|
|
|
#: src\patterns/behavioural/interpreter.md:10
|
|
|
#, fuzzy
|
|
|
msgid "Basically, for any kind of problems we define:"
|
|
|
msgstr "In sostanza, per qualsiasi tipo di problema definiamo:"
|
|
|
|
|
|
#: src\patterns/behavioural/interpreter.md:12
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- A [domain specific "
|
|
|
"language](https://en.wikipedia.org/wiki/Domain-specific_language),\n"
|
|
|
"- A grammar for this language,\n"
|
|
|
"- An interpreter that solves the problem instances."
|
|
|
msgstr ""
|
|
|
"- Una [lingua specifica del "
|
|
|
"dominio](https://en.wikipedia.org/wiki/Domain-specific_language),\n"
|
|
|
"- Una grammatica per questa lingua,\n"
|
|
|
"- Un interprete che risolve le istanze del problema."
|
|
|
|
|
|
#: src\patterns/behavioural/interpreter.md:18
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Our goal is to translate simple mathematical expressions into postfix "
|
|
|
"expressions\n"
|
|
|
"(or [Reverse Polish "
|
|
|
"notation](https://en.wikipedia.org/wiki/Reverse_Polish_notation))\n"
|
|
|
"For simplicity, our expressions consist of ten digits `0`, ..., `9` and two\n"
|
|
|
"operations `+`, `-`. For example, the expression `2 + 4` is translated into\n"
|
|
|
"`2 4 +`."
|
|
|
msgstr ""
|
|
|
"Il nostro obiettivo è tradurre semplici espressioni matematiche in "
|
|
|
"espressioni postfisse\n"
|
|
|
"(o [notazione polacca "
|
|
|
"inversa](https://en.wikipedia.org/wiki/Reverse_Polish_notation))\n"
|
|
|
"Per semplicità, le nostre espressioni sono composte da dieci cifre `0`, ..., "
|
|
|
"`9` e due\n"
|
|
|
"operazioni `+`, `-`. Ad esempio, l'espressione \"2 + 4\" è tradotta in\n"
|
|
|
"`2 4 +`."
|
|
|
|
|
|
#: src\patterns/behavioural/interpreter.md:24
|
|
|
#, fuzzy
|
|
|
msgid "## Context Free Grammar for our problem"
|
|
|
msgstr "## Grammatica senza contesto per il nostro problema"
|
|
|
|
|
|
#: src\patterns/behavioural/interpreter.md:26
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Our task is translating infix expressions into postfix ones. Let's define a "
|
|
|
"context\n"
|
|
|
"free grammar for a set of infix expressions over `0`, ..., `9`, `+`, and "
|
|
|
"`-`,\n"
|
|
|
"where:"
|
|
|
msgstr ""
|
|
|
"Il nostro compito è tradurre le espressioni infisse in postfisse. Definiamo "
|
|
|
"un contesto\n"
|
|
|
"grammatica libera per un insieme di espressioni infisse su `0`, ..., `9`, "
|
|
|
"`+` e `-`,\n"
|
|
|
"Dove:"
|
|
|
|
|
|
#: src\patterns/behavioural/interpreter.md:30
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- Terminal symbols: `0`, `...`, `9`, `+`, `-`\n"
|
|
|
"- Non-terminal symbols: `exp`, `term`\n"
|
|
|
"- Start symbol is `exp`\n"
|
|
|
"- And the following are production rules"
|
|
|
msgstr ""
|
|
|
"- Simboli terminali: `0`, `...`, `9`, `+`, `-`\n"
|
|
|
"- Simboli non terminali: `exp`, `term`\n"
|
|
|
"- Il simbolo di inizio è `exp`\n"
|
|
|
"- E le seguenti sono regole di produzione"
|
|
|
|
|
|
#: src\patterns/behavioural/interpreter.md:35
|
|
|
msgid ""
|
|
|
"```ignore\n"
|
|
|
"exp -> exp + term\n"
|
|
|
"exp -> exp - term\n"
|
|
|
"exp -> term\n"
|
|
|
"term -> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/behavioural/interpreter.md:42
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"**NOTE:** This grammar should be further transformed depending on what we "
|
|
|
"are going\n"
|
|
|
"to do with it. For example, we might need to remove left recursion. For "
|
|
|
"more\n"
|
|
|
"details please see [Compilers: Principles,Techniques, and "
|
|
|
"Tools](https://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools)\n"
|
|
|
"(aka Dragon Book)."
|
|
|
msgstr ""
|
|
|
"**NOTA:** Questa grammatica dovrebbe essere ulteriormente trasformata a "
|
|
|
"seconda di cosa stiamo andando\n"
|
|
|
"a che fare con esso. Ad esempio, potremmo dover rimuovere la ricorsione a "
|
|
|
"sinistra. Per più\n"
|
|
|
"dettagli vedere [Compilers: Principles,Techniques, and "
|
|
|
"Tools](https://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools)\n"
|
|
|
"(alias Libro del Drago)."
|
|
|
|
|
|
#: src\patterns/behavioural/interpreter.md:47
|
|
|
#, fuzzy
|
|
|
msgid "## Solution"
|
|
|
msgstr "## Soluzione"
|
|
|
|
|
|
#: src\patterns/behavioural/interpreter.md:49
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"We simply implement a recursive descent parser. For simplicity's sake, the "
|
|
|
"code\n"
|
|
|
"panics when an expression is syntactically wrong (for example `2-34` or "
|
|
|
"`2+5-`\n"
|
|
|
"are wrong according to the grammar definition)."
|
|
|
msgstr ""
|
|
|
"Implementiamo semplicemente un parser di discesa ricorsivo. Per semplicità, "
|
|
|
"il codice\n"
|
|
|
"va in panico quando un'espressione è sintatticamente errata (ad esempio "
|
|
|
"`2-34` o `2+5-`\n"
|
|
|
"sono errate secondo la definizione grammaticale)."
|
|
|
|
|
|
#: src\patterns/behavioural/interpreter.md:53
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"pub struct Interpreter<'a> {\n"
|
|
|
" it: std::str::Chars<'a>,\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"impl<'a> Interpreter<'a> {\n"
|
|
|
"\n"
|
|
|
" pub fn new(infix: &'a str) -> Self {\n"
|
|
|
" Self { it: infix.chars() }\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" fn next_char(&mut self) -> Option<char> {\n"
|
|
|
" self.it.next()\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" pub fn interpret(&mut self, out: &mut String) {\n"
|
|
|
" self.term(out);\n"
|
|
|
"\n"
|
|
|
" while let Some(op) = self.next_char() {\n"
|
|
|
" if op == '+' || op == '-' {\n"
|
|
|
" self.term(out);\n"
|
|
|
" out.push(op);\n"
|
|
|
" } else {\n"
|
|
|
" panic!(\"Unexpected symbol '{}'\", op);\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" fn term(&mut self, out: &mut String) {\n"
|
|
|
" match self.next_char() {\n"
|
|
|
" Some(ch) if ch.is_digit(10) => out.push(ch),\n"
|
|
|
" Some(ch) => panic!(\"Unexpected symbol '{}'\", ch),\n"
|
|
|
" None => panic!(\"Unexpected end of string\"),\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"pub fn main() {\n"
|
|
|
" let mut intr = Interpreter::new(\"2+3\");\n"
|
|
|
" let mut postfix = String::new();\n"
|
|
|
" intr.interpret(&mut postfix);\n"
|
|
|
" assert_eq!(postfix, \"23+\");\n"
|
|
|
"\n"
|
|
|
" intr = Interpreter::new(\"1-2+3-4\");\n"
|
|
|
" postfix.clear();\n"
|
|
|
" intr.interpret(&mut postfix);\n"
|
|
|
" assert_eq!(postfix, \"12-3+4-\");\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/behavioural/interpreter.md:105
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"There may be a wrong perception that the Interpreter design pattern is about "
|
|
|
"design\n"
|
|
|
"grammars for formal languages and implementation of parsers for these "
|
|
|
"grammars.\n"
|
|
|
"In fact, this pattern is about expressing problem instances in a more "
|
|
|
"specific\n"
|
|
|
"way and implementing functions/classes/structs that solve these problem "
|
|
|
"instances.\n"
|
|
|
"Rust language has `macro_rules!` that allow us to define special syntax and "
|
|
|
"rules\n"
|
|
|
"on how to expand this syntax into source code."
|
|
|
msgstr ""
|
|
|
"Potrebbe esserci una percezione errata che il modello di progettazione di "
|
|
|
"Interpreter riguardi il design\n"
|
|
|
"grammatiche per linguaggi formali e implementazione di parser per queste "
|
|
|
"grammatiche.\n"
|
|
|
"In effetti, questo modello riguarda l'espressione di istanze problematiche "
|
|
|
"in modo più specifico\n"
|
|
|
"modo e implementando funzioni/classi/strutture che risolvono queste istanze "
|
|
|
"del problema.\n"
|
|
|
"Il linguaggio Rust ha `macro_rules!` che ci permettono di definire sintassi "
|
|
|
"e regole speciali\n"
|
|
|
"su come espandere questa sintassi nel codice sorgente."
|
|
|
|
|
|
#: src\patterns/behavioural/interpreter.md:112
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"In the following example we create a simple `macro_rules!` that computes\n"
|
|
|
"[Euclidean length](https://en.wikipedia.org/wiki/Euclidean_distance) of `n`\n"
|
|
|
"dimensional vectors. Writing `norm!(x,1,2)` might be easier to express and "
|
|
|
"more\n"
|
|
|
"efficient than packing `x,1,2` into a `Vec` and calling a function "
|
|
|
"computing\n"
|
|
|
"the length."
|
|
|
msgstr ""
|
|
|
"Nell'esempio seguente creiamo un semplice `macro_rules!` che calcola\n"
|
|
|
"[Lunghezza euclidea](https://en.wikipedia.org/wiki/Euclidean_distance) di "
|
|
|
"`n`\n"
|
|
|
"vettori dimensionali. Scrivere `norma!(x,1,2)` potrebbe essere più facile da "
|
|
|
"esprimere e altro ancora\n"
|
|
|
"efficiente che comprimere `x,1,2` in un `Vec` e chiamare una funzione di "
|
|
|
"calcolo\n"
|
|
|
"la lunghezza."
|
|
|
|
|
|
#: src\patterns/behavioural/interpreter.md:118
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"macro_rules! norm {\n"
|
|
|
" ($($element:expr),*) => {\n"
|
|
|
" {\n"
|
|
|
" let mut n = 0.0;\n"
|
|
|
" $(\n"
|
|
|
" n += ($element as f64)*($element as f64);\n"
|
|
|
" )*\n"
|
|
|
" n.sqrt()\n"
|
|
|
" }\n"
|
|
|
" };\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn main() {\n"
|
|
|
" let x = -3f64;\n"
|
|
|
" let y = 4f64;\n"
|
|
|
"\n"
|
|
|
" assert_eq!(3f64, norm!(x));\n"
|
|
|
" assert_eq!(5f64, norm!(x, y));\n"
|
|
|
" assert_eq!(0f64, norm!(0, 0, 0)); \n"
|
|
|
" assert_eq!(1f64, norm!(0.5, -0.5, 0.5, -0.5));\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/behavioural/interpreter.md:144
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [Interpreter pattern](https://en.wikipedia.org/wiki/Interpreter_pattern)\n"
|
|
|
"- [Context free "
|
|
|
"grammar](https://en.wikipedia.org/wiki/Context-free_grammar)\n"
|
|
|
"- [macro_rules!](https://doc.rust-lang.org/rust-by-example/macros.html)"
|
|
|
msgstr ""
|
|
|
"- [Modello "
|
|
|
"dell'interprete](https://en.wikipedia.org/wiki/Interpreter_pattern)\n"
|
|
|
"- [Grammatica senza "
|
|
|
"contesto](https://en.wikipedia.org/wiki/Context-free_grammar)\n"
|
|
|
"- [macro_rules!](https://doc.rust-lang.org/rust-by-example/macros.html)"
|
|
|
|
|
|
#: src\patterns/behavioural/newtype.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Newtype"
|
|
|
msgstr "# Nuovo tipo"
|
|
|
|
|
|
#: src\patterns/behavioural/newtype.md:3
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"What if in some cases we want a type to behave similar to another type or\n"
|
|
|
"enforce some behaviour at compile time when using only type aliases would\n"
|
|
|
"not be enough?"
|
|
|
msgstr ""
|
|
|
"Cosa succede se in alcuni casi vogliamo che un tipo si comporti in modo "
|
|
|
"simile a un altro tipo o\n"
|
|
|
"applicare alcuni comportamenti in fase di compilazione quando si utilizzano "
|
|
|
"solo alias di tipo\n"
|
|
|
"non essere abbastanza?"
|
|
|
|
|
|
#: src\patterns/behavioural/newtype.md:7
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"For example, if we want to create a custom `Display` implementation for "
|
|
|
"`String`\n"
|
|
|
"due to security considerations (e.g. passwords)."
|
|
|
msgstr ""
|
|
|
"Ad esempio, se vogliamo creare un'implementazione `Display` personalizzata "
|
|
|
"per `String`\n"
|
|
|
"per motivi di sicurezza (ad es. password)."
|
|
|
|
|
|
#: src\patterns/behavioural/newtype.md:10
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"For such cases we could use the `Newtype` pattern to provide **type "
|
|
|
"safety**\n"
|
|
|
"and **encapsulation**."
|
|
|
msgstr ""
|
|
|
"Per questi casi potremmo usare il modello `Newtype` per fornire **sicurezza "
|
|
|
"del tipo**\n"
|
|
|
"e **incapsulamento**."
|
|
|
|
|
|
#: src\patterns/behavioural/newtype.md:15
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Use a tuple struct with a single field to make an opaque wrapper for a "
|
|
|
"type.\n"
|
|
|
"This creates a new type, rather than an alias to a type (`type` items)."
|
|
|
msgstr ""
|
|
|
"Usa una struttura di tupla con un singolo campo per creare un wrapper opaco "
|
|
|
"per un tipo.\n"
|
|
|
"Questo crea un nuovo tipo, piuttosto che un alias di un tipo (elementi "
|
|
|
"`type`)."
|
|
|
|
|
|
#: src\patterns/behavioural/newtype.md:20
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"// Some type, not necessarily in the same module or even crate.\n"
|
|
|
"struct Foo {\n"
|
|
|
" //..\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"impl Foo {\n"
|
|
|
" // These functions are not present on Bar.\n"
|
|
|
" //..\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"// The newtype.\n"
|
|
|
"pub struct Bar(Foo);\n"
|
|
|
"\n"
|
|
|
"impl Bar {\n"
|
|
|
" // Constructor.\n"
|
|
|
" pub fn new(\n"
|
|
|
" //..\n"
|
|
|
" ) -> Self {\n"
|
|
|
"\n"
|
|
|
" //..\n"
|
|
|
"\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" //..\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn main() {\n"
|
|
|
" let b = Bar::new(...);\n"
|
|
|
"\n"
|
|
|
" // Foo and Bar are type incompatible, the following do not type check.\n"
|
|
|
" // let f: Foo = b;\n"
|
|
|
" // let b: Bar = Foo { ... };\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/behavioural/newtype.md:58
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The primary motivation for newtypes is abstraction. It allows you to share\n"
|
|
|
"implementation details between types while precisely controlling the "
|
|
|
"interface.\n"
|
|
|
"By using a newtype rather than exposing the implementation type as part of "
|
|
|
"an\n"
|
|
|
"API, it allows you to change implementation backwards compatibly."
|
|
|
msgstr ""
|
|
|
"La motivazione principale per i newtype è l'astrazione. Ti permette di "
|
|
|
"condividere\n"
|
|
|
"dettagli di implementazione tra i tipi controllando con precisione "
|
|
|
"l'interfaccia.\n"
|
|
|
"Usando un newtype piuttosto che esporre il tipo di implementazione come "
|
|
|
"parte di un\n"
|
|
|
"API, consente di modificare l'implementazione in modo compatibile con le "
|
|
|
"versioni precedenti."
|
|
|
|
|
|
#: src\patterns/behavioural/newtype.md:63
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Newtypes can be used for distinguishing units, e.g., wrapping `f64` to give\n"
|
|
|
"distinguishable `Miles` and `Kilometres`."
|
|
|
msgstr ""
|
|
|
"I newtype possono essere usati per distinguere le unità, ad esempio "
|
|
|
"avvolgendo `f64` per dare\n"
|
|
|
"distinguibili `Miglia` e `Chilometri`."
|
|
|
|
|
|
#: src\patterns/behavioural/newtype.md:68
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The wrapped and wrapper types are not type compatible (as opposed to using\n"
|
|
|
"`type`), so users of the newtype will never 'confuse' the wrapped and "
|
|
|
"wrapper\n"
|
|
|
"types."
|
|
|
msgstr ""
|
|
|
"I tipi wrapper e wrapper non sono compatibili con i tipi (al contrario di "
|
|
|
"using\n"
|
|
|
"`type`), quindi gli utenti del newtype non 'confonderanno' mai il wrapper e "
|
|
|
"il wrapper\n"
|
|
|
"tipi."
|
|
|
|
|
|
#: src\patterns/behavioural/newtype.md:72
|
|
|
#, fuzzy
|
|
|
msgid "Newtypes are a zero-cost abstraction - there is no runtime overhead."
|
|
|
msgstr ""
|
|
|
"I newtype sono un'astrazione a costo zero: non vi è alcun sovraccarico di "
|
|
|
"runtime."
|
|
|
|
|
|
#: src\patterns/behavioural/newtype.md:74
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The privacy system ensures that users cannot access the wrapped type (if "
|
|
|
"the\n"
|
|
|
"field is private, which it is by default)."
|
|
|
msgstr ""
|
|
|
"Il sistema di privacy garantisce che gli utenti non possano accedere al tipo "
|
|
|
"avvolto (se il file\n"
|
|
|
"campo è privato, che è per impostazione predefinita)."
|
|
|
|
|
|
#: src\patterns/behavioural/newtype.md:79
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The downside of newtypes (especially compared with type aliases), is that "
|
|
|
"there\n"
|
|
|
"is no special language support. This means there can be _a lot_ of "
|
|
|
"boilerplate.\n"
|
|
|
"You need a 'pass through' method for every method you want to expose on the\n"
|
|
|
"wrapped type, and an impl for every trait you want to also be implemented "
|
|
|
"for\n"
|
|
|
"the wrapper type."
|
|
|
msgstr ""
|
|
|
"Lo svantaggio dei newtype (soprattutto rispetto agli alias di tipo) è che "
|
|
|
"esiste\n"
|
|
|
"non è un supporto linguistico speciale. Ciò significa che ci possono essere "
|
|
|
"_molti_ standard.\n"
|
|
|
"È necessario un metodo \"pass through\" per ogni metodo che si desidera "
|
|
|
"esporre sul file\n"
|
|
|
"tipo avvolto e un impl per ogni tratto per cui vuoi essere implementato\n"
|
|
|
"il tipo di involucro."
|
|
|
|
|
|
#: src\patterns/behavioural/newtype.md:87
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Newtypes are very common in Rust code. Abstraction or representing units are "
|
|
|
"the\n"
|
|
|
"most common uses, but they can be used for other reasons:"
|
|
|
msgstr ""
|
|
|
"I newtype sono molto comuni nel codice Rust. Le unità di astrazione o di "
|
|
|
"rappresentazione sono le\n"
|
|
|
"usi più comuni, ma possono essere utilizzati per altri motivi:"
|
|
|
|
|
|
#: src\patterns/behavioural/newtype.md:90
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- restricting functionality (reduce the functions exposed or traits "
|
|
|
"implemented),\n"
|
|
|
"- making a type with copy semantics have move semantics,\n"
|
|
|
"- abstraction by providing a more concrete type and thus hiding internal "
|
|
|
"types,\n"
|
|
|
" e.g.,"
|
|
|
msgstr ""
|
|
|
"- limitare la funzionalità (ridurre le funzioni esposte o i tratti "
|
|
|
"implementati),\n"
|
|
|
"- fare in modo che un tipo con semantica di copia abbia semantica di "
|
|
|
"spostamento,\n"
|
|
|
"- astrazione fornendo un tipo più concreto e quindi nascondendo i tipi "
|
|
|
"interni,\n"
|
|
|
" per esempio.,"
|
|
|
|
|
|
#: src\patterns/behavioural/newtype.md:95
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"pub struct Foo(Bar<T1, T2>);\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/behavioural/newtype.md:99
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Here, `Bar` might be some public, generic type and `T1` and `T2` are some "
|
|
|
"internal\n"
|
|
|
"types. Users of our module shouldn't know that we implement `Foo` by using a "
|
|
|
"`Bar`,\n"
|
|
|
"but what we're really hiding here is the types `T1` and `T2`, and how they "
|
|
|
"are used\n"
|
|
|
"with `Bar`."
|
|
|
msgstr ""
|
|
|
"Qui, \"Bar\" potrebbe essere un tipo generico pubblico e \"T1\" e \"T2\" "
|
|
|
"sono interni\n"
|
|
|
"tipi. Gli utenti del nostro modulo non dovrebbero sapere che implementiamo "
|
|
|
"`Foo` utilizzando un `Bar`,\n"
|
|
|
"ma quello che in realtà stiamo nascondendo qui sono i tipi `T1` e `T2`, e "
|
|
|
"come vengono usati\n"
|
|
|
"con \"Barra\"."
|
|
|
|
|
|
#: src\patterns/behavioural/newtype.md:106
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [Advanced Types in the "
|
|
|
"book](https://doc.rust-lang.org/book/ch19-04-advanced-types.html?highlight=newtype#using-the-newtype-pattern-for-type-safety-and-abstraction)\n"
|
|
|
"- [Newtypes in Haskell](https://wiki.haskell.org/Newtype)\n"
|
|
|
"- [Type "
|
|
|
"aliases](https://doc.rust-lang.org/stable/book/ch19-04-advanced-types.html#creating-type-synonyms-with-type-aliases)\n"
|
|
|
"- [derive_more](https://crates.io/crates/derive_more), a crate for deriving "
|
|
|
"many\n"
|
|
|
" builtin traits on newtypes.\n"
|
|
|
"- [The Newtype Pattern In "
|
|
|
"Rust](https://www.worthe-it.co.za/blog/2020-10-31-newtype-pattern-in-rust.html)"
|
|
|
msgstr ""
|
|
|
"- [Tipi avanzati nel "
|
|
|
"libro](https://doc.rust-lang.org/book/ch19-04-advanced-types.html?highlight=newtype#using-the-newtype-pattern-for-type-safety "
|
|
|
"-e-astrazione)\n"
|
|
|
"- [Newtype in Haskell](https://wiki.haskell.org/Newtype)\n"
|
|
|
"- [Alias di "
|
|
|
"tipo](https://doc.rust-lang.org/stable/book/ch19-04-advanced-types.html#creating-type-synonyms-with-type-aliases)\n"
|
|
|
"- [derive_more](https://crates.io/crates/derive_more), una cassa per "
|
|
|
"derivare molti\n"
|
|
|
" tratti incorporati su newtypes.\n"
|
|
|
"- [Il modello Newtype in "
|
|
|
"Rust](https://www.worthe-it.co.za/blog/2020-10-31-newtype-pattern-in-rust.html)"
|
|
|
|
|
|
#: src\patterns/behavioural/RAII.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# RAII with guards"
|
|
|
msgstr "# RAII con le guardie"
|
|
|
|
|
|
#: src\patterns/behavioural/RAII.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"[RAII][wikipedia] stands for \"Resource Acquisition is Initialisation\" "
|
|
|
"which is a\n"
|
|
|
"terrible name. The essence of the pattern is that resource initialisation is "
|
|
|
"done\n"
|
|
|
"in the constructor of an object and finalisation in the destructor. This "
|
|
|
"pattern\n"
|
|
|
"is extended in Rust by using a RAII object as a guard of some resource and "
|
|
|
"relying\n"
|
|
|
"on the type system to ensure that access is always mediated by the guard "
|
|
|
"object."
|
|
|
msgstr ""
|
|
|
"[RAII][wikipedia] sta per \"Resource Acquisition is Initialisation\" che è "
|
|
|
"a\n"
|
|
|
"nome terribile. L'essenza del modello è che l'inizializzazione della risorsa "
|
|
|
"è stata eseguita\n"
|
|
|
"nel costruttore di un oggetto e la finalizzazione nel distruttore. Questo "
|
|
|
"modello\n"
|
|
|
"è esteso in Rust utilizzando un oggetto RAII come protezione di alcune "
|
|
|
"risorse e facendo affidamento\n"
|
|
|
"sul sistema di tipo per garantire che l'accesso sia sempre mediato "
|
|
|
"dall'oggetto di guardia."
|
|
|
|
|
|
#: src\patterns/behavioural/RAII.md:13
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Mutex guards are the classic example of this pattern from the std library "
|
|
|
"(this\n"
|
|
|
"is a simplified version of the real implementation):"
|
|
|
msgstr ""
|
|
|
"Le guardie mutex sono il classico esempio di questo modello dalla libreria "
|
|
|
"std (this\n"
|
|
|
"è una versione semplificata dell'implementazione reale):"
|
|
|
|
|
|
#: src\patterns/behavioural/RAII.md:16
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"use std::ops::Deref;\n"
|
|
|
"\n"
|
|
|
"struct Foo {}\n"
|
|
|
"\n"
|
|
|
"struct Mutex<T> {\n"
|
|
|
" // We keep a reference to our data: T here.\n"
|
|
|
" //..\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"struct MutexGuard<'a, T: 'a> {\n"
|
|
|
" data: &'a T,\n"
|
|
|
" //..\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"// Locking the mutex is explicit.\n"
|
|
|
"impl<T> Mutex<T> {\n"
|
|
|
" fn lock(&self) -> MutexGuard<T> {\n"
|
|
|
" // Lock the underlying OS mutex.\n"
|
|
|
" //..\n"
|
|
|
"\n"
|
|
|
" // MutexGuard keeps a reference to self\n"
|
|
|
" MutexGuard {\n"
|
|
|
" data: self,\n"
|
|
|
" //..\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"// Destructor for unlocking the mutex.\n"
|
|
|
"impl<'a, T> Drop for MutexGuard<'a, T> {\n"
|
|
|
" fn drop(&mut self) {\n"
|
|
|
" // Unlock the underlying OS mutex.\n"
|
|
|
" //..\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"// Implementing Deref means we can treat MutexGuard like a pointer to T.\n"
|
|
|
"impl<'a, T> Deref for MutexGuard<'a, T> {\n"
|
|
|
" type Target = T;\n"
|
|
|
"\n"
|
|
|
" fn deref(&self) -> &T {\n"
|
|
|
" self.data\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn baz(x: Mutex<Foo>) {\n"
|
|
|
" let xx = x.lock();\n"
|
|
|
" xx.foo(); // foo is a method on Foo.\n"
|
|
|
" // The borrow checker ensures we can't store a reference to the "
|
|
|
"underlying\n"
|
|
|
" // Foo which will outlive the guard xx.\n"
|
|
|
"\n"
|
|
|
" // x is unlocked when we exit this function and xx's destructor is "
|
|
|
"executed.\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/behavioural/RAII.md:74
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Where a resource must be finalised after use, RAII can be used to do this\n"
|
|
|
"finalisation. If it is an error to access that resource after finalisation, "
|
|
|
"then\n"
|
|
|
"this pattern can be used to prevent such errors."
|
|
|
msgstr ""
|
|
|
"Laddove una risorsa deve essere finalizzata dopo l'uso, RAII può essere "
|
|
|
"utilizzata per farlo\n"
|
|
|
"finalizzazione. Se è un errore accedere a quella risorsa dopo la "
|
|
|
"finalizzazione, allora\n"
|
|
|
"questo modello può essere utilizzato per prevenire tali errori."
|
|
|
|
|
|
#: src\patterns/behavioural/RAII.md:80
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Prevents errors where a resource is not finalised and where a resource is "
|
|
|
"used\n"
|
|
|
"after finalisation."
|
|
|
msgstr ""
|
|
|
"Previene gli errori in cui una risorsa non è finalizzata e in cui viene "
|
|
|
"utilizzata una risorsa\n"
|
|
|
"dopo la finalizzazione."
|
|
|
|
|
|
#: src\patterns/behavioural/RAII.md:85
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"RAII is a useful pattern for ensuring resources are properly deallocated or\n"
|
|
|
"finalised. We can make use of the borrow checker in Rust to statically "
|
|
|
"prevent\n"
|
|
|
"errors stemming from using resources after finalisation takes place."
|
|
|
msgstr ""
|
|
|
"RAII è un modello utile per garantire che le risorse siano adeguatamente "
|
|
|
"deallocate o\n"
|
|
|
"finalizzato. Possiamo utilizzare il controllo del prestito in Rust per "
|
|
|
"prevenire staticamente\n"
|
|
|
"errori derivanti dall'utilizzo delle risorse dopo la finalizzazione."
|
|
|
|
|
|
#: src\patterns/behavioural/RAII.md:89
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The core aim of the borrow checker is to ensure that references to data do "
|
|
|
"not\n"
|
|
|
"outlive that data. The RAII guard pattern works because the guard object\n"
|
|
|
"contains a reference to the underlying resource and only exposes such\n"
|
|
|
"references. Rust ensures that the guard cannot outlive the underlying "
|
|
|
"resource\n"
|
|
|
"and that references to the resource mediated by the guard cannot outlive "
|
|
|
"the\n"
|
|
|
"guard. To see how this works it is helpful to examine the signature of "
|
|
|
"`deref`\n"
|
|
|
"without lifetime elision:"
|
|
|
msgstr ""
|
|
|
"L'obiettivo principale del controllo del prestito è garantire che i "
|
|
|
"riferimenti ai dati non lo facciano\n"
|
|
|
"sopravvivere a quei dati. Il modello di guardia RAII funziona perché "
|
|
|
"l'oggetto di guardia\n"
|
|
|
"contiene un riferimento alla risorsa sottostante ed espone solo tale\n"
|
|
|
"Riferimenti. Rust assicura che la guardia non possa sopravvivere alla "
|
|
|
"risorsa sottostante\n"
|
|
|
"e che i riferimenti alla risorsa mediati dalla guardia non possono "
|
|
|
"sopravvivere\n"
|
|
|
"guardia. Per vedere come funziona è utile esaminare la firma di `deref`\n"
|
|
|
"senza elisione a vita:"
|
|
|
|
|
|
#: src\patterns/behavioural/RAII.md:97
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"fn deref<'a>(&'a self) -> &'a T {\n"
|
|
|
" //..\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/behavioural/RAII.md:103
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The returned reference to the resource has the same lifetime as `self` "
|
|
|
"(`'a`).\n"
|
|
|
"The borrow checker therefore ensures that the lifetime of the reference to "
|
|
|
"`T`\n"
|
|
|
"is shorter than the lifetime of `self`."
|
|
|
msgstr ""
|
|
|
"Il riferimento restituito alla risorsa ha la stessa durata di `self` "
|
|
|
"(`'a`).\n"
|
|
|
"Il controllo del prestito assicura quindi che la durata del riferimento a "
|
|
|
"\"T\".\n"
|
|
|
"è più breve della durata di `self`."
|
|
|
|
|
|
#: src\patterns/behavioural/RAII.md:107
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Note that implementing `Deref` is not a core part of this pattern, it only "
|
|
|
"makes\n"
|
|
|
"using the guard object more ergonomic. Implementing a `get` method on the "
|
|
|
"guard\n"
|
|
|
"works just as well."
|
|
|
msgstr ""
|
|
|
"Si noti che l'implementazione di \"Deref\" non è una parte fondamentale di "
|
|
|
"questo modello, lo fa solo\n"
|
|
|
"utilizzando l'oggetto di protezione più ergonomico. Implementazione di un "
|
|
|
"metodo `get` in guardia\n"
|
|
|
"funziona altrettanto bene."
|
|
|
|
|
|
#: src\patterns/behavioural/RAII.md:113
|
|
|
#, fuzzy
|
|
|
msgid "[Finalisation in destructors idiom](../../idioms/dtor-finally.md)"
|
|
|
msgstr ""
|
|
|
"[Finalizzazione nell'idioma dei distruttori](../../idioms/dtor-finally.md)"
|
|
|
|
|
|
#: src\patterns/behavioural/RAII.md:115
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"RAII is a common pattern in C++: "
|
|
|
"[cppreference.com](http://en.cppreference.com/w/cpp/language/raii),\n"
|
|
|
"[wikipedia][wikipedia]."
|
|
|
msgstr ""
|
|
|
"RAII è un modello comune in C++: "
|
|
|
"[cppreference.com](http://en.cppreference.com/w/cpp/language/raii),\n"
|
|
|
"[wikipedia][wikipedia]."
|
|
|
|
|
|
#: src\patterns/behavioural/RAII.md:120
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"[Style guide "
|
|
|
"entry](https://doc.rust-lang.org/1.0.0/style/ownership/raii.html)\n"
|
|
|
"(currently just a placeholder)."
|
|
|
msgstr ""
|
|
|
"[Voce della guida di "
|
|
|
"stile](https://doc.rust-lang.org/1.0.0/style/ownership/raii.html)\n"
|
|
|
"(attualmente solo un segnaposto)."
|
|
|
|
|
|
#: src\patterns/behavioural/strategy.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Strategy (aka Policy)"
|
|
|
msgstr "# Strategia (ovvero Politica)"
|
|
|
|
|
|
#: src\patterns/behavioural/strategy.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The [Strategy design "
|
|
|
"pattern](https://en.wikipedia.org/wiki/Strategy_pattern)\n"
|
|
|
"is a technique that enables separation of concerns.\n"
|
|
|
"It also allows to decouple software modules through [Dependency "
|
|
|
"Inversion](https://en.wikipedia.org/wiki/Dependency_inversion_principle)."
|
|
|
msgstr ""
|
|
|
"Il [modello di progettazione della "
|
|
|
"strategia](https://en.wikipedia.org/wiki/Strategy_pattern)\n"
|
|
|
"è una tecnica che consente la separazione delle preoccupazioni.\n"
|
|
|
"Consente inoltre di disaccoppiare i moduli software tramite [Dependency "
|
|
|
"Inversion](https://en.wikipedia.org/wiki/Dependency_inversion_principle)."
|
|
|
|
|
|
#: src\patterns/behavioural/strategy.md:9
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The basic idea behind the Strategy pattern is that, given an algorithm "
|
|
|
"solving\n"
|
|
|
"a particular problem, we define only the skeleton of the algorithm at an "
|
|
|
"abstract\n"
|
|
|
"level, and we separate the specific algorithm’s implementation into "
|
|
|
"different parts."
|
|
|
msgstr ""
|
|
|
"L'idea di base alla base del modello di strategia è che, data la risoluzione "
|
|
|
"di un algoritmo\n"
|
|
|
"un problema particolare, definiamo solo lo scheletro dell'algoritmo in "
|
|
|
"astratto\n"
|
|
|
"livello e separiamo l'implementazione dell'algoritmo specifico in parti "
|
|
|
"diverse."
|
|
|
|
|
|
#: src\patterns/behavioural/strategy.md:13
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"In this way, a client using the algorithm may choose a specific "
|
|
|
"implementation,\n"
|
|
|
"while the general algorithm workflow remains the same. In other words, the "
|
|
|
"abstract\n"
|
|
|
"specification of the class does not depend on the specific implementation of "
|
|
|
"the\n"
|
|
|
"derived class, but specific implementation must adhere to the abstract "
|
|
|
"specification.\n"
|
|
|
"This is why we call it \"Dependency Inversion\"."
|
|
|
msgstr ""
|
|
|
"In questo modo, un client che utilizza l'algoritmo può scegliere "
|
|
|
"un'implementazione specifica,\n"
|
|
|
"mentre il flusso di lavoro generale dell'algoritmo rimane lo stesso. In "
|
|
|
"altre parole, l'astratto\n"
|
|
|
"la specifica della classe non dipende dall'implementazione specifica del\n"
|
|
|
"classe derivata, ma l'implementazione specifica deve aderire alla specifica "
|
|
|
"astratta.\n"
|
|
|
"Questo è il motivo per cui lo chiamiamo \"Dependency Inversion\"."
|
|
|
|
|
|
#: src\patterns/behavioural/strategy.md:21
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Imagine we are working on a project that generates reports every month.\n"
|
|
|
"We need the reports to be generated in different formats (strategies), "
|
|
|
"e.g.,\n"
|
|
|
"in `JSON` or `Plain Text` formats.\n"
|
|
|
"But things vary over time, and we don't know what kind of requirement we may "
|
|
|
"get\n"
|
|
|
"in the future. For example, we may need to generate our report in a "
|
|
|
"completely new\n"
|
|
|
"format, or just modify one of the existing formats."
|
|
|
msgstr ""
|
|
|
"Immagina di lavorare a un progetto che genera report ogni mese.\n"
|
|
|
"Abbiamo bisogno che i report siano generati in diversi formati (strategie), "
|
|
|
"ad es.\n"
|
|
|
"nei formati `JSON` o `Plain Text`.\n"
|
|
|
"Ma le cose variano nel tempo e non sappiamo che tipo di requisiti potremmo "
|
|
|
"ottenere\n"
|
|
|
"in futuro. Ad esempio, potremmo aver bisogno di generare il nostro report in "
|
|
|
"un formato completamente nuovo\n"
|
|
|
"formato, o semplicemente modificare uno dei formati esistenti."
|
|
|
|
|
|
#: src\patterns/behavioural/strategy.md:30
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"In this example our invariants (or abstractions) are `Context`, "
|
|
|
"`Formatter`,\n"
|
|
|
"and `Report`, while `Text` and `Json` are our strategy structs. These "
|
|
|
"strategies\n"
|
|
|
"have to implement the `Formatter` trait."
|
|
|
msgstr ""
|
|
|
"In questo esempio le nostre invarianti (o astrazioni) sono `Context`, "
|
|
|
"`Formatter`,\n"
|
|
|
"e `Report`, mentre `Text` e `Json` sono le nostre strutture strategiche. "
|
|
|
"Queste strategie\n"
|
|
|
"devono implementare il tratto `Formatter`."
|
|
|
|
|
|
#: src\patterns/behavioural/strategy.md:34
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"use std::collections::HashMap;\n"
|
|
|
"\n"
|
|
|
"type Data = HashMap<String, u32>;\n"
|
|
|
"\n"
|
|
|
"trait Formatter {\n"
|
|
|
" fn format(&self, data: &Data, buf: &mut String);\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"struct Report;\n"
|
|
|
"\n"
|
|
|
"impl Report {\n"
|
|
|
" // Write should be used but we kept it as String to ignore error "
|
|
|
"handling\n"
|
|
|
" fn generate<T: Formatter>(g: T, s: &mut String) {\n"
|
|
|
" // backend operations...\n"
|
|
|
" let mut data = HashMap::new();\n"
|
|
|
" data.insert(\"one\".to_string(), 1);\n"
|
|
|
" data.insert(\"two\".to_string(), 2);\n"
|
|
|
" // generate report\n"
|
|
|
" g.format(&data, s);\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"struct Text;\n"
|
|
|
"impl Formatter for Text {\n"
|
|
|
" fn format(&self, data: &Data, buf: &mut String) {\n"
|
|
|
" for (k, v) in data {\n"
|
|
|
" let entry = format!(\"{} {}\\n"
|
|
|
"\", k, v);\n"
|
|
|
" buf.push_str(&entry);\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"struct Json;\n"
|
|
|
"impl Formatter for Json {\n"
|
|
|
" fn format(&self, data: &Data, buf: &mut String) {\n"
|
|
|
" buf.push('[');\n"
|
|
|
" for (k, v) in data.into_iter() {\n"
|
|
|
" let entry = format!(r#\"{{\"{}\":\"{}\"}}\"#, k, v);\n"
|
|
|
" buf.push_str(&entry);\n"
|
|
|
" buf.push(',');\n"
|
|
|
" }\n"
|
|
|
" if !data.is_empty() {\n"
|
|
|
" buf.pop(); // remove extra , at the end\n"
|
|
|
" }\n"
|
|
|
" buf.push(']');\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn main() {\n"
|
|
|
" let mut s = String::from(\"\");\n"
|
|
|
" Report::generate(Text, &mut s);\n"
|
|
|
" assert!(s.contains(\"one 1\"));\n"
|
|
|
" assert!(s.contains(\"two 2\"));\n"
|
|
|
"\n"
|
|
|
" s.clear(); // reuse the same buffer\n"
|
|
|
" Report::generate(Json, &mut s);\n"
|
|
|
" assert!(s.contains(r#\"{\"one\":\"1\"}\"#));\n"
|
|
|
" assert!(s.contains(r#\"{\"two\":\"2\"}\"#));\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/behavioural/strategy.md:98
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The main advantage is separation of concerns. For example, in this case "
|
|
|
"`Report`\n"
|
|
|
"does not know anything about specific implementations of `Json` and `Text`,\n"
|
|
|
"whereas the output implementations does not care about how data is "
|
|
|
"preprocessed,\n"
|
|
|
"stored, and fetched. The only thing they have to know is context and a "
|
|
|
"specific\n"
|
|
|
"trait and method to implement, i.e,`Formatter` and `run`."
|
|
|
msgstr ""
|
|
|
"Il vantaggio principale è la separazione delle preoccupazioni. Ad esempio, "
|
|
|
"in questo caso `Report`\n"
|
|
|
"non sa nulla di specifiche implementazioni di `Json` e `Text`,\n"
|
|
|
"considerando che le implementazioni di output non si preoccupano di come i "
|
|
|
"dati vengono preelaborati,\n"
|
|
|
"memorizzato e recuperato. L'unica cosa che devono sapere è il contesto e uno "
|
|
|
"specifico\n"
|
|
|
"tratto e metodo da implementare, ad esempio `Formatter` e `run`."
|
|
|
|
|
|
#: src\patterns/behavioural/strategy.md:106
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"For each strategy there must be implemented at least one module, so number "
|
|
|
"of modules\n"
|
|
|
"increases with number of strategies. If there are many strategies to choose "
|
|
|
"from\n"
|
|
|
"then users have to know how strategies differ from one another."
|
|
|
msgstr ""
|
|
|
"Per ogni strategia deve essere implementato almeno un modulo, quindi numero "
|
|
|
"di moduli\n"
|
|
|
"aumenta con il numero di strategie. Se ci sono molte strategie tra cui "
|
|
|
"scegliere\n"
|
|
|
"quindi gli utenti devono sapere in che modo le strategie differiscono l'una "
|
|
|
"dall'altra."
|
|
|
|
|
|
#: src\patterns/behavioural/strategy.md:112
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"In the previous example all strategies are implemented in a single file.\n"
|
|
|
"Ways of providing different strategies includes:"
|
|
|
msgstr ""
|
|
|
"Nell'esempio precedente tutte le strategie sono implementate in un singolo "
|
|
|
"file.\n"
|
|
|
"I modi per fornire diverse strategie includono:"
|
|
|
|
|
|
#: src\patterns/behavioural/strategy.md:115
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- All in one file (as shown in this example, similar to being separated as "
|
|
|
"modules)\n"
|
|
|
"- Separated as modules, E.g. `formatter::json` module, `formatter::text` "
|
|
|
"module\n"
|
|
|
"- Use compiler feature flags, E.g. `json` feature, `text` feature\n"
|
|
|
"- Separated as crates, E.g. `json` crate, `text` crate"
|
|
|
msgstr ""
|
|
|
"- Tutto in un file (come mostrato in questo esempio, simile all'essere "
|
|
|
"separati come moduli)\n"
|
|
|
"- Separati come moduli, ad es. modulo `formatter::json`, modulo "
|
|
|
"`formatter::text`\n"
|
|
|
"- Usa i flag delle funzionalità del compilatore, ad es. Funzionalità "
|
|
|
"\"json\", funzionalità \"testo\".\n"
|
|
|
"- Separati come casse, ad es. cassa `json`, cassa `text`"
|
|
|
|
|
|
#: src\patterns/behavioural/strategy.md:120
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Serde crate is a good example of the `Strategy` pattern in action. Serde "
|
|
|
"allows\n"
|
|
|
"[full customization](https://serde.rs/custom-serialization.html) of the "
|
|
|
"serialization\n"
|
|
|
"behavior by manually implementing `Serialize` and `Deserialize` traits for "
|
|
|
"our\n"
|
|
|
"type. For example, we could easily swap `serde_json` with `serde_cbor` since "
|
|
|
"they\n"
|
|
|
"expose similar methods. Having this makes the helper crate `serde_transcode` "
|
|
|
"much\n"
|
|
|
"more useful and ergonomic."
|
|
|
msgstr ""
|
|
|
"Serde crate è un buon esempio del modello \"Strategia\" in azione. Serde "
|
|
|
"consente\n"
|
|
|
"[personalizzazione completa](https://serde.rs/custom-serialization.html) "
|
|
|
"della serializzazione\n"
|
|
|
"comportamento implementando manualmente i tratti `Serialize` e `Deserialize` "
|
|
|
"per il nostro\n"
|
|
|
"tipo. Ad esempio, potremmo facilmente scambiare `serde_json` con "
|
|
|
"`serde_cbor` poiché loro\n"
|
|
|
"esporre metodi simili. Avere questo rende l'helper crate `serde_transcode` "
|
|
|
"molto\n"
|
|
|
"più utile ed ergonomico."
|
|
|
|
|
|
#: src\patterns/behavioural/strategy.md:127
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"However, we don't need to use traits in order to design this pattern in Rust."
|
|
|
msgstr ""
|
|
|
"Tuttavia, non abbiamo bisogno di utilizzare i tratti per progettare questo "
|
|
|
"modello in Rust."
|
|
|
|
|
|
#: src\patterns/behavioural/strategy.md:129
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The following toy example demonstrates the idea of the Strategy pattern "
|
|
|
"using Rust\n"
|
|
|
"`closures`:"
|
|
|
msgstr ""
|
|
|
"Il seguente esempio di giocattolo dimostra l'idea del pattern Strategy "
|
|
|
"usando Rust\n"
|
|
|
"`chiusure`:"
|
|
|
|
|
|
#: src\patterns/behavioural/strategy.md:132
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"struct Adder;\n"
|
|
|
"impl Adder {\n"
|
|
|
" pub fn add<F>(x: u8, y: u8, f: F) -> u8\n"
|
|
|
" where\n"
|
|
|
" F: Fn(u8, u8) -> u8,\n"
|
|
|
" {\n"
|
|
|
" f(x, y)\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn main() {\n"
|
|
|
" let arith_adder = |x, y| x + y;\n"
|
|
|
" let bool_adder = |x, y| {\n"
|
|
|
" if x == 1 || y == 1 {\n"
|
|
|
" 1\n"
|
|
|
" } else {\n"
|
|
|
" 0\n"
|
|
|
" }\n"
|
|
|
" };\n"
|
|
|
" let custom_adder = |x, y| 2 * x + y;\n"
|
|
|
"\n"
|
|
|
" assert_eq!(9, Adder::add(4, 5, arith_adder));\n"
|
|
|
" assert_eq!(0, Adder::add(0, 0, bool_adder));\n"
|
|
|
" assert_eq!(5, Adder::add(1, 3, custom_adder));\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/behavioural/strategy.md:160
|
|
|
#, fuzzy
|
|
|
msgid "In fact, Rust already uses this idea for `Options`'s `map` method:"
|
|
|
msgstr "Infatti, Rust usa già questa idea per il metodo `map` di `Options`:"
|
|
|
|
|
|
#: src\patterns/behavioural/strategy.md:162
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"fn main() {\n"
|
|
|
" let val = Some(\"Rust\");\n"
|
|
|
"\n"
|
|
|
" let len_strategy = |s: &str| s.len();\n"
|
|
|
" assert_eq!(4, val.map(len_strategy).unwrap());\n"
|
|
|
"\n"
|
|
|
" let first_byte_strategy = |s: &str| s.bytes().next().unwrap();\n"
|
|
|
" assert_eq!(82, val.map(first_byte_strategy).unwrap());\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/behavioural/strategy.md:176
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [Strategy Pattern](https://en.wikipedia.org/wiki/Strategy_pattern)\n"
|
|
|
"- [Dependency "
|
|
|
"Injection](https://en.wikipedia.org/wiki/Dependency_injection)\n"
|
|
|
"- [Policy Based "
|
|
|
"Design](https://en.wikipedia.org/wiki/Modern_C++_Design#Policy-based_design)"
|
|
|
msgstr ""
|
|
|
"- [Modello strategico](https://en.wikipedia.org/wiki/Strategy_pattern)\n"
|
|
|
"- [Iniezione di "
|
|
|
"dipendenza](https://en.wikipedia.org/wiki/Dependency_injection)\n"
|
|
|
"- [Progettazione basata su "
|
|
|
"criteri](https://en.wikipedia.org/wiki/Modern_C++_Design#Policy-based_design)"
|
|
|
|
|
|
#: src\patterns/behavioural/visitor.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Visitor"
|
|
|
msgstr "# Visitatore"
|
|
|
|
|
|
#: src\patterns/behavioural/visitor.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"A visitor encapsulates an algorithm that operates over a heterogeneous\n"
|
|
|
"collection of objects. It allows multiple different algorithms to be "
|
|
|
"written\n"
|
|
|
"over the same data without having to modify the data (or their primary\n"
|
|
|
"behaviour)."
|
|
|
msgstr ""
|
|
|
"Un visitatore incapsula un algoritmo che opera su un eterogeneo\n"
|
|
|
"collezione di oggetti. Consente di scrivere più algoritmi diversi\n"
|
|
|
"sugli stessi dati senza dover modificare i dati (o il loro file primario\n"
|
|
|
"comportamento)."
|
|
|
|
|
|
#: src\patterns/behavioural/visitor.md:10
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Furthermore, the visitor pattern allows separating the traversal of\n"
|
|
|
"a collection of objects from the operations performed on each object."
|
|
|
msgstr ""
|
|
|
"Inoltre, il modello del visitatore consente di separare l'attraversamento "
|
|
|
"di\n"
|
|
|
"una raccolta di oggetti dalle operazioni eseguite su ciascun oggetto."
|
|
|
|
|
|
#: src\patterns/behavioural/visitor.md:15
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"// The data we will visit\n"
|
|
|
"mod ast {\n"
|
|
|
" pub enum Stmt {\n"
|
|
|
" Expr(Expr),\n"
|
|
|
" Let(Name, Expr),\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" pub struct Name {\n"
|
|
|
" value: String,\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" pub enum Expr {\n"
|
|
|
" IntLit(i64),\n"
|
|
|
" Add(Box<Expr>, Box<Expr>),\n"
|
|
|
" Sub(Box<Expr>, Box<Expr>),\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"// The abstract visitor\n"
|
|
|
"mod visit {\n"
|
|
|
" use ast::*;\n"
|
|
|
"\n"
|
|
|
" pub trait Visitor<T> {\n"
|
|
|
" fn visit_name(&mut self, n: &Name) -> T;\n"
|
|
|
" fn visit_stmt(&mut self, s: &Stmt) -> T;\n"
|
|
|
" fn visit_expr(&mut self, e: &Expr) -> T;\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"use visit::*;\n"
|
|
|
"use ast::*;\n"
|
|
|
"\n"
|
|
|
"// An example concrete implementation - walks the AST interpreting it as "
|
|
|
"code.\n"
|
|
|
"struct Interpreter;\n"
|
|
|
"impl Visitor<i64> for Interpreter {\n"
|
|
|
" fn visit_name(&mut self, n: &Name) -> i64 { panic!() }\n"
|
|
|
" fn visit_stmt(&mut self, s: &Stmt) -> i64 {\n"
|
|
|
" match *s {\n"
|
|
|
" Stmt::Expr(ref e) => self.visit_expr(e),\n"
|
|
|
" Stmt::Let(..) => unimplemented!(),\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" fn visit_expr(&mut self, e: &Expr) -> i64 {\n"
|
|
|
" match *e {\n"
|
|
|
" Expr::IntLit(n) => n,\n"
|
|
|
" Expr::Add(ref lhs, ref rhs) => self.visit_expr(lhs) + "
|
|
|
"self.visit_expr(rhs),\n"
|
|
|
" Expr::Sub(ref lhs, ref rhs) => self.visit_expr(lhs) - "
|
|
|
"self.visit_expr(rhs),\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/behavioural/visitor.md:69
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"One could implement further visitors, for example a type checker, without "
|
|
|
"having\n"
|
|
|
"to modify the AST data."
|
|
|
msgstr ""
|
|
|
"Si potrebbero implementare ulteriori visitatori, ad esempio un controllo di "
|
|
|
"tipo, senza avere\n"
|
|
|
"per modificare i dati AST."
|
|
|
|
|
|
#: src\patterns/behavioural/visitor.md:74
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The visitor pattern is useful anywhere that you want to apply an algorithm "
|
|
|
"to\n"
|
|
|
"heterogeneous data. If data is homogeneous, you can use an iterator-like "
|
|
|
"pattern.\n"
|
|
|
"Using a visitor object (rather than a functional approach) allows the "
|
|
|
"visitor to\n"
|
|
|
"be stateful and thus communicate information between nodes."
|
|
|
msgstr ""
|
|
|
"Il modello visitatore è utile ovunque tu voglia applicare un algoritmo\n"
|
|
|
"dati eterogenei. Se i dati sono omogenei, puoi utilizzare un modello simile "
|
|
|
"a un iteratore.\n"
|
|
|
"L'utilizzo di un oggetto visitatore (piuttosto che un approccio funzionale) "
|
|
|
"consente al visitatore di\n"
|
|
|
"essere stateful e quindi comunicare informazioni tra i nodi."
|
|
|
|
|
|
#: src\patterns/behavioural/visitor.md:81
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"It is common for the `visit_*` methods to return void (as opposed to in the\n"
|
|
|
"example). In that case it is possible to factor out the traversal code and "
|
|
|
"share\n"
|
|
|
"it between algorithms (and also to provide noop default methods). In Rust, "
|
|
|
"the\n"
|
|
|
"common way to do this is to provide `walk_*` functions for each datum. For\n"
|
|
|
"example,"
|
|
|
msgstr ""
|
|
|
"È comune che i metodi `visit_*` restituiscano void (al contrario di quanto "
|
|
|
"accade nel\n"
|
|
|
"esempio). In tal caso è possibile scomporre il codice di attraversamento e "
|
|
|
"condividerlo\n"
|
|
|
"it tra algoritmi (e anche per fornire metodi predefiniti noop). In Ruggine, "
|
|
|
"il\n"
|
|
|
"un modo comune per farlo è fornire funzioni `walk_*` per ogni dato. Per\n"
|
|
|
"esempio,"
|
|
|
|
|
|
#: src\patterns/behavioural/visitor.md:87
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"pub fn walk_expr(visitor: &mut Visitor, e: &Expr) {\n"
|
|
|
" match *e {\n"
|
|
|
" Expr::IntLit(_) => {},\n"
|
|
|
" Expr::Add(ref lhs, ref rhs) => {\n"
|
|
|
" visitor.visit_expr(lhs);\n"
|
|
|
" visitor.visit_expr(rhs);\n"
|
|
|
" }\n"
|
|
|
" Expr::Sub(ref lhs, ref rhs) => {\n"
|
|
|
" visitor.visit_expr(lhs);\n"
|
|
|
" visitor.visit_expr(rhs);\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/behavioural/visitor.md:103
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"In other languages (e.g., Java) it is common for data to have an `accept` "
|
|
|
"method\n"
|
|
|
"which performs the same duty."
|
|
|
msgstr ""
|
|
|
"In altri linguaggi (ad esempio, Java) è comune che i dati abbiano un metodo "
|
|
|
"`accept`\n"
|
|
|
"che svolge lo stesso compito."
|
|
|
|
|
|
#: src\patterns/behavioural/visitor.md:108
|
|
|
#, fuzzy
|
|
|
msgid "The visitor pattern is a common pattern in most OO languages."
|
|
|
msgstr ""
|
|
|
"Il modello del visitatore è un modello comune nella maggior parte delle "
|
|
|
"lingue OO."
|
|
|
|
|
|
#: src\patterns/behavioural/visitor.md:110
|
|
|
#, fuzzy
|
|
|
msgid "[Wikipedia article](https://en.wikipedia.org/wiki/Visitor_pattern)"
|
|
|
msgstr "[Articolo di Wikipedia](https://en.wikipedia.org/wiki/Visitor_pattern)"
|
|
|
|
|
|
#: src\patterns/behavioural/visitor.md:112
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The [fold](../creational/fold.md) pattern is similar to visitor but "
|
|
|
"produces\n"
|
|
|
"a new version of the visited data structure."
|
|
|
msgstr ""
|
|
|
"Il modello [fold](../creational/fold.md) è simile al visitatore ma produce\n"
|
|
|
"una nuova versione della struttura dati visitata."
|
|
|
|
|
|
#: src\patterns/creational/intro.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Creational Patterns"
|
|
|
msgstr "# Modelli Creativi"
|
|
|
|
|
|
#: src\patterns/creational/intro.md:3
|
|
|
#, fuzzy
|
|
|
msgid "From [Wikipedia](https://en.wikipedia.org/wiki/Creational_pattern):"
|
|
|
msgstr "Da [Wikipedia](https://en.wikipedia.org/wiki/Creational_pattern):"
|
|
|
|
|
|
#: src\patterns/creational/intro.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"> Design patterns that deal with object creation mechanisms, trying to "
|
|
|
"create objects\n"
|
|
|
"> in a manner suitable to the situation. The basic form of object creation "
|
|
|
"could\n"
|
|
|
"> result in design problems or in added complexity to the design. Creational "
|
|
|
"design\n"
|
|
|
"> patterns solve this problem by somehow controlling this object creation."
|
|
|
msgstr ""
|
|
|
"> Design pattern che si occupano di meccanismi di creazione di oggetti, "
|
|
|
"cercando di creare oggetti\n"
|
|
|
"> in modo adeguato alla situazione. La forma base della creazione di oggetti "
|
|
|
"potrebbe\n"
|
|
|
"> comportare problemi di progettazione o una maggiore complessità del "
|
|
|
"progetto. Progettazione creazionale\n"
|
|
|
"> i modelli risolvono questo problema controllando in qualche modo la "
|
|
|
"creazione di questo oggetto."
|
|
|
|
|
|
#: src\patterns/creational/builder.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Builder"
|
|
|
msgstr "# Costruttore"
|
|
|
|
|
|
#: src\patterns/creational/builder.md:5
|
|
|
#, fuzzy
|
|
|
msgid "Construct an object with calls to a builder helper."
|
|
|
msgstr "Costruisci un oggetto con chiamate a un builder helper."
|
|
|
|
|
|
#: src\patterns/creational/builder.md:9
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"#[derive(Debug, PartialEq)]\n"
|
|
|
"pub struct Foo {\n"
|
|
|
" // Lots of complicated fields.\n"
|
|
|
" bar: String,\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"impl Foo {\n"
|
|
|
" // This method will help users to discover the builder\n"
|
|
|
" pub fn builder() -> FooBuilder {\n"
|
|
|
" FooBuilder::default()\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"#[derive(Default)]\n"
|
|
|
"pub struct FooBuilder {\n"
|
|
|
" // Probably lots of optional fields.\n"
|
|
|
" bar: String,\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"impl FooBuilder {\n"
|
|
|
" pub fn new(/* ... */) -> FooBuilder {\n"
|
|
|
" // Set the minimally required fields of Foo.\n"
|
|
|
" FooBuilder {\n"
|
|
|
" bar: String::from(\"X\"),\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" pub fn name(mut self, bar: String) -> FooBuilder {\n"
|
|
|
" // Set the name on the builder itself, and return the builder by "
|
|
|
"value.\n"
|
|
|
" self.bar = bar;\n"
|
|
|
" self\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" // If we can get away with not consuming the Builder here, that is an\n"
|
|
|
" // advantage. It means we can use the FooBuilder as a template for "
|
|
|
"constructing\n"
|
|
|
" // many Foos.\n"
|
|
|
" pub fn build(self) -> Foo {\n"
|
|
|
" // Create a Foo from the FooBuilder, applying all settings in "
|
|
|
"FooBuilder\n"
|
|
|
" // to Foo.\n"
|
|
|
" Foo { bar: self.bar }\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"#[test]\n"
|
|
|
"fn builder_test() {\n"
|
|
|
" let foo = Foo {\n"
|
|
|
" bar: String::from(\"Y\"),\n"
|
|
|
" };\n"
|
|
|
" let foo_from_builder: Foo = "
|
|
|
"FooBuilder::new().name(String::from(\"Y\")).build();\n"
|
|
|
" assert_eq!(foo, foo_from_builder);\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/creational/builder.md:65
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Useful when you would otherwise require many constructors or where\n"
|
|
|
"construction has side effects."
|
|
|
msgstr ""
|
|
|
"Utile quando altrimenti avresti bisogno di molti costruttori o dove\n"
|
|
|
"la costruzione ha effetti collaterali."
|
|
|
|
|
|
#: src\patterns/creational/builder.md:70
|
|
|
#, fuzzy
|
|
|
msgid "Separates methods for building from other methods."
|
|
|
msgstr "Separa i metodi per la compilazione da altri metodi."
|
|
|
|
|
|
#: src\patterns/creational/builder.md:72
|
|
|
#, fuzzy
|
|
|
msgid "Prevents proliferation of constructors."
|
|
|
msgstr "Previene la proliferazione di costruttori."
|
|
|
|
|
|
#: src\patterns/creational/builder.md:74
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Can be used for one-liner initialisation as well as more complex "
|
|
|
"construction."
|
|
|
msgstr ""
|
|
|
"Può essere utilizzato per l'inizializzazione one-liner e per costruzioni più "
|
|
|
"complesse."
|
|
|
|
|
|
#: src\patterns/creational/builder.md:78
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"More complex than creating a struct object directly, or a simple "
|
|
|
"constructor\n"
|
|
|
"function."
|
|
|
msgstr ""
|
|
|
"Più complesso della creazione diretta di un oggetto struct o di un semplice "
|
|
|
"costruttore\n"
|
|
|
"funzione."
|
|
|
|
|
|
#: src\patterns/creational/builder.md:83
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This pattern is seen more frequently in Rust (and for simpler objects) than "
|
|
|
"in\n"
|
|
|
"many other languages because Rust lacks overloading. Since you can only have "
|
|
|
"a\n"
|
|
|
"single method with a given name, having multiple constructors is less nice "
|
|
|
"in\n"
|
|
|
"Rust than in C++, Java, or others."
|
|
|
msgstr ""
|
|
|
"Questo modello è visto più frequentemente in Rust (e per oggetti più "
|
|
|
"semplici) che in\n"
|
|
|
"molte altre lingue perché Rust manca di sovraccarico. Dal momento che puoi "
|
|
|
"avere solo un file\n"
|
|
|
"singolo metodo con un determinato nome, avere più costruttori è meno "
|
|
|
"piacevole\n"
|
|
|
"Rust che in C++, Java o altri."
|
|
|
|
|
|
#: src\patterns/creational/builder.md:88
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This pattern is often used where the builder object is useful in its own "
|
|
|
"right,\n"
|
|
|
"rather than being just a builder. For example, see\n"
|
|
|
"[`std::process::Command`](https://doc.rust-lang.org/std/process/struct.Command.html)\n"
|
|
|
"is a builder for "
|
|
|
"[`Child`](https://doc.rust-lang.org/std/process/struct.Child.html)\n"
|
|
|
"(a process). In these cases, the `T` and `TBuilder` naming pattern is not "
|
|
|
"used."
|
|
|
msgstr ""
|
|
|
"Questo modello viene spesso utilizzato quando l'oggetto builder è utile di "
|
|
|
"per sé,\n"
|
|
|
"piuttosto che essere solo un costruttore. Ad esempio, vedi\n"
|
|
|
"[`std::process::Command`](https://doc.rust-lang.org/std/process/struct.Command.html)\n"
|
|
|
"è un builder per "
|
|
|
"[`Child`](https://doc.rust-lang.org/std/process/struct.Child.html)\n"
|
|
|
"(un processo). In questi casi, il modello di denominazione \"T\" e "
|
|
|
"\"TBuilder\" non viene utilizzato."
|
|
|
|
|
|
#: src\patterns/creational/builder.md:94
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The example takes and returns the builder by value. It is often more "
|
|
|
"ergonomic\n"
|
|
|
"(and more efficient) to take and return the builder as a mutable reference. "
|
|
|
"The\n"
|
|
|
"borrow checker makes this work naturally. This approach has the advantage "
|
|
|
"that\n"
|
|
|
"one can write code like"
|
|
|
msgstr ""
|
|
|
"L'esempio accetta e restituisce il builder per valore. Spesso è più "
|
|
|
"ergonomico\n"
|
|
|
"(e più efficiente) per prendere e restituire il builder come riferimento "
|
|
|
"mutabile. IL\n"
|
|
|
"prendere in prestito checker rende questo lavoro naturale. Questo approccio "
|
|
|
"ha il vantaggio che\n"
|
|
|
"si può scrivere codice come"
|
|
|
|
|
|
#: src\patterns/creational/builder.md:99
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"let mut fb = FooBuilder::new();\n"
|
|
|
"fb.a();\n"
|
|
|
"fb.b();\n"
|
|
|
"let f = fb.build();\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/creational/builder.md:106
|
|
|
#, fuzzy
|
|
|
msgid "as well as the `FooBuilder::new().a().b().build()` style."
|
|
|
msgstr "così come lo stile `FooBuilder::new().a().b().build()`."
|
|
|
|
|
|
#: src\patterns/creational/builder.md:110
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [Description in the style "
|
|
|
"guide](https://web.archive.org/web/20210104103100/https://doc.rust-lang.org/1.12.0/style/ownership/builders.html)\n"
|
|
|
"- [derive_builder](https://crates.io/crates/derive_builder), a crate for "
|
|
|
"automatically\n"
|
|
|
" implementing this pattern while avoiding the boilerplate.\n"
|
|
|
"- [Constructor pattern](../../idioms/ctor.md) for when construction is "
|
|
|
"simpler.\n"
|
|
|
"- [Builder pattern "
|
|
|
"(wikipedia)](https://en.wikipedia.org/wiki/Builder_pattern)\n"
|
|
|
"- [Construction of complex "
|
|
|
"values](https://web.archive.org/web/20210104103000/https://rust-lang.github.io/api-guidelines/type-safety.html#c-builder)"
|
|
|
msgstr ""
|
|
|
"- [Descrizione nella guida di "
|
|
|
"stile](https://web.archive.org/web/20210104103100/https://doc.rust-lang.org/1.12.0/style/ownership/builders.html)\n"
|
|
|
"- [derive_builder](https://crates.io/crates/derive_builder), una cassa per "
|
|
|
"automaticamente\n"
|
|
|
" implementare questo modello evitando il boilerplate.\n"
|
|
|
"- [Modello costruttore](../../idioms/ctor.md) per quando la costruzione è "
|
|
|
"più semplice.\n"
|
|
|
"- [Modello builder "
|
|
|
"(wikipedia)](https://en.wikipedia.org/wiki/Builder_pattern)\n"
|
|
|
"- [Costruzione di valori "
|
|
|
"complessi](https://web.archive.org/web/20210104103000/https://rust-lang.github.io/api-guidelines/type-safety.html#c-builder)"
|
|
|
|
|
|
#: src\patterns/creational/fold.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Fold"
|
|
|
msgstr "# Piega"
|
|
|
|
|
|
#: src\patterns/creational/fold.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Run an algorithm over each item in a collection of data to create a new "
|
|
|
"item,\n"
|
|
|
"thus creating a whole new collection."
|
|
|
msgstr ""
|
|
|
"Esegui un algoritmo su ogni elemento in una raccolta di dati per creare un "
|
|
|
"nuovo elemento,\n"
|
|
|
"creando così una collezione completamente nuova."
|
|
|
|
|
|
#: src\patterns/creational/fold.md:8
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The etymology here is unclear to me. The terms 'fold' and 'folder' are used\n"
|
|
|
"in the Rust compiler, although it appears to me to be more like a map than "
|
|
|
"a\n"
|
|
|
"fold in the usual sense. See the discussion below for more details."
|
|
|
msgstr ""
|
|
|
"L'etimologia qui non mi è chiara. Vengono utilizzati i termini \"piega\" e "
|
|
|
"\"cartella\".\n"
|
|
|
"nel compilatore Rust, anche se mi sembra più simile a una mappa che a\n"
|
|
|
"piegare nel senso comune. Vedere la discussione di seguito per maggiori "
|
|
|
"dettagli."
|
|
|
|
|
|
#: src\patterns/creational/fold.md:14
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"// The data we will fold, a simple AST.\n"
|
|
|
"mod ast {\n"
|
|
|
" pub enum Stmt {\n"
|
|
|
" Expr(Box<Expr>),\n"
|
|
|
" Let(Box<Name>, Box<Expr>),\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" pub struct Name {\n"
|
|
|
" value: String,\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" pub enum Expr {\n"
|
|
|
" IntLit(i64),\n"
|
|
|
" Add(Box<Expr>, Box<Expr>),\n"
|
|
|
" Sub(Box<Expr>, Box<Expr>),\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"// The abstract folder\n"
|
|
|
"mod fold {\n"
|
|
|
" use ast::*;\n"
|
|
|
"\n"
|
|
|
" pub trait Folder {\n"
|
|
|
" // A leaf node just returns the node itself. In some cases, we can "
|
|
|
"do this\n"
|
|
|
" // to inner nodes too.\n"
|
|
|
" fn fold_name(&mut self, n: Box<Name>) -> Box<Name> { n }\n"
|
|
|
" // Create a new inner node by folding its children.\n"
|
|
|
" fn fold_stmt(&mut self, s: Box<Stmt>) -> Box<Stmt> {\n"
|
|
|
" match *s {\n"
|
|
|
" Stmt::Expr(e) => Box::new(Stmt::Expr(self.fold_expr(e))),\n"
|
|
|
" Stmt::Let(n, e) => Box::new(Stmt::Let(self.fold_name(n), "
|
|
|
"self.fold_expr(e))),\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
" fn fold_expr(&mut self, e: Box<Expr>) -> Box<Expr> { ... }\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"use fold::*;\n"
|
|
|
"use ast::*;\n"
|
|
|
"\n"
|
|
|
"// An example concrete implementation - renames every name to 'foo'.\n"
|
|
|
"struct Renamer;\n"
|
|
|
"impl Folder for Renamer {\n"
|
|
|
" fn fold_name(&mut self, n: Box<Name>) -> Box<Name> {\n"
|
|
|
" Box::new(Name { value: \"foo\".to_owned() })\n"
|
|
|
" }\n"
|
|
|
" // Use the default methods for the other nodes.\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/creational/fold.md:65
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The result of running the `Renamer` on an AST is a new AST identical to the "
|
|
|
"old\n"
|
|
|
"one, but with every name changed to `foo`. A real life folder might have "
|
|
|
"some\n"
|
|
|
"state preserved between nodes in the struct itself."
|
|
|
msgstr ""
|
|
|
"Il risultato dell'esecuzione di `Renamer` su un AST è un nuovo AST identico "
|
|
|
"al vecchio\n"
|
|
|
"uno, ma con ogni nome cambiato in `foo`. Una cartella della vita reale "
|
|
|
"potrebbe averne alcuni\n"
|
|
|
"stato preservato tra i nodi nella struttura stessa."
|
|
|
|
|
|
#: src\patterns/creational/fold.md:69
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"A folder can also be defined to map one data structure to a different (but\n"
|
|
|
"usually similar) data structure. For example, we could fold an AST into a "
|
|
|
"HIR\n"
|
|
|
"tree (HIR stands for high-level intermediate representation)."
|
|
|
msgstr ""
|
|
|
"È inoltre possibile definire una cartella per mappare una struttura di dati "
|
|
|
"a un'altra (but\n"
|
|
|
"di solito simile) struttura dei dati. Ad esempio, potremmo piegare un AST in "
|
|
|
"un HIR\n"
|
|
|
"albero (HIR sta per rappresentazione intermedia di alto livello)."
|
|
|
|
|
|
#: src\patterns/creational/fold.md:75
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"It is common to want to map a data structure by performing some operation "
|
|
|
"on\n"
|
|
|
"each node in the structure. For simple operations on simple data "
|
|
|
"structures,\n"
|
|
|
"this can be done using `Iterator::map`. For more complex operations, "
|
|
|
"perhaps\n"
|
|
|
"where earlier nodes can affect the operation on later nodes, or where "
|
|
|
"iteration\n"
|
|
|
"over the data structure is non-trivial, using the fold pattern is more\n"
|
|
|
"appropriate."
|
|
|
msgstr ""
|
|
|
"È comune voler mappare una struttura dati eseguendo alcune operazioni su\n"
|
|
|
"ciascun nodo della struttura. Per operazioni semplici su strutture dati "
|
|
|
"semplici,\n"
|
|
|
"questo può essere fatto usando `Iterator::map`. Per operazioni più "
|
|
|
"complesse, forse\n"
|
|
|
"dove i nodi precedenti possono influenzare l'operazione sui nodi successivi "
|
|
|
"o dove l'iterazione\n"
|
|
|
"sopra la struttura dei dati non è banale, l'utilizzo del modello di "
|
|
|
"piegatura lo è di più\n"
|
|
|
"adeguata."
|
|
|
|
|
|
#: src\patterns/creational/fold.md:82
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Like the visitor pattern, the fold pattern allows us to separate traversal "
|
|
|
"of a\n"
|
|
|
"data structure from the operations performed to each node."
|
|
|
msgstr ""
|
|
|
"Come il modello del visitatore, il modello di piegatura ci consente di "
|
|
|
"separare l'attraversamento di a\n"
|
|
|
"struttura dati dalle operazioni eseguite su ciascun nodo."
|
|
|
|
|
|
#: src\patterns/creational/fold.md:87
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Mapping data structures in this fashion is common in functional languages. "
|
|
|
"In OO\n"
|
|
|
"languages, it would be more common to mutate the data structure in place. "
|
|
|
"The\n"
|
|
|
"'functional' approach is common in Rust, mostly due to the preference for\n"
|
|
|
"immutability. Using fresh data structures, rather than mutating old ones, "
|
|
|
"makes\n"
|
|
|
"reasoning about the code easier in most circumstances."
|
|
|
msgstr ""
|
|
|
"La mappatura delle strutture dati in questo modo è comune nei linguaggi "
|
|
|
"funzionali. Nell'OO\n"
|
|
|
"lingue, sarebbe più comune mutare la struttura dei dati sul posto. IL\n"
|
|
|
"L'approccio \"funzionale\" è comune in Rust, principalmente a causa della "
|
|
|
"preferenza per\n"
|
|
|
"immutabilità. L'utilizzo di nuove strutture di dati, piuttosto che la "
|
|
|
"mutazione di quelle vecchie, rende\n"
|
|
|
"ragionamento sul codice più facile nella maggior parte dei casi."
|
|
|
|
|
|
#: src\patterns/creational/fold.md:93
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The trade-off between efficiency and reusability can be tweaked by changing "
|
|
|
"how\n"
|
|
|
"nodes are accepted by the `fold_*` methods."
|
|
|
msgstr ""
|
|
|
"Il compromesso tra efficienza e riusabilità può essere modificato "
|
|
|
"modificando il modo\n"
|
|
|
"i nodi sono accettati dai metodi `fold_*`."
|
|
|
|
|
|
#: src\patterns/creational/fold.md:96
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"In the above example we operate on `Box` pointers. Since these own their "
|
|
|
"data\n"
|
|
|
"exclusively, the original copy of the data structure cannot be re-used. On "
|
|
|
"the\n"
|
|
|
"other hand if a node is not changed, reusing it is very efficient."
|
|
|
msgstr ""
|
|
|
"Nell'esempio sopra operiamo sui puntatori `Box`. Dal momento che questi "
|
|
|
"possiedono i loro dati\n"
|
|
|
"esclusivamente, la copia originale della struttura dati non può essere "
|
|
|
"riutilizzata. Sul\n"
|
|
|
"d'altra parte se un nodo non viene modificato, riutilizzarlo è molto "
|
|
|
"efficiente."
|
|
|
|
|
|
#: src\patterns/creational/fold.md:100
|
|
|
msgid ""
|
|
|
"If we were to operate on borrowed references, the original data structure "
|
|
|
"can be\n"
|
|
|
"reused; however, a node must be cloned even if unchanged, which can be\n"
|
|
|
"expensive."
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/creational/fold.md:104
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Using a reference counted pointer gives the best of both worlds - we can "
|
|
|
"reuse\n"
|
|
|
"the original data structure, and we don't need to clone unchanged nodes. "
|
|
|
"However,\n"
|
|
|
"they are less ergonomic to use and mean that the data structures cannot be\n"
|
|
|
"mutable."
|
|
|
msgstr ""
|
|
|
"L'uso di un puntatore contato di riferimento offre il meglio di entrambi i "
|
|
|
"mondi: possiamo riutilizzarlo\n"
|
|
|
"la struttura dati originale e non è necessario clonare nodi non modificati. "
|
|
|
"Tuttavia,\n"
|
|
|
"sono meno ergonomici da usare e significano che le strutture dati non "
|
|
|
"possono esserlo\n"
|
|
|
"mutevole."
|
|
|
|
|
|
#: src\patterns/creational/fold.md:111
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Iterators have a `fold` method, however this folds a data structure into a\n"
|
|
|
"value, rather than into a new data structure. An iterator's `map` is more "
|
|
|
"like\n"
|
|
|
"this fold pattern."
|
|
|
msgstr ""
|
|
|
"Gli iteratori hanno un metodo `fold`, tuttavia questo ripiega una struttura "
|
|
|
"di dati in a\n"
|
|
|
"valore, piuttosto che in una nuova struttura di dati. La \"mappa\" di un "
|
|
|
"iteratore è più simile\n"
|
|
|
"questo schema di piegatura."
|
|
|
|
|
|
#: src\patterns/creational/fold.md:115
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"In other languages, fold is usually used in the sense of Rust's iterators,\n"
|
|
|
"rather than this pattern. Some functional languages have powerful constructs "
|
|
|
"for\n"
|
|
|
"performing flexible maps over data structures."
|
|
|
msgstr ""
|
|
|
"In altre lingue, fold è solitamente usato nel senso degli iteratori di "
|
|
|
"Rust,\n"
|
|
|
"piuttosto che questo modello. Alcuni linguaggi funzionali hanno potenti "
|
|
|
"costrutti per\n"
|
|
|
"eseguire mappe flessibili su strutture dati."
|
|
|
|
|
|
#: src\patterns/creational/fold.md:119
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The [visitor](../behavioural/visitor.md) pattern is closely related to "
|
|
|
"fold.\n"
|
|
|
"They share the concept of walking a data structure performing an operation "
|
|
|
"on\n"
|
|
|
"each node. However, the visitor does not create a new data structure nor "
|
|
|
"consume\n"
|
|
|
"the old one."
|
|
|
msgstr ""
|
|
|
"Il pattern [visitor](../behavioural/visitor.md) è strettamente correlato a "
|
|
|
"fold.\n"
|
|
|
"Condividono il concetto di percorrere una struttura dati su cui eseguire "
|
|
|
"un'operazione\n"
|
|
|
"ciascun nodo. Tuttavia, il visitatore non crea una nuova struttura di dati "
|
|
|
"né consuma\n"
|
|
|
"quello vecchio."
|
|
|
|
|
|
#: src\patterns/structural/intro.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Structural Patterns"
|
|
|
msgstr "# Modelli strutturali"
|
|
|
|
|
|
#: src\patterns/structural/intro.md:3
|
|
|
#, fuzzy
|
|
|
msgid "From [Wikipedia](https://en.wikipedia.org/wiki/Structural_pattern):"
|
|
|
msgstr "Da [Wikipedia](https://en.wikipedia.org/wiki/Structural_pattern):"
|
|
|
|
|
|
#: src\patterns/structural/intro.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"> Design patterns that ease the design by identifying a simple way to "
|
|
|
"realize relationships\n"
|
|
|
"> among entities."
|
|
|
msgstr ""
|
|
|
"> Design pattern che facilitano la progettazione individuando un modo "
|
|
|
"semplice per realizzare relazioni\n"
|
|
|
"> tra enti."
|
|
|
|
|
|
#: src\patterns/structural/compose-structs.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Compose structs together for better borrowing"
|
|
|
msgstr "# Comporre le strutture insieme per un migliore prestito"
|
|
|
|
|
|
#: src\patterns/structural/compose-structs.md:3
|
|
|
#, fuzzy
|
|
|
msgid "TODO - this is not a very snappy name"
|
|
|
msgstr "TODO - questo non è un nome molto accattivante"
|
|
|
|
|
|
#: src\patterns/structural/compose-structs.md:7
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Sometimes a large struct will cause issues with the borrow checker - "
|
|
|
"although\n"
|
|
|
"fields can be borrowed independently, sometimes the whole struct ends up "
|
|
|
"being\n"
|
|
|
"used at once, preventing other uses. A solution might be to decompose the "
|
|
|
"struct\n"
|
|
|
"into several smaller structs. Then compose these together into the original\n"
|
|
|
"struct. Then each struct can be borrowed separately and have more flexible\n"
|
|
|
"behaviour."
|
|
|
msgstr ""
|
|
|
"A volte una struttura di grandi dimensioni causerà problemi con il controllo "
|
|
|
"del prestito, anche se\n"
|
|
|
"i campi possono essere presi in prestito indipendentemente, a volte l'intera "
|
|
|
"struttura finisce per esserlo\n"
|
|
|
"utilizzato in una sola volta, impedendo altri usi. Una soluzione potrebbe "
|
|
|
"essere quella di scomporre la struct\n"
|
|
|
"in diverse strutture più piccole. Quindi componili insieme nell'originale\n"
|
|
|
"struct. Quindi ogni struttura può essere presa in prestito separatamente e "
|
|
|
"avere una maggiore flessibilità\n"
|
|
|
"comportamento."
|
|
|
|
|
|
#: src\patterns/structural/compose-structs.md:14
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This will often lead to a better design in other ways: applying this design\n"
|
|
|
"pattern often reveals smaller units of functionality."
|
|
|
msgstr ""
|
|
|
"Questo spesso porterà a un design migliore in altri modi: applicando questo "
|
|
|
"design\n"
|
|
|
"pattern rivela spesso unità di funzionalità più piccole."
|
|
|
|
|
|
#: src\patterns/structural/compose-structs.md:19
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Here is a contrived example of where the borrow checker foils us in our plan "
|
|
|
"to\n"
|
|
|
"use a struct:"
|
|
|
msgstr ""
|
|
|
"Ecco un esempio artificioso di dove il controllore del prestito ci sventa "
|
|
|
"nel nostro piano\n"
|
|
|
"usa una struttura:"
|
|
|
|
|
|
#: src\patterns/structural/compose-structs.md:22
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"struct A {\n"
|
|
|
" f1: u32,\n"
|
|
|
" f2: u32,\n"
|
|
|
" f3: u32,\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn foo(a: &mut A) -> &u32 { &a.f2 }\n"
|
|
|
"fn bar(a: &mut A) -> u32 { a.f1 + a.f3 }\n"
|
|
|
"\n"
|
|
|
"fn baz(a: &mut A) {\n"
|
|
|
" // The later usage of x causes a to be borrowed for the rest of the "
|
|
|
"function.\n"
|
|
|
" let x = foo(a);\n"
|
|
|
" // Borrow checker error:\n"
|
|
|
" // let y = bar(a); // ~ ERROR: cannot borrow `*a` as mutable more than "
|
|
|
"once\n"
|
|
|
" // at a time\n"
|
|
|
" println!(\"{}\", x);\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/structural/compose-structs.md:42
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"We can apply this design pattern and refactor `A` into two smaller structs, "
|
|
|
"thus\n"
|
|
|
"solving the borrow checking issue:"
|
|
|
msgstr ""
|
|
|
"Possiamo quindi applicare questo modello di progettazione e rifattorizzare "
|
|
|
"\"A\" in due strutture più piccole\n"
|
|
|
"risolvere il problema del controllo del prestito:"
|
|
|
|
|
|
#: src\patterns/structural/compose-structs.md:45
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"// A is now composed of two structs - B and C.\n"
|
|
|
"struct A {\n"
|
|
|
" b: B,\n"
|
|
|
" c: C,\n"
|
|
|
"}\n"
|
|
|
"struct B {\n"
|
|
|
" f2: u32,\n"
|
|
|
"}\n"
|
|
|
"struct C {\n"
|
|
|
" f1: u32,\n"
|
|
|
" f3: u32,\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"// These functions take a B or C, rather than A.\n"
|
|
|
"fn foo(b: &mut B) -> &u32 { &b.f2 }\n"
|
|
|
"fn bar(c: &mut C) -> u32 { c.f1 + c.f3 }\n"
|
|
|
"\n"
|
|
|
"fn baz(a: &mut A) {\n"
|
|
|
" let x = foo(&mut a.b);\n"
|
|
|
" // Now it's OK!\n"
|
|
|
" let y = bar(&mut a.c);\n"
|
|
|
" println!(\"{}\", x);\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/structural/compose-structs.md:73
|
|
|
#, fuzzy
|
|
|
msgid "TODO Why and where you should use the pattern"
|
|
|
msgstr "TODO Perché e dove dovresti usare il modello"
|
|
|
|
|
|
#: src\patterns/structural/compose-structs.md:77
|
|
|
#, fuzzy
|
|
|
msgid "Lets you work around limitations in the borrow checker."
|
|
|
msgstr "Consente di aggirare le limitazioni nel controllo del prestito."
|
|
|
|
|
|
#: src\patterns/structural/compose-structs.md:79
|
|
|
#, fuzzy
|
|
|
msgid "Often produces a better design."
|
|
|
msgstr "Spesso produce un design migliore."
|
|
|
|
|
|
#: src\patterns/structural/compose-structs.md:83
|
|
|
#, fuzzy
|
|
|
msgid "Leads to more verbose code."
|
|
|
msgstr "Porta a un codice più dettagliato."
|
|
|
|
|
|
#: src\patterns/structural/compose-structs.md:85
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Sometimes, the smaller structs are not good abstractions, and so we end up "
|
|
|
"with\n"
|
|
|
"a worse design. That is probably a 'code smell', indicating that the "
|
|
|
"program\n"
|
|
|
"should be refactored in some way."
|
|
|
msgstr ""
|
|
|
"A volte, le strutture più piccole non sono buone astrazioni, e quindi ci "
|
|
|
"ritroviamo\n"
|
|
|
"un design peggiore. Questo è probabilmente un \"odore di codice\", che "
|
|
|
"indica che il programma\n"
|
|
|
"dovrebbe essere rifattorizzato in qualche modo."
|
|
|
|
|
|
#: src\patterns/structural/compose-structs.md:91
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This pattern is not required in languages that don't have a borrow checker, "
|
|
|
"so\n"
|
|
|
"in that sense is unique to Rust. However, making smaller units of "
|
|
|
"functionality\n"
|
|
|
"often leads to cleaner code: a widely acknowledged principle of software\n"
|
|
|
"engineering, independent of the language."
|
|
|
msgstr ""
|
|
|
"Questo modello non è richiesto nelle lingue che non hanno un controllo del "
|
|
|
"prestito, quindi\n"
|
|
|
"in questo senso è unico per Rust. Tuttavia, creando unità di funzionalità "
|
|
|
"più piccole\n"
|
|
|
"spesso porta a un codice più pulito: un principio del software ampiamente "
|
|
|
"riconosciuto\n"
|
|
|
"ingegneria, indipendente dalla lingua."
|
|
|
|
|
|
#: src\patterns/structural/compose-structs.md:96
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This pattern relies on Rust's borrow checker to be able to borrow fields\n"
|
|
|
"independently of each other. In the example, the borrow checker knows that "
|
|
|
"`a.b`\n"
|
|
|
"and `a.c` are distinct and can be borrowed independently, it does not try "
|
|
|
"to\n"
|
|
|
"borrow all of `a`, which would make this pattern useless."
|
|
|
msgstr ""
|
|
|
"Questo modello si basa sul controllo del prestito di Rust per poter prendere "
|
|
|
"in prestito i campi\n"
|
|
|
"indipendentemente l'uno dall'altro. Nell'esempio, il controllo del prestito "
|
|
|
"sa che `a.b`\n"
|
|
|
"e \"a.c\" sono distinti e possono essere presi in prestito "
|
|
|
"indipendentemente, non cerca di farlo\n"
|
|
|
"prendi in prestito tutta la `a`, il che renderebbe questo modello inutile."
|
|
|
|
|
|
#: src\patterns/structural/small-crates.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Prefer small crates"
|
|
|
msgstr "# Preferisci casse piccole"
|
|
|
|
|
|
#: src\patterns/structural/small-crates.md:5
|
|
|
#, fuzzy
|
|
|
msgid "Prefer small crates that do one thing well."
|
|
|
msgstr "Preferisci piccole casse che fanno bene una cosa."
|
|
|
|
|
|
#: src\patterns/structural/small-crates.md:7
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Cargo and crates.io make it easy to add third-party libraries, much more so "
|
|
|
"than\n"
|
|
|
"in say C or C++. Moreover, since packages on crates.io cannot be edited or "
|
|
|
"removed\n"
|
|
|
"after publication, any build that works now should continue to work in the "
|
|
|
"future.\n"
|
|
|
"We should take advantage of this tooling, and use smaller, more fine-grained "
|
|
|
"dependencies."
|
|
|
msgstr ""
|
|
|
"Cargo e crates.io semplificano l'aggiunta di librerie di terze parti, molto "
|
|
|
"più di\n"
|
|
|
"diciamo in C o C++. Inoltre, poiché i pacchetti su crates.io non possono "
|
|
|
"essere modificati o rimossi\n"
|
|
|
"dopo la pubblicazione, qualsiasi build che funziona ora dovrebbe continuare "
|
|
|
"a funzionare in futuro.\n"
|
|
|
"Dovremmo trarre vantaggio da questi strumenti e utilizzare dipendenze più "
|
|
|
"piccole e più granulari."
|
|
|
|
|
|
#: src\patterns/structural/small-crates.md:14
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- Small crates are easier to understand, and encourage more modular code.\n"
|
|
|
"- Crates allow for re-using code between projects.\n"
|
|
|
" For example, the `url` crate was developed as part of the Servo browser "
|
|
|
"engine,\n"
|
|
|
" but has since found wide use outside the project.\n"
|
|
|
"- Since the compilation unit\n"
|
|
|
" of Rust is the crate, splitting a project into multiple crates can allow "
|
|
|
"more of\n"
|
|
|
" the code to be built in parallel."
|
|
|
msgstr ""
|
|
|
"- Le casse piccole sono più facili da capire e incoraggiano un codice più "
|
|
|
"modulare.\n"
|
|
|
"- Le casse consentono di riutilizzare il codice tra i progetti.\n"
|
|
|
" Ad esempio, la cassa `url` è stata sviluppata come parte del motore del "
|
|
|
"browser Servo,\n"
|
|
|
" ma da allora ha trovato ampio utilizzo al di fuori del progetto.\n"
|
|
|
"- Dal momento che l'unità di compilazione\n"
|
|
|
" of Rust è la cassa, la suddivisione di un progetto in più casse può "
|
|
|
"consentirne di più\n"
|
|
|
" il codice da costruire in parallelo."
|
|
|
|
|
|
#: src\patterns/structural/small-crates.md:24
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- This can lead to \"dependency hell\", when a project depends on multiple "
|
|
|
"conflicting\n"
|
|
|
" versions of a crate at the same time. For example, the `url` crate has "
|
|
|
"both versions\n"
|
|
|
" 1.0 and 0.5. Since the `Url` from `url:1.0` and the `Url` from `url:0.5` "
|
|
|
"are\n"
|
|
|
" different types, an HTTP client that uses `url:0.5` would not accept `Url` "
|
|
|
"values\n"
|
|
|
" from a web scraper that uses `url:1.0`.\n"
|
|
|
"- Packages on crates.io are not curated. A crate may be poorly written, "
|
|
|
"have\n"
|
|
|
" unhelpful documentation, or be outright malicious.\n"
|
|
|
"- Two small crates may be less optimized than one large one, since the "
|
|
|
"compiler\n"
|
|
|
" does not perform link-time optimization (LTO) by default."
|
|
|
msgstr ""
|
|
|
"- Questo può portare a \"l'inferno della dipendenza\", quando un progetto "
|
|
|
"dipende da più conflitti\n"
|
|
|
" versioni di una cassa allo stesso tempo. Ad esempio, la cassa `url` ha "
|
|
|
"entrambe le versioni\n"
|
|
|
" 1.0 e 0.5. Poiché \"Url\" da \"url:1.0\" e \"Url\" da \"url:0.5\" sono\n"
|
|
|
" tipi diversi, un client HTTP che utilizza `url:0.5` non accetterebbe i "
|
|
|
"valori `Url`\n"
|
|
|
" da un web scraper che utilizza `url:1.0`.\n"
|
|
|
"- I pacchetti su crates.io non sono curati. Una cassa può essere scritta "
|
|
|
"male, avere\n"
|
|
|
" documentazione inutile o essere apertamente malizioso.\n"
|
|
|
"- Due piccole casse possono essere meno ottimizzate di una grande, poiché il "
|
|
|
"compilatore\n"
|
|
|
" non esegue l'ottimizzazione del tempo di collegamento (LTO) per "
|
|
|
"impostazione predefinita."
|
|
|
|
|
|
#: src\patterns/structural/small-crates.md:36
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The [`ref_slice`](https://crates.io/crates/ref_slice) crate provides "
|
|
|
"functions\n"
|
|
|
"for converting `&T` to `&[T]`."
|
|
|
msgstr ""
|
|
|
"Il crate [`ref_slice`](https://crates.io/crates/ref_slice) fornisce "
|
|
|
"funzioni\n"
|
|
|
"per convertire \"&T\" in \"&[T]\"."
|
|
|
|
|
|
#: src\patterns/structural/small-crates.md:39
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The [`url`](https://crates.io/crates/url) crate provides tools for working "
|
|
|
"with\n"
|
|
|
"URLs."
|
|
|
msgstr ""
|
|
|
"Il crate [`url`](https://crates.io/crates/url) fornisce gli strumenti per "
|
|
|
"lavorare con\n"
|
|
|
"URL."
|
|
|
|
|
|
#: src\patterns/structural/small-crates.md:42
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The [`num_cpus`](https://crates.io/crates/num_cpus) crate provides a "
|
|
|
"function to\n"
|
|
|
"query the number of CPUs on a machine."
|
|
|
msgstr ""
|
|
|
"Il crate [`num_cpus`](https://crates.io/crates/num_cpus) fornisce una "
|
|
|
"funzione per\n"
|
|
|
"interrogare il numero di CPU su una macchina."
|
|
|
|
|
|
#: src\patterns/structural/small-crates.md:47
|
|
|
#, fuzzy
|
|
|
msgid "- [crates.io: The Rust community crate host](https://crates.io/)"
|
|
|
msgstr "- [crates.io: host di casse della community di Rust](https://crates.io/)"
|
|
|
|
|
|
#: src\patterns/structural/unsafe-mods.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Contain unsafety in small modules"
|
|
|
msgstr "# Contenere la sicurezza in piccoli moduli"
|
|
|
|
|
|
#: src\patterns/structural/unsafe-mods.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"If you have `unsafe` code, create the smallest possible module that can "
|
|
|
"uphold\n"
|
|
|
"the needed invariants to build a minimal safe interface upon the unsafety. "
|
|
|
"Embed\n"
|
|
|
"this into a larger module that contains only safe code and presents an "
|
|
|
"ergonomic\n"
|
|
|
"interface. Note that the outer module can contain unsafe functions and "
|
|
|
"methods\n"
|
|
|
"that call directly into the unsafe code. Users may use this to gain speed "
|
|
|
"benefits."
|
|
|
msgstr ""
|
|
|
"Se hai un codice \"non sicuro\", crea il modulo più piccolo possibile che "
|
|
|
"possa sostenere\n"
|
|
|
"gli invarianti necessari per costruire un'interfaccia sicura minima "
|
|
|
"sull'insicurezza. Incorporare\n"
|
|
|
"questo in un modulo più grande che contiene solo codice sicuro e presenta "
|
|
|
"un'ergonomia\n"
|
|
|
"interfaccia. Si noti che il modulo esterno può contenere funzioni e metodi "
|
|
|
"non sicuri\n"
|
|
|
"che chiamano direttamente nel codice non sicuro. Gli utenti possono "
|
|
|
"utilizzarlo per ottenere vantaggi in termini di velocità."
|
|
|
|
|
|
#: src\patterns/structural/unsafe-mods.md:13
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- This restricts the unsafe code that must be audited\n"
|
|
|
"- Writing the outer module is much easier, since you can count on the "
|
|
|
"guarantees\n"
|
|
|
" of the inner module"
|
|
|
msgstr ""
|
|
|
"- Questo limita il codice non sicuro che deve essere controllato\n"
|
|
|
"- Scrivere il modulo esterno è molto più semplice, dato che puoi contare "
|
|
|
"sulle garanzie\n"
|
|
|
" del modulo interno"
|
|
|
|
|
|
#: src\patterns/structural/unsafe-mods.md:19
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- Sometimes, it may be hard to find a suitable interface.\n"
|
|
|
"- The abstraction may introduce inefficiencies."
|
|
|
msgstr ""
|
|
|
"- A volte può essere difficile trovare un'interfaccia adatta.\n"
|
|
|
"- L'astrazione può introdurre inefficienze."
|
|
|
|
|
|
#: src\patterns/structural/unsafe-mods.md:24
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- The [`toolshed`](https://docs.rs/toolshed) crate contains its unsafe "
|
|
|
"operations\n"
|
|
|
" in submodules, presenting a safe interface to users.\n"
|
|
|
"- `std`'s `String` class is a wrapper over `Vec<u8>` with the added "
|
|
|
"invariant\n"
|
|
|
" that the contents must be valid UTF-8. The operations on `String` ensure "
|
|
|
"this\n"
|
|
|
" behavior.\n"
|
|
|
" However, users have the option of using an `unsafe` method to create a "
|
|
|
"`String`,\n"
|
|
|
" in which case the onus is on them to guarantee the validity of the "
|
|
|
"contents."
|
|
|
msgstr ""
|
|
|
"- Il crate [`toolshed`](https://docs.rs/toolshed) contiene le sue operazioni "
|
|
|
"non sicure\n"
|
|
|
" nei sottomoduli, presentando un'interfaccia sicura per gli utenti.\n"
|
|
|
"- La classe `String` di `std` è un wrapper su `Vec<u8>` con l'aggiunta "
|
|
|
"dell'invariante\n"
|
|
|
" che i contenuti devono essere UTF-8 validi. Le operazioni su \"Stringa\" "
|
|
|
"assicurano questo\n"
|
|
|
" comportamento.\n"
|
|
|
" Tuttavia, gli utenti hanno la possibilità di utilizzare un metodo \"non "
|
|
|
"sicuro\" per creare una \"Stringa\",\n"
|
|
|
" in tal caso spetta a loro l'onere di garantire la validità dei contenuti."
|
|
|
|
|
|
#: src\patterns/structural/unsafe-mods.md:34
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [Ralf Jung's Blog about invariants in unsafe "
|
|
|
"code](https://www.ralfj.de/blog/2018/08/22/two-kinds-of-invariants.html)"
|
|
|
msgstr ""
|
|
|
"- [Blog di Ralf Jung sulle invarianti nel codice non "
|
|
|
"sicuro](https://www.ralfj.de/blog/2018/08/22/two-kinds-of-invariants.html)"
|
|
|
|
|
|
#: src\patterns/ffi/intro.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# FFI Patterns"
|
|
|
msgstr "# Modelli FFI"
|
|
|
|
|
|
#: src\patterns/ffi/intro.md:3
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Writing FFI code is an entire course in itself.\n"
|
|
|
"However, there are several idioms here that can act as pointers, and avoid "
|
|
|
"traps\n"
|
|
|
"for inexperienced users of unsafe Rust."
|
|
|
msgstr ""
|
|
|
"Scrivere il codice FFI è un intero corso in sé.\n"
|
|
|
"Tuttavia, ci sono diversi idiomi qui che possono fungere da puntatori ed "
|
|
|
"evitare trappole\n"
|
|
|
"per utenti inesperti di Rust non sicuro."
|
|
|
|
|
|
#: src\patterns/ffi/intro.md:7
|
|
|
#, fuzzy
|
|
|
msgid "This section contains design patterns that may be useful when doing FFI."
|
|
|
msgstr ""
|
|
|
"Questa sezione contiene modelli di progettazione che possono essere utili "
|
|
|
"durante l'esecuzione di FFI."
|
|
|
|
|
|
#: src\patterns/ffi/intro.md:9
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"1. [Object-Based API](./export.md) design that has good memory safety "
|
|
|
"characteristics,\n"
|
|
|
" and a clean boundary of what is safe and what is unsafe\n"
|
|
|
"\n"
|
|
|
"2. [Type Consolidation into Wrappers](./wrappers.md) - group multiple Rust "
|
|
|
"types\n"
|
|
|
" together into an opaque \"object\""
|
|
|
msgstr ""
|
|
|
"1. [API basata su oggetti](./export.md) design con buone caratteristiche di "
|
|
|
"sicurezza della memoria,\n"
|
|
|
" e un confine netto di ciò che è sicuro e ciò che non lo è\n"
|
|
|
"\n"
|
|
|
"2. [Type Consolidation into Wrappers](./wrappers.md) - raggruppa più tipi di "
|
|
|
"Rust\n"
|
|
|
" insieme in un \"oggetto\" opaco"
|
|
|
|
|
|
#: src\patterns/ffi/export.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Object-Based APIs"
|
|
|
msgstr "# API basate su oggetti"
|
|
|
|
|
|
#: src\patterns/ffi/export.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"When designing APIs in Rust which are exposed to other languages, there are "
|
|
|
"some\n"
|
|
|
"important design principles which are contrary to normal Rust API design:"
|
|
|
msgstr ""
|
|
|
"Quando si progettano API in Rust che sono esposte ad altri linguaggi, ce ne "
|
|
|
"sono alcune\n"
|
|
|
"importanti principi di progettazione che sono contrari al normale design "
|
|
|
"dell'API di Rust:"
|
|
|
|
|
|
#: src\patterns/ffi/export.md:8
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"1. All Encapsulated types should be _owned_ by Rust, _managed_ by the user,\n"
|
|
|
" and _opaque_.\n"
|
|
|
"2. All Transactional data types should be _owned_ by the user, and "
|
|
|
"_transparent_.\n"
|
|
|
"3. All library behavior should be functions acting upon Encapsulated types.\n"
|
|
|
"4. All library behavior should be encapsulated into types not based on "
|
|
|
"structure,\n"
|
|
|
" but _provenance/lifetime_."
|
|
|
msgstr ""
|
|
|
"1. Tutti i tipi Encapsulated dovrebbero essere _posseduti_ da Rust, "
|
|
|
"_gestiti_ dall'utente,\n"
|
|
|
" e _opaco_.\n"
|
|
|
"2. Tutti i tipi di dati transazionali devono essere _di proprietà_ "
|
|
|
"dell'utente e _trasparenti_.\n"
|
|
|
"3. Tutti i comportamenti delle librerie dovrebbero essere funzioni che "
|
|
|
"agiscono sui tipi incapsulati.\n"
|
|
|
"4. Tutto il comportamento della libreria dovrebbe essere incapsulato in tipi "
|
|
|
"non basati sulla struttura,\n"
|
|
|
" ma _provenienza/vita_."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:17
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Rust has built-in FFI support to other languages.\n"
|
|
|
"It does this by providing a way for crate authors to provide C-compatible "
|
|
|
"APIs\n"
|
|
|
"through different ABIs (though that is unimportant to this practice)."
|
|
|
msgstr ""
|
|
|
"Rust ha il supporto FFI integrato per altre lingue.\n"
|
|
|
"Lo fa fornendo agli autori di crate un modo per fornire API compatibili con "
|
|
|
"C\n"
|
|
|
"attraverso diversi ABI (sebbene ciò non sia importante per questa pratica)."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:21
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Well-designed Rust FFI follows C API design principles, while compromising "
|
|
|
"the\n"
|
|
|
"design in Rust as little as possible. There are three goals with any foreign "
|
|
|
"API:"
|
|
|
msgstr ""
|
|
|
"Rust FFI ben progettato segue i principi di progettazione dell'API C, "
|
|
|
"compromettendo al contempo il\n"
|
|
|
"progettare in Rust il meno possibile. Ci sono tre obiettivi con qualsiasi "
|
|
|
"API esterna:"
|
|
|
|
|
|
#: src\patterns/ffi/export.md:24
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"1. Make it easy to use in the target language.\n"
|
|
|
"2. Avoid the API dictating internal unsafety on the Rust side as much as "
|
|
|
"possible.\n"
|
|
|
"3. Keep the potential for memory unsafety and Rust `undefined behaviour` as "
|
|
|
"small\n"
|
|
|
" as possible."
|
|
|
msgstr ""
|
|
|
"1. Rendilo facile da usare nella lingua di destinazione.\n"
|
|
|
"2. Evita il più possibile che l'API determini l'insicurezza interna sul lato "
|
|
|
"Rust.\n"
|
|
|
"3. Mantenere basso il potenziale di insicurezza della memoria e di "
|
|
|
"\"comportamento indefinito\" di Rust\n"
|
|
|
" possibile."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:29
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Rust code must trust the memory safety of the foreign language beyond a "
|
|
|
"certain\n"
|
|
|
"point. However, every bit of `unsafe` code on the Rust side is an "
|
|
|
"opportunity for\n"
|
|
|
"bugs, or to exacerbate `undefined behaviour`."
|
|
|
msgstr ""
|
|
|
"Il codice Rust deve fidarsi della sicurezza della memoria della lingua "
|
|
|
"straniera oltre un certo\n"
|
|
|
"punto. Tuttavia, ogni bit di codice \"non sicuro\" sul lato Rust è "
|
|
|
"un'opportunità per\n"
|
|
|
"bug o per esacerbare il `comportamento indefinito`."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:33
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"For example, if a pointer provenance is wrong, that may be a segfault due "
|
|
|
"to\n"
|
|
|
"invalid memory access. But if it is manipulated by unsafe code, it could "
|
|
|
"become\n"
|
|
|
"full-blown heap corruption."
|
|
|
msgstr ""
|
|
|
"Ad esempio, se la provenienza di un puntatore è errata, potrebbe trattarsi "
|
|
|
"di un segfault dovuto a\n"
|
|
|
"accesso alla memoria non valido. Ma se viene manipolato da codice non "
|
|
|
"sicuro, potrebbe diventarlo\n"
|
|
|
"corruzione completa dell'heap."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:37
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The Object-Based API design allows for writing shims that have good memory "
|
|
|
"safety\n"
|
|
|
"characteristics, and a clean boundary of what is safe and what is `unsafe`."
|
|
|
msgstr ""
|
|
|
"La progettazione dell'API basata su oggetti consente di scrivere shim con "
|
|
|
"una buona sicurezza della memoria\n"
|
|
|
"caratteristiche e un confine netto tra ciò che è sicuro e ciò che è \"non "
|
|
|
"sicuro\"."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:42
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The POSIX standard defines the API to access an on-file database, known as "
|
|
|
"[DBM](https://web.archive.org/web/20210105035602/https://www.mankier.com/0p/ndbm.h).\n"
|
|
|
"It is an excellent example of an \"object-based\" API."
|
|
|
msgstr ""
|
|
|
"Lo standard POSIX definisce l'API per accedere a un database su file, noto "
|
|
|
"come "
|
|
|
"[DBM](https://web.archive.org/web/20210105035602/https://www.mankier.com/0p/ndbm.h) "
|
|
|
".\n"
|
|
|
"È un eccellente esempio di API \"basata su oggetti\"."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:45
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Here is the definition in C, which hopefully should be easy to read for "
|
|
|
"those\n"
|
|
|
"involved in FFI. The commentary below should help explain it for those who\n"
|
|
|
"miss the subtleties."
|
|
|
msgstr ""
|
|
|
"Ecco la definizione in C, che si spera dovrebbe essere facile da leggere per "
|
|
|
"quelli\n"
|
|
|
"coinvolti in FFI. Il commento qui sotto dovrebbe aiutare a spiegarlo per "
|
|
|
"coloro che\n"
|
|
|
"perdere le sottigliezze."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:49
|
|
|
msgid ""
|
|
|
"```C\n"
|
|
|
"struct DBM;\n"
|
|
|
"typedef struct { void *dptr, size_t dsize } datum;\n"
|
|
|
"\n"
|
|
|
"int dbm_clearerr(DBM *);\n"
|
|
|
"void dbm_close(DBM *);\n"
|
|
|
"int dbm_delete(DBM *, datum);\n"
|
|
|
"int dbm_error(DBM *);\n"
|
|
|
"datum dbm_fetch(DBM *, datum);\n"
|
|
|
"datum dbm_firstkey(DBM *);\n"
|
|
|
"datum dbm_nextkey(DBM *);\n"
|
|
|
"DBM *dbm_open(const char *, int, mode_t);\n"
|
|
|
"int dbm_store(DBM *, datum, datum, int);\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/ffi/export.md:64
|
|
|
#, fuzzy
|
|
|
msgid "This API defines two types: `DBM` and `datum`."
|
|
|
msgstr "Questa API definisce due tipi: `DBM` e `datum`."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:66
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The `DBM` type was called an \"encapsulated\" type above.\n"
|
|
|
"It is designed to contain internal state, and acts as an entry point for "
|
|
|
"the\n"
|
|
|
"library's behavior."
|
|
|
msgstr ""
|
|
|
"Il tipo `DBM` è stato chiamato un tipo \"incapsulato\" sopra.\n"
|
|
|
"È progettato per contenere lo stato interno e funge da punto di ingresso per "
|
|
|
"il\n"
|
|
|
"comportamento della biblioteca"
|
|
|
|
|
|
#: src\patterns/ffi/export.md:70
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"It is completely opaque to the user, who cannot create a `DBM` themselves "
|
|
|
"since\n"
|
|
|
"they don't know its size or layout. Instead, they must call `dbm_open`, and "
|
|
|
"that\n"
|
|
|
"only gives them _a pointer to one_."
|
|
|
msgstr ""
|
|
|
"È completamente opaco per l'utente, che da allora non può creare un "
|
|
|
"\"DBM\".\n"
|
|
|
"non ne conoscono le dimensioni o il layout. Invece, devono chiamare "
|
|
|
"\"dbm_open\" e così via\n"
|
|
|
"dà loro solo _un puntatore a uno_."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:74
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This means all `DBM`s are \"owned\" by the library in a Rust sense.\n"
|
|
|
"The internal state of unknown size is kept in memory controlled by the "
|
|
|
"library,\n"
|
|
|
"not the user. The user can only manage its life cycle with `open` and "
|
|
|
"`close`,\n"
|
|
|
"and perform operations on it with the other functions."
|
|
|
msgstr ""
|
|
|
"Ciò significa che tutti i `DBM` sono \"di proprietà\" della libreria in un "
|
|
|
"certo senso Rust.\n"
|
|
|
"Lo stato interno di dimensioni sconosciute viene mantenuto in memoria "
|
|
|
"controllato dalla libreria,\n"
|
|
|
"non l'utente. L'utente può gestire il suo ciclo di vita solo con `apri` e "
|
|
|
"`chiudi`,\n"
|
|
|
"ed eseguire operazioni su di esso con le altre funzioni."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:79
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The `datum` type was called a \"transactional\" type above.\n"
|
|
|
"It is designed to facilitate the exchange of information between the library "
|
|
|
"and\n"
|
|
|
"its user."
|
|
|
msgstr ""
|
|
|
"Il tipo `datum` era soprannominato tipo \"transazionale\".\n"
|
|
|
"È progettato per facilitare lo scambio di informazioni tra la biblioteca e\n"
|
|
|
"suo utente."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:83
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The database is designed to store \"unstructured data\", with no pre-defined "
|
|
|
"length\n"
|
|
|
"or meaning. As a result, the `datum` is the C equivalent of a Rust slice: a "
|
|
|
"bunch\n"
|
|
|
"of bytes, and a count of how many there are. The main difference is that "
|
|
|
"there is\n"
|
|
|
"no type information, which is what `void` indicates."
|
|
|
msgstr ""
|
|
|
"Il database è progettato per memorizzare \"dati non strutturati\", senza una "
|
|
|
"lunghezza predefinita\n"
|
|
|
"o significato. Di conseguenza, il \"dato\" è l'equivalente in C di una fetta "
|
|
|
"di ruggine: un mucchio\n"
|
|
|
"di byte e un conteggio di quanti ce ne sono. La differenza principale è che "
|
|
|
"c'è\n"
|
|
|
"nessuna informazione sul tipo, che è ciò che indica \"void\"."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:88
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Keep in mind that this header is written from the library's point of view.\n"
|
|
|
"The user likely has some type they are using, which has a known size.\n"
|
|
|
"But the library does not care, and by the rules of C casting, any type "
|
|
|
"behind a\n"
|
|
|
"pointer can be cast to `void`."
|
|
|
msgstr ""
|
|
|
"Tieni presente che questa intestazione è scritta dal punto di vista della "
|
|
|
"biblioteca.\n"
|
|
|
"L'utente probabilmente ha un tipo che sta usando, che ha una dimensione "
|
|
|
"nota.\n"
|
|
|
"Ma alla libreria non interessa, e secondo le regole del casting C, qualsiasi "
|
|
|
"tipo dietro a\n"
|
|
|
"il puntatore può essere lanciato su \"void\"."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:93
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"As noted earlier, this type is _transparent_ to the user. But also, this "
|
|
|
"type is\n"
|
|
|
"_owned_ by the user.\n"
|
|
|
"This has subtle ramifications, due to that pointer inside it.\n"
|
|
|
"The question is, who owns the memory that pointer points to?"
|
|
|
msgstr ""
|
|
|
"Come notato in precedenza, questo tipo è _trasparente_ per l'utente. Ma "
|
|
|
"anche questo tipo lo è\n"
|
|
|
"_posseduto_ dall'utente.\n"
|
|
|
"Questo ha sottili ramificazioni, a causa di quel puntatore al suo interno.\n"
|
|
|
"La domanda è: chi possiede la memoria a cui punta il puntatore?"
|
|
|
|
|
|
#: src\patterns/ffi/export.md:98
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The answer for best memory safety is, \"the user\".\n"
|
|
|
"But in cases such as retrieving a value, the user does not know how to "
|
|
|
"allocate\n"
|
|
|
"it correctly (since they don't know how long the value is). In this case, "
|
|
|
"the library\n"
|
|
|
"code is expected to use the heap that the user has access to -- such as the "
|
|
|
"C library\n"
|
|
|
"`malloc` and `free` -- and then _transfer ownership_ in the Rust sense."
|
|
|
msgstr ""
|
|
|
"La risposta per la migliore sicurezza della memoria è \"l'utente\".\n"
|
|
|
"Ma in casi come il recupero di un valore, l'utente non sa come allocare\n"
|
|
|
"correttamente (poiché non sanno quanto è lungo il valore). In questo caso, "
|
|
|
"la biblioteca\n"
|
|
|
"il codice dovrebbe utilizzare l'heap a cui l'utente ha accesso, come la "
|
|
|
"libreria C\n"
|
|
|
"`malloc` e `free` -- e poi _trasferire la proprietà_ nel senso di Rust."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:104
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This may all seem speculative, but this is what a pointer means in C.\n"
|
|
|
"It means the same thing as Rust: \"user defined lifetime.\"\n"
|
|
|
"The user of the library needs to read the documentation in order to use it "
|
|
|
"correctly.\n"
|
|
|
"That said, there are some decisions that have fewer or greater consequences "
|
|
|
"if users\n"
|
|
|
"do it wrong. Minimizing those are what this best practice is about, and the "
|
|
|
"key\n"
|
|
|
"is to _transfer ownership of everything that is transparent_."
|
|
|
msgstr ""
|
|
|
"Tutto questo può sembrare speculativo, ma questo è ciò che significa un "
|
|
|
"puntatore in C.\n"
|
|
|
"Significa la stessa cosa di Rust: \"durata definita dall'utente\".\n"
|
|
|
"L'utente della libreria deve leggere la documentazione per poterla "
|
|
|
"utilizzare correttamente.\n"
|
|
|
"Detto questo, ci sono alcune decisioni che hanno conseguenze minori o "
|
|
|
"maggiori se gli utenti\n"
|
|
|
"fallo male. Ridurli al minimo è ciò di cui tratta questa best practice e la "
|
|
|
"chiave\n"
|
|
|
"è _trasferire la proprietà di tutto ciò che è trasparente_."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:113
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This minimizes the number of memory safety guarantees the user must uphold "
|
|
|
"to a\n"
|
|
|
"relatively small number:"
|
|
|
msgstr ""
|
|
|
"Ciò riduce al minimo il numero di garanzie di sicurezza della memoria che "
|
|
|
"l'utente deve mantenere a\n"
|
|
|
"numero relativamente piccolo:"
|
|
|
|
|
|
#: src\patterns/ffi/export.md:116
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"1. Do not call any function with a pointer not returned by `dbm_open` "
|
|
|
"(invalid\n"
|
|
|
" access or corruption).\n"
|
|
|
"2. Do not call any function on a pointer after close (use after free).\n"
|
|
|
"3. The `dptr` on any `datum` must be `NULL`, or point to a valid slice of "
|
|
|
"memory\n"
|
|
|
" at the advertised length."
|
|
|
msgstr ""
|
|
|
"1. Non chiamare alcuna funzione con un puntatore non restituito da "
|
|
|
"`dbm_open` (invalid\n"
|
|
|
" accesso o corruzione).\n"
|
|
|
"2. Non chiamare alcuna funzione su un puntatore dopo la chiusura (usa dopo "
|
|
|
"free).\n"
|
|
|
"3. Il `dptr` su qualsiasi `dato` deve essere `NULL` o puntare a una fetta di "
|
|
|
"memoria valida\n"
|
|
|
" alla lunghezza pubblicizzata."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:122
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"In addition, it avoids a lot of pointer provenance issues.\n"
|
|
|
"To understand why, let us consider an alternative in some depth: key "
|
|
|
"iteration."
|
|
|
msgstr ""
|
|
|
"Inoltre, evita molti problemi di provenienza del puntatore.\n"
|
|
|
"Per capire perché, consideriamo un'alternativa in modo approfondito: "
|
|
|
"l'iterazione chiave."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:125
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Rust is well known for its iterators.\n"
|
|
|
"When implementing one, the programmer makes a separate type with a bounded "
|
|
|
"lifetime\n"
|
|
|
"to its owner, and implements the `Iterator` trait."
|
|
|
msgstr ""
|
|
|
"Rust è ben noto per i suoi iteratori.\n"
|
|
|
"Quando ne implementa uno, il programmatore crea un tipo separato con una "
|
|
|
"durata limitata\n"
|
|
|
"al suo proprietario e implementa il tratto `Iterator`."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:129
|
|
|
#, fuzzy
|
|
|
msgid "Here is how iteration would be done in Rust for `DBM`:"
|
|
|
msgstr "Ecco come verrebbe eseguita l'iterazione in Rust per `DBM`:"
|
|
|
|
|
|
#: src\patterns/ffi/export.md:131
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"struct Dbm { ... }\n"
|
|
|
"\n"
|
|
|
"impl Dbm {\n"
|
|
|
" /* ... */\n"
|
|
|
" pub fn keys<'it>(&'it self) -> DbmKeysIter<'it> { ... }\n"
|
|
|
" /* ... */\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"struct DbmKeysIter<'it> {\n"
|
|
|
" owner: &'it Dbm,\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"impl<'it> Iterator for DbmKeysIter<'it> { ... }\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/ffi/export.md:147
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This is clean, idiomatic, and safe. thanks to Rust's guarantees.\n"
|
|
|
"However, consider what a straightforward API translation would look like:"
|
|
|
msgstr ""
|
|
|
"Questo è pulito, idiomatico e sicuro. grazie alle garanzie di Rust.\n"
|
|
|
"Tuttavia, considera come sarebbe una semplice traduzione API:"
|
|
|
|
|
|
#: src\patterns/ffi/export.md:150
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"#[no_mangle]\n"
|
|
|
"pub extern \"C\" fn dbm_iter_new(owner: *const Dbm) -> *mut DbmKeysIter {\n"
|
|
|
" // THIS API IS A BAD IDEA! For real applications, use object-based "
|
|
|
"design instead.\n"
|
|
|
"}\n"
|
|
|
"#[no_mangle]\n"
|
|
|
"pub extern \"C\" fn dbm_iter_next(\n"
|
|
|
" iter: *mut DbmKeysIter,\n"
|
|
|
" key_out: *const datum\n"
|
|
|
") -> libc::c_int {\n"
|
|
|
" // THIS API IS A BAD IDEA! For real applications, use object-based "
|
|
|
"design instead.\n"
|
|
|
"}\n"
|
|
|
"#[no_mangle]\n"
|
|
|
"pub extern \"C\" fn dbm_iter_del(*mut DbmKeysIter) {\n"
|
|
|
" // THIS API IS A BAD IDEA! For real applications, use object-based "
|
|
|
"design instead.\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/ffi/export.md:168
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This API loses a key piece of information: the lifetime of the iterator must "
|
|
|
"not\n"
|
|
|
"exceed the lifetime of the `Dbm` object that owns it. A user of the library "
|
|
|
"could\n"
|
|
|
"use it in a way which causes the iterator to outlive the data it is "
|
|
|
"iterating on,\n"
|
|
|
"resulting in reading uninitialized memory."
|
|
|
msgstr ""
|
|
|
"Questa API perde un'informazione chiave: la durata dell'iteratore no\n"
|
|
|
"superare la durata dell'oggetto `Dbm` che lo possiede. Un utente della "
|
|
|
"biblioteca potrebbe\n"
|
|
|
"usalo in un modo che fa sì che l'iteratore sopravviva ai dati su cui sta "
|
|
|
"iterando,\n"
|
|
|
"con conseguente lettura della memoria non inizializzata."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:173
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This example written in C contains a bug that will be explained afterwards:"
|
|
|
msgstr ""
|
|
|
"Questo esempio scritto in C contiene un bug che verrà spiegato in seguito:"
|
|
|
|
|
|
#: src\patterns/ffi/export.md:175
|
|
|
msgid ""
|
|
|
"```C\n"
|
|
|
"int count_key_sizes(DBM *db) {\n"
|
|
|
" // DO NOT USE THIS FUNCTION. IT HAS A SUBTLE BUT SERIOUS BUG!\n"
|
|
|
" datum key;\n"
|
|
|
" int len = 0;\n"
|
|
|
"\n"
|
|
|
" if (!dbm_iter_new(db)) {\n"
|
|
|
" dbm_close(db);\n"
|
|
|
" return -1;\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" int l;\n"
|
|
|
" while ((l = dbm_iter_next(owner, &key)) >= 0) { // an error is indicated "
|
|
|
"by -1\n"
|
|
|
" free(key.dptr);\n"
|
|
|
" len += key.dsize;\n"
|
|
|
" if (l == 0) { // end of the iterator\n"
|
|
|
" dbm_close(owner);\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
" if l >= 0 {\n"
|
|
|
" return -1;\n"
|
|
|
" } else {\n"
|
|
|
" return len;\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/ffi/export.md:202
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This bug is a classic. Here's what happens when the iterator returns the\n"
|
|
|
"end-of-iteration marker:"
|
|
|
msgstr ""
|
|
|
"Questo bug è un classico. Ecco cosa succede quando l'iteratore restituisce "
|
|
|
"il\n"
|
|
|
"marcatore di fine iterazione:"
|
|
|
|
|
|
#: src\patterns/ffi/export.md:205
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"1. The loop condition sets `l` to zero, and enters the loop because `0 >= "
|
|
|
"0`.\n"
|
|
|
"2. The length is incremented, in this case by zero.\n"
|
|
|
"3. The if statement is true, so the database is closed. There should be a "
|
|
|
"break\n"
|
|
|
" statement here.\n"
|
|
|
"4. The loop condition executes again, causing a `next` call on the closed "
|
|
|
"object."
|
|
|
msgstr ""
|
|
|
"1. La condizione del ciclo imposta \"l\" su zero ed entra nel ciclo perché "
|
|
|
"\"0 >= 0\".\n"
|
|
|
"2. La lunghezza viene incrementata, in questo caso di zero.\n"
|
|
|
"3. L'istruzione if è vera, quindi il database è chiuso. Dovrebbe esserci una "
|
|
|
"pausa\n"
|
|
|
" dichiarazione qui.\n"
|
|
|
"4. La condizione del ciclo viene eseguita di nuovo, causando una chiamata "
|
|
|
"`next` sull'oggetto chiuso."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:211
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The worst part about this bug?\n"
|
|
|
"If the Rust implementation was careful, this code will work most of the "
|
|
|
"time!\n"
|
|
|
"If the memory for the `Dbm` object is not immediately reused, an internal "
|
|
|
"check\n"
|
|
|
"will almost certainly fail, resulting in the iterator returning a `-1` "
|
|
|
"indicating\n"
|
|
|
"an error. But occasionally, it will cause a segmentation fault, or even "
|
|
|
"worse,\n"
|
|
|
"nonsensical memory corruption!"
|
|
|
msgstr ""
|
|
|
"La parte peggiore di questo bug?\n"
|
|
|
"Se l'implementazione di Rust è stata attenta, questo codice funzionerà per "
|
|
|
"la maggior parte del tempo!\n"
|
|
|
"Se la memoria per l'oggetto `Dbm` non viene riutilizzata immediatamente, un "
|
|
|
"controllo interno\n"
|
|
|
"quasi sicuramente fallirà, con il risultato che l'iteratore restituirà un "
|
|
|
"`-1` che indica\n"
|
|
|
"un errore. Ma occasionalmente, causerà un errore di segmentazione o, peggio "
|
|
|
"ancora,\n"
|
|
|
"corruzione della memoria senza senso!"
|
|
|
|
|
|
#: src\patterns/ffi/export.md:218
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"None of this can be avoided by Rust.\n"
|
|
|
"From its perspective, it put those objects on its heap, returned pointers to "
|
|
|
"them,\n"
|
|
|
"and gave up control of their lifetimes. The C code simply must \"play nice\"."
|
|
|
msgstr ""
|
|
|
"Niente di tutto questo può essere evitato da Rust.\n"
|
|
|
"Dal suo punto di vista, ha messo quegli oggetti nel suo heap, ha restituito "
|
|
|
"loro dei puntatori,\n"
|
|
|
"e ha rinunciato al controllo delle loro vite. Il codice C deve semplicemente "
|
|
|
"\"giocare bene\"."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:222
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The programmer must read and understand the API documentation.\n"
|
|
|
"While some consider that par for the course in C, a good API design can "
|
|
|
"mitigate\n"
|
|
|
"this risk. The POSIX API for `DBM` did this by _consolidating the ownership_ "
|
|
|
"of\n"
|
|
|
"the iterator with its parent:"
|
|
|
msgstr ""
|
|
|
"Il programmatore deve leggere e comprendere la documentazione dell'API.\n"
|
|
|
"Sebbene alcuni considerino la norma per il corso in C, una buona "
|
|
|
"progettazione dell'API può mitigare\n"
|
|
|
"questo rischio. L'API POSIX per `DBM` ha fatto questo _consolidando la "
|
|
|
"proprietà_ di\n"
|
|
|
"l'iteratore con il suo genitore:"
|
|
|
|
|
|
#: src\patterns/ffi/export.md:227
|
|
|
msgid ""
|
|
|
"```C\n"
|
|
|
"datum dbm_firstkey(DBM *);\n"
|
|
|
"datum dbm_nextkey(DBM *);\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/ffi/export.md:232
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Thus, all the lifetimes were bound together, and such unsafety was prevented."
|
|
|
msgstr ""
|
|
|
"Così, tutte le vite sono state legate insieme e tale insicurezza è stata "
|
|
|
"prevenuta."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:236
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"However, this design choice also has a number of drawbacks, which should be\n"
|
|
|
"considered as well."
|
|
|
msgstr ""
|
|
|
"Tuttavia, questa scelta progettuale presenta anche una serie di "
|
|
|
"inconvenienti, che dovrebbero essere\n"
|
|
|
"considerato pure."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:239
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"First, the API itself becomes less expressive.\n"
|
|
|
"With POSIX DBM, there is only one iterator per object, and every call "
|
|
|
"changes\n"
|
|
|
"its state. This is much more restrictive than iterators in almost any "
|
|
|
"language,\n"
|
|
|
"even though it is safe. Perhaps with other related objects, whose lifetimes "
|
|
|
"are\n"
|
|
|
"less hierarchical, this limitation is more of a cost than the safety."
|
|
|
msgstr ""
|
|
|
"Innanzitutto, l'API stessa diventa meno espressiva.\n"
|
|
|
"Con POSIX DBM, esiste un solo iteratore per oggetto e ogni chiamata cambia\n"
|
|
|
"il suo stato. Questo è molto più restrittivo degli iteratori in quasi tutte "
|
|
|
"le lingue,\n"
|
|
|
"anche se è sicuro. Forse con altri oggetti correlati, le cui vite sono\n"
|
|
|
"meno gerarchica, questa limitazione è più un costo che la sicurezza."
|
|
|
|
|
|
#: src\patterns/ffi/export.md:245
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Second, depending on the relationships of the API's parts, significant "
|
|
|
"design effort\n"
|
|
|
"may be involved. Many of the easier design points have other patterns "
|
|
|
"associated\n"
|
|
|
"with them:"
|
|
|
msgstr ""
|
|
|
"In secondo luogo, a seconda delle relazioni tra le parti dell'API, uno "
|
|
|
"sforzo di progettazione significativo\n"
|
|
|
"può essere coinvolto. Molti dei punti di progettazione più semplici hanno "
|
|
|
"altri modelli associati\n"
|
|
|
"con loro:"
|
|
|
|
|
|
#: src\patterns/ffi/export.md:249
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [Wrapper Type Consolidation](./wrappers.md) groups multiple Rust types "
|
|
|
"together\n"
|
|
|
" into an opaque \"object\"\n"
|
|
|
"\n"
|
|
|
"- [FFI Error Passing](../../idioms/ffi/errors.md) explains error handling "
|
|
|
"with integer\n"
|
|
|
" codes and sentinel return values (such as `NULL` pointers)\n"
|
|
|
"\n"
|
|
|
"- [Accepting Foreign Strings](../../idioms/ffi/accepting-strings.md) allows "
|
|
|
"accepting\n"
|
|
|
" strings with minimal unsafe code, and is easier to get right than\n"
|
|
|
" [Passing Strings to FFI](../../idioms/ffi/passing-strings.md)"
|
|
|
msgstr ""
|
|
|
"- [Consolidamento del tipo di wrapper](./wrappers.md) raggruppa più tipi di "
|
|
|
"ruggine insieme\n"
|
|
|
" in un \"oggetto\" opaco\n"
|
|
|
"\n"
|
|
|
"- [FFI Error Passing](../../idioms/ffi/errors.md) spiega la gestione degli "
|
|
|
"errori con numeri interi\n"
|
|
|
" codici e valori di ritorno sentinella (come i puntatori `NULL`)\n"
|
|
|
"\n"
|
|
|
"- [Accettare stringhe esterne](../../idioms/ffi/accepting-strings.md) "
|
|
|
"consente di accettare\n"
|
|
|
" stringhe con codice non sicuro minimo ed è più facile da ottenere rispetto "
|
|
|
"a\n"
|
|
|
" [Passaggio di stringhe a FFI](../../idioms/ffi/passing-strings.md)"
|
|
|
|
|
|
#: src\patterns/ffi/export.md:259
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"However, not every API can be done this way.\n"
|
|
|
"It is up to the best judgement of the programmer as to who their audience is."
|
|
|
msgstr ""
|
|
|
"Tuttavia, non tutte le API possono essere eseguite in questo modo.\n"
|
|
|
"Spetta al miglior giudizio del programmatore stabilire chi sia il suo "
|
|
|
"pubblico."
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Type Consolidation into Wrappers"
|
|
|
msgstr "# Digitare Consolidation into Wrapper"
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This pattern is designed to allow gracefully handling multiple related "
|
|
|
"types,\n"
|
|
|
"while minimizing the surface area for memory unsafety."
|
|
|
msgstr ""
|
|
|
"Questo modello è progettato per consentire di gestire con garbo più tipi "
|
|
|
"correlati,\n"
|
|
|
"riducendo al minimo la superficie per l'insicurezza della memoria."
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:8
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"One of the cornerstones of Rust's aliasing rules is lifetimes.\n"
|
|
|
"This ensures that many patterns of access between types can be memory safe,\n"
|
|
|
"data race safety included."
|
|
|
msgstr ""
|
|
|
"Uno dei capisaldi delle regole di aliasing di Rust sono le vite.\n"
|
|
|
"Ciò garantisce che molti modelli di accesso tra i tipi possano essere sicuri "
|
|
|
"per la memoria,\n"
|
|
|
"sicurezza della gara di dati inclusa."
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:12
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"However, when Rust types are exported to other languages, they are usually "
|
|
|
"transformed\n"
|
|
|
"into pointers. In Rust, a pointer means \"the user manages the lifetime of "
|
|
|
"the pointee.\"\n"
|
|
|
"It is their responsibility to avoid memory unsafety."
|
|
|
msgstr ""
|
|
|
"Tuttavia, quando i tipi di Rust vengono esportati in altri linguaggi, di "
|
|
|
"solito vengono trasformati\n"
|
|
|
"in puntatori. In Rust, un puntatore significa \"l'utente gestisce la vita "
|
|
|
"del puntatore\".\n"
|
|
|
"È loro responsabilità evitare l'insicurezza della memoria."
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:16
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Some level of trust in the user code is thus required, notably around "
|
|
|
"use-after-free\n"
|
|
|
"which Rust can do nothing about. However, some API designs place higher "
|
|
|
"burdens\n"
|
|
|
"than others on the code written in the other language."
|
|
|
msgstr ""
|
|
|
"È quindi richiesto un certo livello di fiducia nel codice utente, in "
|
|
|
"particolare per quanto riguarda l'uso dopo il libero\n"
|
|
|
"per cui Rust non può fare nulla. Tuttavia, alcuni progetti di API comportano "
|
|
|
"oneri maggiori\n"
|
|
|
"di altri sul codice scritto nell'altra lingua."
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:20
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The lowest risk API is the \"consolidated wrapper\", where all possible "
|
|
|
"interactions\n"
|
|
|
"with an object are folded into a \"wrapper type\", while keeping the Rust "
|
|
|
"API clean."
|
|
|
msgstr ""
|
|
|
"L'API a rischio più basso è il \"wrapper consolidato\", in cui tutte le "
|
|
|
"possibili interazioni\n"
|
|
|
"con un oggetto vengono piegati in un \"tipo wrapper\", mantenendo pulita "
|
|
|
"l'API di Rust."
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:25
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"To understand this, let us look at a classic example of an API to export: "
|
|
|
"iteration\n"
|
|
|
"through a collection."
|
|
|
msgstr ""
|
|
|
"Per capirlo, esaminiamo un classico esempio di API da esportare: "
|
|
|
"l'iterazione\n"
|
|
|
"attraverso una raccolta"
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:28
|
|
|
#, fuzzy
|
|
|
msgid "That API looks like this:"
|
|
|
msgstr "L'API ha questo aspetto:"
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:30
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"1. The iterator is initialized with `first_key`.\n"
|
|
|
"2. Each call to `next_key` will advance the iterator.\n"
|
|
|
"3. Calls to `next_key` if the iterator is at the end will do nothing.\n"
|
|
|
"4. As noted above, the iterator is \"wrapped into\" the collection (unlike "
|
|
|
"the native\n"
|
|
|
" Rust API)."
|
|
|
msgstr ""
|
|
|
"1. L'iteratore viene inizializzato con `first_key`.\n"
|
|
|
"2. Ogni chiamata a `next_key` farà avanzare l'iteratore.\n"
|
|
|
"3. Le chiamate a `next_key` se l'iteratore è alla fine non faranno nulla.\n"
|
|
|
"4. Come notato sopra, l'iteratore è \"inserito\" nella raccolta (a "
|
|
|
"differenza del file native\n"
|
|
|
" API ruggine)."
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:36
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"If the iterator implements `nth()` efficiently, then it is possible to make "
|
|
|
"it\n"
|
|
|
"ephemeral to each function call:"
|
|
|
msgstr ""
|
|
|
"Se l'iteratore implementa `nth()` in modo efficiente, allora è possibile "
|
|
|
"farlo\n"
|
|
|
"effimero per ogni chiamata di funzione:"
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:39
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"struct MySetWrapper {\n"
|
|
|
" myset: MySet,\n"
|
|
|
" iter_next: usize,\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"impl MySetWrapper {\n"
|
|
|
" pub fn first_key(&mut self) -> Option<&Key> {\n"
|
|
|
" self.iter_next = 0;\n"
|
|
|
" self.next_key()\n"
|
|
|
" }\n"
|
|
|
" pub fn next_key(&mut self) -> Option<&Key> {\n"
|
|
|
" if let Some(next) = self.myset.keys().nth(self.iter_next) {\n"
|
|
|
" self.iter_next += 1;\n"
|
|
|
" Some(next)\n"
|
|
|
" } else {\n"
|
|
|
" None\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:61
|
|
|
#, fuzzy
|
|
|
msgid "As a result, the wrapper is simple and contains no `unsafe` code."
|
|
|
msgstr ""
|
|
|
"Di conseguenza, il wrapper è semplice e non contiene codice \"non sicuro\"."
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:65
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This makes APIs safer to use, avoiding issues with lifetimes between types.\n"
|
|
|
"See [Object-Based APIs](./export.md) for more on the advantages and "
|
|
|
"pitfalls\n"
|
|
|
"this avoids."
|
|
|
msgstr ""
|
|
|
"Questo rende le API più sicure da usare, evitando problemi con la durata tra "
|
|
|
"i tipi.\n"
|
|
|
"Vedere [API basate su oggetti](./export.md) per ulteriori informazioni sui "
|
|
|
"vantaggi e le insidie\n"
|
|
|
"questo evita."
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:71
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Often, wrapping types is quite difficult, and sometimes a Rust API "
|
|
|
"compromise\n"
|
|
|
"would make things easier."
|
|
|
msgstr ""
|
|
|
"Spesso, il wrapping dei tipi è piuttosto difficile e talvolta un compromesso "
|
|
|
"con l'API Rust\n"
|
|
|
"renderebbe le cose più facili."
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:74
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"As an example, consider an iterator which does not efficiently implement "
|
|
|
"`nth()`.\n"
|
|
|
"It would definitely be worth putting in special logic to make the object "
|
|
|
"handle\n"
|
|
|
"iteration internally, or to support a different access pattern efficiently "
|
|
|
"that\n"
|
|
|
"only the Foreign Function API will use."
|
|
|
msgstr ""
|
|
|
"Ad esempio, considera un iteratore che non implementa in modo efficiente "
|
|
|
"`nth()`.\n"
|
|
|
"Varrebbe sicuramente la pena inserire una logica speciale per far gestire "
|
|
|
"l'oggetto\n"
|
|
|
"iterazione interna o per supportare un diverso modello di accesso in modo "
|
|
|
"efficiente\n"
|
|
|
"utilizzerà solo l'API della funzione esterna."
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:79
|
|
|
#, fuzzy
|
|
|
msgid "### Trying to Wrap Iterators (and Failing)"
|
|
|
msgstr "### Tentativo di avvolgere gli iteratori (e fallire)"
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:81
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"To wrap any type of iterator into the API correctly, the wrapper would need "
|
|
|
"to\n"
|
|
|
"do what a C version of the code would do: erase the lifetime of the "
|
|
|
"iterator,\n"
|
|
|
"and manage it manually."
|
|
|
msgstr ""
|
|
|
"Per racchiudere correttamente qualsiasi tipo di iteratore nell'API, il "
|
|
|
"wrapper dovrebbe farlo\n"
|
|
|
"fai quello che farebbe una versione C del codice: cancella la durata "
|
|
|
"dell'iteratore,\n"
|
|
|
"e gestirlo manualmente."
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:85
|
|
|
#, fuzzy
|
|
|
msgid "Suffice it to say, this is _incredibly_ difficult."
|
|
|
msgstr "Basti dire che questo è _incredibilmente_ difficile."
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:87
|
|
|
#, fuzzy
|
|
|
msgid "Here is an illustration of just _one_ pitfall."
|
|
|
msgstr "Ecco un'illustrazione di una sola trappola."
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:89
|
|
|
#, fuzzy
|
|
|
msgid "A first version of `MySetWrapper` would look like this:"
|
|
|
msgstr "Una prima versione di `MySetWrapper` sarebbe simile a questa:"
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:91
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"struct MySetWrapper {\n"
|
|
|
" myset: MySet,\n"
|
|
|
" iter_next: usize,\n"
|
|
|
" // created from a transmuted Box<KeysIter + 'self>\n"
|
|
|
" iterator: Option<NonNull<KeysIter<'static>>>,\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:100
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"With `transmute` being used to extend a lifetime, and a pointer to hide it,\n"
|
|
|
"it's ugly already. But it gets even worse: _any other operation can cause\n"
|
|
|
"Rust `undefined behaviour`_."
|
|
|
msgstr ""
|
|
|
"Con `transmute` utilizzato per estendere una durata e un puntatore per "
|
|
|
"nasconderlo,\n"
|
|
|
"è già brutto. Ma c'è di peggio: _qualsiasi altra operazione può causare\n"
|
|
|
"Rust `comportamento indefinito`_."
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:104
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Consider that the `MySet` in the wrapper could be manipulated by other\n"
|
|
|
"functions during iteration, such as storing a new value to the key it was\n"
|
|
|
"iterating over. The API doesn't discourage this, and in fact some similar C\n"
|
|
|
"libraries expect it."
|
|
|
msgstr ""
|
|
|
"Considera che \"MySet\" nel wrapper potrebbe essere manipolato da altri\n"
|
|
|
"funzioni durante l'iterazione, come la memorizzazione di un nuovo valore "
|
|
|
"nella chiave che era\n"
|
|
|
"iterando. L'API non scoraggia questo, e in effetti alcuni simili C\n"
|
|
|
"le biblioteche se lo aspettano."
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:109
|
|
|
#, fuzzy
|
|
|
msgid "A simple implementation of `myset_store` would be:"
|
|
|
msgstr "Una semplice implementazione di `myset_store` sarebbe:"
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:111
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"pub mod unsafe_module {\n"
|
|
|
"\n"
|
|
|
" // other module content\n"
|
|
|
"\n"
|
|
|
" pub fn myset_store(\n"
|
|
|
" myset: *mut MySetWrapper,\n"
|
|
|
" key: datum,\n"
|
|
|
" value: datum) -> libc::c_int {\n"
|
|
|
"\n"
|
|
|
" // DO NOT USE THIS CODE. IT IS UNSAFE TO DEMONSTRATE A PROLBEM.\n"
|
|
|
"\n"
|
|
|
" let myset: &mut MySet = unsafe { // SAFETY: whoops, UB occurs in "
|
|
|
"here!\n"
|
|
|
" &mut (*myset).myset\n"
|
|
|
" };\n"
|
|
|
"\n"
|
|
|
" /* ...check and cast key and value data... */\n"
|
|
|
"\n"
|
|
|
" match myset.store(casted_key, casted_value) {\n"
|
|
|
" Ok(_) => 0,\n"
|
|
|
" Err(e) => e.into()\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:137
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"If the iterator exists when this function is called, we have violated one of "
|
|
|
"Rust's\n"
|
|
|
"aliasing rules. According to Rust, the mutable reference in this block must "
|
|
|
"have\n"
|
|
|
"_exclusive_ access to the object. If the iterator simply exists, it's not "
|
|
|
"exclusive,\n"
|
|
|
"so we have `undefined behaviour`! "
|
|
|
msgstr ""
|
|
|
"Se l'iteratore esiste quando viene chiamata questa funzione, ne abbiamo "
|
|
|
"violato uno di Rust\n"
|
|
|
"regole di aliasing Secondo Rust, il riferimento mutabile in questo blocco "
|
|
|
"deve avere\n"
|
|
|
"accesso _esclusivo_ all'oggetto. Se l'iteratore esiste semplicemente, non è "
|
|
|
"esclusivo,\n"
|
|
|
"quindi abbiamo un `comportamento indefinito`!"
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:142
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"To avoid this, we must have a way of ensuring that mutable reference really "
|
|
|
"is exclusive.\n"
|
|
|
"That basically means clearing out the iterator's shared reference while it "
|
|
|
"exists,\n"
|
|
|
"and then reconstructing it. In most cases, that will still be less efficient "
|
|
|
"than\n"
|
|
|
"the C version."
|
|
|
msgstr ""
|
|
|
"Per evitare ciò, dobbiamo avere un modo per garantire che il riferimento "
|
|
|
"mutabile sia davvero esclusivo.\n"
|
|
|
"Ciò significa sostanzialmente eliminare il riferimento condiviso "
|
|
|
"dell'iteratore mentre esiste,\n"
|
|
|
"e poi ricostruirlo. Nella maggior parte dei casi, sarà comunque meno "
|
|
|
"efficiente di\n"
|
|
|
"la versione C."
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:147
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Some may ask: how can C do this more efficiently?\n"
|
|
|
"The answer is, it cheats. Rust's aliasing rules are the problem, and C "
|
|
|
"simply ignores\n"
|
|
|
"them for its pointers. In exchange, it is common to see code that is "
|
|
|
"declared\n"
|
|
|
"in the manual as \"not thread safe\" under some or all circumstances. In "
|
|
|
"fact,\n"
|
|
|
"the [GNU C "
|
|
|
"library](https://manpages.debian.org/buster/manpages/attributes.7.en.html)\n"
|
|
|
"has an entire lexicon dedicated to concurrent behavior!"
|
|
|
msgstr ""
|
|
|
"Alcuni potrebbero chiedere: come può C farlo in modo più efficiente?\n"
|
|
|
"La risposta è che imbroglia. Le regole di aliasing di Rust sono il problema "
|
|
|
"e C semplicemente le ignora\n"
|
|
|
"loro per i suoi puntatori. In cambio, è comune vedere il codice che viene "
|
|
|
"dichiarato\n"
|
|
|
"nel manuale come \"non thread-safe\" in alcune o tutte le circostanze. "
|
|
|
"Infatti,\n"
|
|
|
"la [libreria GNU "
|
|
|
"C](https://manpages.debian.org/buster/manpages/attributes.7.en.html)\n"
|
|
|
"ha un intero lessico dedicato al comportamento concorrente!"
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:154
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Rust would rather make everything memory safe all the time, for both safety "
|
|
|
"and\n"
|
|
|
"optimizations that C code cannot attain. Being denied access to certain "
|
|
|
"shortcuts\n"
|
|
|
"is the price Rust programmers need to pay."
|
|
|
msgstr ""
|
|
|
"Rust preferirebbe rendere ogni memoria sempre al sicuro, sia per sicurezza "
|
|
|
"che per\n"
|
|
|
"ottimizzazioni che il codice C non può raggiungere. Viene negato l'accesso a "
|
|
|
"determinate scorciatoie\n"
|
|
|
"è il prezzo che i programmatori di Rust devono pagare."
|
|
|
|
|
|
#: src\patterns/ffi/wrappers.md:158
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"For the C programmers out there scratching their heads, the iterator need\n"
|
|
|
"not be read _during_ this code cause the UB. The exclusivity rule also "
|
|
|
"enables\n"
|
|
|
"compiler optimizations which may cause inconsistent observations by the "
|
|
|
"iterator's\n"
|
|
|
"shared reference (e.g. stack spills or reordering instructions for "
|
|
|
"efficiency).\n"
|
|
|
"These observations may happen _any time after_ the mutable reference is "
|
|
|
"created."
|
|
|
msgstr ""
|
|
|
"Per i programmatori C là fuori che si grattano la testa, l'iteratore ha "
|
|
|
"bisogno\n"
|
|
|
"non essere letto _durante_ questo codice causa l'UB. La regola di "
|
|
|
"esclusività consente anche\n"
|
|
|
"ottimizzazioni del compilatore che possono causare osservazioni incoerenti "
|
|
|
"da parte dell'iteratore\n"
|
|
|
"riferimento condiviso (ad es. stack spill o riordino delle istruzioni per "
|
|
|
"l'efficienza).\n"
|
|
|
"Queste osservazioni possono verificarsi _qualsiasi momento dopo_ la "
|
|
|
"creazione del riferimento mutabile."
|
|
|
|
|
|
#: src\anti_patterns/index.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Anti-patterns"
|
|
|
msgstr "# Anti-modelli"
|
|
|
|
|
|
#: src\anti_patterns/index.md:3
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"An [anti-pattern](https://en.wikipedia.org/wiki/Anti-pattern) is a solution "
|
|
|
"to\n"
|
|
|
"a \"recurring problem that is usually ineffective and risks being highly\n"
|
|
|
"counterproductive\". Just as valuable as knowing how to solve a problem, is\n"
|
|
|
"knowing how _not_ to solve it. Anti-patterns give us great counter-examples "
|
|
|
"to\n"
|
|
|
"consider relative to design patterns. Anti-patterns are not confined to "
|
|
|
"code.\n"
|
|
|
"For example, a process can be an anti-pattern, too."
|
|
|
msgstr ""
|
|
|
"Un [anti-pattern](https://en.wikipedia.org/wiki/Anti-pattern) è una "
|
|
|
"soluzione a\n"
|
|
|
"un \"problema ricorrente che di solito è inefficace e rischia di essere "
|
|
|
"altamente\n"
|
|
|
"controproducente\". Altrettanto prezioso quanto sapere come risolvere un "
|
|
|
"problema, lo è\n"
|
|
|
"sapere come _non_ risolverlo. Gli anti-pattern ci forniscono ottimi "
|
|
|
"contro-esempi\n"
|
|
|
"considerare rispetto ai modelli di progettazione. Gli anti-pattern non sono "
|
|
|
"limitati al codice.\n"
|
|
|
"Ad esempio, anche un processo può essere un anti-pattern."
|
|
|
|
|
|
#: src\anti_patterns/borrow_clone.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Clone to satisfy the borrow checker"
|
|
|
msgstr "# Clona per soddisfare il controllore del prestito"
|
|
|
|
|
|
#: src\anti_patterns/borrow_clone.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The borrow checker prevents Rust users from developing otherwise unsafe code "
|
|
|
"by\n"
|
|
|
"ensuring that either: only one mutable reference exists, or potentially many "
|
|
|
"but\n"
|
|
|
"all immutable references exist. If the code written does not hold true to "
|
|
|
"these\n"
|
|
|
"conditions, this anti-pattern arises when the developer resolves the "
|
|
|
"compiler\n"
|
|
|
"error by cloning the variable."
|
|
|
msgstr ""
|
|
|
"Il controllo del prestito impedisce agli utenti di Rust di sviluppare codice "
|
|
|
"altrimenti non sicuro\n"
|
|
|
"assicurando che: esista un solo riferimento mutabile, o potenzialmente molti "
|
|
|
"ma\n"
|
|
|
"esistono tutti i riferimenti immutabili. Se il codice scritto non è vero per "
|
|
|
"questi\n"
|
|
|
"condizioni, questo anti-pattern si verifica quando lo sviluppatore risolve "
|
|
|
"il compilatore\n"
|
|
|
"errore clonando la variabile."
|
|
|
|
|
|
#: src\anti_patterns/borrow_clone.md:13
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"// define any variable\n"
|
|
|
"let mut x = 5;\n"
|
|
|
"\n"
|
|
|
"// Borrow `x` -- but clone it first\n"
|
|
|
"let y = &mut (x.clone());\n"
|
|
|
"\n"
|
|
|
"// without the x.clone() two lines prior, this line would fail on compile "
|
|
|
"as\n"
|
|
|
"// x has been borrowed\n"
|
|
|
"// thanks to x.clone(), x was never borrowed, and this line will run.\n"
|
|
|
"println!(\"{}\", x);\n"
|
|
|
"\n"
|
|
|
"// perform some action on the borrow to prevent rust from optimizing this\n"
|
|
|
"//out of existence\n"
|
|
|
"*y += 1;\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\anti_patterns/borrow_clone.md:32
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"It is tempting, particularly for beginners, to use this pattern to resolve\n"
|
|
|
"confusing issues with the borrow checker. However, there are serious\n"
|
|
|
"consequences. Using `.clone()` causes a copy of the data to be made. Any "
|
|
|
"changes\n"
|
|
|
"between the two are not synchronized -- as if two completely separate "
|
|
|
"variables\n"
|
|
|
"exist."
|
|
|
msgstr ""
|
|
|
"È allettante, in particolare per i principianti, utilizzare questo schema "
|
|
|
"per risolvere\n"
|
|
|
"problemi di confusione con il controllo del prestito. Tuttavia, ci sono "
|
|
|
"gravi\n"
|
|
|
"conseguenze. L'uso di `.clone()` provoca la creazione di una copia dei dati. "
|
|
|
"Eventuali modifiche\n"
|
|
|
"tra i due non sono sincronizzati -- come se due variabili completamente "
|
|
|
"separate\n"
|
|
|
"esistere."
|
|
|
|
|
|
#: src\anti_patterns/borrow_clone.md:38
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"There are special cases -- `Rc<T>` is designed to handle clones "
|
|
|
"intelligently.\n"
|
|
|
"It internally manages exactly one copy of the data, and cloning it will "
|
|
|
"only\n"
|
|
|
"clone the reference."
|
|
|
msgstr ""
|
|
|
"Ci sono casi speciali -- `Rc<T>` è progettato per gestire i cloni in modo "
|
|
|
"intelligente.\n"
|
|
|
"Gestisce internamente esattamente una copia dei dati e la clonazione lo farà "
|
|
|
"solo\n"
|
|
|
"clonare il riferimento."
|
|
|
|
|
|
#: src\anti_patterns/borrow_clone.md:42
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"There is also `Arc<T>` which provides shared ownership of a value of type T\n"
|
|
|
"that is allocated in the heap. Invoking `.clone()` on `Arc` produces a new "
|
|
|
"`Arc`\n"
|
|
|
"instance, which points to the same allocation on the heap as the source "
|
|
|
"`Arc`,\n"
|
|
|
"while increasing a reference count."
|
|
|
msgstr ""
|
|
|
"C'è anche `Arc<T>` che fornisce la proprietà condivisa di un valore di tipo "
|
|
|
"T\n"
|
|
|
"allocato nell'heap. Invocare `.clone()` su `Arc` produce un nuovo `Arc`\n"
|
|
|
"istanza, che punta alla stessa allocazione sull'heap della sorgente `Arc`,\n"
|
|
|
"durante l'aumento di un conteggio di riferimento."
|
|
|
|
|
|
#: src\anti_patterns/borrow_clone.md:47
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"In general, clones should be deliberate, with full understanding of the\n"
|
|
|
"consequences. If a clone is used to make a borrow checker error disappear,\n"
|
|
|
"that's a good indication this anti-pattern may be in use."
|
|
|
msgstr ""
|
|
|
"In generale, i cloni dovrebbero essere deliberati, con piena comprensione "
|
|
|
"del\n"
|
|
|
"conseguenze. Se viene utilizzato un clone per far scomparire un errore di "
|
|
|
"verifica del prestito,\n"
|
|
|
"questa è una buona indicazione che questo anti-pattern potrebbe essere in "
|
|
|
"uso."
|
|
|
|
|
|
#: src\anti_patterns/borrow_clone.md:51
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Even though `.clone()` is an indication of a bad pattern, sometimes\n"
|
|
|
"**it is fine to write inefficient code**, in cases such as when:"
|
|
|
msgstr ""
|
|
|
"Anche se `.clone()` è un'indicazione di uno schema errato, a volte\n"
|
|
|
"**va bene scrivere codice inefficiente**, in casi come quando:"
|
|
|
|
|
|
#: src\anti_patterns/borrow_clone.md:54
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- the developer is still new to ownership\n"
|
|
|
"- the code doesn't have great speed or memory constraints\n"
|
|
|
" (like hackathon projects or prototypes)\n"
|
|
|
"- satisfying the borrow checker is really complicated, and you prefer to\n"
|
|
|
" optimize readability over performance"
|
|
|
msgstr ""
|
|
|
"- lo sviluppatore è ancora nuovo alla proprietà\n"
|
|
|
"- il codice non ha grandi velocità o vincoli di memoria\n"
|
|
|
" (come progetti di hackathon o prototipi)\n"
|
|
|
"- soddisfare il controllore del prestito è davvero complicato e preferisci "
|
|
|
"farlo\n"
|
|
|
" ottimizzare la leggibilità rispetto alle prestazioni"
|
|
|
|
|
|
#: src\anti_patterns/borrow_clone.md:60
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"If an unnecessary clone is suspected, The [Rust Book's chapter on "
|
|
|
"Ownership](https://doc.rust-lang.org/book/ownership.html)\n"
|
|
|
"should be understood fully before assessing whether the clone is required or "
|
|
|
"not."
|
|
|
msgstr ""
|
|
|
"Se si sospetta un clone non necessario, il [capitolo sulla proprietà di Rust "
|
|
|
"Book](https://doc.rust-lang.org/book/ownership.html)\n"
|
|
|
"dovrebbe essere compreso appieno prima di valutare se il clone è necessario "
|
|
|
"o meno."
|
|
|
|
|
|
#: src\anti_patterns/borrow_clone.md:63
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Also be sure to always run `cargo clippy` in your project, which will detect "
|
|
|
"some\n"
|
|
|
"cases in which `.clone()` is not necessary, like "
|
|
|
"[1](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone),\n"
|
|
|
"[2](https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy),\n"
|
|
|
"[3](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone) or "
|
|
|
"[4](https://rust-lang.github.io/rust-clippy/master/index.html#clone_double_ref)."
|
|
|
msgstr ""
|
|
|
"Assicurati anche di eseguire sempre `cargo clippy` nel tuo progetto, che ne "
|
|
|
"rileverà alcuni\n"
|
|
|
"casi in cui `.clone()` non è necessario, come "
|
|
|
"[1](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone),\n"
|
|
|
"[2](https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy),\n"
|
|
|
"[3](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone) o "
|
|
|
"[4](https://rust-lang.github.io/rust-clippy/master "
|
|
|
"/index.html#clone_double_ref)."
|
|
|
|
|
|
#: src\anti_patterns/borrow_clone.md:70
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [`mem::{take(_), replace(_)}` to keep owned values in changed "
|
|
|
"enums](../idioms/mem-replace.md)\n"
|
|
|
"- [`Rc<T>` documentation, which handles .clone() "
|
|
|
"intelligently](http://doc.rust-lang.org/std/rc/)\n"
|
|
|
"- [`Arc<T>` documentation, a thread-safe reference-counting "
|
|
|
"pointer](https://doc.rust-lang.org/std/sync/struct.Arc.html)\n"
|
|
|
"- [Tricks with ownership in "
|
|
|
"Rust](https://web.archive.org/web/20210120233744/https://xion.io/post/code/rust-borrowchk-tricks.html)"
|
|
|
msgstr ""
|
|
|
"- [`mem::{take(_), replace(_)}` per mantenere i valori di proprietà nelle "
|
|
|
"enum modificate](../idioms/mem-replace.md)\n"
|
|
|
"- [documentazione `Rc<T>`, che gestisce .clone() in modo "
|
|
|
"intelligente](http://doc.rust-lang.org/std/rc/)\n"
|
|
|
"- [documentazione `Arc<T>`, un puntatore thread-safe per il conteggio dei "
|
|
|
"riferimenti](https://doc.rust-lang.org/std/sync/struct.Arc.html)\n"
|
|
|
"- [Trucchi con la proprietà in "
|
|
|
"Rust](https://web.archive.org/web/20210120233744/https://xion.io/post/code/rust-borrowchk-tricks.html)"
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# `#![deny(warnings)]`"
|
|
|
msgstr "# `#![nega(avvisi)]`"
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"A well-intentioned crate author wants to ensure their code builds without\n"
|
|
|
"warnings. So they annotate their crate root with the following:"
|
|
|
msgstr ""
|
|
|
"Un autore di casse ben intenzionato vuole assicurarsi che il proprio codice "
|
|
|
"venga compilato senza\n"
|
|
|
"avvertimenti. Quindi annotano la loro radice di cassa con quanto segue:"
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:10
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"#![deny(warnings)]\n"
|
|
|
"\n"
|
|
|
"// All is well.\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:18
|
|
|
#, fuzzy
|
|
|
msgid "It is short and will stop the build if anything is amiss."
|
|
|
msgstr "È breve e interromperà la compilazione se qualcosa non va."
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:20
|
|
|
#, fuzzy
|
|
|
msgid "## Drawbacks"
|
|
|
msgstr "## Svantaggi"
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:22
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"By disallowing the compiler to build with warnings, a crate author opts out "
|
|
|
"of\n"
|
|
|
"Rust's famed stability. Sometimes new features or old misfeatures need a "
|
|
|
"change\n"
|
|
|
"in how things are done, thus lints are written that `warn` for a certain "
|
|
|
"grace\n"
|
|
|
"period before being turned to `deny`."
|
|
|
msgstr ""
|
|
|
"Impedendo al compilatore di compilare con avvertimenti, un autore di crate "
|
|
|
"rinuncia\n"
|
|
|
"La famosa stabilità di Rust. A volte nuove funzionalità o vecchie "
|
|
|
"funzionalità errate richiedono un cambiamento\n"
|
|
|
"nel modo in cui si fanno le cose, così si scrive lanugine che 'avvertono' "
|
|
|
"per una certa grazia\n"
|
|
|
"periodo prima di essere trasformato in \"deny\"."
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:27
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"For example, it was discovered that a type could have two `impl`s with the "
|
|
|
"same\n"
|
|
|
"method. This was deemed a bad idea, but in order to make the transition "
|
|
|
"smooth,\n"
|
|
|
"the `overlapping-inherent-impls` lint was introduced to give a warning to "
|
|
|
"those\n"
|
|
|
"stumbling on this fact, before it becomes a hard error in a future release."
|
|
|
msgstr ""
|
|
|
"Ad esempio, è stato scoperto che un tipo potrebbe avere due `impl` con lo "
|
|
|
"stesso\n"
|
|
|
"metodo. Questa è stata considerata una cattiva idea, ma per facilitare la "
|
|
|
"transizione,\n"
|
|
|
"il lint `overlapping-inherent-impls` è stato introdotto per dare un "
|
|
|
"avvertimento a quelli\n"
|
|
|
"inciampando su questo fatto, prima che diventi un grave errore in una "
|
|
|
"versione futura."
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:32
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Also sometimes APIs get deprecated, so their use will emit a warning where\n"
|
|
|
"before there was none."
|
|
|
msgstr ""
|
|
|
"Inoltre, a volte le API vengono deprecate, quindi il loro utilizzo emetterà "
|
|
|
"un avviso dove\n"
|
|
|
"prima non ce n'era nessuno."
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:35
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"All this conspires to potentially break the build whenever something changes."
|
|
|
msgstr ""
|
|
|
"Tutto ciò cospira potenzialmente per interrompere la build ogni volta che "
|
|
|
"qualcosa cambia."
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:37
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Furthermore, crates that supply additional lints (e.g. [rust-clippy]) can "
|
|
|
"no\n"
|
|
|
"longer be used unless the annotation is removed. This is mitigated with\n"
|
|
|
"[--cap-lints]. The `--cap-lints=warn` command line argument, turns all "
|
|
|
"`deny`\n"
|
|
|
"lint errors into warnings."
|
|
|
msgstr ""
|
|
|
"Inoltre, le casse che forniscono pelucchi aggiuntivi (ad es. "
|
|
|
"[ruggine-clippy]) non possono\n"
|
|
|
"essere più utilizzato a meno che l'annotazione non venga rimossa. Questo è "
|
|
|
"mitigato con\n"
|
|
|
"[--cap-pelucchi]. L'argomento della riga di comando `--cap-lints=warn` "
|
|
|
"trasforma tutto in `deny`\n"
|
|
|
"errori di lint in avvisi."
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:42
|
|
|
#: src\functional/generics-type-classes.md:227
|
|
|
#, fuzzy
|
|
|
msgid "## Alternatives"
|
|
|
msgstr "## Alternative"
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:44
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"There are two ways of tackling this problem: First, we can decouple the "
|
|
|
"build\n"
|
|
|
"setting from the code, and second, we can name the lints we want to deny\n"
|
|
|
"explicitly."
|
|
|
msgstr ""
|
|
|
"Ci sono due modi per affrontare questo problema: in primo luogo, possiamo "
|
|
|
"disaccoppiare la build\n"
|
|
|
"impostazione dal codice e, in secondo luogo, possiamo nominare i lint che "
|
|
|
"vogliamo negare\n"
|
|
|
"esplicitamente."
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:48
|
|
|
#, fuzzy
|
|
|
msgid "The following command line will build with all warnings set to `deny`:"
|
|
|
msgstr ""
|
|
|
"La seguente riga di comando verrà compilata con tutti gli avvisi impostati "
|
|
|
"su \"deny\":"
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:50
|
|
|
#, fuzzy
|
|
|
msgid "`RUSTFLAGS=\"-D warnings\" cargo build`"
|
|
|
msgstr "`RUSTFLAGS=\"-D warnings\" costruzione del carico`"
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:52
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This can be done by any individual developer (or be set in a CI tool like\n"
|
|
|
"Travis, but remember that this may break the build when something changes)\n"
|
|
|
"without requiring a change to the code."
|
|
|
msgstr ""
|
|
|
"Questo può essere fatto da qualsiasi singolo sviluppatore (o essere "
|
|
|
"impostato in uno strumento CI come\n"
|
|
|
"Travis, ma ricorda che questo potrebbe interrompere la build quando qualcosa "
|
|
|
"cambia)\n"
|
|
|
"senza richiedere una modifica al codice."
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:56
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Alternatively, we can specify the lints that we want to `deny` in the code.\n"
|
|
|
"Here is a list of warning lints that is (hopefully) safe to deny (as of "
|
|
|
"Rustc 1.48.0):"
|
|
|
msgstr ""
|
|
|
"In alternativa, possiamo specificare i lint che vogliamo \"negare\" nel "
|
|
|
"codice.\n"
|
|
|
"Ecco un elenco di avvertenze che è (si spera) sicuro negare (a partire da "
|
|
|
"Rustc 1.48.0):"
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:59
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"#![deny(bad_style,\n"
|
|
|
" const_err,\n"
|
|
|
" dead_code,\n"
|
|
|
" improper_ctypes,\n"
|
|
|
" non_shorthand_field_patterns,\n"
|
|
|
" no_mangle_generic_items,\n"
|
|
|
" overflowing_literals,\n"
|
|
|
" path_statements,\n"
|
|
|
" patterns_in_fns_without_body,\n"
|
|
|
" private_in_public,\n"
|
|
|
" unconditional_recursion,\n"
|
|
|
" unused,\n"
|
|
|
" unused_allocation,\n"
|
|
|
" unused_comparisons,\n"
|
|
|
" unused_parens,\n"
|
|
|
" while_true)]\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:78
|
|
|
#, fuzzy
|
|
|
msgid "In addition, the following `allow`ed lints may be a good idea to `deny`:"
|
|
|
msgstr ""
|
|
|
"Inoltre, i seguenti lint \"consentiti\" possono essere una buona idea da "
|
|
|
"\"negare\":"
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:80
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"#![deny(missing_debug_implementations,\n"
|
|
|
" missing_docs,\n"
|
|
|
" trivial_casts,\n"
|
|
|
" trivial_numeric_casts,\n"
|
|
|
" unused_extern_crates,\n"
|
|
|
" unused_import_braces,\n"
|
|
|
" unused_qualifications,\n"
|
|
|
" unused_results)]\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:91
|
|
|
#, fuzzy
|
|
|
msgid "Some may also want to add `missing-copy-implementations` to their list."
|
|
|
msgstr ""
|
|
|
"Alcuni potrebbero anche voler aggiungere `missing-copy-implementations` alla "
|
|
|
"loro lista."
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:93
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Note that we explicitly did not add the `deprecated` lint, as it is fairly\n"
|
|
|
"certain that there will be more deprecated APIs in the future."
|
|
|
msgstr ""
|
|
|
"Si noti che non abbiamo esplicitamente aggiunto il lint `deprecato`, poiché "
|
|
|
"è corretto\n"
|
|
|
"certi che in futuro ci saranno più API obsolete."
|
|
|
|
|
|
#: src\anti_patterns/deny-warnings.md:98
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [A collection of all clippy "
|
|
|
"lints](https://rust-lang.github.io/rust-clippy/master)\n"
|
|
|
"- [deprecate attribute] documentation\n"
|
|
|
"- Type `rustc -W help` for a list of lints on your system. Also type\n"
|
|
|
" `rustc --help` for a general list of options\n"
|
|
|
"- [rust-clippy] is a collection of lints for better Rust code"
|
|
|
msgstr ""
|
|
|
"- [Una raccolta di tutti i pelucchi "
|
|
|
"clippy](https://rust-lang.github.io/rust-clippy/master)\n"
|
|
|
"- [attributo obsoleto] documentazione\n"
|
|
|
"- Digita `rustc -W help` per un elenco di lint sul tuo sistema. Digita "
|
|
|
"anche\n"
|
|
|
" `rustc --help` per un elenco generale di opzioni\n"
|
|
|
"- [rust-clippy] è una raccolta di lanugine per migliorare il codice Rust"
|
|
|
|
|
|
#: src\anti_patterns/deref.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# `Deref` polymorphism"
|
|
|
msgstr "# Polimorfismo `Deref`"
|
|
|
|
|
|
#: src\anti_patterns/deref.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Misuse the `Deref` trait to emulate inheritance between structs, and thus "
|
|
|
"reuse\n"
|
|
|
"methods."
|
|
|
msgstr ""
|
|
|
"Usa in modo improprio il tratto `Deref` per emulare l'ereditarietà tra "
|
|
|
"struct e quindi riutilizzarlo\n"
|
|
|
"metodi."
|
|
|
|
|
|
#: src\anti_patterns/deref.md:10
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Sometimes we want to emulate the following common pattern from OO languages "
|
|
|
"such\n"
|
|
|
"as Java:"
|
|
|
msgstr ""
|
|
|
"A volte vogliamo emulare il seguente modello comune da linguaggi OO come\n"
|
|
|
"come Java:"
|
|
|
|
|
|
#: src\anti_patterns/deref.md:13
|
|
|
msgid ""
|
|
|
"```java\n"
|
|
|
"class Foo {\n"
|
|
|
" void m() { ... }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"class Bar extends Foo {}\n"
|
|
|
"\n"
|
|
|
"public static void main(String[] args) {\n"
|
|
|
" Bar b = new Bar();\n"
|
|
|
" b.m();\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\anti_patterns/deref.md:26
|
|
|
#, fuzzy
|
|
|
msgid "We can use the deref polymorphism anti-pattern to do so:"
|
|
|
msgstr "Possiamo usare l'anti-pattern del polimorfismo deref per farlo:"
|
|
|
|
|
|
#: src\anti_patterns/deref.md:28
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"use std::ops::Deref;\n"
|
|
|
"\n"
|
|
|
"struct Foo {}\n"
|
|
|
"\n"
|
|
|
"impl Foo {\n"
|
|
|
" fn m(&self) {\n"
|
|
|
" //..\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"struct Bar {\n"
|
|
|
" f: Foo,\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"impl Deref for Bar {\n"
|
|
|
" type Target = Foo;\n"
|
|
|
" fn deref(&self) -> &Foo {\n"
|
|
|
" &self.f\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn main() {\n"
|
|
|
" let b = Bar { f: Foo {} };\n"
|
|
|
" b.m();\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\anti_patterns/deref.md:56
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"There is no struct inheritance in Rust. Instead we use composition and "
|
|
|
"include\n"
|
|
|
"an instance of `Foo` in `Bar` (since the field is a value, it is stored "
|
|
|
"inline,\n"
|
|
|
"so if there were fields, they would have the same layout in memory as the "
|
|
|
"Java\n"
|
|
|
"version (probably, you should use `#[repr(C)]` if you want to be sure))."
|
|
|
msgstr ""
|
|
|
"Non c'è ereditarietà struct in Rust. Usiamo invece composizione e "
|
|
|
"inclusione\n"
|
|
|
"un'istanza di `Foo` in `Bar` (poiché il campo è un valore, viene memorizzato "
|
|
|
"in linea,\n"
|
|
|
"quindi se ci fossero campi, avrebbero lo stesso layout in memoria di Java\n"
|
|
|
"versione (probabilmente, dovresti usare `#[repr(C)]` se vuoi essere sicuro))."
|
|
|
|
|
|
#: src\anti_patterns/deref.md:61
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"In order to make the method call work we implement `Deref` for `Bar` with "
|
|
|
"`Foo`\n"
|
|
|
"as the target (returning the embedded `Foo` field). That means that when we\n"
|
|
|
"dereference a `Bar` (for example, using `*`) then we will get a `Foo`. That "
|
|
|
"is\n"
|
|
|
"pretty weird. Dereferencing usually gives a `T` from a reference to `T`, "
|
|
|
"here we\n"
|
|
|
"have two unrelated types. However, since the dot operator does implicit\n"
|
|
|
"dereferencing, it means that the method call will search for methods on "
|
|
|
"`Foo` as\n"
|
|
|
"well as `Bar`."
|
|
|
msgstr ""
|
|
|
"Per far funzionare la chiamata al metodo, implementiamo `Deref` per `Bar` "
|
|
|
"con `Foo`\n"
|
|
|
"come destinazione (restituendo il campo `Foo` incorporato). Ciò significa "
|
|
|
"che quando noi\n"
|
|
|
"dereferenziare un `Bar` (ad esempio, utilizzando `*`), otterremo un `Foo`. "
|
|
|
"Questo è\n"
|
|
|
"abbastanza strano. La dereferenziazione di solito dà una \"T\" da un "
|
|
|
"riferimento a \"T\", qui noi\n"
|
|
|
"hanno due tipi non correlati. Tuttavia, poiché l'operatore punto fa "
|
|
|
"implicit\n"
|
|
|
"dereferenziando, significa che la chiamata al metodo cercherà i metodi su "
|
|
|
"`Foo` as\n"
|
|
|
"così come \"Bar\"."
|
|
|
|
|
|
#: src\anti_patterns/deref.md:71
|
|
|
#, fuzzy
|
|
|
msgid "You save a little boilerplate, e.g.,"
|
|
|
msgstr "Risparmi un po' di standard, ad esempio,"
|
|
|
|
|
|
#: src\anti_patterns/deref.md:73
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"impl Bar {\n"
|
|
|
" fn m(&self) {\n"
|
|
|
" self.f.m()\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\anti_patterns/deref.md:83
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Most importantly this is a surprising idiom - future programmers reading "
|
|
|
"this in\n"
|
|
|
"code will not expect this to happen. That's because we are misusing the "
|
|
|
"`Deref`\n"
|
|
|
"trait rather than using it as intended (and documented, etc.). It's also "
|
|
|
"because\n"
|
|
|
"the mechanism here is completely implicit."
|
|
|
msgstr ""
|
|
|
"La cosa più importante è che questo è un linguaggio sorprendente: i futuri "
|
|
|
"programmatori lo leggono\n"
|
|
|
"il codice non si aspetterà che ciò accada. Questo perché stiamo abusando del "
|
|
|
"`Deref`\n"
|
|
|
"tratto piuttosto che usarlo come previsto (e documentato, ecc.). È anche "
|
|
|
"perché\n"
|
|
|
"il meccanismo qui è del tutto implicito."
|
|
|
|
|
|
#: src\anti_patterns/deref.md:88
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This pattern does not introduce subtyping between `Foo` and `Bar` like\n"
|
|
|
"inheritance in Java or C++ does. Furthermore, traits implemented by `Foo` "
|
|
|
"are\n"
|
|
|
"not automatically implemented for `Bar`, so this pattern interacts badly "
|
|
|
"with\n"
|
|
|
"bounds checking and thus generic programming."
|
|
|
msgstr ""
|
|
|
"Questo modello non introduce il sottotipo tra `Foo` e `Bar` come\n"
|
|
|
"l'ereditarietà in Java o C++ lo fa. Inoltre, i tratti implementati da "
|
|
|
"\"Foo\" lo sono\n"
|
|
|
"non implementato automaticamente per `Bar`, quindi questo modello "
|
|
|
"interagisce male con\n"
|
|
|
"controllo dei limiti e quindi programmazione generica."
|
|
|
|
|
|
#: src\anti_patterns/deref.md:93
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Using this pattern gives subtly different semantics from most OO languages "
|
|
|
"with\n"
|
|
|
"regards to `self`. Usually it remains a reference to the sub-class, with "
|
|
|
"this\n"
|
|
|
"pattern it will be the 'class' where the method is defined."
|
|
|
msgstr ""
|
|
|
"L'uso di questo modello fornisce una semantica leggermente diversa dalla "
|
|
|
"maggior parte dei linguaggi OO con\n"
|
|
|
"riguardo a \"sé\". Di solito rimane un riferimento alla sottoclasse, con "
|
|
|
"questo\n"
|
|
|
"pattern sarà la 'classe' in cui è definito il metodo."
|
|
|
|
|
|
#: src\anti_patterns/deref.md:97
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Finally, this pattern only supports single inheritance, and has no notion "
|
|
|
"of\n"
|
|
|
"interfaces, class-based privacy, or other inheritance-related features. So, "
|
|
|
"it\n"
|
|
|
"gives an experience that will be subtly surprising to programmers used to "
|
|
|
"Java\n"
|
|
|
"inheritance, etc."
|
|
|
msgstr ""
|
|
|
"Infine, questo modello supporta solo l'ereditarietà singola e non ha alcuna "
|
|
|
"nozione di\n"
|
|
|
"interfacce, privacy basata su classi o altre funzionalità relative "
|
|
|
"all'ereditarietà. Quindi, esso\n"
|
|
|
"offre un'esperienza che sarà sottilmente sorprendente per i programmatori "
|
|
|
"abituati a Java\n"
|
|
|
"eredità, ecc."
|
|
|
|
|
|
#: src\anti_patterns/deref.md:104
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"There is no one good alternative. Depending on the exact circumstances it "
|
|
|
"might\n"
|
|
|
"be better to re-implement using traits or to write out the facade methods "
|
|
|
"to\n"
|
|
|
"dispatch to `Foo` manually. We do intend to add a mechanism for inheritance\n"
|
|
|
"similar to this to Rust, but it is likely to be some time before it reaches\n"
|
|
|
"stable Rust. See these "
|
|
|
"[blog](http://aturon.github.io/blog/2015/09/18/reuse/)\n"
|
|
|
"[posts](http://smallcultfollowing.com/babysteps/blog/2015/10/08/virtual-structs-part-4-extended-enums-and-thin-traits/)\n"
|
|
|
"and this [RFC issue](https://github.com/rust-lang/rfcs/issues/349) for more "
|
|
|
"details."
|
|
|
msgstr ""
|
|
|
"Non esiste una buona alternativa. A seconda delle circostanze esatte "
|
|
|
"potrebbe\n"
|
|
|
"sarebbe meglio reimplementare usando i tratti o scrivere i metodi di "
|
|
|
"facciata a\n"
|
|
|
"invia a `Foo` manualmente. Intendiamo aggiungere un meccanismo per "
|
|
|
"l'ereditarietà\n"
|
|
|
"simile a questo per Rust, ma è probabile che ci voglia del tempo prima che "
|
|
|
"raggiunga\n"
|
|
|
"Ruggine stabile. Vedi questi "
|
|
|
"[blog](http://aturon.github.io/blog/2015/09/18/reuse/)\n"
|
|
|
"[post](http://smallcultfollowing.com/babysteps/blog/2015/10/08/virtual-structs-part-4-extended-enums-and-thin-traits/)\n"
|
|
|
"e questo [problema RFC](https://github.com/rust-lang/rfcs/issues/349) per "
|
|
|
"maggiori dettagli."
|
|
|
|
|
|
#: src\anti_patterns/deref.md:112
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The `Deref` trait is designed for the implementation of custom pointer "
|
|
|
"types.\n"
|
|
|
"The intention is that it will take a pointer-to-`T` to a `T`, not convert\n"
|
|
|
"between different types. It is a shame that this isn't (probably cannot be)\n"
|
|
|
"enforced by the trait definition."
|
|
|
msgstr ""
|
|
|
"Il tratto `Deref` è progettato per l'implementazione di tipi di puntatore "
|
|
|
"personalizzati.\n"
|
|
|
"L'intenzione è che prenderà un puntatore a `T` in una `T`, non convertirà\n"
|
|
|
"tra tipi diversi. È un peccato che questo non sia (probabilmente non può "
|
|
|
"essere)\n"
|
|
|
"imposto dalla definizione di tratto."
|
|
|
|
|
|
#: src\anti_patterns/deref.md:117
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Rust tries to strike a careful balance between explicit and implicit "
|
|
|
"mechanisms,\n"
|
|
|
"favouring explicit conversions between types. Automatic dereferencing in the "
|
|
|
"dot\n"
|
|
|
"operator is a case where the ergonomics strongly favour an implicit "
|
|
|
"mechanism,\n"
|
|
|
"but the intention is that this is limited to degrees of indirection, not\n"
|
|
|
"conversion between arbitrary types."
|
|
|
msgstr ""
|
|
|
"Rust cerca di trovare un attento equilibrio tra meccanismi espliciti e "
|
|
|
"impliciti,\n"
|
|
|
"favorendo conversioni esplicite tra i tipi. Dereferenziazione automatica nel "
|
|
|
"punto\n"
|
|
|
"operatore è un caso in cui l'ergonomia favorisce fortemente un meccanismo "
|
|
|
"implicito,\n"
|
|
|
"ma l'intenzione è che questo sia limitato a gradi di indirezione, no\n"
|
|
|
"conversione tra tipi arbitrari."
|
|
|
|
|
|
#: src\anti_patterns/deref.md:125
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [Collections are smart pointers idiom](../idioms/deref.md).\n"
|
|
|
"- Delegation crates for less boilerplate like "
|
|
|
"[delegate](https://crates.io/crates/delegate)\n"
|
|
|
" or [ambassador](https://crates.io/crates/ambassador)\n"
|
|
|
"- [Documentation for `Deref` "
|
|
|
"trait](https://doc.rust-lang.org/std/ops/trait.Deref.html)."
|
|
|
msgstr ""
|
|
|
"- [Le raccolte sono idiomi di puntatori intelligenti](../idioms/deref.md).\n"
|
|
|
"- Casse di delega per meno boilerplate come "
|
|
|
"[delegate](https://crates.io/crates/delegate)\n"
|
|
|
" o [ambasciatore](https://crates.io/crates/ambassador)\n"
|
|
|
"- [Documentazione per il tratto "
|
|
|
"`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html)."
|
|
|
|
|
|
#: src\functional/index.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Functional Usage of Rust"
|
|
|
msgstr "# Utilizzo funzionale di Rust"
|
|
|
|
|
|
#: src\functional/index.md:3
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Rust is an imperative language, but it follows many\n"
|
|
|
"[functional "
|
|
|
"programming](https://en.wikipedia.org/wiki/Functional_programming) paradigms."
|
|
|
msgstr ""
|
|
|
"Rust è un linguaggio imperativo, ma ne segue molti\n"
|
|
|
"[programmazione "
|
|
|
"funzionale](https://en.wikipedia.org/wiki/Functional_programming) paradigmi."
|
|
|
|
|
|
#: src\functional/index.md:6
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"> In computer science, _functional programming_ is a programming paradigm "
|
|
|
"where\n"
|
|
|
"> programs are constructed by applying and composing functions.\n"
|
|
|
"> It is a declarative programming paradigm in which function definitions "
|
|
|
"are\n"
|
|
|
"> trees of expressions that each return a value, rather than a sequence of\n"
|
|
|
"> imperative statements which change the state of the program."
|
|
|
msgstr ""
|
|
|
"> In informatica, la _programmazione funzionale_ è un paradigma di "
|
|
|
"programmazione in cui\n"
|
|
|
"> i programmi sono costruiti applicando e componendo funzioni.\n"
|
|
|
"> È un paradigma di programmazione dichiarativo in cui le definizioni di "
|
|
|
"funzione sono\n"
|
|
|
"> alberi di espressioni che restituiscono ciascuno un valore, piuttosto che "
|
|
|
"una sequenza di\n"
|
|
|
"> affermazioni imperative che cambiano lo stato del programma."
|
|
|
|
|
|
#: src\functional/paradigms.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Programming paradigms"
|
|
|
msgstr "# Paradigmi di programmazione"
|
|
|
|
|
|
#: src\functional/paradigms.md:3
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"One of the biggest hurdles to understanding functional programs when coming\n"
|
|
|
"from an imperative background is the shift in thinking. Imperative programs\n"
|
|
|
"describe **how** to do something, whereas declarative programs describe\n"
|
|
|
"**what** to do. Let's sum the numbers from 1 to 10 to show this."
|
|
|
msgstr ""
|
|
|
"Uno dei maggiori ostacoli alla comprensione dei programmi funzionali in "
|
|
|
"arrivo\n"
|
|
|
"da uno sfondo imperativo è il cambiamento nel pensiero. Programmi "
|
|
|
"imperativi\n"
|
|
|
"descrivono **come** fare qualcosa, mentre i programmi dichiarativi "
|
|
|
"descrivono\n"
|
|
|
"**cosa fare. Sommiamo i numeri da 1 a 10 per mostrarlo."
|
|
|
|
|
|
#: src\functional/paradigms.md:8
|
|
|
#, fuzzy
|
|
|
msgid "## Imperative"
|
|
|
msgstr "## Imperativo"
|
|
|
|
|
|
#: src\functional/paradigms.md:10
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"let mut sum = 0;\n"
|
|
|
"for i in 1..11 {\n"
|
|
|
" sum += i;\n"
|
|
|
"}\n"
|
|
|
"println!(\"{}\", sum);\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\functional/paradigms.md:18
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"With imperative programs, we have to play compiler to see what is "
|
|
|
"happening.\n"
|
|
|
"Here, we start with a `sum` of `0`.\n"
|
|
|
"Next, we iterate through the range from 1 to 10.\n"
|
|
|
"Each time through the loop, we add the corresponding value in the range.\n"
|
|
|
"Then we print it out."
|
|
|
msgstr ""
|
|
|
"Con i programmi imperativi, dobbiamo giocare al compilatore per vedere cosa "
|
|
|
"sta succedendo.\n"
|
|
|
"Qui, iniziamo con una \"somma\" di \"0\".\n"
|
|
|
"Successivamente, iteriamo attraverso l'intervallo da 1 a 10.\n"
|
|
|
"Ogni volta attraverso il ciclo, aggiungiamo il valore corrispondente "
|
|
|
"nell'intervallo.\n"
|
|
|
"Quindi lo stampiamo."
|
|
|
|
|
|
#: src\functional/paradigms.md:24
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"| `i` | `sum` |\n"
|
|
|
"| :-: | :---: |\n"
|
|
|
"| 1 | 1 |\n"
|
|
|
"| 2 | 3 |\n"
|
|
|
"| 3 | 6 |\n"
|
|
|
"| 4 | 10 |\n"
|
|
|
"| 5 | 15 |\n"
|
|
|
"| 6 | 21 |\n"
|
|
|
"| 7 | 28 |\n"
|
|
|
"| 8 | 36 |\n"
|
|
|
"| 9 | 45 |\n"
|
|
|
"| 10 | 55 |"
|
|
|
msgstr ""
|
|
|
"| `io` | `somma` |\n"
|
|
|
"| :-: | :---: |\n"
|
|
|
"| 1 | 1 |\n"
|
|
|
"| 2 | 3 |\n"
|
|
|
"| 3 | 6 |\n"
|
|
|
"| 4 | 10 |\n"
|
|
|
"| 5 | 15 |\n"
|
|
|
"| 6 | 21 |\n"
|
|
|
"| 7 | 28 |\n"
|
|
|
"| 8 | 36 |\n"
|
|
|
"| 9 | 45 |\n"
|
|
|
"| 10 | 55|"
|
|
|
|
|
|
#: src\functional/paradigms.md:37
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This is how most of us start out programming. We learn that a program is a "
|
|
|
"set\n"
|
|
|
"of steps."
|
|
|
msgstr ""
|
|
|
"Questo è il modo in cui la maggior parte di noi inizia a programmare. "
|
|
|
"Impariamo che un programma è un insieme\n"
|
|
|
"di passi."
|
|
|
|
|
|
#: src\functional/paradigms.md:40
|
|
|
#, fuzzy
|
|
|
msgid "## Declarative"
|
|
|
msgstr "## Dichiarativo"
|
|
|
|
|
|
#: src\functional/paradigms.md:42
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"println!(\"{}\", (1..11).fold(0, |a, b| a + b));\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\functional/paradigms.md:46
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Whoa! This is really different! What's going on here?\n"
|
|
|
"Remember that with declarative programs we are describing **what** to do,\n"
|
|
|
"rather than **how** to do it. `fold` is a function that "
|
|
|
"[composes](https://en.wikipedia.org/wiki/Function_composition)\n"
|
|
|
"functions. The name is a convention from Haskell."
|
|
|
msgstr ""
|
|
|
"Ehi! Questo è davvero diverso! Cosa sta succedendo qui?\n"
|
|
|
"Ricorda che con i programmi dichiarativi stiamo descrivendo **cosa** fare,\n"
|
|
|
"piuttosto che **come** farlo. `fold` è una funzione che "
|
|
|
"[compone](https://en.wikipedia.org/wiki/Function_composition)\n"
|
|
|
"funzioni. Il nome è una convenzione di Haskell."
|
|
|
|
|
|
#: src\functional/paradigms.md:51
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Here, we are composing functions of addition (this closure: `|a, b| a + b`)\n"
|
|
|
"with a range from 1 to 10. The `0` is the starting point, so `a` is `0` at\n"
|
|
|
"first. `b` is the first element of the range, `1`. `0 + 1 = 1` is the "
|
|
|
"result.\n"
|
|
|
"So now we `fold` again, with `a = 1`, `b = 2` and so `1 + 2 = 3` is the "
|
|
|
"next\n"
|
|
|
"result. This process continues until we get to the last element in the "
|
|
|
"range,\n"
|
|
|
"`10`."
|
|
|
msgstr ""
|
|
|
"Qui stiamo componendo funzioni di addizione (questa chiusura: `|a, b| a + "
|
|
|
"b`)\n"
|
|
|
"con un intervallo da 1 a 10. Lo \"0\" è il punto di partenza, quindi \"a\" è "
|
|
|
"\"0\" a\n"
|
|
|
"Primo. \"b\" è il primo elemento dell'intervallo, \"1\". `0 + 1 = 1` è il "
|
|
|
"risultato.\n"
|
|
|
"Quindi ora `pieghiamo` di nuovo, con `a = 1`, `b = 2` e quindi `1 + 2 = 3` è "
|
|
|
"il prossimo\n"
|
|
|
"risultato. Questo processo continua finché non arriviamo all'ultimo elemento "
|
|
|
"dell'intervallo,\n"
|
|
|
"`10`."
|
|
|
|
|
|
#: src\functional/paradigms.md:58
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"| `a` | `b` | result |\n"
|
|
|
"| :-: | :-: | :----: |\n"
|
|
|
"| 0 | 1 | 1 |\n"
|
|
|
"| 1 | 2 | 3 |\n"
|
|
|
"| 3 | 3 | 6 |\n"
|
|
|
"| 6 | 4 | 10 |\n"
|
|
|
"| 10 | 5 | 15 |\n"
|
|
|
"| 15 | 6 | 21 |\n"
|
|
|
"| 21 | 7 | 28 |\n"
|
|
|
"| 28 | 8 | 36 |\n"
|
|
|
"| 36 | 9 | 45 |\n"
|
|
|
"| 45 | 10 | 55 |"
|
|
|
msgstr ""
|
|
|
"| `a` | `b` | risultato |\n"
|
|
|
"| :-: | :-: | :----: |\n"
|
|
|
"| 0 | 1 | 1 |\n"
|
|
|
"| 1 | 2 | 3 |\n"
|
|
|
"| 3 | 3 | 6 |\n"
|
|
|
"| 6 | 4 | 10 |\n"
|
|
|
"| 10 | 5 | 15 |\n"
|
|
|
"| 15 | 6 | 21 |\n"
|
|
|
"| 21 | 7 | 28 |\n"
|
|
|
"| 28 | 8 | 36 |\n"
|
|
|
"| 36 | 9 | 45 |\n"
|
|
|
"| 45 | 10 | 55|"
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Generics as Type Classes"
|
|
|
msgstr "# Generics come classi di tipo"
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:5
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Rust's type system is designed more like functional languages (like "
|
|
|
"Haskell)\n"
|
|
|
"rather than imperative languages (like Java and C++). As a result, Rust can "
|
|
|
"turn\n"
|
|
|
"many kinds of programming problems into \"static typing\" problems. This is "
|
|
|
"one\n"
|
|
|
"of the biggest wins of choosing a functional language, and is critical to "
|
|
|
"many\n"
|
|
|
"of Rust's compile time guarantees."
|
|
|
msgstr ""
|
|
|
"Il sistema di tipi di Rust è progettato più come linguaggi funzionali (come "
|
|
|
"Haskell)\n"
|
|
|
"piuttosto che linguaggi imperativi (come Java e C++). Di conseguenza, Rust "
|
|
|
"può trasformarsi\n"
|
|
|
"molti tipi di problemi di programmazione in problemi di \"tipizzazione "
|
|
|
"statica\". Questo è uno\n"
|
|
|
"delle più grandi vittorie nella scelta di un linguaggio funzionale ed è "
|
|
|
"fondamentale per molti\n"
|
|
|
"delle garanzie di tempo di compilazione di Rust."
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:11
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"A key part of this idea is the way generic types work. In C++ and Java, for\n"
|
|
|
"example, generic types are a meta-programming construct for the compiler.\n"
|
|
|
"`vector<int>` and `vector<char>` in C++ are just two different copies of "
|
|
|
"the\n"
|
|
|
"same boilerplate code for a `vector` type (known as a `template`) with two\n"
|
|
|
"different types filled in."
|
|
|
msgstr ""
|
|
|
"Una parte fondamentale di questa idea è il modo in cui funzionano i tipi "
|
|
|
"generici. In C++ e Java, per\n"
|
|
|
"esempio, i tipi generici sono un costrutto di metaprogrammazione per il "
|
|
|
"compilatore.\n"
|
|
|
"`vector<int>` e `vector<char>` in C++ sono solo due copie diverse di\n"
|
|
|
"stesso codice boilerplate per un tipo `vettoriale` (noto come `template`) "
|
|
|
"con due\n"
|
|
|
"diversi tipi compilati."
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:17
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"In Rust, a generic type parameter creates what is known in functional "
|
|
|
"languages\n"
|
|
|
"as a \"type class constraint\", and each different parameter filled in by an "
|
|
|
"end\n"
|
|
|
"user _actually changes the type_. In other words, `Vec<isize>` and "
|
|
|
"`Vec<char>`\n"
|
|
|
"_are two different types_, which are recognized as distinct by all parts of "
|
|
|
"the\n"
|
|
|
"type system."
|
|
|
msgstr ""
|
|
|
"In Rust, un parametro di tipo generico crea ciò che è noto nei linguaggi "
|
|
|
"funzionali\n"
|
|
|
"come \"vincolo di classe di tipo\" e ogni diverso parametro riempito da una "
|
|
|
"fine\n"
|
|
|
"l'utente _effettivamente cambia il tipo_. In altre parole, `Vec<isize>` e "
|
|
|
"`Vec<char>`\n"
|
|
|
"_sono due tipi diversi_, che sono riconosciuti come distinti da tutte le "
|
|
|
"parti del\n"
|
|
|
"sistema tipo."
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:23
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This is called **monomorphization**, where different types are created from\n"
|
|
|
"**polymorphic** code. This special behavior requires `impl` blocks to "
|
|
|
"specify\n"
|
|
|
"generic parameters. Different values for the generic type cause different "
|
|
|
"types,\n"
|
|
|
"and different types can have different `impl` blocks."
|
|
|
msgstr ""
|
|
|
"Questo è chiamato **monomorfizzazione**, da cui vengono creati diversi tipi\n"
|
|
|
"codice **polimorfico**. Questo comportamento speciale richiede la "
|
|
|
"specificazione dei blocchi \"impl\".\n"
|
|
|
"parametri generici. Valori diversi per il tipo generico causano tipi "
|
|
|
"diversi,\n"
|
|
|
"e diversi tipi possono avere diversi blocchi `impl`."
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:28
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"In object-oriented languages, classes can inherit behavior from their "
|
|
|
"parents.\n"
|
|
|
"However, this allows the attachment of not only additional behavior to\n"
|
|
|
"particular members of a type class, but extra behavior as well."
|
|
|
msgstr ""
|
|
|
"Nei linguaggi orientati agli oggetti, le classi possono ereditare il "
|
|
|
"comportamento dai loro genitori.\n"
|
|
|
"Tuttavia, ciò consente l'attaccamento non solo di comportamenti aggiuntivi "
|
|
|
"a\n"
|
|
|
"membri particolari di una classe di tipo, ma anche un comportamento extra."
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:32
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The nearest equivalent is the runtime polymorphism in Javascript and "
|
|
|
"Python,\n"
|
|
|
"where new members can be added to objects willy-nilly by any constructor.\n"
|
|
|
"However, unlike those languages, all of Rust's additional methods can be "
|
|
|
"type\n"
|
|
|
"checked when they are used, because their generics are statically defined. "
|
|
|
"That\n"
|
|
|
"makes them more usable while remaining safe."
|
|
|
msgstr ""
|
|
|
"L'equivalente più vicino è il polimorfismo di runtime in Javascript e "
|
|
|
"Python,\n"
|
|
|
"dove i nuovi membri possono essere aggiunti agli oggetti volenti o nolenti "
|
|
|
"da qualsiasi costruttore.\n"
|
|
|
"Tuttavia, a differenza di questi linguaggi, tutti i metodi aggiuntivi di "
|
|
|
"Rust possono essere digitati\n"
|
|
|
"controllati quando vengono utilizzati, perché i loro generici sono definiti "
|
|
|
"staticamente. Quello\n"
|
|
|
"li rende più utilizzabili pur rimanendo al sicuro."
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:40
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Suppose you are designing a storage server for a series of lab machines.\n"
|
|
|
"Because of the software involved, there are two different protocols you "
|
|
|
"need\n"
|
|
|
"to support: BOOTP (for PXE network boot), and NFS (for remote mount storage)."
|
|
|
msgstr ""
|
|
|
"Si supponga di progettare un server di archiviazione per una serie di "
|
|
|
"computer da laboratorio.\n"
|
|
|
"A causa del software coinvolto, sono necessari due diversi protocolli\n"
|
|
|
"per supportare: BOOTP (per l'avvio di rete PXE) e NFS (per l'archiviazione "
|
|
|
"di montaggio remoto)."
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:44
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Your goal is to have one program, written in Rust, which can handle both of\n"
|
|
|
"them. It will have protocol handlers and listen for both kinds of requests. "
|
|
|
"The\n"
|
|
|
"main application logic will then allow a lab administrator to configure "
|
|
|
"storage\n"
|
|
|
"and security controls for the actual files."
|
|
|
msgstr ""
|
|
|
"Il tuo obiettivo è avere un programma, scritto in Rust, in grado di gestirli "
|
|
|
"entrambi\n"
|
|
|
"loro. Avrà gestori di protocollo e ascolterà entrambi i tipi di richieste. "
|
|
|
"IL\n"
|
|
|
"la logica dell'applicazione principale consentirà quindi a un amministratore "
|
|
|
"di laboratorio di configurare l'archiviazione\n"
|
|
|
"e controlli di sicurezza per i file effettivi."
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:49
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The requests from machines in the lab for files contain the same basic\n"
|
|
|
"information, no matter what protocol they came from: an authentication "
|
|
|
"method,\n"
|
|
|
"and a file name to retrieve. A straightforward implementation would look\n"
|
|
|
"something like this:"
|
|
|
msgstr ""
|
|
|
"Le richieste di file dalle macchine nel laboratorio contengono la stessa "
|
|
|
"base\n"
|
|
|
"informazioni, indipendentemente dal protocollo da cui provengono: un metodo "
|
|
|
"di autenticazione,\n"
|
|
|
"e un nome file da recuperare. Sembrerebbe un'implementazione semplice\n"
|
|
|
"qualcosa come questo:"
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:54
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"enum AuthInfo {\n"
|
|
|
" Nfs(crate::nfs::AuthInfo),\n"
|
|
|
" Bootp(crate::bootp::AuthInfo),\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"struct FileDownloadRequest {\n"
|
|
|
" file_name: PathBuf,\n"
|
|
|
" authentication: AuthInfo,\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:66
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This design might work well enough. But now suppose you needed to support\n"
|
|
|
"adding metadata that was _protocol specific_. For example, with NFS, you\n"
|
|
|
"wanted to determine what their mount point was in order to enforce "
|
|
|
"additional\n"
|
|
|
"security rules."
|
|
|
msgstr ""
|
|
|
"Questo design potrebbe funzionare abbastanza bene. Ma ora supponiamo di aver "
|
|
|
"bisogno di supporto\n"
|
|
|
"aggiunta di metadati che erano _protocol specific_. Ad esempio, con NFS, tu\n"
|
|
|
"voleva determinare quale fosse il loro punto di montaggio per applicare "
|
|
|
"ulteriori\n"
|
|
|
"regole di sicurezza."
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:71
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The way the current struct is designed leaves the protocol decision until\n"
|
|
|
"runtime. That means any method that applies to one protocol and not the "
|
|
|
"other\n"
|
|
|
"requires the programmer to do a runtime check."
|
|
|
msgstr ""
|
|
|
"Il modo in cui è progettata la struttura corrente lascia la decisione del "
|
|
|
"protocollo fino a quando\n"
|
|
|
"tempo di esecuzione. Ciò significa qualsiasi metodo che si applica a un "
|
|
|
"protocollo e non all'altro\n"
|
|
|
"richiede al programmatore di eseguire un controllo di runtime."
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:75
|
|
|
#, fuzzy
|
|
|
msgid "Here is how getting an NFS mount point would look:"
|
|
|
msgstr "Ecco come sarebbe ottenere un punto di montaggio NFS:"
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:77
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"struct FileDownloadRequest {\n"
|
|
|
" file_name: PathBuf,\n"
|
|
|
" authentication: AuthInfo,\n"
|
|
|
" mount_point: Option<PathBuf>,\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"impl FileDownloadRequest {\n"
|
|
|
" // ... other methods ...\n"
|
|
|
"\n"
|
|
|
" /// Gets an NFS mount point if this is an NFS request. Otherwise,\n"
|
|
|
" /// return None.\n"
|
|
|
" pub fn mount_point(&self) -> Option<&Path> {\n"
|
|
|
" self.mount_point.as_ref()\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:95
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Every caller of `mount_point()` must check for `None` and write code to "
|
|
|
"handle\n"
|
|
|
"it. This is true even if they know only NFS requests are ever used in a "
|
|
|
"given\n"
|
|
|
"code path!"
|
|
|
msgstr ""
|
|
|
"Ogni chiamante di `mount_point()` deve verificare la presenza di `None` e "
|
|
|
"scrivere il codice da gestire\n"
|
|
|
"Esso. Questo è vero anche se sanno che solo le richieste NFS vengono "
|
|
|
"utilizzate in un dato dato\n"
|
|
|
"percorso del codice!"
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:99
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"It would be far more optimal to cause a compile-time error if the different\n"
|
|
|
"request types were confused. After all, the entire path of the user's code,\n"
|
|
|
"including what functions from the library they use, will know whether a "
|
|
|
"request\n"
|
|
|
"is an NFS request or a BOOTP request."
|
|
|
msgstr ""
|
|
|
"Sarebbe molto più ottimale causare un errore in fase di compilazione se il "
|
|
|
"diverso\n"
|
|
|
"i tipi di richiesta erano confusi. Dopo tutto, l'intero percorso del codice "
|
|
|
"dell'utente,\n"
|
|
|
"comprese le funzioni della libreria che usano, sapranno se una richiesta\n"
|
|
|
"è una richiesta NFS o una richiesta BOOTP."
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:104
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"In Rust, this is actually possible! The solution is to _add a generic type_ "
|
|
|
"in\n"
|
|
|
"order to split the API."
|
|
|
msgstr ""
|
|
|
"In Rust, questo è effettivamente possibile! La soluzione è _aggiungere un "
|
|
|
"tipo generico_ in\n"
|
|
|
"per dividere l'API."
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:107
|
|
|
#, fuzzy
|
|
|
msgid "Here is what that looks like:"
|
|
|
msgstr "Ecco come appare:"
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:109
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"use std::path::{Path, PathBuf};\n"
|
|
|
"\n"
|
|
|
"mod nfs {\n"
|
|
|
" #[derive(Clone)]\n"
|
|
|
" pub(crate) struct AuthInfo(String); // NFS session management omitted\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"mod bootp {\n"
|
|
|
" pub(crate) struct AuthInfo(); // no authentication in bootp\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"// private module, lest outside users invent their own protocol kinds!\n"
|
|
|
"mod proto_trait {\n"
|
|
|
" use std::path::{Path, PathBuf};\n"
|
|
|
" use super::{bootp, nfs};\n"
|
|
|
"\n"
|
|
|
" pub(crate) trait ProtoKind {\n"
|
|
|
" type AuthInfo;\n"
|
|
|
" fn auth_info(&self) -> Self::AuthInfo;\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" pub struct Nfs {\n"
|
|
|
" auth: nfs::AuthInfo,\n"
|
|
|
" mount_point: PathBuf,\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" impl Nfs {\n"
|
|
|
" pub(crate) fn mount_point(&self) -> &Path {\n"
|
|
|
" &self.mount_point\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" impl ProtoKind for Nfs {\n"
|
|
|
" type AuthInfo = nfs::AuthInfo;\n"
|
|
|
" fn auth_info(&self) -> Self::AuthInfo {\n"
|
|
|
" self.auth.clone()\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" pub struct Bootp(); // no additional metadata\n"
|
|
|
"\n"
|
|
|
" impl ProtoKind for Bootp {\n"
|
|
|
" type AuthInfo = bootp::AuthInfo;\n"
|
|
|
" fn auth_info(&self) -> Self::AuthInfo {\n"
|
|
|
" bootp::AuthInfo()\n"
|
|
|
" }\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"use proto_trait::ProtoKind; // keep internal to prevent impls\n"
|
|
|
"pub use proto_trait::{Nfs, Bootp}; // re-export so callers can see them\n"
|
|
|
"\n"
|
|
|
"struct FileDownloadRequest<P: ProtoKind> {\n"
|
|
|
" file_name: PathBuf,\n"
|
|
|
" protocol: P,\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"// all common API parts go into a generic impl block\n"
|
|
|
"impl<P: ProtoKind> FileDownloadRequest<P> {\n"
|
|
|
" fn file_path(&self) -> &Path {\n"
|
|
|
" &self.file_name\n"
|
|
|
" }\n"
|
|
|
"\n"
|
|
|
" fn auth_info(&self) -> P::AuthInfo {\n"
|
|
|
" self.protocol.auth_info()\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"// all protocol-specific impls go into their own block\n"
|
|
|
"impl FileDownloadRequest<Nfs> {\n"
|
|
|
" fn mount_point(&self) -> &Path {\n"
|
|
|
" self.protocol.mount_point()\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn main() {\n"
|
|
|
" // your code here\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:190
|
|
|
msgid ""
|
|
|
"With this approach, if the user were to make a mistake and use the wrong\n"
|
|
|
"type;"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:193
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"fn main() {\n"
|
|
|
" let mut socket = crate::bootp::listen()?;\n"
|
|
|
" while let Some(request) = socket.next_request()? {\n"
|
|
|
" match request.mount_point().as_ref()\n"
|
|
|
" \"/secure\" => socket.send(\"Access denied\"),\n"
|
|
|
" _ => {} // continue on...\n"
|
|
|
" }\n"
|
|
|
" // Rest of the code here\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:206
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"They would get a syntax error. The type `FileDownloadRequest<Bootp>` does "
|
|
|
"not\n"
|
|
|
"implement `mount_point()`, only the type `FileDownloadRequest<Nfs>` does. "
|
|
|
"And\n"
|
|
|
"that is created by the NFS module, not the BOOTP module of course!"
|
|
|
msgstr ""
|
|
|
"Otterrebbero un errore di sintassi. Il tipo `FileDownloadRequest<Bootp>` no\n"
|
|
|
"implementa `mount_point()`, solo il tipo `FileDownloadRequest<Nfs>` lo fa. "
|
|
|
"E\n"
|
|
|
"creato dal modulo NFS, non dal modulo BOOTP ovviamente!"
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:212
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"First, it allows fields that are common to multiple states to be "
|
|
|
"de-duplicated.\n"
|
|
|
"By making the non-shared fields generic, they are implemented once."
|
|
|
msgstr ""
|
|
|
"Innanzitutto, consente di deduplicare i campi comuni a più stati.\n"
|
|
|
"Rendendo generici i campi non condivisi, questi vengono implementati una "
|
|
|
"volta."
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:215
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Second, it makes the `impl` blocks easier to read, because they are broken "
|
|
|
"down\n"
|
|
|
"by state. Methods common to all states are typed once in one block, and "
|
|
|
"methods\n"
|
|
|
"unique to one state are in a separate block."
|
|
|
msgstr ""
|
|
|
"In secondo luogo, rende i blocchi `impl` più facili da leggere, perché sono "
|
|
|
"scomposti\n"
|
|
|
"per stato. I metodi comuni a tutti gli stati vengono digitati una volta in "
|
|
|
"un blocco e i metodi\n"
|
|
|
"univoci per uno stato si trovano in un blocco separato."
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:219
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Both of these mean there are fewer lines of code, and they are better "
|
|
|
"organized."
|
|
|
msgstr ""
|
|
|
"Entrambi significano che ci sono meno righe di codice e sono meglio "
|
|
|
"organizzati."
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:223
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This currently increases the size of the binary, due to the way "
|
|
|
"monomorphization\n"
|
|
|
"is implemented in the compiler. Hopefully the implementation will be able "
|
|
|
"to\n"
|
|
|
"improve in the future."
|
|
|
msgstr ""
|
|
|
"Questo attualmente aumenta la dimensione del binario, a causa del modo in "
|
|
|
"cui monomorfizzazione\n"
|
|
|
"è implementato nel compilatore. Speriamo che l'attuazione sarà in grado di\n"
|
|
|
"migliorare in futuro."
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:229
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- If a type seems to need a \"split API\" due to construction or partial\n"
|
|
|
" initialization, consider the\n"
|
|
|
" [Builder Pattern](../patterns/creational/builder.md) instead.\n"
|
|
|
"\n"
|
|
|
"- If the API between types does not change -- only the behavior does -- "
|
|
|
"then\n"
|
|
|
" the [Strategy Pattern](../patterns/behavioural/strategy.md) is better "
|
|
|
"used\n"
|
|
|
" instead."
|
|
|
msgstr ""
|
|
|
"- Se un tipo sembra aver bisogno di una \"split API\" a causa della "
|
|
|
"costruzione o parziale\n"
|
|
|
" inizializzazione, considerare il\n"
|
|
|
" [Builder Pattern](../patterns/creational/builder.md) invece.\n"
|
|
|
"\n"
|
|
|
"- Se l'API tra i tipi non cambia, solo il comportamento cambia, allora\n"
|
|
|
" il [Strategy Pattern](../patterns/behavioural/strategy.md) è meglio usato\n"
|
|
|
" Invece."
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:239
|
|
|
#, fuzzy
|
|
|
msgid "This pattern is used throughout the standard library:"
|
|
|
msgstr "Questo modello è utilizzato in tutta la libreria standard:"
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:241
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- `Vec<u8>` can be cast from a String, unlike every other type of "
|
|
|
"`Vec<T>`.[^1]\n"
|
|
|
"- They can also be cast into a binary heap, but only if they contain a type\n"
|
|
|
" that implements the `Ord` trait.[^2]\n"
|
|
|
"- The `to_string` method was specialized for `Cow` only of type `str`.[^3]"
|
|
|
msgstr ""
|
|
|
"- `Vec<u8>` può essere lanciato da una stringa, a differenza di ogni altro "
|
|
|
"tipo di `Vec<T>`.[^1]\n"
|
|
|
"- Possono anche essere inseriti in un heap binario, ma solo se contengono un "
|
|
|
"tipo\n"
|
|
|
" che implementa il tratto `Ord`.[^2]\n"
|
|
|
"- Il metodo `to_string` era specializzato per `Cow` solo di tipo `str`.[^3]"
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:246
|
|
|
#, fuzzy
|
|
|
msgid "It is also used by several popular crates to allow API flexibility:"
|
|
|
msgstr ""
|
|
|
"Viene anche utilizzato da diverse casse popolari per consentire la "
|
|
|
"flessibilità dell'API:"
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:248
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- The `embedded-hal` ecosystem used for embedded devices makes extensive use "
|
|
|
"of\n"
|
|
|
" this pattern. For example, it allows statically verifying the "
|
|
|
"configuration of\n"
|
|
|
" device registers used to control embedded pins. When a pin is put into a "
|
|
|
"mode,\n"
|
|
|
" it returns a `Pin<MODE>` struct, whose generic determines the functions\n"
|
|
|
" usable in that mode, which are not on the `Pin` itself. [^4]\n"
|
|
|
"\n"
|
|
|
"- The `hyper` HTTP client library uses this to expose rich APIs for "
|
|
|
"different\n"
|
|
|
" pluggable requests. Clients with different connectors have different "
|
|
|
"methods\n"
|
|
|
" on them as well as different trait implementations, while a core set of\n"
|
|
|
" methods apply to any connector. [^5]\n"
|
|
|
"\n"
|
|
|
"- The \"type state\" pattern -- where an object gains and loses API based on "
|
|
|
"an\n"
|
|
|
" internal state or invariant -- is implemented in Rust using the same "
|
|
|
"basic\n"
|
|
|
" concept, and a slightly different technique. [^6]"
|
|
|
msgstr ""
|
|
|
"- L'ecosistema `embedded-hal` utilizzato per i dispositivi embedded fa ampio "
|
|
|
"uso di\n"
|
|
|
" questo modello. Ad esempio, consente di verificare staticamente la "
|
|
|
"configurazione di\n"
|
|
|
" registri del dispositivo utilizzati per controllare i pin incorporati. "
|
|
|
"Quando un pin viene messo in una modalità,\n"
|
|
|
" restituisce una struttura `Pin<MODE>`, il cui generico determina le "
|
|
|
"funzioni\n"
|
|
|
" utilizzabili in quella modalità, che non sono sul `Pin` stesso. [^4]\n"
|
|
|
"\n"
|
|
|
"- La libreria client `hyper` HTTP utilizza questo per esporre ricche API per "
|
|
|
"diversi\n"
|
|
|
" richieste collegabili. I client con connettori diversi hanno metodi "
|
|
|
"diversi\n"
|
|
|
" su di essi così come diverse implementazioni di tratti, mentre un set di "
|
|
|
"base di\n"
|
|
|
" metodi si applicano a qualsiasi connettore. [^5]\n"
|
|
|
"\n"
|
|
|
"- Il modello \"tipo stato\" -- in cui un oggetto guadagna e perde l'API in "
|
|
|
"base a un\n"
|
|
|
" stato interno o invariante -- è implementato in Rust usando la stessa "
|
|
|
"base\n"
|
|
|
" concetto e una tecnica leggermente diversa. [^6]"
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:263
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"See: [impl From\\<CString\\> for "
|
|
|
"Vec\\<u8\\>](https://doc.rust-lang.org/1.59.0/src/std/ffi/c_str.rs.html#803-811)"
|
|
|
msgstr ""
|
|
|
"Vedere: [impl From\\<CString\\> for "
|
|
|
"Vec\\<u8\\>](https://doc.rust-lang.org/1.59.0/src/std/ffi/c_str.rs.html#803-811 "
|
|
|
")"
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:265
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"See: [impl\\<T\\> From\\<Vec\\<T, Global\\>\\> for "
|
|
|
"BinaryHeap\\<T\\>](https://doc.rust-lang.org/stable/src/alloc/collections/binary_heap.rs.html#1345-1354)"
|
|
|
msgstr ""
|
|
|
"Vedere: [impl\\<T\\> From\\<Vec\\<T, Global\\>\\> for "
|
|
|
"BinaryHeap\\<T\\>](https://doc.rust-lang.org/stable/src/alloc/collections "
|
|
|
"/binary_heap.rs.html#1345-1354)"
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:267
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"See: [impl\\<'\\_\\> ToString for Cow\\<'\\_, "
|
|
|
"str>](https://doc.rust-lang.org/stable/src/alloc/string.rs.html#2235-2240)"
|
|
|
msgstr ""
|
|
|
"Vedi: [impl\\<'\\_\\> ToString for Cow\\<'\\_, "
|
|
|
"str>](https://doc.rust-lang.org/stable/src/alloc/string.rs.html#2235- 2240)"
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:269
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Example:\n"
|
|
|
"[https://docs.rs/stm32f30x-hal/0.1.0/stm32f30x_hal/gpio/gpioa/struct.PA0.html](https://docs.rs/stm32f30x-hal/0.1.0/stm32f30x_hal/gpio/gpioa/struct.PA0.html)"
|
|
|
msgstr ""
|
|
|
"Esempio:\n"
|
|
|
"[https://docs.rs/stm32f30x-hal/0.1.0/stm32f30x_hal/gpio/gpioa/struct.PA0.html](https://docs.rs/stm32f30x-hal/0.1.0/stm32f30x_hal/gpio/ "
|
|
|
"gpioa/struct.PA0.html)"
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:272
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"See:\n"
|
|
|
"[https://docs.rs/hyper/0.14.5/hyper/client/struct.Client.html](https://docs.rs/hyper/0.14.5/hyper/client/struct.Client.html)"
|
|
|
msgstr ""
|
|
|
"Vedere:\n"
|
|
|
"[https://docs.rs/hyper/0.14.5/hyper/client/struct.Client.html](https://docs.rs/hyper/0.14.5/hyper/client/struct.Client.html)"
|
|
|
|
|
|
#: src\functional/generics-type-classes.md:275
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"See:\n"
|
|
|
"[The Case for the Type State "
|
|
|
"Pattern](https://web.archive.org/web/20210325065112/https://www.novatec-gmbh.de/en/blog/the-case-for-the-typestate-pattern-the-typestate-pattern-itself/)\n"
|
|
|
"and\n"
|
|
|
"[Rusty Typestate Series (an extensive "
|
|
|
"thesis)](https://web.archive.org/web/20210328164854/https://rustype.github.io/notes/notes/rust-typestate-series/rust-typestate-index)"
|
|
|
msgstr ""
|
|
|
"Vedere:\n"
|
|
|
"[The Case for the Type State "
|
|
|
"Pattern](https://web.archive.org/web/20210325065112/https://www.novatec-gmbh.de/en/blog/the-case-for-the-typestate- "
|
|
|
"pattern-the-typestate-pattern-itself/)\n"
|
|
|
"E\n"
|
|
|
"[Rusty Typestate Series (una tesi "
|
|
|
"estesa)](https://web.archive.org/web/20210328164854/https://rustype.github.io/notes/notes/rust-typestate-series/rust-typestate-index "
|
|
|
")"
|
|
|
|
|
|
#: src\functional/lenses.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Lenses and Prisms"
|
|
|
msgstr "# Lenti e prismi"
|
|
|
|
|
|
#: src\functional/lenses.md:3
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This is a pure functional concept that is not frequently used in Rust.\n"
|
|
|
"Nevertheless, exploring the concept may be helpful to understand other\n"
|
|
|
"patterns in Rust APIs, such as "
|
|
|
"[visitors](../patterns/behavioural/visitor.md).\n"
|
|
|
"They also have niche use cases."
|
|
|
msgstr ""
|
|
|
"Questo è un puro concetto funzionale che non viene usato frequentemente in "
|
|
|
"Rust.\n"
|
|
|
"Tuttavia, esplorare il concetto può essere utile per capirne altri\n"
|
|
|
"pattern nelle API di Rust, come "
|
|
|
"[visitors](../patterns/behavioural/visitor.md).\n"
|
|
|
"Hanno anche casi d'uso di nicchia."
|
|
|
|
|
|
#: src\functional/lenses.md:8
|
|
|
#, fuzzy
|
|
|
msgid "## Lenses: Uniform Access Across Types"
|
|
|
msgstr "## Lenti: accesso uniforme tra i tipi"
|
|
|
|
|
|
#: src\functional/lenses.md:10
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"A lens is a concept from functional programming languages that allows\n"
|
|
|
"accessing parts of a data type in an abstract, unified way.[^1]\n"
|
|
|
"In basic concept, it is similar to the way Rust traits work with type "
|
|
|
"erasure,\n"
|
|
|
"but it has a bit more power and flexibility."
|
|
|
msgstr ""
|
|
|
"Una lente è un concetto dei linguaggi di programmazione funzionale che "
|
|
|
"consente\n"
|
|
|
"accedere a parti di un tipo di dati in modo astratto e unificato.[^1]\n"
|
|
|
"Nel concetto di base, è simile al modo in cui i tratti di Rust funzionano "
|
|
|
"con la cancellazione del tipo,\n"
|
|
|
"ma ha un po' più di potenza e flessibilità."
|
|
|
|
|
|
#: src\functional/lenses.md:15
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"For example, suppose a bank contains several JSON formats for customer\n"
|
|
|
"data.\n"
|
|
|
"This is because they come from different databases or legacy systems.\n"
|
|
|
"One database contains the data needed to perform credit checks:"
|
|
|
msgstr ""
|
|
|
"Ad esempio, supponiamo che una banca contenga diversi formati JSON per il "
|
|
|
"cliente\n"
|
|
|
"dati.\n"
|
|
|
"Questo perché provengono da diversi database o sistemi legacy.\n"
|
|
|
"Un database contiene i dati necessari per eseguire i controlli del credito:"
|
|
|
|
|
|
#: src\functional/lenses.md:20
|
|
|
msgid ""
|
|
|
"```json\n"
|
|
|
"{ \"name\": \"Jane Doe\",\n"
|
|
|
" \"dob\": \"2002-02-24\",\n"
|
|
|
" [...]\n"
|
|
|
" \"customer_id\": 1048576332,\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\functional/lenses.md:28
|
|
|
#, fuzzy
|
|
|
msgid "Another one contains the account information:"
|
|
|
msgstr "Un altro contiene le informazioni sull'account:"
|
|
|
|
|
|
#: src\functional/lenses.md:30
|
|
|
msgid ""
|
|
|
"```json\n"
|
|
|
"{ \"customer_id\": 1048576332,\n"
|
|
|
" \"accounts\": [\n"
|
|
|
" { \"account_id\": 2121,\n"
|
|
|
" \"account_type: \"savings\",\n"
|
|
|
" \"joint_customer_ids\": [],\n"
|
|
|
" [...]\n"
|
|
|
" },\n"
|
|
|
" { \"account_id\": 2122,\n"
|
|
|
" \"account_type: \"checking\",\n"
|
|
|
" \"joint_customer_ids\": [1048576333],\n"
|
|
|
" [...]\n"
|
|
|
" },\n"
|
|
|
" ]\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\functional/lenses.md:47
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Notice that both types have a customer ID number which corresponds to a "
|
|
|
"person.\n"
|
|
|
"How would a single function handle both records of different types?"
|
|
|
msgstr ""
|
|
|
"Si noti che entrambi i tipi hanno un numero ID cliente che corrisponde a una "
|
|
|
"persona.\n"
|
|
|
"In che modo una singola funzione gestirà entrambi i record di tipi diversi?"
|
|
|
|
|
|
#: src\functional/lenses.md:50
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"In Rust, a `struct` could represent each of these types, and a trait would "
|
|
|
"have\n"
|
|
|
"a `get_customer_id` function they would implement:"
|
|
|
msgstr ""
|
|
|
"In Rust, una `struct` potrebbe rappresentare ciascuno di questi tipi e un "
|
|
|
"tratto lo farebbe\n"
|
|
|
"una funzione `get_customer_id` che implementerebbero:"
|
|
|
|
|
|
#: src\functional/lenses.md:53
|
|
|
msgid ""
|
|
|
"```rust\n"
|
|
|
"use std::collections::HashSet;\n"
|
|
|
"\n"
|
|
|
"pub struct Account {\n"
|
|
|
" account_id: u32,\n"
|
|
|
" account_type: String,\n"
|
|
|
" // other fields omitted\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"pub trait CustomerId {\n"
|
|
|
" fn get_customer_id(&self) -> u64;\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"pub struct CreditRecord {\n"
|
|
|
" customer_id: u64,\n"
|
|
|
" name: String,\n"
|
|
|
" dob: String,\n"
|
|
|
" // other fields omitted\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"impl CustomerId for CreditRecord {\n"
|
|
|
" fn get_customer_id(&self) -> u64 {\n"
|
|
|
" self.customer_id\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"pub struct AccountRecord {\n"
|
|
|
" customer_id: u64,\n"
|
|
|
" accounts: Vec<Account>,\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"impl CustomerId for AccountRecord {\n"
|
|
|
" fn get_customer_id(&self) -> u64 {\n"
|
|
|
" self.customer_id\n"
|
|
|
" }\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"// static polymorphism: only one type, but each function call can choose it\n"
|
|
|
"fn unique_ids_set<R: CustomerId>(records: &[R]) -> HashSet<u64> {\n"
|
|
|
" records.iter().map(|r| r.get_customer_id()).collect()\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"// dynamic dispatch: iterates over any type with a customer ID, collecting "
|
|
|
"all\n"
|
|
|
"// values together\n"
|
|
|
"fn unique_ids_iter<I>(iterator: I) -> HashSet<u64>\n"
|
|
|
" where I: Iterator<Item=Box<dyn CustomerId>>\n"
|
|
|
"{\n"
|
|
|
" iterator.map(|r| r.as_ref().get_customer_id()).collect()\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\functional/lenses.md:104
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Lenses, however, allow the code supporting customer ID to be moved from the\n"
|
|
|
"_type_ to the _accessor function_.\n"
|
|
|
"Rather than implementing a trait on each type, all matching structures can\n"
|
|
|
"simply be accessed the same way."
|
|
|
msgstr ""
|
|
|
"Le lenti, tuttavia, consentono di spostare il codice che supporta l'ID "
|
|
|
"cliente dal file\n"
|
|
|
"_type_ alla _funzione di accesso_.\n"
|
|
|
"Invece di implementare un tratto su ciascun tipo, tutte le strutture "
|
|
|
"corrispondenti possono farlo\n"
|
|
|
"essere semplicemente accessibile allo stesso modo."
|
|
|
|
|
|
#: src\functional/lenses.md:109
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"While the Rust language itself does not support this (type erasure is the\n"
|
|
|
"preferred solution to this problem), the [lens-rs "
|
|
|
"crate](https://github.com/TOETOE55/lens-rs/blob/master/guide.md) allows "
|
|
|
"code\n"
|
|
|
"that feels like this to be written with macros:"
|
|
|
msgstr ""
|
|
|
"Anche se il linguaggio Rust stesso non lo supporta (la cancellazione del "
|
|
|
"tipo è il file\n"
|
|
|
"soluzione preferita a questo problema), il [lens-rs "
|
|
|
"crate](https://github.com/TOETOE55/lens-rs/blob/master/guide.md) consente il "
|
|
|
"codice\n"
|
|
|
"che sembra così da scrivere con le macro:"
|
|
|
|
|
|
#: src\functional/lenses.md:113
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"use std::collections::HashSet;\n"
|
|
|
"\n"
|
|
|
"use lens_rs::{optics, Lens, LensRef, Optics};\n"
|
|
|
"\n"
|
|
|
"#[derive(Clone, Debug, Lens /* derive to allow lenses to work */)]\n"
|
|
|
"pub struct CreditRecord {\n"
|
|
|
" #[optic(ref)] // macro attribute to allow viewing this field\n"
|
|
|
" customer_id: u64,\n"
|
|
|
" name: String,\n"
|
|
|
" dob: String,\n"
|
|
|
" // other fields omitted\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"#[derive(Clone, Debug)]\n"
|
|
|
"pub struct Account {\n"
|
|
|
" account_id: u32,\n"
|
|
|
" account_type: String,\n"
|
|
|
" // other fields omitted\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"#[derive(Clone, Debug, Lens)]\n"
|
|
|
"pub struct AccountRecord {\n"
|
|
|
" #[optic(ref)]\n"
|
|
|
" customer_id: u64,\n"
|
|
|
" accounts: Vec<Account>,\n"
|
|
|
"}\n"
|
|
|
"\n"
|
|
|
"fn unique_ids_lens<T>(iter: impl Iterator<Item = T>) -> HashSet<u64>\n"
|
|
|
"where\n"
|
|
|
" T: LensRef<Optics![customer_id], u64>, // any type with this field\n"
|
|
|
"{\n"
|
|
|
" iter.map(|r| *r.view_ref(optics!(customer_id))).collect()\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\functional/lenses.md:149
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The version of `unique_ids_lens` shown here allows any type to be in the "
|
|
|
"iterator,\n"
|
|
|
"so long as it has an attribute called `customer_id` which can be accessed "
|
|
|
"by\n"
|
|
|
"the function.\n"
|
|
|
"This is how most functional programming languages operate on lenses."
|
|
|
msgstr ""
|
|
|
"La versione di `unique_ids_lens` mostrata qui consente a qualsiasi tipo di "
|
|
|
"essere nell'iteratore,\n"
|
|
|
"fintanto che ha un attributo chiamato `customer_id` a cui è possibile "
|
|
|
"accedere\n"
|
|
|
"la funzione.\n"
|
|
|
"Questo è il modo in cui la maggior parte dei linguaggi di programmazione "
|
|
|
"funzionali opera sugli obiettivi."
|
|
|
|
|
|
#: src\functional/lenses.md:154
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Rather than macros, they achieve this with a technique known as "
|
|
|
"\"currying\".\n"
|
|
|
"That is, they \"partially construct\" the function, leaving the type of the\n"
|
|
|
"final parameter (the value being operated on) unfilled until the function "
|
|
|
"is\n"
|
|
|
"called.\n"
|
|
|
"Thus it can be called with different types dynamically even from one place "
|
|
|
"in\n"
|
|
|
"the code.\n"
|
|
|
"That is what the `optics!` and `view_ref` in the example above simulates."
|
|
|
msgstr ""
|
|
|
"Piuttosto che macro, ottengono questo risultato con una tecnica nota come "
|
|
|
"\"currying\".\n"
|
|
|
"Cioè, \"costruiscono parzialmente\" la funzione, lasciando il tipo di\n"
|
|
|
"parametro finale (il valore su cui si sta operando) vuoto finché la funzione "
|
|
|
"non lo è\n"
|
|
|
"chiamato.\n"
|
|
|
"Quindi può essere chiamato dinamicamente con tipi diversi anche da un posto "
|
|
|
"all'interno\n"
|
|
|
"il codice.\n"
|
|
|
"Questo è ciò che simulano `optics!` e `view_ref` nell'esempio precedente."
|
|
|
|
|
|
#: src\functional/lenses.md:162
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The functional approach need not be restricted to accessing members.\n"
|
|
|
"More powerful lenses can be created which both _set_ and _get_ data in a\n"
|
|
|
"structure.\n"
|
|
|
"But the concept really becomes interesting when used as a building block "
|
|
|
"for\n"
|
|
|
"composition.\n"
|
|
|
"That is where the concept appears more clearly in Rust."
|
|
|
msgstr ""
|
|
|
"L'approccio funzionale non deve essere limitato all'accesso ai membri.\n"
|
|
|
"È possibile creare lenti più potenti che sia _set_ che _get_ dati in a\n"
|
|
|
"struttura.\n"
|
|
|
"Ma il concetto diventa davvero interessante se usato come elemento "
|
|
|
"costitutivo per\n"
|
|
|
"composizione.\n"
|
|
|
"È qui che il concetto appare più chiaramente in Rust."
|
|
|
|
|
|
#: src\functional/lenses.md:169
|
|
|
#, fuzzy
|
|
|
msgid "## Prisms: A Higher-Order form of \"Optics\""
|
|
|
msgstr "## Prismi: una forma di \"ottica\" di ordine superiore"
|
|
|
|
|
|
#: src\functional/lenses.md:171
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"A simple function such as `unique_ids_lens` above operates on a single "
|
|
|
"lens.\n"
|
|
|
"A _prism_ is a function that operates on a _family_ of lenses.\n"
|
|
|
"It is one conceptual level higher, using lenses as a building block, and\n"
|
|
|
"continuing the metaphor, is part of a family of \"optics\".\n"
|
|
|
"It is the main one that is useful in understanding Rust APIs, so will be "
|
|
|
"the\n"
|
|
|
"focus here."
|
|
|
msgstr ""
|
|
|
"Una semplice funzione come `unique_ids_lens` sopra opera su un singolo "
|
|
|
"obiettivo.\n"
|
|
|
"Un _prisma_ è una funzione che opera su una _famiglia_ di lenti.\n"
|
|
|
"È un livello concettuale più alto, usando le lenti come elemento "
|
|
|
"costitutivo, e\n"
|
|
|
"continuando la metafora, fa parte di una famiglia di \"ottiche\".\n"
|
|
|
"È il principale utile per comprendere le API di Rust, così come lo sarà il\n"
|
|
|
"concentrati qui."
|
|
|
|
|
|
#: src\functional/lenses.md:178
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The same way that traits allow \"lens-like\" design with static polymorphism "
|
|
|
"and\n"
|
|
|
"dynamic dispatch, prism-like designs appear in Rust APIs which split "
|
|
|
"problems\n"
|
|
|
"into multiple associated types to be composed.\n"
|
|
|
"A good example of this is the traits in the parsing crate _Serde_."
|
|
|
msgstr ""
|
|
|
"Allo stesso modo in cui i tratti consentono un design \"simile a una lente\" "
|
|
|
"con polimorfismo statico e\n"
|
|
|
"invio dinamico, i design simili a prismi appaiono nelle API di Rust che "
|
|
|
"suddividono i problemi\n"
|
|
|
"in più tipi associati da comporre.\n"
|
|
|
"Un buon esempio di ciò sono i tratti nella cassa di analisi _Serde_."
|
|
|
|
|
|
#: src\functional/lenses.md:183
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Trying to understand the way _Serde_ works by only reading the API is a\n"
|
|
|
"challenge, especially the first time.\n"
|
|
|
"Consider the `Deserializer` trait, implemented by some type in any library\n"
|
|
|
"which parses a new format:"
|
|
|
msgstr ""
|
|
|
"Cercare di capire il modo in cui funziona _Serde_ leggendo solo l'API è un\n"
|
|
|
"sfida, soprattutto la prima volta.\n"
|
|
|
"Considera il tratto `Deserializer`, implementato da qualche tipo in "
|
|
|
"qualsiasi libreria\n"
|
|
|
"che analizza un nuovo formato:"
|
|
|
|
|
|
#: src\functional/lenses.md:188
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"pub trait Deserializer<'de>: Sized {\n"
|
|
|
" type Error: Error;\n"
|
|
|
"\n"
|
|
|
" fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, "
|
|
|
"Self::Error>\n"
|
|
|
" where\n"
|
|
|
" V: Visitor<'de>;\n"
|
|
|
"\n"
|
|
|
" fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, "
|
|
|
"Self::Error>\n"
|
|
|
" where\n"
|
|
|
" V: Visitor<'de>;\n"
|
|
|
"\n"
|
|
|
" // remainder ommitted\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\functional/lenses.md:204
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"For a trait that is just supposed to parse data from a format and return a\n"
|
|
|
"value, this looks odd."
|
|
|
msgstr ""
|
|
|
"Per un tratto che dovrebbe solo analizzare i dati da un formato e restituire "
|
|
|
"a\n"
|
|
|
"valore, questo sembra strano."
|
|
|
|
|
|
#: src\functional/lenses.md:207
|
|
|
#, fuzzy
|
|
|
msgid "Why are all the return types type erased?"
|
|
|
msgstr "Perché tutti i tipi restituiti vengono cancellati?"
|
|
|
|
|
|
#: src\functional/lenses.md:209
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"To understand that, we need to keep the lens concept in mind and look at\n"
|
|
|
"the definition of the `Visitor` type that is passed in generically:"
|
|
|
msgstr ""
|
|
|
"Per capirlo, dobbiamo tenere a mente il concetto di obiettivo e guardare\n"
|
|
|
"la definizione del tipo `Visitor` che viene passata genericamente:"
|
|
|
|
|
|
#: src\functional/lenses.md:212
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"pub trait Visitor<'de>: Sized {\n"
|
|
|
" type Value;\n"
|
|
|
"\n"
|
|
|
" fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>\n"
|
|
|
" where\n"
|
|
|
" E: Error;\n"
|
|
|
"\n"
|
|
|
" fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>\n"
|
|
|
" where\n"
|
|
|
" E: Error;\n"
|
|
|
"\n"
|
|
|
" fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>\n"
|
|
|
" where\n"
|
|
|
" E: Error;\n"
|
|
|
"\n"
|
|
|
" // remainder omitted\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\functional/lenses.md:232
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The job of the `Visitor` type is to construct values in the _Serde_ data "
|
|
|
"model,\n"
|
|
|
"which are represented by its associated `Value` type."
|
|
|
msgstr ""
|
|
|
"Il compito del tipo `Visitor` è costruire valori nel modello di dati "
|
|
|
"_Serde_,\n"
|
|
|
"che sono rappresentati dal tipo \"Valore\" associato."
|
|
|
|
|
|
#: src\functional/lenses.md:235
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"These values represent parts of the Rust value being deserialized.\n"
|
|
|
"If this fails, it returns an `Error` type - an error type determined by the\n"
|
|
|
"`Deserializer` when its methods were called."
|
|
|
msgstr ""
|
|
|
"Questi valori rappresentano parti del valore Rust che vengono "
|
|
|
"deserializzate.\n"
|
|
|
"Se fallisce, restituisce un tipo `Error` - un tipo di errore determinato dal "
|
|
|
"file\n"
|
|
|
"`Deserializer` quando sono stati chiamati i suoi metodi."
|
|
|
|
|
|
#: src\functional/lenses.md:239
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This highlights that `Deserializer` is similar to `CustomerId` from "
|
|
|
"earlier,\n"
|
|
|
"allowing any format parser which implements it to create `Value`s based on "
|
|
|
"what\n"
|
|
|
"it parsed.\n"
|
|
|
"The `Value` trait is acting like a lens in functional programming languages."
|
|
|
msgstr ""
|
|
|
"Ciò evidenzia che \"Deserializer\" è simile a \"CustomerId\" di prima,\n"
|
|
|
"consentendo a qualsiasi parser di formato che lo implementa di creare "
|
|
|
"`Valori` in base a cosa\n"
|
|
|
"ha analizzato.\n"
|
|
|
"Il tratto \"Valore\" agisce come una lente nei linguaggi di programmazione "
|
|
|
"funzionale."
|
|
|
|
|
|
#: src\functional/lenses.md:244
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"But unlike the `CustomerId` trait, the return types of `Visitor` methods "
|
|
|
"are\n"
|
|
|
"_generic_, and the concrete `Value` type is _determined by the Visitor "
|
|
|
"itself_."
|
|
|
msgstr ""
|
|
|
"Ma a differenza del tratto `CustomerId`, i tipi restituiti dei metodi "
|
|
|
"`Visitor` lo sono\n"
|
|
|
"_generico_, e il tipo `Valore` concreto è _determinato dal Visitatore "
|
|
|
"stesso_."
|
|
|
|
|
|
#: src\functional/lenses.md:247
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Instead of acting as one lens, it effectively acts as a family of\n"
|
|
|
"lenses, one for each concrete type of `Visitor`."
|
|
|
msgstr ""
|
|
|
"Invece di agire come una lente, agisce effettivamente come una famiglia di\n"
|
|
|
"lenti, una per ogni concreto tipo di `Visitatore`."
|
|
|
|
|
|
#: src\functional/lenses.md:250
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The `Deserializer` API is based on having a generic set of \"lenses\" work "
|
|
|
"across\n"
|
|
|
"a set of other generic types for \"observation\".\n"
|
|
|
"It is a _prism_."
|
|
|
msgstr ""
|
|
|
"L'API `Deserializer` si basa sull'utilizzo di un insieme generico di "
|
|
|
"\"lenti\".\n"
|
|
|
"un insieme di altri tipi generici per \"osservazione\".\n"
|
|
|
"È un _prisma_."
|
|
|
|
|
|
#: src\functional/lenses.md:254
|
|
|
#, fuzzy
|
|
|
msgid "For example, consider the identity record from earlier but simplified:"
|
|
|
msgstr "Ad esempio, considera il record di identità precedente ma semplificato:"
|
|
|
|
|
|
#: src\functional/lenses.md:256
|
|
|
msgid ""
|
|
|
"```json\n"
|
|
|
"{ \"name\": \"Jane Doe\",\n"
|
|
|
" \"customer_id\": 1048576332,\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\functional/lenses.md:262
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"How would the _Serde_ library deserialize this JSON into `struct "
|
|
|
"CreditRecord`?"
|
|
|
msgstr ""
|
|
|
"In che modo la libreria _Serde_ deserializzerebbe questo JSON in \"struct "
|
|
|
"CreditRecord\"?"
|
|
|
|
|
|
#: src\functional/lenses.md:264
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"1. The user would call a library function to deserialize the data. This "
|
|
|
"would\n"
|
|
|
" create a `Deserializer` based on the JSON format.\n"
|
|
|
"1. Based on the fields in the struct, a `Visitor` would be created (more on\n"
|
|
|
" that in a moment) which knows how to create each type in a generic data\n"
|
|
|
" model that was needed to represent it: `u64` and `String`.\n"
|
|
|
"1. The deserializer would make calls to the `Visitor` as it parsed items.\n"
|
|
|
"1. The `Visitor` would indicate if the items found were expected, and if "
|
|
|
"not,\n"
|
|
|
" raise an error to indicate deserialization has failed."
|
|
|
msgstr ""
|
|
|
"1. L'utente chiamerebbe una funzione di libreria per deserializzare i dati. "
|
|
|
"Questo sarebbe\n"
|
|
|
" creare un \"Deserializer\" basato sul formato JSON.\n"
|
|
|
"1. Sulla base dei campi nella struttura, verrebbe creato un \"Visitatore\" "
|
|
|
"(maggiori informazioni su\n"
|
|
|
" che in un attimo) che sa creare ogni tipo in un dato generico\n"
|
|
|
" modello necessario per rappresentarlo: `u64` e `String`.\n"
|
|
|
"1. Il deserializzatore effettuerebbe chiamate al \"Visitatore\" durante "
|
|
|
"l'analisi degli elementi.\n"
|
|
|
"1. Il \"Visitatore\" indicherebbe se gli elementi trovati erano attesi e, in "
|
|
|
"caso contrario,\n"
|
|
|
" genera un errore per indicare che la deserializzazione non è riuscita."
|
|
|
|
|
|
#: src\functional/lenses.md:273
|
|
|
#, fuzzy
|
|
|
msgid "For our very simple structure above, the expected pattern would be:"
|
|
|
msgstr ""
|
|
|
"Per la nostra struttura molto semplice sopra, il modello previsto sarebbe:"
|
|
|
|
|
|
#: src\functional/lenses.md:275
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"1. Visit a map (_Serde_'s equvialent to `HashMap` or JSON's dictionary).\n"
|
|
|
"1. Visit a string key called \"name\".\n"
|
|
|
"1. Visit a string value, which will go into the `name` field.\n"
|
|
|
"1. Visit a string key called \"customer_id\".\n"
|
|
|
"1. Visit a string value, which will go into the `customer_id` field.\n"
|
|
|
"1. Visit the end of the map."
|
|
|
msgstr ""
|
|
|
"1. Visita una mappa (l'equivalente di _Serde_ a `HashMap` o il dizionario di "
|
|
|
"JSON).\n"
|
|
|
"1. Visita una chiave di stringa chiamata \"nome\".\n"
|
|
|
"1. Visita un valore stringa, che andrà nel campo `name`.\n"
|
|
|
"1. Visita una chiave stringa chiamata \"customer_id\".\n"
|
|
|
"1. Visita un valore stringa, che andrà nel campo `customer_id`.\n"
|
|
|
"1. Visita la fine della mappa."
|
|
|
|
|
|
#: src\functional/lenses.md:282
|
|
|
#, fuzzy
|
|
|
msgid "But what determines which \"observation\" pattern is expected?"
|
|
|
msgstr "Ma cosa determina quale modello di \"osservazione\" ci si aspetta?"
|
|
|
|
|
|
#: src\functional/lenses.md:284
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"A functional programming language would be able to use currying to create\n"
|
|
|
"reflection of each type based on the type itself.\n"
|
|
|
"Rust does not support that, so every single type would need to have its own\n"
|
|
|
"code written based on its fields and their properties."
|
|
|
msgstr ""
|
|
|
"Un linguaggio di programmazione funzionale sarebbe in grado di utilizzare il "
|
|
|
"currying per creare\n"
|
|
|
"riflesso di ogni tipo in base al tipo stesso.\n"
|
|
|
"Rust non lo supporta, quindi ogni singolo tipo dovrebbe averne uno proprio\n"
|
|
|
"codice scritto in base ai suoi campi e alle loro proprietà."
|
|
|
|
|
|
#: src\functional/lenses.md:289
|
|
|
#, fuzzy
|
|
|
msgid "_Serde_ solves this usability challenge with a derive macro:"
|
|
|
msgstr "_Serde_ risolve questa sfida di usabilità con una deriva macro:"
|
|
|
|
|
|
#: src\functional/lenses.md:291
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"use serde::Deserialize;\n"
|
|
|
"\n"
|
|
|
"#[derive(Deserialize)]\n"
|
|
|
"struct IdRecord {\n"
|
|
|
" name: String,\n"
|
|
|
" customer_id: String,\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\functional/lenses.md:301
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"That macro simply generates an impl block causing the struct to implement a\n"
|
|
|
"trait called `Deserialize`."
|
|
|
msgstr ""
|
|
|
"Quella macro genera semplicemente un blocco impl che fa sì che la struct "
|
|
|
"implementi a\n"
|
|
|
"tratto chiamato \"Deserialize\"."
|
|
|
|
|
|
#: src\functional/lenses.md:304
|
|
|
#, fuzzy
|
|
|
msgid "It is defined this way:"
|
|
|
msgstr "È definito in questo modo:"
|
|
|
|
|
|
#: src\functional/lenses.md:306
|
|
|
msgid ""
|
|
|
"```rust,ignore\n"
|
|
|
"pub trait Deserialize<'de>: Sized {\n"
|
|
|
" fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n"
|
|
|
" where\n"
|
|
|
" D: Deserializer<'de>;\n"
|
|
|
"}\n"
|
|
|
"```"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\functional/lenses.md:314
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"This is the function that determines how to create the struct itself.\n"
|
|
|
"Code is generated based on the struct's fields.\n"
|
|
|
"When the parsing library is called - in our example, a JSON parsing library "
|
|
|
"-\n"
|
|
|
"it creates a `Deserializer` and calls `Type::deserialize` with it as a\n"
|
|
|
"parameter."
|
|
|
msgstr ""
|
|
|
"Questa è la funzione che determina come creare la struttura stessa.\n"
|
|
|
"Il codice viene generato in base ai campi della struttura.\n"
|
|
|
"Quando viene chiamata la libreria di analisi, nel nostro esempio una "
|
|
|
"libreria di analisi JSON,\n"
|
|
|
"crea un \"Deserializer\" e chiama \"Type::deserialize\" con esso come a\n"
|
|
|
"parametro."
|
|
|
|
|
|
#: src\functional/lenses.md:320
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The `deserialize` code will then create a `Visitor` which will have its "
|
|
|
"calls\n"
|
|
|
"\"refracted\" by the `Deserializer`.\n"
|
|
|
"If everything goes well, eventually that `Visitor` will construct a value\n"
|
|
|
"corresponding to the type being parsed and return it."
|
|
|
msgstr ""
|
|
|
"Il codice `deserialize` creerà quindi un `Visitor` che avrà le sue chiamate\n"
|
|
|
"\"rifratta\" dal `Deserializzatore`.\n"
|
|
|
"Se tutto va bene, alla fine quel \"Visitatore\" costruirà un valore\n"
|
|
|
"corrispondente al tipo analizzato e lo restituisce."
|
|
|
|
|
|
#: src\functional/lenses.md:325
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"For a complete example, see the [_Serde_ "
|
|
|
"documentation](https://serde.rs/deserialize-struct.html)."
|
|
|
msgstr ""
|
|
|
"Per un esempio completo, consulta la "
|
|
|
"[documentazione_Serde_](https://serde.rs/deserialize-struct.html)."
|
|
|
|
|
|
#: src\functional/lenses.md:327
|
|
|
#, fuzzy
|
|
|
msgid "To wrap up, this is the power of _Serde_:"
|
|
|
msgstr "Per concludere, questo è il potere di _Serde_:"
|
|
|
|
|
|
#: src\functional/lenses.md:329
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"1. The structure being parsed is represented by an `impl` block for "
|
|
|
"`Deserialize`\n"
|
|
|
"1. The input data format (e.g. JSON) is represented by a `Deserializer` "
|
|
|
"called\n"
|
|
|
" by `Deserialize`\n"
|
|
|
"1. The `Deserializer` acts like a prism which \"refracts\" lens-like "
|
|
|
"`Visitor`\n"
|
|
|
" calls which actually build the data value"
|
|
|
msgstr ""
|
|
|
"1. La struttura analizzata è rappresentata da un blocco `impl` per "
|
|
|
"`Deserialize`\n"
|
|
|
"1. Il formato dei dati di input (ad es. JSON) è rappresentato da un "
|
|
|
"`Deserializzatore` chiamato\n"
|
|
|
" da \"Deserializzare\".\n"
|
|
|
"1. Il \"Deserializzatore\" agisce come un prisma che \"rifrange\" il "
|
|
|
"\"Visitatore\" simile a una lente\n"
|
|
|
" chiamate che effettivamente costruiscono il valore dei dati"
|
|
|
|
|
|
#: src\functional/lenses.md:335
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"The result is that types to be deserialized only implement the \"top layer\" "
|
|
|
"of\n"
|
|
|
"the API, and file formats only need to implement the \"bottom layer\".\n"
|
|
|
"Each piece can then \"just work\" with the rest of the ecosystem, since "
|
|
|
"generic\n"
|
|
|
"types will bridge them."
|
|
|
msgstr ""
|
|
|
"Il risultato è che i tipi da deserializzare implementano solo il \"livello "
|
|
|
"superiore\" di\n"
|
|
|
"l'API e i formati di file devono solo implementare il \"livello "
|
|
|
"inferiore\".\n"
|
|
|
"Ogni pezzo può quindi \"funzionare semplicemente\" con il resto "
|
|
|
"dell'ecosistema, poiché generico\n"
|
|
|
"i tipi li collegheranno."
|
|
|
|
|
|
#: src\functional/lenses.md:340
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"To emphasize, the only reason this model works on any format and any type "
|
|
|
"is\n"
|
|
|
"because the `Deserializer` trait's output type **is specified by the\n"
|
|
|
"implementor of `Visitor` it is passed**, rather than being tied to one "
|
|
|
"specific\n"
|
|
|
"type.\n"
|
|
|
"This was not true in the account example earlier."
|
|
|
msgstr ""
|
|
|
"Per sottolineare, l'unico motivo per cui questo modello funziona su "
|
|
|
"qualsiasi formato e qualsiasi tipo è\n"
|
|
|
"perché il tipo di output del tratto `Deserializer` **è specificato da\n"
|
|
|
"implementatore di `Visitor` viene passato**, piuttosto che essere legato a "
|
|
|
"uno specifico\n"
|
|
|
"tipo.\n"
|
|
|
"Questo non era vero nell'esempio dell'account precedente."
|
|
|
|
|
|
#: src\functional/lenses.md:346
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"Rust's generic-inspired type system can bring it close to these concepts "
|
|
|
"and\n"
|
|
|
"use their power, as shown in this API design.\n"
|
|
|
"But it may also need procedural macros to create bridges for its generics."
|
|
|
msgstr ""
|
|
|
"Il sistema di tipi di ispirazione generica di Rust può avvicinarlo a questi "
|
|
|
"concetti e\n"
|
|
|
"usa il loro potere, come mostrato in questo progetto API.\n"
|
|
|
"Ma potrebbe anche aver bisogno di macro procedurali per creare ponti per i "
|
|
|
"suoi generici."
|
|
|
|
|
|
#: src\functional/lenses.md:350
|
|
|
#, fuzzy
|
|
|
msgid "## See Also"
|
|
|
msgstr "## Guarda anche"
|
|
|
|
|
|
#: src\functional/lenses.md:352
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [lens-rs crate](https://crates.io/crates/lens-rs) for a pre-built lenses\n"
|
|
|
" implementation, with a cleaner interface than these examples\n"
|
|
|
"- [serde](https://serde.rs) itself, which makes these concepts intuitive "
|
|
|
"for\n"
|
|
|
" end users (i.e. defining the structs) without needing to undestand the\n"
|
|
|
" details\n"
|
|
|
"- [luminance](https://github.com/phaazon/luminance-rs) is a crate for "
|
|
|
"drawing\n"
|
|
|
" computer graphics that uses lens API design, including proceducal macros "
|
|
|
"to\n"
|
|
|
" create full prisms for buffers of different pixel types that remain "
|
|
|
"generic\n"
|
|
|
"- [An Article about Lenses in "
|
|
|
"Scala](https://web.archive.org/web/20221128185849/https://medium.com/zyseme-technology/functional-references-lens-and-other-optics-in-scala-e5f7e2fdafe)\n"
|
|
|
" that is very readable even without Scala expertise.\n"
|
|
|
"- [Paper: Profunctor Optics: Modular Data\n"
|
|
|
" "
|
|
|
"Accessors](https://web.archive.org/web/20220701102832/https://arxiv.org/ftp/arxiv/papers/1703/1703.10857.pdf)"
|
|
|
msgstr ""
|
|
|
"- [lens-rs crate](https://crates.io/crates/lens-rs) per obiettivi "
|
|
|
"predefiniti\n"
|
|
|
" implementazione, con un'interfaccia più pulita rispetto a questi esempi\n"
|
|
|
"- [serde](https://serde.rs) stesso, che rende questi concetti intuitivi per\n"
|
|
|
" utenti finali (ovvero definendo le strutture) senza la necessità di "
|
|
|
"comprendere il\n"
|
|
|
" dettagli\n"
|
|
|
"- [luminance](https://github.com/phaazon/luminance-rs) è una cassa per "
|
|
|
"disegnare\n"
|
|
|
" computer grafica che utilizza la progettazione dell'API dell'obiettivo, "
|
|
|
"comprese le macro procedurali per\n"
|
|
|
" creare prismi completi per buffer di diversi tipi di pixel che rimangono "
|
|
|
"generici\n"
|
|
|
"- [Un articolo sulle lenti in "
|
|
|
"Scala](https://web.archive.org/web/20221128185849/https://medium.com/zyseme-technology/functional-references-lens-and-other-optics-in- "
|
|
|
"scala-e5f7e2fdafe)\n"
|
|
|
" che è molto leggibile anche senza l'esperienza di Scala.\n"
|
|
|
"- [Documento: Profunctor Optics: Modular Data\n"
|
|
|
" "
|
|
|
"Accessor](https://web.archive.org/web/20220701102832/https://arxiv.org/ftp/arxiv/papers/1703/1703.10857.pdf)"
|
|
|
|
|
|
#: src\functional/lenses.md:365
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"[School of Haskell: A Little Lens Starter "
|
|
|
"Tutorial](https://web.archive.org/web/20221128190041/https://www.schoolofhaskell.com/school/to-infinity-and-beyond/pick-of-the-week/a-little-lens-starter-tutorial)"
|
|
|
msgstr ""
|
|
|
"[Scuola di Haskell: un piccolo tutorial per iniziare con "
|
|
|
"l'obiettivo](https://web.archive.org/web/20221128190041/https://www.schoolofhaskell.com/school/to-infinity-and-beyond/pick-of- "
|
|
|
"la-settimana/un-piccolo-tutorial-di-avviamento)"
|
|
|
|
|
|
#: src\additional_resources/index.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Additional resources"
|
|
|
msgstr "# Risorse addizionali"
|
|
|
|
|
|
#: src\additional_resources/index.md:3
|
|
|
#, fuzzy
|
|
|
msgid "A collection of complementary helpful content"
|
|
|
msgstr "Una raccolta di contenuti utili complementari"
|
|
|
|
|
|
#: src\additional_resources/index.md:5
|
|
|
#, fuzzy
|
|
|
msgid "## Talks"
|
|
|
msgstr "## Colloqui"
|
|
|
|
|
|
#: src\additional_resources/index.md:7
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [Design Patterns in Rust](https://www.youtube.com/watch?v=Pm_oO0N5B9k) by\n"
|
|
|
" Nicholas Cameron at the PDRust (2016)\n"
|
|
|
"- [Writing Idiomatic Libraries in "
|
|
|
"Rust](https://www.youtube.com/watch?v=0zOg8_B71gE)\n"
|
|
|
" by Pascal Hertleif at RustFest (2017)\n"
|
|
|
"- [Rust Programming Techniques](https://www.youtube.com/watch?v=vqavdUGKeb4) "
|
|
|
"by\n"
|
|
|
" Nicholas Cameron at LinuxConfAu (2018)"
|
|
|
msgstr ""
|
|
|
"- [Modelli di design in "
|
|
|
"ruggine](https://www.youtube.com/watch?v=Pm_oO0N5B9k) di\n"
|
|
|
" Nicholas Cameron al PDRust (2016)\n"
|
|
|
"- [Scrivere librerie idiomatiche in "
|
|
|
"Rust](https://www.youtube.com/watch?v=0zOg8_B71gE)\n"
|
|
|
" di Pascal Hertleif al RustFest (2017)\n"
|
|
|
"- [Tecniche di programmazione "
|
|
|
"Rust](https://www.youtube.com/watch?v=vqavdUGKeb4) di\n"
|
|
|
" Nicholas Cameron alla LinuxConfAu (2018)"
|
|
|
|
|
|
#: src\additional_resources/index.md:14
|
|
|
#, fuzzy
|
|
|
msgid "## Books (Online)"
|
|
|
msgstr "## Libri (online)"
|
|
|
|
|
|
#: src\additional_resources/index.md:16
|
|
|
#, fuzzy
|
|
|
msgid "- [The Rust API Guidelines](https://rust-lang.github.io/api-guidelines)"
|
|
|
msgstr ""
|
|
|
"- [Le linee guida dell'API di "
|
|
|
"Rust](https://rust-lang.github.io/api-guidelines)"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:1
|
|
|
#, fuzzy
|
|
|
msgid "# Design principles"
|
|
|
msgstr "# Principi di progettazione"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:3
|
|
|
#, fuzzy
|
|
|
msgid "## A brief overview over common design principles"
|
|
|
msgstr "## Una breve panoramica sui principi di progettazione comuni"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:7
|
|
|
#, fuzzy
|
|
|
msgid "## [SOLID](https://en.wikipedia.org/wiki/SOLID)"
|
|
|
msgstr "## [SOLIDO](https://en.wikipedia.org/wiki/SOLIDO)"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:9
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"- [Single Responsibility Principle "
|
|
|
"(SRP)](https://en.wikipedia.org/wiki/Single-responsibility_principle):\n"
|
|
|
" A class should only have a single responsibility, that is, only changes "
|
|
|
"to\n"
|
|
|
" one part of the software's specification should be able to affect the\n"
|
|
|
" specification of the class.\n"
|
|
|
"- [Open/Closed Principle "
|
|
|
"(OCP)](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle):\n"
|
|
|
" \"Software entities ... should be open for extension, but closed for\n"
|
|
|
" modification.\"\n"
|
|
|
"- [Liskov Substitution Principle "
|
|
|
"(LSP)](https://en.wikipedia.org/wiki/Liskov_substitution_principle):\n"
|
|
|
" \"Objects in a program should be replaceable with instances of their "
|
|
|
"subtypes\n"
|
|
|
" without altering the correctness of that program.\"\n"
|
|
|
"- [Interface Segregation Principle "
|
|
|
"(ISP)](https://en.wikipedia.org/wiki/Interface_segregation_principle):\n"
|
|
|
" \"Many client-specific interfaces are better than one general-purpose\n"
|
|
|
" interface.\"\n"
|
|
|
"- [Dependency Inversion Principle "
|
|
|
"(DIP)](https://en.wikipedia.org/wiki/Dependency_inversion_principle):\n"
|
|
|
" One should \"depend upon abstractions, [not] concretions.\""
|
|
|
msgstr ""
|
|
|
"- [Principio di responsabilità singola "
|
|
|
"(SRP)](https://en.wikipedia.org/wiki/Single-responsibility_principle):\n"
|
|
|
" Una classe dovrebbe avere una sola responsabilità, cioè solo modifiche a\n"
|
|
|
" una parte delle specifiche del software dovrebbe essere in grado di "
|
|
|
"influenzare il file\n"
|
|
|
" specifica della classe.\n"
|
|
|
"- [Principio aperto/chiuso "
|
|
|
"(OCP)](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle):\n"
|
|
|
" \"Le entità software ... dovrebbero essere aperte per l'estensione, ma "
|
|
|
"chiuse per\n"
|
|
|
" modifica.\"\n"
|
|
|
"- [Principio di sostituzione di Liskov "
|
|
|
"(LSP)](https://en.wikipedia.org/wiki/Liskov_substitution_principle):\n"
|
|
|
" \"Gli oggetti in un programma dovrebbero essere sostituibili con istanze "
|
|
|
"dei loro sottotipi\n"
|
|
|
" senza alterare la correttezza di quel programma.\"\n"
|
|
|
"- [Principio di segregazione dell'interfaccia "
|
|
|
"(ISP)](https://en.wikipedia.org/wiki/Interface_segregation_principle):\n"
|
|
|
" \"Molte interfacce specifiche del client sono migliori di una generica\n"
|
|
|
" interfaccia.\"\n"
|
|
|
"- [Principio di inversione delle dipendenze "
|
|
|
"(DIP)](https://en.wikipedia.org/wiki/Dependency_inversion_principle):\n"
|
|
|
" Si dovrebbe \"dipendere dalle astrazioni, [non] dalle concrezioni\"."
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:25
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"## [DRY (Don’t Repeat "
|
|
|
"Yourself)](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)"
|
|
|
msgstr ""
|
|
|
"## [DRY (Non "
|
|
|
"ripeterti)](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:27
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"\"Every piece of knowledge must have a single, unambiguous, authoritative\n"
|
|
|
"representation within a system\""
|
|
|
msgstr ""
|
|
|
"\"Ogni conoscenza deve avere un unico, univoco, autorevole\n"
|
|
|
"rappresentazione all'interno di un sistema\""
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:30
|
|
|
#, fuzzy
|
|
|
msgid "## [KISS principle](https://en.wikipedia.org/wiki/KISS_principle)"
|
|
|
msgstr "## [Principio KISS](https://en.wikipedia.org/wiki/KISS_principle)"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:32
|
|
|
msgid ""
|
|
|
"most systems work best if they are kept simple rather than made "
|
|
|
"complicated;\n"
|
|
|
"therefore, simplicity should be a key goal in design, and unnecessary\n"
|
|
|
"complexity should be avoided"
|
|
|
msgstr ""
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:36
|
|
|
#, fuzzy
|
|
|
msgid "## [Law of Demeter (LoD)](https://en.wikipedia.org/wiki/Law_of_Demeter)"
|
|
|
msgstr ""
|
|
|
"## [Legge di Demetra (LoD)](https://en.wikipedia.org/wiki/Law_of_Demeter)"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:38
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"a given object should assume as little as possible about the structure or\n"
|
|
|
"properties of anything else (including its subcomponents), in accordance "
|
|
|
"with\n"
|
|
|
"the principle of \"information hiding\""
|
|
|
msgstr ""
|
|
|
"un dato oggetto dovrebbe presumere il meno possibile sulla struttura o\n"
|
|
|
"proprietà di qualsiasi altra cosa (compresi i suoi sottocomponenti), in "
|
|
|
"conformità con\n"
|
|
|
"il principio di \"occultamento delle informazioni\""
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:42
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"## [Design by contract "
|
|
|
"(DbC)](https://en.wikipedia.org/wiki/Design_by_contract)"
|
|
|
msgstr ""
|
|
|
"## [Design by contract "
|
|
|
"(DbC)](https://en.wikipedia.org/wiki/Design_by_contract)"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:44
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"software designers should define formal, precise and verifiable interface\n"
|
|
|
"specifications for software components, which extend the ordinary definition "
|
|
|
"of\n"
|
|
|
"abstract data types with preconditions, postconditions and invariants"
|
|
|
msgstr ""
|
|
|
"i progettisti di software dovrebbero definire un'interfaccia formale, "
|
|
|
"precisa e verificabile\n"
|
|
|
"specifiche per i componenti software, che estendono la definizione ordinaria "
|
|
|
"di\n"
|
|
|
"tipi di dati astratti con precondizioni, postcondizioni e invarianti"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:48
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"## "
|
|
|
"[Encapsulation](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming))"
|
|
|
msgstr ""
|
|
|
"## "
|
|
|
"[Incapsulamento](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming))"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:50
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"bundling of data with the methods that operate on that data, or the "
|
|
|
"restricting\n"
|
|
|
"of direct access to some of an object's components. Encapsulation is used "
|
|
|
"to\n"
|
|
|
"hide the values or state of a structured data object inside a class, "
|
|
|
"preventing\n"
|
|
|
"unauthorized parties' direct access to them."
|
|
|
msgstr ""
|
|
|
"raggruppamento di dati con i metodi che operano su tali dati o la "
|
|
|
"restrizione\n"
|
|
|
"di accesso diretto ad alcuni dei componenti di un oggetto. L'incapsulamento "
|
|
|
"è utilizzato per\n"
|
|
|
"nascondere i valori o lo stato di un oggetto di dati strutturati all'interno "
|
|
|
"di una classe, impedendo\n"
|
|
|
"l'accesso diretto di soggetti non autorizzati."
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:55
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"## "
|
|
|
"[Command-Query-Separation(CQS)](https://en.wikipedia.org/wiki/Command%E2%80%93query_separation)"
|
|
|
msgstr ""
|
|
|
"## "
|
|
|
"[Command-Query-Separation(CQS)](https://en.wikipedia.org/wiki/Command%E2%80%93query_separation)"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:57
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"“Functions should not produce abstract side effects...only commands\n"
|
|
|
"(procedures) will be permitted to produce side effects.” - Bertrand Meyer:\n"
|
|
|
"Object-Oriented Software Construction"
|
|
|
msgstr ""
|
|
|
"“Le funzioni non dovrebbero produrre effetti collaterali astratti... solo "
|
|
|
"comandi\n"
|
|
|
"(procedure) potranno produrre effetti collaterali”. -Bertrand Mayer:\n"
|
|
|
"Costruzione software orientata agli oggetti"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:61
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"## [Principle of least astonishment "
|
|
|
"(POLA)](https://en.wikipedia.org/wiki/Principle_of_least_astonishment)"
|
|
|
msgstr ""
|
|
|
"## [Principio del minimo stupore "
|
|
|
"(POLA)](https://en.wikipedia.org/wiki/Principle_of_least_astonishment)"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:63
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"a component of a system should behave in a way that most users will expect "
|
|
|
"it\n"
|
|
|
"to behave. The behavior should not astonish or surprise users"
|
|
|
msgstr ""
|
|
|
"un componente di un sistema dovrebbe comportarsi in un modo che la maggior "
|
|
|
"parte degli utenti se lo aspetta\n"
|
|
|
"comportarsi. Il comportamento non deve stupire o sorprendere gli utenti"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:66
|
|
|
#, fuzzy
|
|
|
msgid "## Linguistic-Modular-Units"
|
|
|
msgstr "## Unità linguistiche-modulari"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:68
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"“Modules must correspond to syntactic units in the language used.” - "
|
|
|
"Bertrand\n"
|
|
|
"Meyer: Object-Oriented Software Construction"
|
|
|
msgstr ""
|
|
|
"\"I moduli devono corrispondere alle unità sintattiche nella lingua "
|
|
|
"utilizzata.\" - Bertrand\n"
|
|
|
"Meyer: costruzione di software orientato agli oggetti"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:71
|
|
|
#, fuzzy
|
|
|
msgid "## Self-Documentation"
|
|
|
msgstr "## Autodocumentazione"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:73
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"“The designer of a module should strive to make all information about the\n"
|
|
|
"module part of the module itself.” - Bertrand Meyer: Object-Oriented "
|
|
|
"Software\n"
|
|
|
"Construction"
|
|
|
msgstr ""
|
|
|
"“Il progettista di un modulo dovrebbe sforzarsi di rendere tutte le "
|
|
|
"informazioni sul\n"
|
|
|
"modulo parte del modulo stesso.” - Bertrand Meyer: Software orientato agli "
|
|
|
"oggetti\n"
|
|
|
"Costruzione"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:77
|
|
|
#, fuzzy
|
|
|
msgid "## Uniform-Access"
|
|
|
msgstr "## Accesso uniforme"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:79
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"“All services offered by a module should be available through a uniform\n"
|
|
|
"notation, which does not betray whether they are implemented through storage "
|
|
|
"or\n"
|
|
|
"through computation.” - Bertrand Meyer: Object-Oriented Software Construction"
|
|
|
msgstr ""
|
|
|
"“Tutti i servizi offerti da un modulo dovrebbero essere disponibili "
|
|
|
"attraverso un'uniforme\n"
|
|
|
"notazione, che non tradisce se sono implementati tramite archiviazione o\n"
|
|
|
"attraverso il calcolo.” - Bertrand Meyer: Costruzione di software orientato "
|
|
|
"agli oggetti"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:83
|
|
|
#, fuzzy
|
|
|
msgid "## Single-Choice"
|
|
|
msgstr "## Scelta singola"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:85
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"“Whenever a software system must support a set of alternatives, one and "
|
|
|
"only\n"
|
|
|
"one module in the system should know their exhaustive list.” - Bertrand "
|
|
|
"Meyer:\n"
|
|
|
"Object-Oriented Software Construction"
|
|
|
msgstr ""
|
|
|
"“Ogni volta che un sistema software deve supportare un insieme di "
|
|
|
"alternative, una e sola\n"
|
|
|
"un modulo nel sistema dovrebbe conoscere il loro elenco esaustivo. -Bertrand "
|
|
|
"Mayer:\n"
|
|
|
"Costruzione software orientata agli oggetti"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:89
|
|
|
#, fuzzy
|
|
|
msgid "## Persistence-Closure"
|
|
|
msgstr "## Persistenza-Chiusura"
|
|
|
|
|
|
#: src\additional_resources/design-principles.md:91
|
|
|
#, fuzzy
|
|
|
msgid ""
|
|
|
"“Whenever a storage mechanism stores an object, it must store with it the\n"
|
|
|
"dependents of that object. Whenever a retrieval mechanism retrieves a\n"
|
|
|
"previously stored object, it must also retrieve any dependent of that "
|
|
|
"object\n"
|
|
|
"that has not yet been retrieved.” - Bertrand Meyer: Object-Oriented "
|
|
|
"Software\n"
|
|
|
"Construction"
|
|
|
msgstr ""
|
|
|
"“Ogni volta che un meccanismo di archiviazione immagazzina un oggetto, deve "
|
|
|
"immagazzinare con esso il\n"
|
|
|
"dipendenti di quell'oggetto. Ogni volta che un meccanismo di recupero "
|
|
|
"recupera a\n"
|
|
|
"oggetto precedentemente memorizzato, deve anche recuperare qualsiasi "
|
|
|
"dipendente di quell'oggetto\n"
|
|
|
"che non è stato ancora recuperato. - Bertrand Meyer: Software orientato agli "
|
|
|
"oggetti\n"
|
|
|
"Costruzione"
|
|
|
|
|
|
msgid ""
|
|
|
msgstr ""
|
|
|
|
|
|
msgid ""
|
|
|
msgstr ""
|
|
|
|
|
|
msgid ""
|
|
|
msgstr ""
|
|
|
|
|
|
msgid ""
|
|
|
msgstr ""
|
|
|
|
|
|
msgid ""
|
|
|
msgstr ""
|
|
|
|
|
|
msgid ""
|
|
|
msgstr ""
|
|
|
|
|
|
msgid ""
|
|
|
msgstr ""
|
|
|
|
|
|
msgid ""
|
|
|
msgstr ""
|
|
|
|
|
|
msgid ""
|
|
|
msgstr ""
|
|
|
|
|
|
msgid ""
|
|
|
msgstr ""
|
|
|
|
|
|
msgid ""
|
|
|
msgstr ""
|
|
|
|