Repository: rust-unofficial/patterns Branch: main Commit: f279f3541c37 Files: 80 Total size: 1.4 MB Directory structure: gitextract_1gr8fib9/ ├── .dprint.json ├── .github/ │ ├── dependabot.yml │ └── workflows/ │ ├── build.yml │ ├── install-mdbook/ │ │ └── action.yml │ ├── lint.yml │ ├── publish.yml │ ├── setup-rust-cache/ │ │ └── action.yml │ ├── url-check-on-change.yml │ └── url-check-periodic.yml ├── .gitignore ├── .lycheeignore ├── .markdownlint.yaml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── book.toml ├── po/ │ ├── es.po │ ├── it.po │ ├── messages.pot │ └── pt-BR.po ├── src/ │ ├── SUMMARY.md │ ├── additional_resources/ │ │ ├── design-principles.md │ │ └── index.md │ ├── anti_patterns/ │ │ ├── borrow_clone.md │ │ ├── deny-warnings.md │ │ ├── deref.md │ │ └── index.md │ ├── functional/ │ │ ├── generics-type-classes.md │ │ ├── index.md │ │ ├── optics.md │ │ └── paradigms.md │ ├── idioms/ │ │ ├── coercion-arguments.md │ │ ├── concat-format.md │ │ ├── ctor.md │ │ ├── default.md │ │ ├── deref.md │ │ ├── dtor-finally.md │ │ ├── ffi/ │ │ │ ├── accepting-strings.md │ │ │ ├── errors.md │ │ │ ├── intro.md │ │ │ └── passing-strings.md │ │ ├── index.md │ │ ├── mem-replace.md │ │ ├── on-stack-dyn-dispatch.md │ │ ├── option-iter.md │ │ ├── pass-var-to-closure.md │ │ ├── priv-extend.md │ │ ├── return-consumed-arg-on-error.md │ │ ├── rustdoc-init.md │ │ └── temporary-mutability.md │ ├── intro.md │ ├── patterns/ │ │ ├── behavioural/ │ │ │ ├── RAII.md │ │ │ ├── command.md │ │ │ ├── interpreter.md │ │ │ ├── intro.md │ │ │ ├── newtype.md │ │ │ ├── strategy.md │ │ │ └── visitor.md │ │ ├── creational/ │ │ │ ├── builder.md │ │ │ ├── fold.md │ │ │ └── intro.md │ │ ├── ffi/ │ │ │ ├── export.md │ │ │ ├── intro.md │ │ │ └── wrappers.md │ │ ├── index.md │ │ └── structural/ │ │ ├── compose-structs.md │ │ ├── intro.md │ │ ├── small-crates.md │ │ ├── trait-for-bounds.md │ │ └── unsafe-mods.md │ ├── refactoring/ │ │ └── index.md │ └── translations.md ├── styles/ │ └── last-changed.css ├── template.md ├── theme/ │ ├── css/ │ │ └── language-picker.css │ ├── head.hbs │ └── index.hbs └── third_party/ └── mdbook/ ├── LICENSE ├── README.md └── book.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .dprint.json ================================================ { "lineWidth": 80, "markdown": { "lineWidth": 80, "emphasisKind": "asterisks", "strongKind": "asterisks", "textWrap": "always" }, "toml": { "lineWidth": 80 }, "json": { "lineWidth": 80, "indentWidth": 4 }, "includes": [ "**/*.{md}", "**/*.{toml}", "**/*.{json}", "**/*.{js,ts,tsx,jsx}" ], "excludes": [ "book/**/book.js", "theme/book.js", "target/**/*" ], "exec": { "commands": [{ "command": "rustfmt --edition 2021", "exts": ["rs"] }] }, "plugins": [ "https://plugins.dprint.dev/markdown-0.20.0.wasm", "https://plugins.dprint.dev/toml-0.7.0.wasm", "https://plugins.dprint.dev/json-0.21.0.wasm", "https://plugins.dprint.dev/typescript-0.95.13.wasm", "https://plugins.dprint.dev/exec-0.6.0.json@a054130d458f124f9b5c91484833828950723a5af3f8ff2bd1523bd47b83b364" ] } ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: "github-actions" directory: "/" # Check for updates every Monday schedule: interval: "weekly" open-pull-requests-limit: 10 ================================================ FILE: .github/workflows/build.yml ================================================ name: Test mdbook chapters on: pull_request: push: branches: - main env: CARGO_TERM_COLOR: always jobs: mdbook-test: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Rust cache uses: ./.github/workflows/setup-rust-cache - name: Install mdbook uses: ./.github/workflows/install-mdbook - name: Test code snippets run: mdbook test # TODO: Activate when first translation is available # i18n-helpers: # runs-on: ubuntu-latest # steps: # - name: Checkout # uses: actions/checkout@v4 # - name: Install Gettext # run: sudo apt install gettext # - name: Setup Rust cache # uses: ./.github/workflows/setup-rust-cache # - name: Install mdbook # uses: ./.github/workflows/install-mdbook # - name: Generate po/messages.pot # run: mdbook build -d po # env: # MDBOOK_OUTPUT: '{"xgettext": {"pot-file": "messages.pot"}}' # - name: Test messages.pot # run: msgfmt --statistics -o /dev/null po/messages.pot # - name: Expand includes without translation # run: mdbook build -d expanded # env: # MDBOOK_OUTPUT: '{"markdown": {}}' # - name: Expand includes with no-op translation # run: mdbook build -d no-op # env: # MDBOOK_OUTPUT: '{"markdown": {}}' # MDBOOK_PREPROCESSOR__GETTEXT__PO_FILE: po/messages.pot # - name: Compare no translation to no-op translation # run: diff --color=always --unified --recursive expanded no-op # find-translations: # runs-on: ubuntu-latest # outputs: # languages: ${{ steps.find-translations.outputs.languages }} # steps: # - name: Checkout # uses: actions/checkout@v4 # - name: Find translations # id: find-translations # shell: python # run: | # import os, json, pathlib # languages = [p.stem for p in pathlib.Path("po").iterdir() if p.suffix == ".po"] # github_output = open(os.environ["GITHUB_OUTPUT"], "a") # github_output.write("languages=") # json.dump(sorted(languages), github_output) # translations: # runs-on: ubuntu-latest # needs: # - find-translations # strategy: # matrix: # language: ${{ fromJSON(needs.find-translations.outputs.languages) }} # env: # MDBOOK_BOOK__LANGUAGE: ${{ matrix.language }} # steps: # - name: Checkout # uses: actions/checkout@v4 # - name: Install Gettext # run: sudo apt install gettext # - name: Setup Rust cache # uses: ./.github/workflows/setup-rust-cache # - name: Install mdbook # uses: ./.github/workflows/install-mdbook # - name: Test ${{ matrix.language }} translation # run: msgfmt --statistics -o /dev/null po/${{ matrix.language }}.po # - name: Build book with ${{ matrix.language }} translation # run: mdbook build # - name: Upload ${{ matrix.language }} translation # uses: actions/upload-artifact@v3 # with: # name: rust-design-patterns-${{ matrix.language }} # path: book/ # - name: Test code snippets with ${{ matrix.language }} translation # run: mdbook test ================================================ FILE: .github/workflows/install-mdbook/action.yml ================================================ name: Install mdbook and dependencies description: Install the mdbook with the dependencies we need. runs: using: composite steps: - name: Read mdbook version from .env id: mdbook-version run: | . ./.env echo "version=$MDBOOK_VERSION" >> $GITHUB_OUTPUT shell: bash - name: Read mdbook-i18n-helpers version from .env id: mdbook-i18n-helpers-version run: | . ./.env echo "version=$MDBOOK_I18N_HELPERS_VERSION" >> $GITHUB_OUTPUT shell: bash - name: Read mdbook-pandoc version from .env id: mdbook-pandoc-version run: | . ./.env echo "version=$MDBOOK_PANDOC_VERSION" >> $GITHUB_OUTPUT shell: bash - name: Read mdbook-last-changed version from .env id: mdbook-last-changed-version run: | . ./.env echo "version=$MDBOOK_LAST_CHANGED_VERSION" >> $GITHUB_OUTPUT shell: bash - name: Install dependencies uses: taiki-e/install-action@v2 with: tool: mdbook@${{ steps.mdbook-version.outputs.version }},mdbook-pandoc@${{ steps.mdbook-pandoc-version.outputs.version }},mdbook-i18n-helpers@${{ steps.mdbook-i18n-helpers-version.outputs.version }},mdbook-last-changed@${{ steps.mdbook-last-changed-version.outputs.version }} - name: Install mdbook-pandoc and related dependencies run: | . ./.env sudo apt-get update sudo apt-get install -y texlive texlive-latex-extra texlive-luatex texlive-lang-cjk librsvg2-bin fonts-noto curl -LsSf https://github.com/jgm/pandoc/releases/download/$PANDOC_VERSION/pandoc-$PANDOC_VERSION-linux-amd64.tar.gz | tar zxf - echo "$PWD/pandoc-$PANDOC_VERSION/bin" >> $GITHUB_PATH shell: bash ================================================ FILE: .github/workflows/lint.yml ================================================ name: Lint with dprint on: push: branches: [main] pull_request: jobs: style: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install Rust toolchain uses: dtolnay/rust-toolchain@f7ccc83f9ed1e5b9c81d8a67d7ad1a747e22a561 # v1 with: toolchain: stable components: rustfmt - uses: Swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3 # v2 - uses: dprint/check@v2.3 ================================================ FILE: .github/workflows/publish.yml ================================================ name: Deploy mdBook sites to GH Pages on: push: branches: ["main"] workflow_dispatch: permissions: contents: read pages: write id-token: write # Allow one concurrent deployment concurrency: group: "pages" cancel-in-progress: true env: CARGO_TERM_COLOR: always # TODO: Update the language picker in index.hbs to link new languages. # TODO: As long as https://github.com/google/mdbook-i18n-helpers/issues/12 is not implemented, yet. # TODO: Activate when first translation is available # These are the languages in addition to 'en', which is the main language # LANGUAGES: xx jobs: publish: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Rust cache uses: ./.github/workflows/setup-rust-cache - name: Install mdbook uses: ./.github/workflows/install-mdbook - name: Build course in English run: | mdbook build -d book mv book/html/* book/pandoc/pdf/rust-design-patterns.pdf book/ rm -r book/html book/pandoc # TODO: Activate when first translation is available # - name: Build all translations # run: | # for po_lang in ${{ env.LANGUAGES }}; do # echo "::group::Building $po_lang translation" # MDBOOK_BOOK__LANGUAGE=$po_lang \ # MDBOOK_OUTPUT__HTML__SITE_URL=/patterns/$po_lang/ \ # mdbook build -d book/$po_lang # echo "::endgroup::" # done - name: Setup Pages id: pages uses: actions/configure-pages@v5 - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: path: ./book - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 ================================================ FILE: .github/workflows/setup-rust-cache/action.yml ================================================ name: Setup Rust cache description: Configure the rust-cache workflow. runs: using: composite steps: - name: Setup Rust cache uses: Swatinem/rust-cache@v2 with: prefix-key: v1 ================================================ FILE: .github/workflows/url-check-on-change.yml ================================================ name: Check Markdown links on: push: branches: [main] pull_request: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true permissions: {} jobs: markdown-link-check: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: Restore lychee cache uses: actions/cache@v5 with: path: .lycheecache key: cache-lychee-${{ github.sha }} restore-keys: cache-lychee- - name: Link Checker uses: lycheeverse/lychee-action@a8c4c7cb88f0c7386610c35eb25108e448569cb0 # v2.7.0 env: # set the GitHub token to avoid rate limits GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: fail: true args: | --no-progress --accept '100..=103, 200..=299, 429' . ================================================ FILE: .github/workflows/url-check-periodic.yml ================================================ name: Check Markdown links Periodically on: schedule: # Run everyday at 0:00 AM - cron: "0 0 * * *" permissions: {} jobs: markdown-link-check-periodic: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: Restore lychee cache uses: actions/cache@v5 with: path: .lycheecache key: cache-lychee-${{ github.sha }} restore-keys: cache-lychee- - name: Link Checker uses: lycheeverse/lychee-action@a8c4c7cb88f0c7386610c35eb25108e448569cb0 # v2.7.0 env: # set the GitHub token to avoid rate limits GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: fail: true args: | --no-progress --accept '100..=103, 200..=299, 429' . ================================================ FILE: .gitignore ================================================ # Generated output of mdbook /book .DS_Store .vscode/settings.json ================================================ FILE: .lycheeignore ================================================ ^(http|https)://crates.io/ ================================================ FILE: .markdownlint.yaml ================================================ --- # Use `#` for headers MD003: style: atx # Set maximum line length MD013: line_length: 80 # Use `---` for horizontal rule MD035: style: --- # Use ``` for code blocks MD046: style: fenced MD048: style: backtick # See https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md for # additional info ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing ## Introduction This book is a catalogue of Rust programming techniques, (anti-)patterns, idioms and other explanations. It is a compilation of collective (sometimes implicit) knowledge as well as experiences that have emerged through collaborative work. The patterns described here are **not rules**, but should be taken as guidelines for writing idiomatic code in Rust. We are collecting Rust patterns in this book so people can learn the tradeoffs between Rust idioms and use them properly in their own code. If you want to be part of this effort here are some ways you can participate: ## Discussion board If you have a question or an idea regarding certain content, but you want to have feedback of fellow community members, and you think it may not be appropriate to file an issue open a discussion in our [discussion board](https://github.com/rust-unofficial/patterns/discussions). ## Writing a new article Before writing a new article please check in one of the following resources if there is an existing discussion or if someone is already working on that topic: - [Umbrella issue](https://github.com/rust-unofficial/patterns/issues/116), - [All issues](https://github.com/rust-unofficial/patterns/issues), - [Pull Requests](https://github.com/rust-unofficial/patterns/pulls) If you don't find an issue regarding your topic, and you are sure it is not more feasible to open a thread in the [discussion board](https://github.com/rust-unofficial/patterns/discussions) please open a new issue, so we can discuss the ideas and future content of the article together and maybe give some feedback/input on it. When writing a new article it's recommended to copy the [pattern template](https://github.com/rust-unofficial/patterns/blob/master/template.md) into the appropriate directory and start editing it. You may not want to fill out every section and remove it, or you might want to add extra sections. Consider writing your article in a way that has a low barrier of entry so also [Rustlings](https://github.com/rust-lang/rustlings) can follow and understand the thought process behind it. So we can encourage people to use these patterns early on. We encourage you to write idiomatic Rust code that builds in the [playground](https://play.rust-lang.org/). If you use links to blogposts or in general content that is not to be sure existing in a few years (e.g. pdfs) please take a snapshot with the [Wayback Machine](https://web.archive.org/) and use the link to that snapshot in your article. Don't forget to add your new article to the `SUMMARY.md` to let it be rendered to the book. Please make `Draft Pull requests` early, so we can follow your progress and can give early feedback (see the following section). ## Style guide In order to have a consistent style across the book, we suggest to: - Follow the official Rust book's [style guide](https://github.com/rust-lang/book/blob/master/style-guide.md). - Follow [RFC 1574](https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md#appendix-a-full-conventions-text). Tl;dr: - Prefer full types name. For example `Option` instead of `Option`. - Prefer line comments (`//`) over block comments (`/* */`) where applicable. ## Check the article locally Before submitting the PR launch the commands `mdbook build` to make sure that the book builds and `mdbook test` to make sure that code examples are correct. ### Markdown lint To make sure the files comply with our Markdown style we use [markdownlint-cli](https://github.com/igorshubovych/markdownlint-cli). To spare you some manual work to get through the CI test you can use the following commands to automatically fix most of the emerging problems when writing Markdown files. - Install: ```sh npm install -g markdownlint-cli ``` - Check all markdown files: - unix: `markdownlint '**/*.md'` - windows: `markdownlint **/*.md` - Automatically fix basic errors: - unix: `markdownlint -f '**/*.md'` - windows: `markdownlint -f **/*.md` ## Creating a Pull Request "Release early and often!" also applies to pull requests! Once your article has some visible work, create a `[WIP]` draft pull request and give it a description of what you did or want to do. Early reviews of the community are not meant as an offense but to give feedback. A good principle: "Work together, share ideas, teach others." ### Important Note Please **don't force push** commits in your branch, in order to keep commit history and make it easier for us to see changes between reviews. Make sure to `Allow edits of maintainers` (under the text box) in the PR so people can actually collaborate on things or fix smaller issues themselves. ## Maintainers This repository is maintained by the following people: - [simonsan](https://github.com/simonsan). - [marcoieni](https://github.com/marcoieni). Marco only works on the book CI. He doesn't review the book content and he doesn't receive notifications on new issues and pull requests. If you want him to have a look at a CI issue, ping him directly. ================================================ FILE: LICENSE ================================================ Mozilla Public License Version 2.0 ================================== 1. Definitions -------------- 1.1. "Contributor" means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. 1.2. "Contributor Version" means the combination of the Contributions of others (if any) used by a Contributor and that particular Contributor's Contribution. 1.3. "Contribution" means Covered Software of a particular Contributor. 1.4. "Covered Software" means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. 1.5. "Incompatible With Secondary Licenses" means (a) that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or (b) that the Covered Software was made available under the terms of version 1.1 or earlier of the License, but not also under the terms of a Secondary License. 1.6. "Executable Form" means any form of the work other than Source Code Form. 1.7. "Larger Work" means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software. 1.8. "License" means this document. 1.9. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently, any and all of the rights conveyed by this License. 1.10. "Modifications" means any of the following: (a) any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software; or (b) any new file in Source Code Form that contains any Covered Software. 1.11. "Patent Claims" of a Contributor means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of either its Contributions or its Contributor Version. 1.12. "Secondary License" means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. 1.13. "Source Code Form" means the form of the work preferred for making modifications. 1.14. "You" (or "Your") means an individual or a legal entity exercising rights under this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. License Grants and Conditions -------------------------------- 2.1. Grants Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: (a) under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and (b) under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and otherwise transfer either its Contributions or its Contributor Version. 2.2. Effective Date The licenses granted in Section 2.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first distributes such Contribution. 2.3. Limitations on Grant Scope The licenses granted in this Section 2 are the only rights granted under this License. No additional rights or licenses will be implied from the distribution or licensing of Covered Software under this License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor: (a) for any code that a Contributor has removed from Covered Software; or (b) for infringements caused by: (i) Your and any other third party's modifications of Covered Software, or (ii) the combination of its Contributions with other software (except as part of its Contributor Version); or (c) under Patent Claims infringed by Covered Software in the absence of its Contributions. This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the notice requirements in Section 3.4). 2.4. Subsequent Licenses No Contributor makes additional grants as a result of Your choice to distribute the Covered Software under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary License (if permitted under the terms of Section 3.3). 2.5. Representation Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. 2.6. Fair Use This License is not intended to limit any rights You have under applicable copyright doctrines of fair use, fair dealing, or other equivalents. 2.7. Conditions Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1. 3. Responsibilities ------------------- 3.1. Distribution of Source Form All distribution of Covered Software in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License. You must inform recipients that the Source Code Form of the Covered Software is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter or restrict the recipients' rights in the Source Code Form. 3.2. Distribution of Executable Form If You distribute Covered Software in Executable Form then: (a) such Covered Software must also be made available in Source Code Form, as described in Section 3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and (b) You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients' rights in the Source Code Form under this License. 3.3. Distribution of a Larger Work You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s). 3.4. Notices You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Covered Software, except that You may alter any license notices to the extent required to remedy known factual inaccuracies. 3.5. Application of Additional Terms You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, You may do so only on Your own behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any jurisdiction. 4. Inability to Comply Due to Statute or Regulation --------------------------------------------------- If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Software due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be placed in a text file included with all distributions of the Covered Software under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5. Termination -------------- 5.1. The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30 days after Your receipt of the notice. 5.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or Your distributors under this License prior to termination shall survive termination. ************************************************************************ * * * 6. Disclaimer of Warranty * * ------------------------- * * * * Covered Software is provided under this License on an "as is" * * basis, without warranty of any kind, either expressed, implied, or * * statutory, including, without limitation, warranties that the * * Covered Software is free of defects, merchantable, fit for a * * particular purpose or non-infringing. The entire risk as to the * * quality and performance of the Covered Software is with You. * * Should any Covered Software prove defective in any respect, You * * (not any Contributor) assume the cost of any necessary servicing, * * repair, or correction. This disclaimer of warranty constitutes an * * essential part of this License. No use of any Covered Software is * * authorized under this License except under this disclaimer. * * * ************************************************************************ ************************************************************************ * * * 7. Limitation of Liability * * -------------------------- * * * * Under no circumstances and under no legal theory, whether tort * * (including negligence), contract, or otherwise, shall any * * Contributor, or anyone who distributes Covered Software as * * permitted above, be liable to You for any direct, indirect, * * special, incidental, or consequential damages of any character * * including, without limitation, damages for lost profits, loss of * * goodwill, work stoppage, computer failure or malfunction, or any * * and all other commercial damages or losses, even if such party * * shall have been informed of the possibility of such damages. This * * limitation of liability shall not apply to liability for death or * * personal injury resulting from such party's negligence to the * * extent applicable law prohibits such limitation. Some * * jurisdictions do not allow the exclusion or limitation of * * incidental or consequential damages, so this exclusion and * * limitation may not apply to You. * * * ************************************************************************ 8. Litigation ------------- Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party's ability to bring cross-claims or counter-claims. 9. Miscellaneous ---------------- This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor. 10. Versions of the License --------------------------- 10.1. New Versions Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number. 10.2. Effect of New Versions You may distribute the Covered Software under the terms of the version of the License under which You originally received the Covered Software, or under the terms of any subsequent version published by the license steward. 10.3. Modified Versions If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the license steward (except to note that such modified license differs from this License). 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the notice described in Exhibit B of this License must be attached. Exhibit A - Source Code Form License Notice ------------------------------------------- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice. You may add additional accurate notices of copyright ownership. Exhibit B - "Incompatible With Secondary Licenses" Notice --------------------------------------------------------- This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. ================================================ FILE: README.md ================================================ # Rust Design Patterns An open source book about design patterns and idioms in the Rust programming language that you can read [here](https://rust-unofficial.github.io/patterns/). You can also download the book in PDF format from [this link](https://rust-unofficial.github.io/patterns/rust-design-patterns.pdf). ## Contributing You are missing content in this repository that can be helpful for others, and you are eager to explain it? Awesome! We are always happy about new contributions (e.g. elaboration or corrections on certain topics) to this project. You can check the [Umbrella issue](https://github.com/rust-unofficial/patterns/issues/116) for all the patterns, anti-patterns, and idioms that could be added. We suggest reading our [Contribution guide](./CONTRIBUTING.md) to get more information on how contributing to this repository works. ## Building with mdbook This book is built with [mdbook](https://rust-lang.github.io/mdBook/). You can install it by running `cargo install mdbook`. ### Additional dependencies - `cargo install mdbook-last-changed` for date changes in the footer - `cargo install mdbook-pandoc` for rendering the book to PDF - `cargo install mdbook-i18n-helpers` for translation and i8n support #### Texlive ```sh # Source the .env file to get the PANDOC_VERSION . ./.env sudo apt-get update sudo apt-get install -y texlive texlive-latex-extra texlive-luatex texlive-lang-cjk librsvg2-bin fonts-noto curl -LsSf https://github.com/jgm/pandoc/releases/download/$PANDOC_VERSION/pandoc-$PANDOC_VERSION-linux-amd64.tar.gz | tar zxf - ``` ### Building the book If you want to build it locally you can run one of these two commands in the root directory of the repository: - `mdbook build` Builds static html pages as output and place them in the `/book` directory by default. - `mdbook serve` Serves the book at `http://localhost:3000` (port is changeable, take a look at the terminal output to be sure) and reloads the browser when a change occurs. ## License The content of this repository is licensed under **MPL-2.0**; see [LICENSE](./LICENSE). ================================================ FILE: book.toml ================================================ [book] title = "Rust Design Patterns" authors = ["the rust-unofficial authors"] description = "A catalogue of Rust design patterns, anti-patterns and idioms" language = "en" src = "src" [build] create-missing = false extra-watch-dirs = ["po", "third_party"] [preprocessor.gettext] after = ["links"] [rust] edition = "2024" [output.html] smart-punctuation = true default-theme = "rust" site-url = "/patterns/" git-repository-url = "https://github.com/rust-unofficial/patterns" edit-url-template = "https://github.com/rust-unofficial/patterns/edit/main/{path}" additional-css = [ "./theme/css/language-picker.css", "./styles/last-changed.css", ] [preprocessor.last-changed] optional = true command = "mdbook-last-changed" renderer = ["html"] [output.html.fold] enable = true level = 1 [output.html.playground] editable = false # [output.linkcheck] # enable the "mdbook-linkcheck" renderer, disabled due to gh-actions [output.html.redirect] # Redirects in the form of "old-path" = "new-path", where the new path # is relative to the old path. "functional/lenses.html" = "optics.html" [output.pandoc] optional = true hosted-html = "https://rust-unofficial.github.io/patterns/" [output.pandoc.profile.pdf] output-file = "rust-design-patterns.pdf" pdf-engine = "lualatex" [output.pandoc.profile.pdf.variables] mainfont = "Noto Serif" sansfont = "Noto Sans" monofont = "Noto Sans Mono" mainfontfallback = ["NotoSerifCJKSC:"] geometry = ["margin=1in"] linkcolor = "blue" urlcolor = "red" ================================================ FILE: po/es.po ================================================ msgid "" msgstr "" "Project-Id-Version: Rust Design Patterns\n" "POT-Creation-Date: \n" "PO-Revision-Date: 2023-04-08 21:55+0200\n" "Last-Translator: \n" "Language-Team: Spanish\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: src\SUMMARY.md:3 #, fuzzy msgid "Introduction" msgstr "Introducción" #: src\SUMMARY.md:4 #, fuzzy msgid "Translations" msgstr "Traducciones" #: src\SUMMARY.md:5 #, fuzzy msgid "Idioms" msgstr "Modismos" #: src\SUMMARY.md:6 #, fuzzy msgid "Use borrowed types for arguments" msgstr "Usar tipos prestados para argumentos" #: src\SUMMARY.md:7 #, fuzzy msgid "Concatenating Strings with format!" msgstr "¡Concatenación de cadenas con formato!" #: src\SUMMARY.md:8 #, fuzzy msgid "Constructor" msgstr "Constructor" #: src\SUMMARY.md:9 #, fuzzy msgid "The Default Trait" msgstr "El rasgo predeterminado" #: src\SUMMARY.md:10 #, fuzzy msgid "Collections Are Smart Pointers" msgstr "Las colecciones son punteros inteligentes" #: src\SUMMARY.md:11 #, fuzzy msgid "Finalisation in Destructors" msgstr "Finalización en Destructores" #: src\SUMMARY.md:12 #, fuzzy msgid "mem::{take(_), replace(_)}" msgstr "mem::{tomar(_), reemplazar(_)}" #: src\SUMMARY.md:13 #, fuzzy msgid "On-Stack Dynamic Dispatch" msgstr "Despacho dinámico en pila" #: src\SUMMARY.md:14 src\SUMMARY.md:40 #, fuzzy msgid "Foreign function interface (FFI)" msgstr "Interfaz de función externa (FFI)" #: src\SUMMARY.md:15 #, fuzzy msgid "Idiomatic Errors" msgstr "Errores idiomáticos" #: src\SUMMARY.md:16 #, fuzzy msgid "Accepting Strings" msgstr "Aceptar cadenas" #: src\SUMMARY.md:17 #, fuzzy msgid "Passing Strings" msgstr "Pasar cuerdas" #: src\SUMMARY.md:18 #, fuzzy msgid "Iterating over an Option" msgstr "Iterando sobre una opción" #: src\SUMMARY.md:19 #, fuzzy msgid "Pass Variables to Closure" msgstr "Pasar variables al cierre" #: src\SUMMARY.md:20 #, fuzzy msgid "Privacy For Extensibility" msgstr "Privacidad para extensibilidad" #: src\SUMMARY.md:21 #, fuzzy msgid "Easy doc initialization" msgstr "Fácil inicialización de documentos" #: src\SUMMARY.md:22 #, fuzzy msgid "Temporary mutability" msgstr "Mutabilidad temporal" #: src\SUMMARY.md:23 #, fuzzy msgid "Return consumed arg on error" msgstr "Devolver argumento consumido en caso de error" #: src\SUMMARY.md:25 #, fuzzy msgid "Design Patterns" msgstr "Patrones de diseño" #: src\SUMMARY.md:26 #, fuzzy msgid "Behavioural" msgstr "conductual" #: src\SUMMARY.md:27 #, fuzzy msgid "Command" msgstr "Dominio" #: src\SUMMARY.md:28 #, fuzzy msgid "Interpreter" msgstr "Intérprete" #: src\SUMMARY.md:29 #, fuzzy msgid "Newtype" msgstr "Nuevo tipo" #: src\SUMMARY.md:30 #, fuzzy msgid "RAII Guards" msgstr "Guardias RAII" #: src\SUMMARY.md:31 #, fuzzy msgid "Strategy" msgstr "Estrategia" #: src\SUMMARY.md:32 #, fuzzy msgid "Visitor" msgstr "Visitante" #: src\SUMMARY.md:33 #, fuzzy msgid "Creational" msgstr "Creacional" #: src\SUMMARY.md:34 #, fuzzy msgid "Builder" msgstr "Constructor" #: src\SUMMARY.md:35 #, fuzzy msgid "Fold" msgstr "Doblar" #: src\SUMMARY.md:36 #, fuzzy msgid "Structural" msgstr "Estructural" #: src\SUMMARY.md:37 #, fuzzy msgid "Compose Structs" msgstr "Componer estructuras" #: src\SUMMARY.md:38 #, fuzzy msgid "Prefer Small Crates" msgstr "Preferir cajas pequeñas" #: src\SUMMARY.md:39 #, fuzzy msgid "Contain unsafety in small modules" msgstr "Contener la inseguridad en pequeños módulos" #: src\SUMMARY.md:41 #, fuzzy msgid "Object-Based APIs" msgstr "API basadas en objetos" #: src\SUMMARY.md:42 #, fuzzy msgid "Type Consolidation into Wrappers" msgstr "Escriba la consolidación en contenedores" #: src\SUMMARY.md:44 #, fuzzy msgid "Anti-patterns" msgstr "Anti-patrones" #: src\SUMMARY.md:45 #, fuzzy msgid "Clone to satisfy the borrow checker" msgstr "Clonar para satisfacer el verificador de préstamo" #: src\SUMMARY.md:46 #, fuzzy msgid "#[deny(warnings)]" msgstr "#[negar(advertencias)]" #: src\SUMMARY.md:47 #, fuzzy msgid "Deref Polymorphism" msgstr "Polimorfismo Deref" #: src\SUMMARY.md:49 #, fuzzy msgid "Functional Programming" msgstr "Programación funcional" #: src\SUMMARY.md:50 #, fuzzy msgid "Programming paradigms" msgstr "Paradigmas de programación" #: src\SUMMARY.md:51 #, fuzzy msgid "Generics as Type Classes" msgstr "Genéricos como clases de tipos" #: src\SUMMARY.md:52 #, fuzzy msgid "Lenses and Prisms" msgstr "lentes y prismas" #: src\SUMMARY.md:54 #, fuzzy msgid "Additional Resources" msgstr "Recursos adicionales" #: src\SUMMARY.md:55 #, fuzzy msgid "Design principles" msgstr "Criterios de diseño" #: src\intro.md:1 #, fuzzy msgid "# Introduction" msgstr "# Introducción" #: src\intro.md:3 #, fuzzy msgid "## Participation" msgstr "## Participación" #: 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 "" "Si está interesado en contribuir a este libro, consulte el\n" "[directrices de " "contribución](https://github.com/rust-unofficial/patterns/blob/master/CONTRIBUTING.md)." #: src\intro.md:8 #, fuzzy msgid "## Design patterns" msgstr "## Patrones de diseño" #: 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 "" "En el desarrollo de software, a menudo nos encontramos con problemas que " "comparten\n" "similitudes independientemente del entorno en el que aparecen. Aunque el\n" "detalles de implementación son cruciales para resolver la tarea en cuestión, " "podemos\n" "abstraerse de estas particularidades para encontrar las prácticas comunes " "que\n" "son de aplicación genérica." #: 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 "" "Los patrones de diseño son una colección de soluciones reutilizables y " "probadas para\n" "problemas recurrentes en ingeniería. Hacen que nuestro software sea más " "modular,\n" "mantenible y extensible. Además, estos patrones proporcionan un común\n" "lenguaje para desarrolladores, lo que los convierte en una excelente " "herramienta para\n" "comunicación en la resolución de problemas en equipo." #: src\intro.md:22 src\patterns/index.md:14 #, fuzzy msgid "## Design patterns in Rust" msgstr "## Patrones de diseño en 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 no está orientado a objetos, y la combinación de todas sus " "características,\n" "tales como elementos funcionales, un sistema de tipo fuerte y el verificador " "de préstamo,\n" "lo hace único.\n" "Debido a esto, los patrones de diseño de Rust varían con respecto a otros\n" "lenguajes de programación tradicionales orientados a objetos.\n" "Por eso decidimos escribir este libro. ¡Esperamos que disfrutes leyéndolo!\n" "El libro se divide en tres capítulos principales:" #: 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 "" "- [Expresiones idiomáticas](./idioms/index.md): pautas a seguir al " "codificar.\n" " Son las normas sociales de la comunidad.\n" " Debe romperlos solo si tiene una buena razón para ello.\n" "- [Patrones de diseño] (./patrones/index.md): métodos para resolver " "problemas comunes\n" " al codificar.\n" "- [Anti-patterns](./anti_patterns/index.md): métodos para resolver problemas " "comunes\n" " al codificar.\n" " Sin embargo, mientras que los patrones de diseño nos dan beneficios,\n" " los antipatrones crean más problemas." #: src\translations.md:1 #, fuzzy msgid "# Translations" msgstr "# Traducciones" #: 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 "" "Estamos utilizando " "[mdbook-i18n-helper](https://github.com/google/mdbook-i18n-helpers).\n" "Lea cómo _agregar_ y _actualizar_ traducciones en [su " "repositorio](https://github.com/google/mdbook-i18n-helpers#creating-and-updating-translations)" #: src\translations.md:6 #, fuzzy msgid "## External translations" msgstr "## Traducciones externas" #: 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 "" "Si desea agregar una traducción, abra un problema en el\n" "[repositorio principal](https://github.com/rust-unofficial/patterns)." #: src\idioms/index.md:1 #, fuzzy msgid "# Idioms" msgstr "# Modismos" #: 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 "" "[Los modismos] (https://en.wikipedia.org/wiki/Programming_idiom) se usan " "comúnmente\n" "estilos, pautas y patrones acordados en gran medida por una comunidad.\n" "Escribir código idiomático permite que otros desarrolladores entiendan mejor " "qué es\n" "sucediendo." #: 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 "" "Después de todo, a la computadora solo le importa el código de máquina que " "se genera.\n" "por el compilador.\n" "En cambio, el código fuente es principalmente beneficioso para el " "desarrollador.\n" "Entonces, ya que tenemos esta capa de abstracción, ¿por qué no hacerla más " "legible?" #: 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 "" "> El código está ahí para que lo entiendan los humanos, no las computadoras." #: src\idioms/coercion-arguments.md:1 #, fuzzy msgid "# Use borrowed types for arguments" msgstr "# Usar tipos prestados para argumentos" #: 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 "## Descripción" #: 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 "" "El uso de un objetivo de coerción de desref puede aumentar la flexibilidad " "de su código\n" "cuando está decidiendo qué tipo de argumento usar para un argumento de " "función.\n" "De esta forma, la función aceptará más tipos de entrada." #: 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`, or `&T` over `&Box`." msgstr "" "Esto no se limita a los tipos de puntero gordo o rebanable.\n" "De hecho, siempre debe preferir usar el **tipo prestado** en lugar de\n" "**tomando prestado el tipo propio**.\n" "Como `&str` sobre `&String`, `&[T]` sobre `&Vec`, o `&T` sobre `&Box`." #: 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 "" "Usando tipos prestados puede evitar capas de direccionamiento indirecto para " "esas instancias\n" "donde el tipo propio ya proporciona una capa de direccionamiento indirecto. " "Por ejemplo, un\n" "`String` tiene una capa de direccionamiento indirecto, por lo que `&String` " "tendrá dos capas de\n" "indirección Podemos evitar esto usando `&str` en su lugar, y dejando que " "`&String`\n" "coaccionar a `&str` cada vez que se invoca la función." #: 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 "## Ejemplo" #: 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` versus using a `&[T]` or using a `&Box` versus a `&T`." msgstr "" "Para este ejemplo, ilustraremos algunas diferencias al usar `&String` como\n" "argumento de función versus usar `&str`, pero las ideas se aplican también " "al uso\n" "`&Vec` versus usar `&[T]` o usar `&Box` versus `&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 "" "Considere un ejemplo donde deseamos determinar si una palabra contiene tres\n" "vocales consecutivas. No necesitamos ser dueños de la cadena para determinar " "esto, así que\n" "tomará una referencia." #: src\idioms/coercion-arguments.md:30 #, fuzzy msgid "The code might look something like this:" msgstr "El código podría ser algo como esto:" #: 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 "" "Esto funciona bien porque estamos pasando un tipo `&String` como parámetro.\n" "Si eliminamos los comentarios de las dos últimas líneas, el ejemplo fallará. " "Este\n" "es porque un tipo `&str` no forzará a un tipo `&String`. podemos arreglar " "esto\n" "simplemente modificando el tipo de nuestro argumento." #: src\idioms/coercion-arguments.md:67 #, fuzzy msgid "For instance, if we change our function declaration to:" msgstr "Por ejemplo, si cambiamos nuestra declaración de función a:" #: 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 "entonces ambas versiones compilarán e imprimirán el mismo resultado." #: 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 "" "Pero espera, ¡eso no es todo! Hay más en esta historia.\n" "Es probable que te digas a ti mismo: eso no importa, nunca seré\n" "usando `&'static str` como entrada de todos modos (como hicimos cuando " "usamos `\"Ferris\"`).\n" "Incluso ignorando este ejemplo especial, aún puede encontrar que usar " "`&str`\n" "darle más flexibilidad que usar un `&String`." #: 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 "" "Ahora tomemos un ejemplo en el que alguien nos da una oración y queremos\n" "determinar si alguna de las palabras de la oración contiene tres vocales " "consecutivas.\n" "Probablemente deberíamos hacer uso de la función que ya hemos definido y " "simplemente\n" "Introduzca cada palabra de la oración." #: src\idioms/coercion-arguments.md:91 #, fuzzy msgid "An example of this could look like this:" msgstr "Un ejemplo de esto podría verse así:" #: 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 "" "Ejecutando este ejemplo usando nuestra función declarada con un tipo de " "argumento `&str`\n" "rendirá" #: 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 "" "Sin embargo, este ejemplo no se ejecutará cuando nuestra función se declare " "con un\n" "tipo de argumento `&String`. Esto se debe a que los segmentos de cadena son " "un `&str` y no un\n" "`&String` que requeriría convertir una asignación a `&String` que\n" "no es implícito, mientras que convertir de `String` a `&str` es económico e " "implícito." #: 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 "## Ver también" #: 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 "" "- [Referencia del lenguaje Rust sobre coerciones de " "tipos](https://doc.rust-lang.org/reference/type-coercions.html)\n" "- Para obtener más información sobre cómo manejar `String` y `&str`, " "consulte\n" " [esta serie de blogs " "(2015)](https://web.archive.org/web/20201112023149/https://hermanradtke.com/2015/05/03/string-vs-str-in-rust-functions.html " ")\n" " por Herman J. Radtke III" #: src\idioms/concat-format.md:1 #, fuzzy msgid "# Concatenating strings with `format!`" msgstr "# Concatenar cadenas con `formato!`" #: 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 "" "Es posible construir cadenas usando los métodos `push` y `push_str` en un\n" "`String` mutable, o usando su operador `+`. Sin embargo, a menudo es más\n" "conveniente usar `formato!`, especialmente donde hay una mezcla de literal " "y\n" "cadenas no literales." #: 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 "## Ventajas" #: src\idioms/concat-format.md:27 #, fuzzy msgid "" "Using `format!` is usually the most succinct and readable way to combine " "strings." msgstr "" "Usar `format!` suele ser la forma más sucinta y legible de combinar cadenas." #: 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 "## Desventajas" #: 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 "" "Por lo general, no es la forma más eficiente de combinar cadenas: una serie " "de `push`\n" "operaciones en una cadena mutable suele ser la más eficiente (especialmente " "si el\n" "cadena se ha preasignado al tamaño esperado)." #: src\idioms/ctor.md:1 #, fuzzy msgid "# Constructors\r" msgstr "# Constructores\r" #: src\idioms/ctor.md:3 src\idioms/rustdoc-init.md:3 #, fuzzy msgid "## Description\r" msgstr "## Descripción\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 no tiene constructores como una construcción de lenguaje. En cambio, " "el\r\n" "la convención es usar una [función asociada][función asociada] `nueva` para " "crear un objeto:" #: 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 "## Constructores predeterminados\r" #: src\idioms/ctor.md:37 #, fuzzy msgid "" "Rust supports default constructors with the [`Default`][std-default] trait:" msgstr "" "Rust admite constructores predeterminados con el rasgo " "[`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 "" "`Predeterminado` también se puede derivar si todos los tipos de todos los " "campos implementan `Predeterminado`,\r\n" "como lo hacen con `Second`:" #: 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:** Es común y se espera que los tipos implementen ambos\r\n" "'Predeterminado' y un constructor 'nuevo' vacío. `nuevo` es el " "constructor\r\n" "convención en Rust, y los usuarios esperan que exista, por lo que si es\r\n" "razonable que el constructor básico no tome argumentos, entonces\r\n" "debería, incluso si es funcionalmente idéntico al predeterminado." #: 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 "" "**Sugerencia:** La ventaja de implementar o derivar `Default` es que su " "tipo\r\n" "ahora se puede usar donde se requiere una implementación 'Predeterminada', " "más prominentemente,\r\n" "cualquiera de las funciones [`*or_default` en la biblioteca " "estándar][std-or-default]." #: src\idioms/ctor.md:101 #, fuzzy msgid "## See also\r" msgstr "## Ver también\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 "" "- El [modismo predeterminado](default.md) para una descripción más detallada " "del\r\n" " Rasgo 'predeterminado'.\r\n" "\r\n" "- El [patrón del constructor] (../patterns/creational/builder.md) para " "construir\r\n" " objetos donde hay múltiples configuraciones.\r\n" "\r\n" "- [Directrices API/C-COMMON-TRAITS][Directrices API/C-COMMON-TRAITS] para\r\n" " implementando ambos, `Predeterminado` y `nuevo`.\r\n" "\r" #: src\idioms/default.md:1 #, fuzzy msgid "# The `Default` Trait" msgstr "# El rasgo `Por defecto`" #: 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 "" "No solo implementan contenedores de un elemento como `Cow`, `Box` o `Arc`\n" "'Predeterminado' para los tipos 'Predeterminados' contenidos, uno puede " "automáticamente\n" "`#[derive(Default)]` para estructuras cuyos campos lo implementan, así que " "cuanto más\n" "tipos implementan `Default`, más útil se vuelve." #: 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 "" "Por otro lado, los constructores pueden tomar múltiples argumentos, mientras " "que los\n" "El método `default()` no lo hace. Incluso puede haber múltiples " "constructores con\n" "nombres diferentes, pero solo puede haber una implementación " "`Predeterminada` por 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,\n" " // Vecs default to empty vector\n" " search_path: Vec,\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 "" "- El lenguaje [constructor] es otra forma de generar instancias que pueden o " "pueden\n" " no ser \"predeterminado\"\n" "- La documentación [`Default`] (desplácese hacia abajo para ver la lista de " "implementadores)\n" "- [`Opción::unwrap_or_default()`]\n" "- [`derivar(nuevo)`]" #: src\idioms/deref.md:1 #, fuzzy msgid "# Collections are smart pointers" msgstr "# Las colecciones son punteros inteligentes" #: 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 "" "Utilice [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html)\n" "rasgo para tratar las colecciones como punteros inteligentes, ofreciendo " "propiedad\n" "y vistas prestadas de datos." #: src\idioms/deref.md:11 msgid "" "```rust,ignore\n" "use std::ops::Deref;\n" "\n" "struct Vec {\n" " data: RawVec,\n" " //..\n" "}\n" "\n" "impl Deref for Vec {\n" " type Target = [T];\n" "\n" " fn deref(&self) -> &[T] {\n" " //..\n" " }\n" "}\n" "```" msgstr "" #: src\idioms/deref.md:28 #, fuzzy msgid "" "A `Vec` 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` 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` es una colección propietaria de `T`s, mientras que un segmento " "(`&[T]`) es un préstamo\n" "colección de `T`s. La implementación de `Deref` para `Vec` permite la " "desreferenciación implícita\n" "de `&Vec` a `&[T]` e incluye la relación en la eliminación automática de " "referencias\n" "búsquedas. La mayoría de los métodos que podría esperar que se implementen " "para `Vec`s son en su lugar\n" "implementado para rebanadas." #: src\idioms/deref.md:34 #, fuzzy msgid "Also `String` and `&str` have a similar relation." msgstr "También `String` y `&str` tienen una relación similar." #: 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 "## Motivación" #: 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 propiedad y el préstamo son aspectos clave del lenguaje Rust. Estructuras " "de datos\n" "debe tener en cuenta esta semántica correctamente para dar a un buen " "usuario\n" "experiencia. Al implementar una estructura de datos que posee sus datos, " "ofrecer una\n" "La vista prestada de esos datos permite API más flexibles." #: 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 mayoría de los métodos se pueden implementar solo para la vista prestada, " "luego se\n" "implícitamente disponible para la vista propietaria." #: src\idioms/deref.md:48 #, fuzzy msgid "Gives clients a choice between borrowing or taking ownership of data." msgstr "" "Brinda a los clientes la opción de tomar prestados o tomar posesión de los " "datos." #: 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 "" "No se tienen en cuenta los métodos y características que solo están " "disponibles a través de la desreferenciación.\n" "cuando se verifican los límites, por lo que la programación genérica con " "estructuras de datos usa esto\n" "El patrón puede volverse complejo (ver los rasgos `Borrow` y `AsRef`, etc.)." #: 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 "## Discusión" #: 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 "" "Los punteros inteligentes y las colecciones son análogos: un puntero " "inteligente apunta a un solo\n" "objeto, mientras que una colección apunta a muchos objetos. Desde el punto " "de vista de\n" "el sistema de tipos, hay poca diferencia entre los dos. Una colección posee\n" "sus datos si la única forma de acceder a cada dato es a través de la " "recopilación y el\n" "recogida es responsable de la eliminación de los datos (incluso en los casos " "de compartir\n" "propiedad, algún tipo de vista prestada puede ser apropiado). Si una " "colección posee\n" "sus datos, por lo general es útil proporcionar una vista de los datos como " "prestados para que\n" "puede ser referenciado varias veces." #: src\idioms/deref.md:67 #, fuzzy msgid "" "Most smart pointers (e.g., `Foo`) implement `Deref`. 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` " "can\n" "implement `Deref>` where `Bar` is a dynamically sized type " "and\n" "`&Bar` is a borrowed view of the data in `Foo`." msgstr "" "La mayoría de los punteros inteligentes (por ejemplo, `Foo`) implementan " "`Deref`. Sin embargo,\n" "las colecciones por lo general dejarán de hacer referencia a un tipo " "personalizado. `[T]` y `str` tienen algunos\n" "soporte de idioma, pero en el caso general, esto no es necesario. `Foo` " "puede\n" "implementar `Deref>` donde `Bar` es un tipo de tamaño dinámico " "y\n" "`&Bar` es una vista prestada de los datos en `Foo`." #: 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 "" "Comúnmente, las colecciones ordenadas implementarán `Index` para `Range`s " "para proporcionar\n" "sintaxis de corte. El objetivo será la vista prestada." #: 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 "" "- [Antipatrón de polimorfismo de deref](../anti_patterns/deref.md).\n" "- [Documentación para el rasgo " "`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html)." #: src\idioms/dtor-finally.md:1 #, fuzzy msgid "# Finalisation in destructors" msgstr "# Finalización en destructores" #: 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 no proporciona el equivalente a los bloques `finally` - código que " "será\n" "se ejecuta sin importar cómo se sale de una función. En cambio, el " "destructor de un objeto puede\n" "usarse para ejecutar código que debe ejecutarse antes de salir." #: 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 "" "Si una función tiene varios puntos de retorno, la ejecución del código al " "salir se vuelve\n" "difícil y repetitivo (y por lo tanto propenso a errores). Este es " "especialmente el caso donde\n" "el retorno es implícito debido a una macro. Un caso común es el operador `?` " "que\n" "devuelve si el resultado es `Err`, pero continúa si es `Ok`. `?` se utiliza " "como\n" "un mecanismo de manejo de excepciones, pero a diferencia de Java (que tiene " "`finally`), hay\n" "no hay forma de programar el código para que se ejecute tanto en casos " "normales como excepcionales.\n" "El pánico también hará que salga de una función antes de tiempo." #: src\idioms/dtor-finally.md:44 #, fuzzy msgid "" "Code in destructors will (nearly) always be run - copes with panics, early\n" "returns, etc." msgstr "" "El código en los destructores (casi) siempre se ejecutará: hace frente a " "pánicos, temprano\n" "devoluciones, etc" #: 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 "" "No se garantiza que los destructores funcionen. Por ejemplo, si hay un\n" "bucle infinito en una función o si la ejecución de una función falla antes " "de salir.\n" "Los destructores tampoco se ejecutan en caso de pánico en un país que ya " "está en pánico.\n" "hilo. Por lo tanto, no se puede confiar en los destructores como " "finalizadores donde es\n" "absolutamente esencial que ocurra la finalización." #: 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 "" "Este patrón introduce un código implícito difícil de notar. Lectura de una " "función\n" "no da una indicación clara de los destructores que se ejecutarán en la " "salida. esto puede hacer\n" "depuración complicada." #: src\idioms/dtor-finally.md:59 #, fuzzy msgid "" "Requiring an object and `Drop` impl just for finalisation is heavy on " "boilerplate." msgstr "" "Requerir un objeto y el impl `Drop` solo para la finalización es pesado en " "el modelo." #: 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`). 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 "" "Hay cierta sutileza sobre cómo almacenar exactamente el objeto utilizado " "como\n" "finalizador Debe mantenerse vivo hasta el final de la función y luego debe " "ser\n" "destruido. El objeto siempre debe ser un valor o un puntero de propiedad " "única (por ejemplo,\n" "`Cuadro`). Si se usa un puntero compartido (como `Rc`), entonces el " "finalizador puede\n" "mantenerse vivo más allá del tiempo de vida de la función. Por razones " "similares, el\n" "el finalizador no debe moverse ni devolverse." #: 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 "" "El finalizador debe asignarse a una variable, de lo contrario, se destruirá\n" "inmediatamente, en lugar de cuando se sale del alcance. El nombre de la " "variable debe comenzar\n" "con `_` si la variable solo se usa como finalizador, de lo contrario, el " "compilador\n" "advertirá que el finalizador nunca se utiliza. Sin embargo, no llame a la " "variable\n" "`_` sin sufijo - en ese caso será destruido inmediatamente." #: 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 "" "En Rust, los destructores se ejecutan cuando un objeto queda fuera del " "alcance. Esto pasa\n" "ya sea que lleguemos al final del bloque, que haya un regreso anticipado o " "que el programa\n" "entra en pánico Cuando entra en pánico, Rust desenrolla la pila ejecutando " "destructores para cada\n" "objeto en cada marco de pila. Entonces, se llama a los destructores incluso " "si ocurre el pánico.\n" "en una función que se está llamando." #: 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 "" "Si un destructor entra en pánico mientras se desenrolla, no hay una buena " "acción que tomar, por lo que Rust\n" "aborta el subproceso inmediatamente, sin ejecutar más destructores. Esto " "significa\n" "que los destructores no están absolutamente garantizados para funcionar. " "También significa que usted\n" "debe tener especial cuidado en sus destructores para no entrar en pánico, ya " "que podría salir\n" "recursos en un estado inesperado." #: src\idioms/dtor-finally.md:90 #, fuzzy msgid "[RAII guards](../patterns/behavioural/RAII.md)." msgstr "[Guardias RAII](../patrones/comportamiento/RAII.md)." #: src\idioms/mem-replace.md:1 #, fuzzy msgid "# `mem::{take(_), replace(_)}` to keep owned values in changed enums" msgstr "" "# `mem::{take(_), replace(_)}` para mantener los valores propios en las " "enumeraciones modificadas" #: 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 "" "Digamos que tenemos un `&mut MyEnum` que tiene (al menos) dos variantes,\n" "`A { nombre: Cadena, x: u8 }` y `B { nombre: Cadena }`. Ahora queremos " "cambiar\n" "`MyEnum::A` a `B` si `x` es cero, manteniendo `MyEnum::B` intacto." #: src\idioms/mem-replace.md:9 #, fuzzy msgid "We can do this without cloning the `name`." msgstr "Podemos hacer esto sin clonar el `nombre`." #: 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 "Esto también funciona con más variantes:" #: 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 "" "Al trabajar con enumeraciones, es posible que deseemos cambiar un valor de " "enumeración en su lugar, tal vez\n" "a otra variante. Esto generalmente se hace en dos fases para mantener el " "préstamo\n" "corrector feliz. En la primera fase, observamos el valor existente y " "miramos\n" "sus partes para decidir qué hacer a continuación. En la segunda fase podemos " "condicionalmente\n" "cambiar el valor (como en el ejemplo anterior)." #: 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 "" "El verificador de préstamos no nos permitirá sacar el `nombre` de la " "enumeración (porque\n" "_algo_ debe estar allí.) Podríamos, por supuesto, el nombre `.clone()` y " "poner el clon\n" "en nuestro `MyEnum::B`, pero eso sería una instancia del antipatrón [Clonar " "para satisfacer el comprobador de " "préstamos](../anti_patterns/borrow_clone.md). De todos modos, nosotros\n" "puede evitar la asignación adicional cambiando `e` con solo un préstamo " "mutable." #: 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` nos permite intercambiar el valor, reemplazándolo con su valor " "predeterminado,\n" "y devolviendo el valor anterior. Para `String`, el valor predeterminado es " "un vacío\n" "`String`, que no es necesario asignar. Como resultado, obtenemos el " "original.\n" "`nombre` _como valor propio_. Luego podemos envolver esto en otra " "enumeración." #: 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` es muy similar, pero nos permite especificar qué\n" "reemplace el valor con. Un equivalente a nuestra línea `mem::take` sería\n" "`mem::replace(nombre, Cadena::nuevo())`." #: 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 "" "Tenga en cuenta, sin embargo, que si estamos usando una `Opción` y queremos " "reemplazar su\n" "valor con `Ninguno`, el método `take()` de `Option` proporciona un método " "más corto y\n" "alternativa más idiomática." #: src\idioms/mem-replace.md:85 #, fuzzy msgid "" "Look ma, no allocation! Also you may feel like Indiana Jones while doing it." msgstr "" "¡Mira mamá, no hay asignación! También puedes sentirte como Indiana Jones " "mientras lo haces." #: 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 "" "Esto se pone un poco prolijo. Hacerlo mal repetidamente te hará odiar el\n" "prestador de cheques. El compilador puede fallar al optimizar el almacén " "doble,\n" "lo que resulta en un rendimiento reducido en comparación con lo que haría en " "un entorno inseguro\n" "idiomas" #: 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 "" "Además, el tipo que está tomando debe implementar el [rasgo " "`Predeterminado`] (./default.md). Sin embargo, si el tipo con el que está " "trabajando no\n" "implementar esto, en su lugar puede usar `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 "" "Este patrón solo es de interés en Rust. En los idiomas de GC, tomarías la\n" "referencia al valor por defecto (y el GC haría un seguimiento de las " "referencias), y en\n" "otros lenguajes de bajo nivel como C simplemente haría un alias del puntero " "y arreglaría las cosas\n" "más tarde." #: 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 "" "Sin embargo, en Rust, tenemos que trabajar un poco más para hacer esto. Un " "valor propio\n" "Es posible que solo tenga un propietario, por lo que para sacarlo, debemos " "volver a colocar algo:\n" "como Indiana Jones, reemplazando el artefacto con una bolsa de arena." #: 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 "" "Esto elimina el [Clonar para satisfacer el comprobador de " "préstamo](../anti_patterns/borrow_clone.md)\n" "anti-patrón en un caso específico." #: src\idioms/on-stack-dyn-dispatch.md:1 #, fuzzy msgid "# On-Stack Dynamic Dispatch" msgstr "# Envío dinámico en la 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 "" "Podemos despachar dinámicamente sobre múltiples valores, sin embargo, para " "hacerlo, necesitamos\n" "para declarar múltiples variables para vincular objetos de diferente tipo. " "para extender el\n" "vida útil según sea necesario, podemos usar la inicialización condicional " "diferida, como se ve\n" "abajo:" #: src\idioms/on-stack-dyn-dispatch.md:12 msgid "" "```rust\n" "use std::io;\n" "use std::fs;\n" "\n" "# fn main() -> Result<(), Box> {\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 monomorfiza el código por defecto. Esto significa que una copia del " "código será\n" "generado para cada tipo con el que se utiliza y optimizado de forma " "independiente. Mientras esto\n" "permite un código muy rápido en la ruta activa, también infla el código en " "algunos lugares\n" "donde el rendimiento no es esencial, lo que cuesta tiempo de compilación y " "caché\n" "uso." #: 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 "" "Afortunadamente, Rust nos permite usar el envío dinámico, pero tenemos que " "preguntar explícitamente\n" "para ello." #: 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 "" "No necesitamos asignar nada en el montón. Tampoco necesitamos\n" "inicializar algo que no usaremos más tarde, ni necesitamos monomorfizar el\n" "código completo que sigue para trabajar con `File` o `Stdin`." #: src\idioms/on-stack-dyn-dispatch.md:56 #, fuzzy msgid "The code needs more moving parts than the `Box`-based version:" msgstr "El código necesita más partes móviles que la versión basada en `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 = 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 "" "Los recién llegados a Rust generalmente aprenderán que Rust requiere que " "todas las variables sean\n" "inicializado _antes de su uso_, por lo que es fácil pasar por alto el hecho " "de que _unused_\n" "las variables bien pueden no estar inicializadas. Rust trabaja muy duro para " "garantizar que esto\n" "funciona bien y solo los valores inicializados se eliminan al final de su\n" "alcance." #: src\idioms/on-stack-dyn-dispatch.md:76 #, fuzzy msgid "The example meets all the constraints Rust places on us:" msgstr "El ejemplo cumple con todas las restricciones que Rust nos 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 "" "- Todas las variables se inicializan antes de usarlas (en este caso, " "tomarlas prestadas)\n" "- Cada variable solo contiene valores de un solo tipo. En nuestro ejemplo, " "`stdin` es\n" " de tipo `Stdin`, `file` es de tipo `File` y `readable` es de tipo `&mut " "dyn Read`\n" "- Cada valor prestado sobrevive a todas las referencias tomadas de él" #: 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` directly and use its [`.as_ref()`] method to get " "an\n" " optional reference." msgstr "" "- [Finalización en destructores](dtor-finally.md) y\n" " [Guardias RAII](../patterns/behavioural/RAII.md) pueden beneficiarse de un " "control estricto sobre\n" " vidas\n" "- Para `Option<&T>`s de referencias (mutables) rellenadas condicionalmente, " "se puede\n" " inicialice una `Option` directamente y use su método [`.as_ref()`] para " "obtener una\n" " referencia opcional." #: src\idioms/ffi/intro.md:1 #, fuzzy msgid "# FFI Idioms" msgstr "# modismos 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 "" "Escribir código FFI es un curso completo en sí mismo.\n" "Sin embargo, aquí hay varios modismos que pueden actuar como indicadores y " "evitar\n" "trampas para usuarios inexpertos de Rust `inseguro`." #: src\idioms/ffi/intro.md:7 #, fuzzy msgid "This section contains idioms that may be useful when doing FFI." msgstr "Esta sección contiene modismos que pueden ser útiles al hacer 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. [Errores idiomáticos](./errors.md) - Manejo de errores con códigos " "enteros y\n" " valores de retorno centinela (como punteros `NULL`)\n" "\n" "2. [Accepting Strings](./accepting-strings.md) con código inseguro mínimo\n" "\n" "3. [Pasar cadenas] (./pasar cadenas.md) a funciones FFI" #: src\idioms/ffi/errors.md:1 #, fuzzy msgid "# Error Handling in FFI" msgstr "# Manejo de errores en 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 "" "En idiomas extranjeros como C, los errores se representan mediante códigos " "de retorno.\n" "Sin embargo, el sistema de tipos de Rust permite obtener información de " "error mucho más rica.\n" "capturado y propagado a través de 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 "" "Esta práctica recomendada muestra diferentes tipos de códigos de error y " "cómo exponerlos\n" "de una manera utilizable:" #: 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. Las enumeraciones planas deben convertirse en números enteros y " "devolverse como códigos.\n" "2. Las enumeraciones estructuradas deben convertirse a un código entero con " "un error de cadena\n" " mensaje para el detalle.\n" "3. Los tipos de error personalizados deben volverse \"transparentes\", con " "una representación 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 "## Ejemplo de código" #: src\idioms/ffi/errors.md:19 #, fuzzy msgid "### Flat Enums" msgstr "### Enumeraciones planas" #: 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 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 "### Enumeraciones estructuradas" #: 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 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 "### Tipos de errores personalizados" #: 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 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 "" "Esto asegura que el idioma extranjero tenga un acceso claro a la información " "de error.\n" "sin comprometer en absoluto la API del código 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 "" "Es mucho escribir, y es posible que algunos tipos no se puedan convertir " "fácilmente\n" "a c" #: src\idioms/ffi/accepting-strings.md:1 #, fuzzy msgid "# Accepting Strings" msgstr "# Aceptar cadenas" #: 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 "" "Al aceptar cadenas a través de FFI a través de punteros, hay dos principios " "que\n" "debe ser seguido:" #: 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. Mantenga las cadenas extranjeras \"prestadas\", en lugar de copiarlas " "directamente.\n" "2. Minimice la cantidad de complejidad y el código \"inseguro\" involucrado " "en la conversión\n" " desde una cadena de estilo C hasta cadenas nativas de Rust." #: src\idioms/ffi/accepting-strings.md:14 #, fuzzy msgid "" "The strings used in C have different behaviours to those used in Rust, " "namely:" msgstr "" "Las cadenas utilizadas en C tienen comportamientos diferentes a los " "utilizados en Rust, a saber:" #: 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 "" "- Las cadenas C terminan en nulo, mientras que las cadenas Rust almacenan su " "longitud\n" "- Las cadenas C pueden contener cualquier byte arbitrario distinto de cero, " "mientras que las cadenas Rust deben ser\n" " UTF-8\n" "- Se accede a las cadenas C y se manipulan mediante operaciones de puntero " "\"no seguras\".\n" " mientras que las interacciones con cadenas de Rust pasan por métodos " "seguros" #: 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 biblioteca estándar de Rust viene con equivalentes en C de `String` y " "`&str` de Rust\n" "llamados `CString` y `&CStr`, que nos permiten evitar mucha de la " "complejidad\n" "y código 'inseguro' involucrado en la conversión entre cadenas C y cadenas " "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 "" "El tipo `&CStr` también nos permite trabajar con datos prestados, lo que " "significa pasar\n" "cadenas entre Rust y C es una operación de costo cero." #: 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 "El ejemplo está escrito para garantizar que:" #: 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. El bloque \"inseguro\" es lo más pequeño posible.\n" "2. El puntero con una vida útil \"sin seguimiento\" se convierte en un " "puntero compartido \"seguido\"\n" " referencia" #: src\idioms/ffi/accepting-strings.md:76 #, fuzzy msgid "Consider an alternative, where the string is actually copied:" msgstr "Considere una alternativa, donde la cadena en realidad se copia:" #: 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 "Este código es inferior al original en dos aspectos:" #: 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. Hay mucho más código \"inseguro\" y, lo que es más importante, más " "invariantes.\n" " debe sostener.\n" "2. Debido a la extensa aritmética requerida, hay un error en esta versión\n" " que casos Rust `comportamiento indefinido`." #: 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 "" "El error aquí es un simple error en la aritmética de punteros: la cadena fue " "copiada,\n" "todos los `msg_len` bytes del mismo. Sin embargo, el terminador `NUL` al " "final no 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 "" "Luego, el Vector tenía su tamaño _establecido_ en la longitud de la _cadena " "con relleno cero_ --\n" "en lugar de _redimensionarlo_, lo que podría haber agregado un cero al " "final.\n" "Como resultado, el último byte del Vector es una memoria no inicializada.\n" "Cuando se crea el `CString` en la parte inferior del bloque, se lee el\n" "¡El vector causará un \"comportamiento indefinido\"!" #: 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 "" "Como muchos de estos problemas, este sería un problema difícil de rastrear.\n" "A veces entraba en pánico porque la cadena no era `UTF-8`, a veces\n" "poner un carácter extraño al final de la cadena, a veces simplemente\n" "chocar completamente." #: src\idioms/ffi/accepting-strings.md:143 #: src\idioms/ffi/passing-strings.md:105 #, fuzzy msgid "None?" msgstr "¿Ninguno?" #: src\idioms/ffi/passing-strings.md:1 #, fuzzy msgid "# Passing Strings" msgstr "# Cuerdas de paso" #: 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 "" "Al pasar cadenas a funciones FFI, hay cuatro principios que deben ser\n" "seguido:" #: 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. Haga que la vida útil de las cadenas propias sea lo más larga posible.\n" "2. Minimice el código \"inseguro\" durante la conversión.\n" "3. Si el código C puede modificar los datos de la cadena, use `Vec` en lugar " "de `CString`.\n" "4. A menos que la API de función externa lo requiera, la propiedad de la " "cadena\n" " no debe transferirse al destinatario." #: 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 tiene soporte incorporado para cadenas de estilo C con su `CString` y " "`CStr`\n" "tipos Sin embargo, hay diferentes enfoques que uno puede tomar con cadenas " "que\n" "se envían a una llamada de función externa desde una función de 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 mejor práctica es simple: use `CString` de tal manera que minimice\n" "Código `inseguro`. Sin embargo, una advertencia secundaria es que\n" "_el objeto debe vivir lo suficiente_, lo que significa que la vida útil debe " "maximizarse.\n" "Además, la documentación explica que \"viajar de ida y vuelta\" un `CString` " "después\n" "la modificación es UB, por lo que se necesita trabajo adicional en ese caso." #: 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>(\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 {\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 "El ejemplo está escrito de manera que se asegure que:" #: 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. El bloque \"inseguro\" es lo más pequeño posible.\n" "2. El `CString` vive lo suficiente.\n" "3. Los errores con typecasts siempre se propagan cuando es posible." #: 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 error común (tan común que está en la documentación) es no usar el\n" "variable en el primer bloque:" #: 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>(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 "" "Este código dará como resultado un puntero colgante, porque la vida útil " "del\n" "'CString' no se extiende por la creación del puntero, a diferencia de si una " "referencia fuera\n" "creado." #: 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 "" "Otro problema que se plantea con frecuencia es que la inicialización de un " "vector de 1k de\n" "ceros es \"lento\". Sin embargo, las versiones recientes de Rust en realidad " "optimizan eso\n" "macro particular a una llamada a `zmalloc`, lo que significa que es tan " "rápido como el operador\n" "la capacidad del sistema para devolver la memoria puesta a cero (lo cual es " "bastante rápido)." #: src\idioms/option-iter.md:1 #, fuzzy msgid "# Iterating over an `Option`" msgstr "# Iterando sobre una `Opción`" #: 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 "" "`Opción` se puede ver como un contenedor que contiene cero o uno\n" "elemento. En particular, implementa el rasgo `IntoIterator`, y como tal\n" "se puede usar con código genérico que necesita ese 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 "## Ejemplos" #: 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 "" "Dado que `Option` implementa `IntoIterator`, se puede usar como argumento " "para\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 "" "Si necesita agregar una `Opción` al final de un iterador existente, puede\n" "páselo 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 "" "Tenga en cuenta que si la `Opción` siempre es `Algunos`, entonces es más " "idiomático de usar\n" "[`std::iter::once`](https://doc.rust-lang.org/std/iter/fn.once.html) en el\n" "elemento en su lugar." #: 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 "" "Además, dado que `Option` implementa `IntoIterator`, es posible iterar " "sobre\n" "usando un bucle `for`. Esto es equivalente a emparejarlo con `if let " "Some(...)`,\n" "y en la mayoría de los casos deberías preferir lo último." #: 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`](https://doc.rust-lang.org/std/option/enum.Option.html)" msgstr "" "- [`std::iter::once`](https://doc.rust-lang.org/std/iter/fn.once.html) es " "un\n" " iterador que produce exactamente un elemento. Es una alternativa más " "legible a\n" " `Algunos(foo).into_iter()`.\n" "\n" "- " "[`Iterador::filter_map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter_map)\n" " es una versión de " "[`Iterator::map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map),\n" " especializado en funciones de mapeo que devuelven `Opción`.\n" "\n" "- La caja [`ref_slice`](https://crates.io/crates/ref_slice) proporciona " "funciones\n" " para convertir una `Opción` en una rebanada de cero o un elemento.\n" "\n" "- [Documentación para " "`Option`](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 "# Pasar variables al cierre" #: 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 "" "De forma predeterminada, los cierres capturan su entorno tomando prestado. O " "puedes usar\n" "cierre `mover` para mover todo el entorno. Sin embargo, a menudo desea " "moverse solo\n" "algunas variables para el cierre, darle copia de algunos datos, pasarlo por " "referencia, o\n" "realizar alguna otra transformación." #: src\idioms/pass-var-to-closure.md:10 #, fuzzy msgid "Use variable rebinding in separate scope for that." msgstr "Use la revinculación de variables en un alcance separado para eso." #: src\idioms/pass-var-to-closure.md:14 #, fuzzy msgid "Use" msgstr "Usar" #: 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 "en lugar de" #: 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 "" "Los datos copiados se agrupan junto con la definición de cierre, por lo que " "su propósito es\n" "más claras, y se dejarán caer inmediatamente incluso si no se consumen\n" "por cierre." #: 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 "" "El cierre usa los mismos nombres de variables que el código circundante, ya " "sea que los datos se copien o\n" "movido." #: src\idioms/pass-var-to-closure.md:59 #, fuzzy msgid "Additional indentation of closure body." msgstr "Muesca adicional del cuerpo del cierre." #: src\idioms/priv-extend.md:1 #, fuzzy msgid "# `#[non_exhaustive]` and private fields for extensibility" msgstr "# `#[no_exhaustivo]` y campos privados para extensibilidad" #: 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 "" "Existe un pequeño conjunto de escenarios en los que un autor de la " "biblioteca puede querer agregar público\n" "campos a una estructura pública o nuevas variantes a una enumeración sin " "retroceder\n" "compatibilidad." #: src\idioms/priv-extend.md:9 #, fuzzy msgid "Rust offers two solutions to this problem:" msgstr "Rust ofrece dos soluciones a este 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 "" "- Use `#[non_exhaustive]` en las variantes `struct`s, `enum`s y `enum`.\n" " Para obtener documentación detallada sobre todos los lugares donde " "`#[non_exhaustive]` puede ser\n" " utilizado, consulte [los documentos] " "(https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute).\n" "\n" "- Puede agregar un campo privado a una estructura para evitar que sea " "directamente\n" " instanciado o comparado con (ver 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: `Campos privados` para estructuras" #: 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]` solo funciona a través de los límites de las cajas.\n" "Dentro de una caja, se puede utilizar el método de campo privado." #: 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 "" "Agregar un campo a una estructura es un cambio en su mayoría compatible con " "versiones anteriores.\n" "Sin embargo, si un cliente usa un patrón para deconstruir una instancia de " "estructura,\n" "podría nombrar todos los campos en la estructura y agregar uno nuevo " "rompería eso\n" "patrón.\n" "El cliente podría nombrar algunos campos y usar `..` en el patrón, en cuyo " "caso agregando\n" "otro campo es compatible con versiones anteriores.\n" "Hacer que al menos uno de los campos de la estructura sea privado obliga a " "los clientes a usar este último\n" "forma de patrones, asegurando que la estructura esté preparada para el " "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 "" "La desventaja de este enfoque es que es posible que deba agregar un\n" "campo a la estructura.\n" "Puede usar el tipo `()` para que no haya sobrecarga de tiempo de ejecución y " "anteponer `_` a\n" "el nombre del campo para evitar la advertencia de campo no utilizado." #: 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 "" "En `struct`s, `#[non_exhaustive]` permite agregar campos adicionales al " "revés\n" "forma compatible.\n" "También evitará que los clientes usen el constructor de estructuras, incluso " "si todos los\n" "Los campos son públicos.\n" "Esto puede ser útil, pero vale la pena considerarlo si _quiere_ un campo " "adicional\n" "ser encontrado por los clientes como un error del compilador en lugar de " "algo que puede ser silenciosamente\n" "sin descubrir" #: 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]` también se puede aplicar a las variantes de " "enumeración.\n" "Una variante `#[no_exhaustiva]` se comporta de la misma manera que una " "estructura `#[no_exhaustiva]`." #: 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 "" "Use esto deliberadamente y con precaución: incrementando la versión " "principal al agregar\n" "campos o variantes suele ser una mejor opción.\n" "`#[non_exhaustive]` puede ser apropiado en escenarios en los que está " "modelando un\n" "recurso que puede cambiar fuera de sincronización con su biblioteca, pero no " "es un propósito general\n" "herramienta." #: src\idioms/priv-extend.md:104 #, fuzzy msgid "### Disadvantages" msgstr "### Desventajas" #: 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]` puede hacer que su código sea mucho menos ergonómico de " "usar, especialmente cuando\n" "forzado a manejar variantes de enumeración desconocidas.\n" "Solo debe usarse cuando se requieren este tipo de evoluciones **sin**\n" "incrementando la versión principal." #: 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 presenta el atributo #[no_exhaustivo] para enumeraciones y " "estructuras](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 "# Fácil inicialización de documentos\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 "" "Si una estructura requiere un esfuerzo significativo para inicializarse al " "escribir documentos, puede ser\r\n" "más rápido para envolver su ejemplo con una función de ayuda que toma la " "estructura como una\r\n" "argumento." #: src\idioms/rustdoc-init.md:9 #, fuzzy msgid "## Motivation\r" msgstr "## Motivación\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 veces hay una estructura con parámetros múltiples o complicados y " "varios\r\n" "métodos. Cada uno de estos métodos debe tener ejemplos." #: src\idioms/rustdoc-init.md:14 #, fuzzy msgid "For example:" msgstr "Por ejemplo:" #: 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 {\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 "## Ejemplo\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 "" "En lugar de escribir todo este texto repetitivo para crear una `Conexión` " "y\r\n" "`Solicitud`, es más fácil simplemente crear una función auxiliar de " "envoltura que tome\r\n" "ellos como argumentos:" #: 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 "## Ventajas\r" #: src\idioms/rustdoc-init.md:79 #, fuzzy msgid "This is much more concise and avoids repetitive code in examples." msgstr "Esto es mucho más conciso y evita el código repetitivo en los ejemplos." #: src\idioms/rustdoc-init.md:81 #, fuzzy msgid "## Disadvantages\r" msgstr "## Desventajas\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 "" "Como el ejemplo está en una función, el código no se probará. Aunque seguirá " "siendo\r\n" "verificado para asegurarse de que compila cuando se ejecuta una `prueba de " "carga`. Así que este patrón es\r\n" "más útil cuando necesitas `no_run`. Con esto, no necesita agregar `no_run`." #: src\idioms/rustdoc-init.md:87 #, fuzzy msgid "## Discussion\r" msgstr "## Discusión\r" #: src\idioms/rustdoc-init.md:89 #, fuzzy msgid "If assertions are not required this pattern works well." msgstr "Si no se requieren aserciones, este patrón funciona bien." #: 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 "" "Si lo son, una alternativa puede ser crear un método público para crear un " "ayudante.\r\n" "instancia que está anotada con `#[doc(hidden)]` (para que los usuarios no la " "vean).\r\n" "Entonces este método se puede llamar dentro de rustdoc porque es parte " "del\r\n" "API pública de crate." #: src\idioms/temporary-mutability.md:1 #, fuzzy msgid "# Temporary mutability" msgstr "# Mutabilidad temporal" #: 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 "" "A menudo es necesario preparar y procesar algunos datos, pero después de eso " "los datos son\n" "solo inspeccionado y nunca modificado. La intención puede hacerse explícita " "redefiniendo\n" "la variable mutable como inmutable." #: 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 "" "Se puede hacer procesando datos dentro de un bloque anidado o redefiniendo\n" "La variable." #: src\idioms/temporary-mutability.md:14 #, fuzzy msgid "Say, vector must be sorted before usage." msgstr "Digamos que el vector debe ordenarse antes de su uso." #: src\idioms/temporary-mutability.md:16 #, fuzzy msgid "Using nested block:" msgstr "Usando bloque anidado:" #: 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 "Usando el reenlace variable:" #: 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 "" "El compilador garantiza que no mute accidentalmente los datos después de " "algún momento." #: 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 "" "El bloque anidado requiere sangría adicional del cuerpo del bloque.\n" "Una línea más para devolver datos del bloque o redefinir variable." #: src\idioms/return-consumed-arg-on-error.md:1 #, fuzzy msgid "# Return consumed argument on error" msgstr "# Devolver argumento consumido en caso de error" #: 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 "" "Si una función falible consume (mueve) un argumento, devuelva ese argumento " "al interior\n" "un error." #: 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 "" "En caso de error, es posible que desee probar alguna forma alternativa o\n" "reintentar la acción en caso de función no determinista. Pero si el " "argumento\n" "siempre se consume, se ve obligado a clonarlo en cada llamada, lo que\n" "no es muy eficiente." #: 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 biblioteca estándar utiliza este enfoque en, p. Método " "`String::from_utf8`.\n" "Cuando se le da un vector que no contiene UTF-8 válido, un `FromUtf8Error`\n" "es regresado.\n" "Puede recuperar el vector original usando el método " "`FromUtf8Error::into_bytes`." #: src\idioms/return-consumed-arg-on-error.md:57 #, fuzzy msgid "Better performance because of moving arguments whenever possible." msgstr "" "Mejor rendimiento debido a los argumentos en movimiento siempre que sea " "posible." #: src\idioms/return-consumed-arg-on-error.md:61 #, fuzzy msgid "Slightly more complex error types." msgstr "Tipos de error ligeramente más complejos." #: src\patterns/index.md:1 #, fuzzy msgid "# Design Patterns" msgstr "# Patrones de diseño" #: 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 "" "[Patrones de diseño](https://en.wikipedia.org/wiki/Software_design_pattern) " "son\n" "\"soluciones generales reutilizables para un problema común dentro de un " "determinado\n" "contexto en el diseño de software\". Los patrones de diseño son una " "excelente manera de describir el\n" "cultura de un lenguaje de programación. Los patrones de diseño son muy " "específicos del idioma:\n" "lo que es un patrón en un idioma puede ser innecesario en otro debido a una\n" "característica del idioma, o imposible de expresar debido a la falta de una " "característica." #: 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 "" "Si se usan en exceso, los patrones de diseño pueden agregar una complejidad " "innecesaria a los programas.\n" "Sin embargo, son una excelente manera de compartir conocimientos de nivel " "intermedio y avanzado.\n" "sobre un lenguaje de programación." #: 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 tiene muchas características únicas. Estas características nos brindan " "un gran beneficio al eliminar\n" "Clases enteras de problemas. Algunos de ellos también son patrones que son " "_exclusivos_ de 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 es un acrónimo que significa `No lo vas a necesitar'.\n" "Es un principio vital de diseño de software para aplicar mientras escribe " "código." #: src\patterns/index.md:24 #, fuzzy msgid "> The best code I ever wrote was code I never wrote." msgstr "> El mejor código que jamás escribí fue código que nunca escribí." #: 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 "" "Si aplicamos YAGNI a los patrones de diseño, vemos que las características " "de Rust nos permiten\n" "tirar muchos patrones. Por ejemplo, no es necesario el [patrón de " "estrategia] (https://en.wikipedia.org/wiki/Strategy_pattern)\n" "en Rust porque solo podemos usar " "[traits](https://doc.rust-lang.org/book/traits.html)." #: src\patterns/behavioural/intro.md:1 #, fuzzy msgid "# Behavioural Patterns" msgstr "# Patrones de comportamiento" #: src\patterns/behavioural/intro.md:3 #, fuzzy msgid "From [Wikipedia](https://en.wikipedia.org/wiki/Behavioral_pattern):" msgstr "De [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 "" "> Patrones de diseño que identifican patrones de comunicación comunes entre " "objetos.\n" "> Al hacerlo, estos patrones aumentan la flexibilidad en la realización de " "la comunicación." #: src\patterns/behavioural/command.md:1 #, fuzzy msgid "# Command" msgstr "# Dominio" #: 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 "" "La idea básica del patrón Comando es separar las acciones en sus propias\n" "objetos y pasarlos como parámetros." #: 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 "" "Supongamos que tenemos una secuencia de acciones o transacciones " "encapsuladas como objetos.\n" "Queremos que estas acciones o comandos se ejecuten o invoquen en algún orden " "más adelante\n" "en tiempo diferente. Estos comandos también pueden activarse como resultado " "de algún evento.\n" "Por ejemplo, cuando un usuario presiona un botón o cuando llega un paquete " "de datos.\n" "Además, estos comandos se pueden deshacer. Esto puede ser útil para\n" "operaciones de un editor. Podríamos querer almacenar registros de comandos " "ejecutados para que\n" "podríamos volver a aplicar los cambios más tarde si el sistema falla." #: 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 "" "Defina dos operaciones de base de datos `crear tabla` y `agregar campo`. " "Cada uno de estos\n" "operaciones es un comando que sabe cómo deshacer el comando, por ejemplo, " "`drop table`\n" "y `eliminar campo`. Cuando un usuario invoca una operación de migración de " "base de datos, cada\n" "el comando se ejecuta en el orden definido, y cuando el usuario invoca la " "reversión\n" "operación, entonces todo el conjunto de comandos se invoca en orden inverso." #: src\patterns/behavioural/command.md:26 #, fuzzy msgid "## Approach: Using trait objects" msgstr "## Enfoque: uso de objetos de rasgos" #: 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 "" "Definimos un rasgo común que encapsula nuestro comando con dos operaciones\n" "`ejecutar` y `retroceder`. Todas las `estructuras` de comando deben " "implementar este rasgo." #: 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>,\n" "}\n" "\n" "impl Schema {\n" " fn new() -> Self {\n" " Self { commands: vec![] }\n" " }\n" "\n" " fn add_migration(&mut self, cmd: Box) {\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 "## Enfoque: uso de punteros de función" #: 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 "" "Podríamos seguir otro enfoque creando cada comando individual como\n" "una función diferente y almacenar punteros de función para invocar estas " "funciones más tarde\n" "en un momento diferente. Dado que los punteros de función implementan los " "tres rasgos `Fn`,\n" "`FnMut` y `FnOnce` también podríamos pasar y almacenar cierres en lugar de\n" "punteros de función." #: 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,\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 {\n" " self.commands.iter().map(|cmd| (cmd.execute)()).collect()\n" " }\n" " fn rollback(&self) -> Vec {\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 "## Enfoque: Uso de objetos de rasgos `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 "" "Finalmente, en lugar de definir un rasgo de comando común, podríamos " "almacenar\n" "cada comando implementa el rasgo `Fn` por separado en vectores." #: src\patterns/behavioural/command.md:155 msgid "" "```rust\n" "type Migration<'a> = Box &'a str>;\n" "\n" "struct Schema<'a> {\n" " executes: Vec>,\n" " rollbacks: Vec>,\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(&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 "" "Si nuestros comandos son pequeños y pueden definirse como funciones o " "pasarse como cierre\n" "entonces podría ser preferible usar punteros de función, ya que no explota\n" "despacho dinámico. Pero si nuestro comando es una estructura completa con un " "montón de funciones\n" "y variables definidas como módulo separado, entonces usar objetos de rasgos " "sería\n" "mas apropiado. Se puede encontrar un caso de aplicación en " "[`actix`](https://actix.rs/),\n" "que usa objetos de rasgos cuando registra una función de controlador para " "rutas.\n" "En caso de usar objetos de rasgo `Fn` podemos crear y usar comandos en el " "mismo\n" "tal como lo usamos en el caso de los punteros de función." #: 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 "" "Como rendimiento, siempre hay una compensación entre el rendimiento y el " "código.\n" "sencillez y organización. El despacho estático proporciona un rendimiento " "más rápido, mientras que\n" "El despacho dinámico proporciona flexibilidad cuando estructuramos nuestra " "aplicación." #: 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 "" "- [Patrón de comando](https://en.wikipedia.org/wiki/Command_pattern)\n" "\n" "- [Otro ejemplo del patrón " "`comando`](https://web.archive.org/web/20210223131236/https://chercher.tech/rust/command-design-pattern-rust)" #: src\patterns/behavioural/interpreter.md:1 #, fuzzy msgid "# Interpreter" msgstr "# Intérprete" #: 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 "" "Si un problema ocurre con mucha frecuencia y requiere pasos largos y " "repetitivos para resolverlo\n" "entonces las instancias del problema podrían expresarse en un lenguaje " "simple y un\n" "El objeto intérprete podría resolverlo interpretando las oraciones escritas " "en este\n" "lenguaje sencillo" #: src\patterns/behavioural/interpreter.md:10 #, fuzzy msgid "Basically, for any kind of problems we define:" msgstr "Básicamente, para cualquier tipo de problema definimos:" #: 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 "" "- Un [idioma específico del " "dominio](https://en.wikipedia.org/wiki/Domain-specific_language),\n" "- Una gramática para este idioma,\n" "- Un intérprete que resuelve las instancias 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 "" "Nuestro objetivo es traducir expresiones matemáticas simples en expresiones " "postfix\n" "(o [notación polaca " "inversa](https://en.wikipedia.org/wiki/Reverse_Polish_notation))\n" "Para simplificar, nuestras expresiones constan de diez dígitos `0`, ..., `9` " "y dos\n" "operaciones `+`, `-`. Por ejemplo, la expresión `2 + 4` se traduce a\n" "`2 4 +`." #: src\patterns/behavioural/interpreter.md:24 #, fuzzy msgid "## Context Free Grammar for our problem" msgstr "## Gramática libre de contexto para nuestro 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 "" "Nuestra tarea es traducir expresiones infijas a postfijas. Definamos un " "contexto\n" "gramática libre para un conjunto de expresiones infijas sobre `0`, ..., `9`, " "`+` y `-`,\n" "dónde:" #: 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 "" "- Símbolos terminales: `0`, `...`, `9`, `+`, `-`\n" "- Símbolos no terminales: `exp`, `term`\n" "- El símbolo de inicio es `exp`\n" "- Y las siguientes son reglas de producción." #: 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:** Esta gramática debe transformarse aún más dependiendo de lo que " "estemos haciendo\n" "hacer con eso Por ejemplo, es posible que necesitemos eliminar la " "recursividad por la izquierda. Para más\n" "detalles, consulte [Compiladores: principios, técnicas y herramientas] " "(https://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools)\n" "(también conocido como Libro del Dragón)." #: src\patterns/behavioural/interpreter.md:47 #, fuzzy msgid "## Solution" msgstr "## Solución" #: 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 "" "Simplemente implementamos un analizador de descenso recursivo. En aras de la " "simplicidad, el código\n" "entra en pánico cuando una expresión es sintácticamente incorrecta (por " "ejemplo, `2-34` o `2+5-`\n" "están mal según la definición gramatical)." #: 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 {\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 "" "Puede haber una percepción errónea de que el patrón de diseño del Intérprete " "se trata de diseño\n" "gramáticas para lenguajes formales e implementación de analizadores para " "estas gramáticas.\n" "De hecho, este patrón se trata de expresar instancias de problemas en una " "forma más específica.\n" "e implementando funciones/clases/estructuras que resuelven estas instancias " "de problemas.\n" "El lenguaje Rust tiene `macro_rules!` que nos permiten definir sintaxis y " "reglas especiales\n" "sobre cómo expandir esta sintaxis en el código fuente." #: 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 "" "En el siguiente ejemplo, creamos un `macro_rules!` simple que calcula\n" "[Longitud euclidiana](https://en.wikipedia.org/wiki/Euclidean_distance) de " "`n`\n" "vectores dimensionales. Escribir `norma!(x,1,2)` podría ser más fácil de " "expresar y más\n" "más eficiente que empaquetar `x,1,2` en un `Vec` y llamar a una función " "informática\n" "la longitud." #: 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 "" "- [Patrón de intérprete](https://en.wikipedia.org/wiki/Interpreter_pattern)\n" "- [Gramática libre de " "contexto](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 "# Nuevo 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 "" "¿Qué pasa si en algunos casos queremos que un tipo se comporte de manera " "similar a otro tipo o\n" "hacer cumplir algún comportamiento en tiempo de compilación cuando usar solo " "alias de tipo sería\n" "no ser suficiente?" #: 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 "" "Por ejemplo, si queremos crear una implementación `Display` personalizada " "para `String`\n" "debido a consideraciones de seguridad (por ejemplo, contraseñas)." #: 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 "" "Para tales casos, podríamos usar el patrón `Newtype` para proporcionar " "**seguridad de tipo**\n" "y **encapsulación**." #: 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 "" "Use una estructura de tupla con un solo campo para crear un contenedor opaco " "para un tipo.\n" "Esto crea un nuevo tipo, en lugar de un alias para un tipo (elementos " "`tipo`)." #: 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 principal motivación para los nuevos tipos es la abstracción. Te permite " "compartir\n" "detalles de implementación entre tipos mientras controla con precisión la " "interfaz.\n" "Al usar un nuevo tipo en lugar de exponer el tipo de implementación como " "parte de un\n" "API, le permite cambiar la implementación de manera retrocompatible." #: 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 "" "Los tipos nuevos se pueden usar para distinguir unidades, por ejemplo, " "envolviendo `f64` para dar\n" "distinguibles `Millas` y `Kilómetros`." #: 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 "" "Los tipos wrapper y wrapper no son compatibles (a diferencia de usar\n" "`tipo`), por lo que los usuarios del nuevo tipo nunca 'confundirán' el " "envuelto y el envoltorio\n" "tipos" #: src\patterns/behavioural/newtype.md:72 #, fuzzy msgid "Newtypes are a zero-cost abstraction - there is no runtime overhead." msgstr "" "Los tipos nuevos son una abstracción de costo cero: no hay sobrecarga de " "tiempo de ejecución." #: 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 "" "El sistema de privacidad garantiza que los usuarios no puedan acceder al " "tipo envuelto (si el\n" "el campo es privado, que es por defecto)." #: 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 "" "La desventaja de los nuevos tipos (especialmente en comparación con los " "alias de tipo) es que no\n" "no hay soporte de idioma especial. Esto significa que puede haber _mucho_ " "repetitivo.\n" "Necesita un método de 'paso a través' para cada método que desee exponer en " "el\n" "tipo envuelto, y un impl para cada rasgo que desea implementar también para\n" "el tipo de envoltura." #: 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 "" "Los tipos nuevos son muy comunes en el código de Rust. Las unidades de " "abstracción o representación son las\n" "usos más comunes, pero pueden ser utilizados por otras razones:" #: 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 "" "- restringir la funcionalidad (reducir las funciones expuestas o los rasgos " "implementados),\n" "- hacer que un tipo con semántica de copia tenga semántica de movimiento,\n" "- abstracción proporcionando un tipo más concreto y ocultando así los tipos " "internos,\n" " p.ej.," #: src\patterns/behavioural/newtype.md:95 msgid "" "```rust,ignore\n" "pub struct Foo(Bar);\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 "" "Aquí, 'Bar' podría ser un tipo genérico público y 'T1' y 'T2' son algunos " "internos.\n" "tipos Los usuarios de nuestro módulo no deberían saber que implementamos " "`Foo` usando una `Bar`,\n" "pero lo que realmente estamos ocultando aquí son los tipos `T1` y `T2`, y " "cómo se usan\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 "" "- [Tipos avanzados en el " "libro](https://doc.rust-lang.org/book/ch19-04-advanced-types.html?highlight=newtype#using-the-newtype-pattern-for-type-safety " "-y-abstracción)\n" "- [Nuevos tipos en Haskell](https://wiki.haskell.org/Newtype)\n" "- [Escriba " "alias](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 caja para derivar " "muchos\n" " rasgos incorporados en newtypes.\n" "- [El patrón Newtype en " "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 guardias" #: 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] significa \"Adquisición de recursos es inicialización\", " "que es una\n" "terrible nombre La esencia del patrón es que la inicialización de recursos " "se realiza\n" "en el constructor de un objeto y finalización en el destructor. este patrón\n" "se extiende en Rust usando un objeto RAII como guardián de algún recurso y " "confiando\n" "en el sistema de tipos para garantizar que el acceso siempre esté mediado " "por el objeto guardián." #: 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 "" "Los protectores Mutex son el ejemplo clásico de este patrón de la biblioteca " "estándar (este\n" "es una versión simplificada de la implementación real):" #: src\patterns/behavioural/RAII.md:16 msgid "" "```rust,ignore\n" "use std::ops::Deref;\n" "\n" "struct Foo {}\n" "\n" "struct Mutex {\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 Mutex {\n" " fn lock(&self) -> MutexGuard {\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) {\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 "" "Cuando un recurso debe finalizarse después de su uso, se puede usar RAII " "para hacer esto\n" "finalización Si es un error acceder a ese recurso después de la " "finalización, entonces\n" "este patrón se puede utilizar para evitar tales errores." #: 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 errores donde un recurso no está finalizado y donde se usa un " "recurso\n" "después de la finalización." #: 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 es un patrón útil para garantizar que los recursos se desasignen o\n" "finalizado. Podemos hacer uso del verificador de préstamos en Rust para " "evitar estáticamente\n" "errores derivados del uso de recursos después de la finalización." #: 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 "" "El objetivo principal del verificador de préstamos es garantizar que las " "referencias a los datos no\n" "sobrevivir a esos datos. El patrón de protección RAII funciona porque el " "objeto de protección\n" "contiene una referencia al recurso subyacente y solo expone tal\n" "referencias Rust asegura que el guardia no puede sobrevivir al recurso " "subyacente\n" "y que las referencias al recurso mediado por la guardia no pueden sobrevivir " "al\n" "guardia. Para ver cómo funciona esto, es útil examinar la firma de `deref`\n" "sin elisión de por vida:" #: 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 "" "La referencia devuelta al recurso tiene la misma duración que `self` " "(`'a`).\n" "Por lo tanto, el verificador de préstamos garantiza que la vida útil de la " "referencia a `T`\n" "es más corto que el tiempo de vida de `sí mismo`." #: 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 "" "Tenga en cuenta que la implementación de `Deref` no es una parte central de " "este patrón, solo hace\n" "utilizando el objeto de guardia más ergonómico. Implementando un método " "`get` en el guardia\n" "funciona igual de bien." #: src\patterns/behavioural/RAII.md:113 #, fuzzy msgid "[Finalisation in destructors idiom](../../idioms/dtor-finally.md)" msgstr "[Finalización en idioma de destructores](../../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 es un patrón común en 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 "" "[Entrada de guía de " "estilo](https://doc.rust-lang.org/1.0.0/style/ownership/raii.html)\n" "(actualmente solo un marcador de posición)." #: src\patterns/behavioural/strategy.md:1 #, fuzzy msgid "# Strategy (aka Policy)" msgstr "# Estrategia (también conocida como Política)" #: 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 "" "El [patrón de diseño de estrategia] " "(https://en.wikipedia.org/wiki/Strategy_pattern)\n" "es una técnica que permite la separación de preocupaciones.\n" "También permite desacoplar módulos de software a través de [Inversión de " "dependencia] (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 "" "La idea básica detrás del patrón de estrategia es que, dado un algoritmo que " "resuelve\n" "un problema particular, definimos solo el esqueleto del algoritmo en un " "resumen\n" "nivel, y separamos la implementación del algoritmo específico en diferentes " "partes." #: 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 "" "De esta forma, un cliente que utilice el algoritmo puede elegir una " "implementación específica,\n" "mientras que el flujo de trabajo general del algoritmo sigue siendo el " "mismo. En otras palabras, el resumen\n" "especificación de la clase no depende de la implementación específica de la\n" "clase derivada, pero la implementación específica debe adherirse a la " "especificación abstracta.\n" "Es por eso que lo llamamos \"Inversión de Dependencia\"." #: 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 "" "Imagina que estamos trabajando en un proyecto que genera informes todos los " "meses.\n" "Necesitamos que los informes se generen en diferentes formatos " "(estrategias), por ejemplo,\n" "en formatos `JSON` o `Plain Text`.\n" "Pero las cosas varían con el tiempo, y no sabemos qué tipo de requisito " "podemos obtener\n" "en el futuro. Por ejemplo, es posible que necesitemos generar nuestro " "informe en un formato completamente nuevo.\n" "formato, o simplemente modificar uno de los formatos existentes." #: 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 "" "En este ejemplo, nuestras invariantes (o abstracciones) son `Context`, " "`Formatter`,\n" "y `Report`, mientras que `Text` y `Json` son nuestras estructuras de " "estrategia. Estas estrategias\n" "tiene que implementar el rasgo `Formatter`." #: src\patterns/behavioural/strategy.md:34 msgid "" "```rust\n" "use std::collections::HashMap;\n" "\n" "type Data = HashMap;\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(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 "" "La principal ventaja es la separación de preocupaciones. Por ejemplo, en " "este caso `Informe`\n" "no sabe nada sobre implementaciones específicas de `Json` y `Text`,\n" "mientras que las implementaciones de salida no se preocupan por cómo se " "preprocesan los datos,\n" "almacenado y obtenido. Lo único que tienen que saber es el contexto y una " "determinada\n" "rasgo y método a implementar, es decir, `Formatter` y `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 "" "Para cada estrategia debe implementarse al menos un módulo, por lo que el " "número de módulos\n" "aumenta con el número de estrategias. Si hay muchas estrategias para elegir\n" "luego los usuarios tienen que saber en qué se diferencian las estrategias " "entre sí." #: 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 "" "En el ejemplo anterior todas las estrategias se implementan en un solo " "archivo.\n" "Las formas de proporcionar diferentes estrategias incluyen:" #: 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 "" "- Todo en un archivo (como se muestra en este ejemplo, similar a estar " "separados como módulos)\n" "- Separados como módulos, p. módulo `formateador::json`, módulo " "`formateador::texto`\n" "- Use indicadores de características del compilador, p. función `json`, " "función `texto`\n" "- Separados como cajas, p. caja `json`, caja `texto`" #: 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 es un buen ejemplo del patrón 'Estrategia' en acción. Serde " "permite\n" "[personalización completa](https://serde.rs/custom-serialization.html) de la " "serialización\n" "comportamiento implementando manualmente `Serialize` y `Deserialize` rasgos " "para nuestro\n" "tipo. Por ejemplo, podríamos intercambiar fácilmente `serde_json` con " "`serde_cbor` ya que\n" "exponer métodos similares. Tener esto hace que el asistente cree " "`serde_transcode` mucho\n" "más útil y ergonómico." #: 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 "" "Sin embargo, no necesitamos usar rasgos para diseñar este patrón en 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 "" "El siguiente ejemplo de juguete demuestra la idea del patrón de estrategia " "usando Rust\n" "`cierres`:" #: src\patterns/behavioural/strategy.md:132 msgid "" "```rust\n" "struct Adder;\n" "impl Adder {\n" " pub fn add(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 "De hecho, Rust ya usa esta idea para el método `map` de `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 "" "- [Patrón de estrategia](https://en.wikipedia.org/wiki/Strategy_pattern)\n" "- [Inyección de " "dependencia](https://en.wikipedia.org/wiki/Dependency_injection)\n" "- [Diseño basado en políticas] " "(https://en.wikipedia.org/wiki/Modern_C++_Design#Policy-based_design)" #: src\patterns/behavioural/visitor.md:1 #, fuzzy msgid "# Visitor" msgstr "# Visitante" #: 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 visitante encapsula un algoritmo que opera sobre un heterogéneo\n" "colección de objetos. Permite escribir múltiples algoritmos diferentes.\n" "sobre los mismos datos sin tener que modificar los datos (o su principal\n" "comportamiento)." #: 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 "" "Además, el patrón de visitante permite separar el recorrido de\n" "una colección de objetos de las operaciones realizadas en cada objeto." #: 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, Box),\n" " Sub(Box, Box),\n" " }\n" "}\n" "\n" "// The abstract visitor\n" "mod visit {\n" " use ast::*;\n" "\n" " pub trait Visitor {\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 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 "" "Se podrían implementar más visitantes, por ejemplo, un verificador de tipos, " "sin tener\n" "para modificar los datos 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 "" "El patrón de visitante es útil en cualquier lugar al que desee aplicar un " "algoritmo\n" "datos heterogéneos. Si los datos son homogéneos, puede usar un patrón " "similar a un iterador.\n" "El uso de un objeto de visitante (en lugar de un enfoque funcional) le " "permite al visitante\n" "tener estado y así comunicar información entre nodos." #: 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 "" "Es común que los métodos `visit_*` devuelvan void (a diferencia del método\n" "ejemplo). En ese caso, es posible factorizar el código transversal y " "compartir\n" "entre algoritmos (y también para proporcionar métodos predeterminados de " "noop). En óxido, el\n" "La forma común de hacer esto es proporcionar funciones `walk_*` para cada " "dato. Para\n" "ejemplo," #: 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 "" "En otros lenguajes (por ejemplo, Java) es común que los datos tengan un " "método `aceptar`\n" "que cumple el mismo deber." #: src\patterns/behavioural/visitor.md:108 #, fuzzy msgid "The visitor pattern is a common pattern in most OO languages." msgstr "" "El patrón de visitante es un patrón común en la mayoría de los lenguajes OO." #: src\patterns/behavioural/visitor.md:110 #, fuzzy msgid "[Wikipedia article](https://en.wikipedia.org/wiki/Visitor_pattern)" msgstr "[Artículo de 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 "" "El patrón [fold](../creational/fold.md) es similar al visitante pero " "produce\n" "una nueva versión de la estructura de datos visitada." #: src\patterns/creational/intro.md:1 #, fuzzy msgid "# Creational Patterns" msgstr "# Patrones de creación" #: src\patterns/creational/intro.md:3 #, fuzzy msgid "From [Wikipedia](https://en.wikipedia.org/wiki/Creational_pattern):" msgstr "De [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 "" "> Patrones de diseño que se ocupan de los mecanismos de creación de objetos, " "tratando de crear objetos\n" "> de una manera adecuada a la situación. La forma básica de creación de " "objetos podría\n" "> resultar en problemas de diseño o en complejidad adicional al diseño. " "diseño creacional\n" "> los patrones resuelven este problema controlando de alguna manera la " "creación de este objeto." #: src\patterns/creational/builder.md:1 #, fuzzy msgid "# Builder" msgstr "# Constructor" #: src\patterns/creational/builder.md:5 #, fuzzy msgid "Construct an object with calls to a builder helper." msgstr "Construya un objeto con llamadas a un asistente de construcción." #: 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 "" "Útil cuando de otro modo necesitaría muchos constructores o donde\n" "la construcción tiene efectos secundarios." #: src\patterns/creational/builder.md:70 #, fuzzy msgid "Separates methods for building from other methods." msgstr "Separa los métodos de construcción de otros métodos." #: src\patterns/creational/builder.md:72 #, fuzzy msgid "Prevents proliferation of constructors." msgstr "Evita la proliferación de constructores." #: src\patterns/creational/builder.md:74 #, fuzzy msgid "" "Can be used for one-liner initialisation as well as more complex " "construction." msgstr "" "Se puede utilizar para la inicialización de una sola línea, así como para " "construcciones más complejas." #: src\patterns/creational/builder.md:78 #, fuzzy msgid "" "More complex than creating a struct object directly, or a simple " "constructor\n" "function." msgstr "" "Más complejo que crear un objeto de estructura directamente o un constructor " "simple\n" "función." #: 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 "" "Este patrón se ve con más frecuencia en Rust (y para objetos más simples) " "que en\n" "muchos otros lenguajes porque Rust carece de sobrecarga. Ya que solo puedes " "tener un\n" "método único con un nombre dado, tener múltiples constructores es menos " "agradable en\n" "Rust que en C++, Java u otros." #: 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 "" "Este patrón se usa a menudo cuando el objeto constructor es útil por derecho " "propio,\n" "en lugar de ser sólo un constructor. Por ejemplo, ver\n" "[`std::process::Command`](https://doc.rust-lang.org/std/process/struct.Command.html)\n" "es un constructor para " "[`Child`](https://doc.rust-lang.org/std/process/struct.Child.html)\n" "(un proceso). En estos casos, no se utiliza el patrón de nomenclatura `T` y " "`TBuilder`." #: 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 "" "El ejemplo toma y devuelve el constructor por valor. A menudo es más " "ergonómico.\n" "(y más eficiente) para tomar y devolver el constructor como una referencia " "mutable. El\n" "El verificador de préstamos hace que esto funcione de forma natural. Este " "enfoque tiene la ventaja de que\n" "uno puede escribir código como" #: 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 "así como el estilo `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 "" "- [Descripción en la guía de " "estilo](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 caja para " "automáticamente\n" " implementar este patrón mientras se evita el repetitivo.\n" "- [Patrón de constructor](../../idioms/ctor.md) para cuando la construcción " "es más sencilla.\n" "- [Patrón de constructor " "(wikipedia)](https://en.wikipedia.org/wiki/Builder_pattern)\n" "- [Construcción de valores " "complejos](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 "# Doblar" #: 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 "" "Ejecute un algoritmo sobre cada elemento en una colección de datos para " "crear un nuevo elemento,\n" "creando así una colección completamente nueva." #: 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 "" "La etimología aquí no está clara para mí. Los términos 'doblar' y 'carpeta' " "se utilizan\n" "en el compilador de Rust, aunque me parece más un mapa que un\n" "doblar en el sentido habitual. Consulte la discusión a continuación para " "obtener más detalles." #: 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),\n" " Let(Box, Box),\n" " }\n" "\n" " pub struct Name {\n" " value: String,\n" " }\n" "\n" " pub enum Expr {\n" " IntLit(i64),\n" " Add(Box, Box),\n" " Sub(Box, Box),\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) -> Box { n }\n" " // Create a new inner node by folding its children.\n" " fn fold_stmt(&mut self, s: Box) -> Box {\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) -> Box { ... }\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) -> Box {\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 "" "El resultado de ejecutar `Renamer` en un AST es un nuevo AST idéntico al " "antiguo\n" "one, pero con todos los nombres cambiados a `foo`. Una carpeta de la vida " "real podría tener algunos\n" "estado preservado entre nodos en la estructura misma." #: 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 "" "También se puede definir una carpeta para asignar una estructura de datos a " "otra diferente (pero\n" "generalmente similar) estructura de datos. Por ejemplo, podríamos convertir " "un AST en un HIR\n" "árbol (HIR significa representación intermedia de alto nivel)." #: 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 "" "Es común querer mapear una estructura de datos realizando alguna operación " "en\n" "cada nodo de la estructura. Para operaciones simples en estructuras de datos " "simples,\n" "esto se puede hacer usando `Iterator::map`. Para operaciones más complejas, " "tal vez\n" "donde los nodos anteriores pueden afectar la operación en nodos posteriores, " "o donde la iteración\n" "sobre la estructura de datos no es trivial, usar el patrón de plegado es " "más\n" "adecuado." #: 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 "" "Al igual que el patrón de visitante, el patrón de plegado nos permite " "separar el recorrido de un\n" "estructura de datos de las operaciones realizadas a cada 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 "" "Mapear estructuras de datos de esta manera es común en lenguajes " "funcionales. en OO\n" "idiomas, sería más común mutar la estructura de datos en su lugar. El\n" "El enfoque 'funcional' es común en Rust, principalmente debido a la " "preferencia por\n" "inmutabilidad. El uso de estructuras de datos nuevas, en lugar de mutar las " "antiguas, hace\n" "razonar sobre el código es más fácil en la mayoría de las circunstancias." #: 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 "" "La compensación entre la eficiencia y la reutilización se puede ajustar " "cambiando cómo\n" "los nodos son aceptados por los métodos `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 "" "En el ejemplo anterior, operamos con punteros `Box`. Ya que estos son dueños " "de sus datos\n" "exclusivamente, la copia original de la estructura de datos no puede ser " "reutilizada. Sobre el\n" "Por otro lado, si un nodo no se cambia, reutilizarlo es muy eficiente." #: 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 "" "El uso de un puntero contado de referencia ofrece lo mejor de ambos mundos: " "podemos reutilizar\n" "la estructura de datos original, y no necesitamos clonar nodos sin cambios. " "Sin embargo,\n" "son menos ergonómicos de usar y significan que las estructuras de datos no " "pueden ser\n" "mudable." #: 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 "" "Los iteradores tienen un método `doblar`, sin embargo, este dobla una " "estructura de datos en una\n" "valor, en lugar de en una nueva estructura de datos. El `mapa` de un " "iterador es más como\n" "este patrón de plegado." #: 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 "" "En otros lenguajes, fold se usa generalmente en el sentido de los iteradores " "de Rust,\n" "en lugar de este patrón. Algunos lenguajes funcionales tienen poderosas " "construcciones para\n" "realizar mapas flexibles sobre estructuras de datos." #: 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 "" "El patrón [visitante](../behavioural/visitor.md) está estrechamente " "relacionado con el pliegue.\n" "Comparten el concepto de recorrer una estructura de datos realizando una " "operación sobre\n" "cada nodo. Sin embargo, el visitante no crea una nueva estructura de datos " "ni consume\n" "el viejo." #: src\patterns/structural/intro.md:1 #, fuzzy msgid "# Structural Patterns" msgstr "# Patrones Estructurales" #: src\patterns/structural/intro.md:3 #, fuzzy msgid "From [Wikipedia](https://en.wikipedia.org/wiki/Structural_pattern):" msgstr "De [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 "" "> Patrones de diseño que facilitan el diseño al identificar una forma " "sencilla de realizar relaciones\n" "> entre entidades." #: src\patterns/structural/compose-structs.md:1 #, fuzzy msgid "# Compose structs together for better borrowing" msgstr "# Componer estructuras juntas para un mejor préstamo" #: src\patterns/structural/compose-structs.md:3 #, fuzzy msgid "TODO - this is not a very snappy name" msgstr "TODO - este no es un nombre muy ágil" #: 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 veces, una estructura grande causará problemas con el verificador de " "préstamos, aunque\n" "los campos se pueden tomar prestados de forma independiente, a veces toda la " "estructura termina siendo\n" "utilizados de una sola vez, impidiendo otros usos. Una solución podría ser " "descomponer la estructura\n" "en varias estructuras más pequeñas. Luego componga estos juntos en el " "original\n" "estructura Luego, cada estructura se puede tomar prestada por separado y " "tener más flexibilidad\n" "comportamiento." #: 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 "" "Esto a menudo conducirá a un mejor diseño de otras maneras: aplicar este " "diseño\n" "patrón a menudo revela unidades más pequeñas de funcionalidad." #: 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 "" "Aquí hay un ejemplo artificial de dónde el verificador de préstamos nos " "frustra en nuestro plan para\n" "usar una estructura:" #: 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 "" "Podemos aplicar este patrón de diseño y refactorizar `A` en dos estructuras " "más pequeñas, por lo tanto\n" "resolviendo el problema de verificación de préstamo:" #: 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 Por qué y dónde deberías usar el patrón" #: src\patterns/structural/compose-structs.md:77 #, fuzzy msgid "Lets you work around limitations in the borrow checker." msgstr "Le permite sortear las limitaciones del verificador de préstamos." #: src\patterns/structural/compose-structs.md:79 #, fuzzy msgid "Often produces a better design." msgstr "A menudo produce un mejor diseño." #: src\patterns/structural/compose-structs.md:83 #, fuzzy msgid "Leads to more verbose code." msgstr "Conduce a un código más detallado." #: 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 veces, las estructuras más pequeñas no son buenas abstracciones, por lo " "que terminamos con\n" "un diseño peor. Eso es probablemente un 'olor a código', lo que indica que " "el programa\n" "debe ser refactorizado de alguna manera." #: 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 "" "Este patrón no es necesario en los idiomas que no tienen un verificador de " "préstamos, por lo que\n" "en ese sentido es exclusivo de Rust. Sin embargo, hacer unidades más " "pequeñas de funcionalidad\n" "a menudo conduce a un código más limpio: un principio de software " "ampliamente reconocido\n" "ingeniería, independiente del idioma." #: 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 "" "Este patrón se basa en el verificador de préstamos de Rust para poder tomar " "prestados campos.\n" "independientemente unos de otros. En el ejemplo, el verificador de préstamos " "sabe que `a.b`\n" "y `a.c` son distintos y se pueden tomar prestados de forma independiente, no " "intenta\n" "toma prestada toda `a`, lo que haría que este patrón fuera inútil." #: src\patterns/structural/small-crates.md:1 #, fuzzy msgid "# Prefer small crates" msgstr "# Preferir cajas pequeñas" #: src\patterns/structural/small-crates.md:5 #, fuzzy msgid "Prefer small crates that do one thing well." msgstr "Prefiere cajas pequeñas que hacen una sola cosa bien." #: 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 y crates.io facilitan la adición de bibliotecas de terceros, mucho más " "que\n" "en decir C o C++. Además, dado que los paquetes en crates.io no se pueden " "editar ni eliminar\n" "después de la publicación, cualquier compilación que funcione ahora debería " "continuar funcionando en el futuro.\n" "Deberíamos aprovechar esta herramienta y usar dependencias más pequeñas y " "detalladas." #: 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 "" "- Las cajas pequeñas son más fáciles de entender y fomentan un código más " "modular.\n" "- Las cajas permiten reutilizar código entre proyectos.\n" " Por ejemplo, la caja `url` se desarrolló como parte del motor del " "navegador Servo,\n" " pero desde entonces ha encontrado un amplio uso fuera del proyecto.\n" "- Desde la unidad de compilación\n" " de Rust es la caja, dividir un proyecto en varias cajas puede permitir más " "de\n" " el código que se construirá en paralelo." #: 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 "" "- Esto puede conducir al \"infierno de la dependencia\", cuando un proyecto " "depende de múltiples conflictos\n" " versiones de una caja al mismo tiempo. Por ejemplo, la caja `url` tiene " "ambas versiones\n" " 1.0 y 0.5. Dado que la `Url` de `url:1.0` y la `Url` de `url:0.5` son\n" " diferentes tipos, un cliente HTTP que usa `url:0.5` no aceptaría valores " "`Url`\n" " de un web scraper que usa `url:1.0`.\n" "- Los paquetes en crates.io no están curados. Una caja puede estar mal " "escrita, tener\n" " documentación poco útil, o ser totalmente malicioso.\n" "- Dos cajas pequeñas pueden estar menos optimizadas que una grande, ya que " "el compilador\n" " no realiza la optimización del tiempo de enlace (LTO) de forma " "predeterminada." #: 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 "" "El cajón [`ref_slice`](https://crates.io/crates/ref_slice) proporciona " "funciones\n" "para convertir `&T` a `&[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 "" "El cajón [`url`](https://crates.io/crates/url) proporciona herramientas para " "trabajar 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 "" "El cajón [`num_cpus`](https://crates.io/crates/num_cpus) proporciona una " "función para\n" "consultar el número de CPU en una máquina." #: src\patterns/structural/small-crates.md:47 #, fuzzy msgid "- [crates.io: The Rust community crate host](https://crates.io/)" msgstr "" "- [crates.io: El host de cajas de la comunidad de Rust](https://crates.io/)" #: src\patterns/structural/unsafe-mods.md:1 #, fuzzy msgid "# Contain unsafety in small modules" msgstr "# Contener la inseguridad en pequeños módulos" #: 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 "" "Si tiene un código \"inseguro\", cree el módulo más pequeño posible que " "pueda mantener\n" "las invariantes necesarias para construir una interfaz segura mínima sobre " "la inseguridad. Empotrar\n" "esto en un módulo más grande que contiene solo código seguro y presenta un " "diseño ergonómico\n" "interfaz. Tenga en cuenta que el módulo externo puede contener funciones y " "métodos no seguros\n" "que llaman directamente al código no seguro. Los usuarios pueden usar esto " "para obtener beneficios de velocidad." #: 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 "" "- Esto restringe el código inseguro que debe ser auditado\n" "- Escribir el módulo exterior es mucho más fácil, ya que puedes contar con " "las garantías\n" " del módulo interior" #: 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 veces, puede ser difícil encontrar una interfaz adecuada.\n" "- La abstracción puede introducir ineficiencias." #: 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` 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 "" "- La caja [`toolshed`](https://docs.rs/toolshed) contiene sus operaciones " "inseguras\n" " en submódulos, presentando una interfaz segura para los usuarios.\n" "- La clase `String` de `std` es un contenedor sobre `Vec` con el " "invariante agregado\n" " que el contenido debe ser UTF-8 válido. Las operaciones en `String` " "aseguran esto\n" " comportamiento.\n" " Sin embargo, los usuarios tienen la opción de usar un método \"no seguro\" " "para crear una \"Cadena\",\n" " en cuyo caso corresponde a ellos garantizar la vigencia de los contenidos." #: 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 de Ralf Jung sobre invariantes en código no " "seguro](https://www.ralfj.de/blog/2018/08/22/two-kinds-of-invariants.html)" #: src\patterns/ffi/intro.md:1 #, fuzzy msgid "# FFI Patterns" msgstr "# Patrones 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 "" "Escribir código FFI es un curso completo en sí mismo.\n" "Sin embargo, aquí hay varios modismos que pueden actuar como indicadores y " "evitar trampas.\n" "para usuarios inexpertos de Rust inseguro." #: src\patterns/ffi/intro.md:7 #, fuzzy msgid "This section contains design patterns that may be useful when doing FFI." msgstr "" "Esta sección contiene patrones de diseño que pueden ser útiles al hacer 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. Diseño de [API basada en objetos] (./export.md) que tiene buenas " "características de seguridad de memoria,\n" " y un límite limpio de lo que es seguro y lo que es inseguro\n" "\n" "2. [Consolidación de tipos en envoltorios] (./wrappers.md) - agrupa varios " "tipos de Rust\n" " juntos en un \"objeto\" opaco" #: src\patterns/ffi/export.md:1 #, fuzzy msgid "# Object-Based APIs" msgstr "# API basadas en objetos" #: 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 "" "Al diseñar API en Rust que están expuestas a otros lenguajes, hay algunos\n" "principios de diseño importantes que son contrarios al diseño normal de la " "API de 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. Todos los tipos encapsulados deben ser _propiedad_ de Rust, " "_administrados_ por el usuario,\n" " y _opaco_.\n" "2. Todos los tipos de datos transaccionales deben ser _propiedad_ del " "usuario y _transparentes_.\n" "3. Todo el comportamiento de la biblioteca debe ser funciones que actúen " "sobre tipos encapsulados.\n" "4. Todo el comportamiento de la biblioteca debe encapsularse en tipos que no " "se basen en la estructura,\n" " pero _procedencia/tiempo de vida_." #: 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 tiene soporte FFI integrado para otros idiomas.\n" "Lo hace al proporcionar una forma para que los autores de cajas proporcionen " "API compatibles con C\n" "a través de diferentes ABI (aunque eso no es importante para esta práctica)." #: 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 bien diseñado sigue los principios de diseño de C API, al tiempo " "que compromete la\n" "diseño en Rust lo menos posible. Hay tres objetivos con cualquier API " "extranjera:" #: 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. Facilite su uso en el idioma de destino.\n" "2. Evite que la API dicte inseguridad interna en el lado de Rust tanto como " "sea posible.\n" "3. Mantenga el potencial de inseguridad de la memoria y el \"comportamiento " "indefinido\" de Rust como pequeño\n" " como sea posible." #: 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 "" "El código Rust debe confiar en la seguridad de la memoria del idioma " "extranjero más allá de cierto\n" "punto. Sin embargo, cada fragmento de código \"inseguro\" en el lado de Rust " "es una oportunidad para\n" "errores, o para exacerbar el \"comportamiento indefinido\"." #: 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 "" "Por ejemplo, si la procedencia de un puntero es incorrecta, eso puede ser un " "error de segmentación debido a\n" "acceso a memoria inválido. Pero si es manipulado por un código no seguro, " "podría volverse\n" "corrupción del montón en toda regla." #: 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 "" "El diseño de la API basada en objetos permite escribir correcciones que " "tienen buena seguridad de memoria\n" "características, y un límite claro de lo que es seguro y lo que es " "\"inseguro\"." #: 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 "" "El estándar POSIX define la API para acceder a una base de datos en archivo, " "conocida como " "[DBM](https://web.archive.org/web/20210105035602/https://www.mankier.com/0p/ndbm.h) " ".\n" "Es un excelente ejemplo de una API \"basada en objetos\"." #: 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 "" "Aquí está la definición en C, que con suerte debería ser fácil de leer para " "aquellos\n" "involucrados en FFI. El comentario a continuación debería ayudar a " "explicarlo para aquellos que\n" "perder las sutilezas." #: 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 "Esta API define dos tipos: `DBM` y `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 "" "El tipo `DBM` se denominó tipo \"encapsulado\" anteriormente.\n" "Está diseñado para contener el estado interno y actúa como un punto de " "entrada para el\n" "comportamiento de la 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 "" "Es completamente opaco para el usuario, que no puede crear un 'DBM' por sí " "mismo ya que\n" "no saben su tamaño o diseño. En su lugar, deben llamar a `dbm_open`, y eso\n" "solo les da _un puntero 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 "" "Esto significa que todos los 'DBM' son \"propiedad\" de la biblioteca en el " "sentido de Rust.\n" "El estado interno de tamaño desconocido se mantiene en la memoria controlada " "por la biblioteca,\n" "no el usuario. El usuario solo puede gestionar su ciclo de vida con `abrir` " "y `cerrar`,\n" "y realizar operaciones en él con las otras funciones." #: 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 "" "El tipo `datum` se denominó tipo \"transaccional\" anteriormente.\n" "Está diseñado para facilitar el intercambio de información entre la " "biblioteca y\n" "su usuario." #: 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 "" "La base de datos está diseñada para almacenar \"datos no estructurados\", " "sin longitud predefinida\n" "o significado. Como resultado, el `dato` es el equivalente en C de una " "rebanada de Rust: un montón\n" "de bytes, y un recuento de cuántos hay. La principal diferencia es que hay\n" "sin información de tipo, que es lo que 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 "" "Tenga en cuenta que este encabezado está escrito desde el punto de vista de " "la biblioteca.\n" "Es probable que el usuario tenga algún tipo que esté usando, que tenga un " "tamaño conocido.\n" "Pero a la biblioteca no le importa, y según las reglas de conversión de C, " "cualquier tipo detrás de un\n" "el puntero se puede convertir en `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 "" "Como se señaló anteriormente, este tipo es _transparente_ para el usuario. " "Pero también, este tipo es\n" "_propiedad_ del usuario.\n" "Esto tiene ramificaciones sutiles, debido a ese puntero en su interior.\n" "La pregunta es, ¿quién posee la memoria a la que apunta el puntero?" #: 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 respuesta para la mejor seguridad de la memoria es \"el usuario\".\n" "Pero en casos como recuperar un valor, el usuario no sabe cómo asignar\n" "correctamente (ya que no saben cuánto tiempo es el valor). En este caso, la " "biblioteca.\n" "Se espera que el código use el montón al que el usuario tiene acceso, como " "la biblioteca C.\n" "`malloc` y `free` -- y luego _transferir propiedad_ en el sentido de 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 "" "Todo esto puede parecer especulativo, pero esto es lo que significa un " "puntero en C.\n" "Significa lo mismo que Rust: \"vida útil definida por el usuario\".\n" "El usuario de la biblioteca necesita leer la documentación para utilizarla " "correctamente.\n" "Dicho esto, hay algunas decisiones que tienen menos o mayores consecuencias " "si los usuarios\n" "hazlo mal Minimizarlos es de lo que se trata esta mejor práctica, y la " "clave\n" "es _transferir la propiedad de todo lo que es transparente_." #: 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 "" "Esto minimiza el número de garantías de seguridad de la memoria que el " "usuario debe mantener a un nivel\n" "número relativamente pequeño:" #: 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. No llame a ninguna función con un puntero no devuelto por `dbm_open` " "(inválido\n" " acceso o corrupción).\n" "2. No llame a ninguna función en un puntero después de cerrar (usar después " "de liberar).\n" "3. El `dptr` en cualquier `datum` debe ser `NULL`, o apuntar a una porción " "válida de memoria\n" " en la longitud anunciada." #: 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 "" "Además, evita muchos problemas de procedencia de punteros.\n" "Para entender por qué, consideremos una alternativa con cierta profundidad: " "iteración clave." #: 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 es bien conocido por sus iteradores.\n" "Al implementar uno, el programador crea un tipo separado con una vida útil " "limitada\n" "a su propietario, e implementa el rasgo `Iterator`." #: src\patterns/ffi/export.md:129 #, fuzzy msgid "Here is how iteration would be done in Rust for `DBM`:" msgstr "Así es como se haría la iteración en Rust para `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 "" "Esto es limpio, idiomático y seguro. gracias a las garantías de Rust.\n" "Sin embargo, considere cómo se vería una traducción de API sencilla:" #: 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 "" "Esta API pierde una pieza clave de información: la vida útil del iterador no " "debe\n" "exceda la vida útil del objeto `Dbm` que lo posee. Un usuario de la " "biblioteca podría\n" "úselo de una manera que haga que el iterador sobreviva a los datos en los " "que está iterando,\n" "resultando en la lectura de la memoria no inicializada." #: src\patterns/ffi/export.md:173 #, fuzzy msgid "" "This example written in C contains a bug that will be explained afterwards:" msgstr "" "Este ejemplo escrito en C contiene un error que se explicará más adelante:" #: 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 "" "Este error es un clásico. Esto es lo que sucede cuando el iterador devuelve " "el\n" "marcador de fin de iteración:" #: 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 condición del bucle establece `l` en cero y entra en el bucle porque " "`0 >= 0`.\n" "2. La longitud se incrementa, en este caso por cero.\n" "3. La declaración if es verdadera, por lo que la base de datos está cerrada. " "debe haber un descanso\n" " declaración aquí.\n" "4. La condición de bucle se ejecuta de nuevo, provocando una llamada " "`siguiente` en el objeto cerrado." #: 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 peor parte de este error?\n" "Si la implementación de Rust fue cuidadosa, ¡este código funcionará la mayor " "parte del tiempo!\n" "Si la memoria para el objeto `Dbm` no se reutiliza de inmediato, una " "verificación interna\n" "es casi seguro que fallará, lo que hará que el iterador devuelva un `-1` que " "indica\n" "un error. Pero en ocasiones, provocará un fallo de segmentación, o peor " "aún,\n" "Corrupción de memoria sin sentido!" #: 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 "" "Rust no puede evitar nada de esto.\n" "Desde su perspectiva, puso esos objetos en su montón, les devolvió " "punteros,\n" "y cedieron el control de sus vidas. El código C simplemente debe \"jugar " "bien\"." #: 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 "" "El programador debe leer y comprender la documentación de la API.\n" "Mientras que algunos consideran que está a la par del curso en C, un buen " "diseño de API puede mitigar\n" "este riesgo La API POSIX para `DBM` hizo esto al _consolidar la propiedad_ " "de\n" "el iterador con su padre:" #: 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 "" "Por lo tanto, todas las vidas estaban unidas y se previno tal inseguridad." #: 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 "" "Sin embargo, esta elección de diseño también tiene una serie de " "inconvenientes, que deben ser\n" "considerado también." #: 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 "" "Primero, la propia API se vuelve menos expresiva.\n" "Con POSIX DBM, solo hay un iterador por objeto y cada llamada cambia\n" "su estado Esto es mucho más restrictivo que los iteradores en casi cualquier " "idioma,\n" "aunque sea seguro. Tal vez con otros objetos relacionados, cuyas vidas son\n" "menos jerárquica, esta limitación es más costosa que la seguridad." #: 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 "" "Segundo, dependiendo de las relaciones de las partes de la API, un esfuerzo " "de diseño significativo\n" "puede estar implicado. Muchos de los puntos de diseño más fáciles tienen " "otros patrones asociados\n" "con ellos:" #: 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 "" "- [Consolidación de tipos de contenedor] (./wrappers.md) agrupa varios tipos " "de Rust juntos\n" " en un \"objeto\" opaco\n" "\n" "- [FFI Error Passing](../../idioms/ffi/errors.md) explica el manejo de " "errores con enteros\n" " códigos y valores de retorno de centinela (como punteros `NULL`)\n" "\n" "- [Accepting Foreign Strings](../../idioms/ffi/accepting-strings.md) permite " "aceptar\n" " cadenas con código inseguro mínimo, y es más fácil hacerlo bien que\n" " [Pasar cadenas 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 "" "Sin embargo, no todas las API se pueden hacer de esta manera.\n" "Depende del mejor juicio del programador quién es su audiencia." #: src\patterns/ffi/wrappers.md:1 #, fuzzy msgid "# Type Consolidation into Wrappers" msgstr "# Escriba la consolidación en contenedores" #: 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 "" "Este patrón está diseñado para permitir el manejo elegante de múltiples " "tipos relacionados,\n" "mientras minimiza el área de superficie para la inseguridad de la 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 "" "Una de las piedras angulares de las reglas de aliasing de Rust son las " "vidas.\n" "Esto asegura que muchos patrones de acceso entre tipos puedan ser seguros " "para la memoria,\n" "seguridad de carrera de datos incluida." #: 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 "" "Sin embargo, cuando los tipos de Rust se exportan a otros lenguajes, " "generalmente se transforman\n" "en punteros. En Rust, un puntero significa \"el usuario administra la vida " "útil del pointee\".\n" "Es su responsabilidad evitar la inseguridad de la 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 "" "Por lo tanto, se requiere cierto nivel de confianza en el código de usuario, " "especialmente en torno al uso después de la liberación.\n" "sobre el cual Rust no puede hacer nada. Sin embargo, algunos diseños de API " "imponen mayores cargas\n" "que otros en el código escrito en el otro idioma." #: 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 "" "La API de menor riesgo es el \"contenedor consolidado\", donde todas las " "posibles interacciones\n" "con un objeto se pliegan en un \"tipo contenedor\", mientras se mantiene " "limpia la API de 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 "" "Para entender esto, veamos un ejemplo clásico de una API para exportar: " "iteración\n" "a través de una colección." #: src\patterns/ffi/wrappers.md:28 #, fuzzy msgid "That API looks like this:" msgstr "Esa API se ve así:" #: 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. El iterador se inicializa con `first_key`.\n" "2. Cada llamada a `next_key` hará avanzar el iterador.\n" "3. Las llamadas a `next_key` si el iterador está al final no harán nada.\n" "4. Como se señaló anteriormente, el iterador está \"envuelto\" en la " "colección (a diferencia del nativo\n" " API de óxido)." #: 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 "" "Si el iterador implementa `nth()` de manera eficiente, entonces es posible " "hacerlo\n" "efímero a cada llamada de función:" #: 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 "" "Como resultado, el envoltorio es simple y no contiene código \"no seguro\"." #: 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 "" "Esto hace que las API sean más seguras de usar, evitando problemas con la " "vida útil entre tipos.\n" "Consulte [API basadas en objetos] (./export.md) para obtener más información " "sobre las ventajas y desventajas\n" "esto 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 "" "A menudo, envolver tipos es bastante difícil y, a veces, un compromiso de la " "API de Rust\n" "facilitaría las cosas." #: 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 "" "Como ejemplo, considere un iterador que no implementa eficientemente " "`nth()`.\n" "Definitivamente valdría la pena poner una lógica especial para hacer que el " "objeto maneje\n" "iteración internamente, o para admitir un patrón de acceso diferente de " "manera eficiente que\n" "solo se utilizará la API de funciones externas." #: src\patterns/ffi/wrappers.md:79 #, fuzzy msgid "### Trying to Wrap Iterators (and Failing)" msgstr "### Tratando de envolver iteradores (y fallando)" #: 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 "" "Para envolver cualquier tipo de iterador en la API correctamente, el " "envoltorio tendría que\n" "hacer lo que haría una versión C del código: borrar la vida útil del " "iterador,\n" "y administrarlo manualmente." #: src\patterns/ffi/wrappers.md:85 #, fuzzy msgid "Suffice it to say, this is _incredibly_ difficult." msgstr "Baste decir que esto es _increíblemente_ difícil." #: src\patterns/ffi/wrappers.md:87 #, fuzzy msgid "Here is an illustration of just _one_ pitfall." msgstr "Aquí hay una ilustración de solo _one_ escollo." #: src\patterns/ffi/wrappers.md:89 #, fuzzy msgid "A first version of `MySetWrapper` would look like this:" msgstr "Una primera versión de `MySetWrapper` se vería así:" #: 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\n" " iterator: Option>>,\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 'transmutar' que se usa para extender la vida útil y un puntero para " "ocultarlo,\n" "ya es feo. Pero se pone aún peor: _cualquier otra operación puede causar\n" "Rust `comportamiento indefinido`_." #: 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 "" "Considere que `MySet` en el contenedor podría ser manipulado por otros\n" "funciones durante la iteración, como almacenar un nuevo valor en la clave " "que fue\n" "iterando sobre. La API no desaconseja esto, y de hecho algunos C similares\n" "las bibliotecas lo esperan." #: src\patterns/ffi/wrappers.md:109 #, fuzzy msgid "A simple implementation of `myset_store` would be:" msgstr "Una implementación simple de `myset_store` sería:" #: 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 "" "Si el iterador existe cuando se llama a esta función, hemos violado una de " "las reglas de Rust\n" "reglas de alias. Según Rust, la referencia mutable en este bloque debe " "tener\n" "acceso _exclusivo_ al objeto. Si el iterador simplemente existe, no es " "exclusivo,\n" "¡así que tenemos un `comportamiento indefinido`!" #: 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 "" "Para evitar esto, debemos tener una forma de asegurar que la referencia " "mutable sea realmente exclusiva.\n" "Eso básicamente significa borrar la referencia compartida del iterador " "mientras existe,\n" "y luego reconstruirlo. En la mayoría de los casos, seguirá siendo menos " "eficiente que\n" "la versión 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 "" "Algunos pueden preguntarse: ¿cómo puede C hacer esto de manera más " "eficiente?\n" "La respuesta es que hace trampa. Las reglas de alias de Rust son el " "problema, y C simplemente ignora\n" "ellos por sus punteros. A cambio, es común ver código que se declara\n" "en el manual como \"no seguro para subprocesos\" en algunas o todas las " "circunstancias. De hecho,\n" "la [biblioteca GNU " "C](https://manpages.debian.org/buster/manpages/attributes.7.en.html)\n" "tiene un léxico completo dedicado al comportamiento concurrente!" #: 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 prefiere que todo sea seguro para la memoria todo el tiempo, tanto por " "seguridad como por\n" "optimizaciones que el código C no puede lograr. Ser denegado el acceso a " "ciertos accesos directos\n" "es el precio que los programadores de Rust deben pagar." #: 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 "" "Para los programadores de C que se rascan la cabeza, el iterador necesita\n" "no se leerá _durante_ este código causará la UB. La regla de exclusividad " "también permite\n" "optimizaciones del compilador que pueden causar observaciones inconsistentes " "por parte del iterador\n" "referencia compartida (por ejemplo, derrames de pilas o instrucciones de " "reordenación para mayor eficiencia).\n" "Estas observaciones pueden ocurrir _en cualquier momento después de_ que se " "cree la referencia mutable." #: src\anti_patterns/index.md:1 #, fuzzy msgid "# Anti-patterns" msgstr "# Anti-patrones" #: 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 [antipatrón](https://en.wikipedia.org/wiki/Anti-pattern) es una solución " "para\n" "un \"problema recurrente que generalmente es ineficaz y corre el riesgo de " "ser altamente\n" "contraproducente\". Tan valioso como saber cómo resolver un problema, es\n" "saber cómo _no_ resolverlo. Los antipatrones nos dan grandes contraejemplos " "para\n" "considerar en relación con los patrones de diseño. Los antipatrones no se " "limitan al código.\n" "Por ejemplo, un proceso también puede ser un antipatrón." #: src\anti_patterns/borrow_clone.md:1 #, fuzzy msgid "# Clone to satisfy the borrow checker" msgstr "# Clonar para satisfacer el verificador de préstamo" #: 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 "" "El verificador de préstamos evita que los usuarios de Rust desarrollen " "código que de otro modo no sería seguro.\n" "asegurando que: solo existe una referencia mutable, o potencialmente muchas " "pero\n" "todas las referencias inmutables existen. Si el código escrito no es fiel a " "estos\n" "condiciones, este antipatrón surge cuando el desarrollador resuelve el " "compilador\n" "error al clonar la variable." #: 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 "" "Es tentador, especialmente para los principiantes, usar este patrón para " "resolver\n" "Problemas confusos con el verificador de préstamos. Sin embargo, existen " "graves\n" "consecuencias. El uso de `.clone()` hace que se haga una copia de los datos. " "Algún cambio\n" "entre los dos no están sincronizados, como si dos variables completamente " "separadas\n" "existir." #: src\anti_patterns/borrow_clone.md:38 #, fuzzy msgid "" "There are special cases -- `Rc` 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 "" "Hay casos especiales: `Rc` está diseñado para manejar clones de forma " "inteligente.\n" "Administra internamente exactamente una copia de los datos, y clonarlos " "solo\n" "clonar la referencia." #: src\anti_patterns/borrow_clone.md:42 #, fuzzy msgid "" "There is also `Arc` 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 "" "También existe `Arc` que proporciona la propiedad compartida de un valor " "de tipo T\n" "que se asigna en el montón. Invocar `.clone()` en `Arc` produce un nuevo " "`Arc`\n" "instancia, que apunta a la misma asignación en el montón que la fuente " "`Arc`,\n" "mientras aumenta un recuento de referencia." #: 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 "" "En general, los clones deben ser deliberados, con pleno conocimiento de los\n" "consecuencias. Si se usa un clon para hacer que desaparezca un error del " "comprobador de préstamo,\n" "esa es una buena indicación de que este antipatrón puede estar en 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 "" "Aunque `.clone()` es una indicación de un mal patrón, a veces\n" "**está bien escribir código ineficiente**, en casos como cuando:" #: 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 "" "- el desarrollador aún es nuevo en la propiedad\n" "- el código no tiene grandes limitaciones de velocidad o memoria\n" " (como proyectos de hackathon o prototipos)\n" "- satisfacer el verificador de préstamos es realmente complicado, y " "prefieres\n" " optimizar la legibilidad sobre el rendimiento" #: 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 "" "Si se sospecha de un clon innecesario, el [capítulo de Rust Book sobre " "propiedad] (https://doc.rust-lang.org/book/ownership.html)\n" "debe entenderse completamente antes de evaluar si el clon es necesario o no." #: 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 "" "También asegúrese de ejecutar siempre `cargo clippy` en su proyecto, que " "detectará algunos\n" "casos en los que `.clone()` no es necesario, como " "[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` documentation, which handles .clone() " "intelligently](http://doc.rust-lang.org/std/rc/)\n" "- [`Arc` 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(_)}` para mantener los valores propios en las " "enumeraciones modificadas](../idioms/mem-replace.md)\n" "- [Documentación `Rc`, que maneja .clone() " "inteligentemente](http://doc.rust-lang.org/std/rc/)\n" "- [Documentación de `Arc`, un puntero de recuento de referencia seguro " "para subprocesos] (https://doc.rust-lang.org/std/sync/struct.Arc.html)\n" "- [Trucos con propiedad en " "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 "# `#![negar(advertencias)]`" #: 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 autor de cajas bien intencionado quiere asegurarse de que su código se " "construya sin\n" "advertencias Así que anotan su raíz de caja con lo siguiente:" #: 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 "Es breve y detendrá la compilación si algo anda mal." #: src\anti_patterns/deny-warnings.md:20 #, fuzzy msgid "## Drawbacks" msgstr "## Inconvenientes" #: 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 "" "Al no permitir que el compilador construya con advertencias, el autor de un " "cajón opta por no participar\n" "La famosa estabilidad de Rust. A veces, las nuevas características o las " "antiguas características incorrectas necesitan un cambio.\n" "en cómo se hacen las cosas, así se escriben hilachas que `advierten` para " "cierta gracia\n" "antes de pasar a `denegar`." #: 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 "" "Por ejemplo, se descubrió que un tipo podía tener dos `impl`s con el mismo\n" "método. Esto se consideró una mala idea, pero para que la transición sea " "fluida,\n" "el lint `overlapping-inherent-impls` se introdujo para dar una advertencia a " "aquellos\n" "tropezando con este hecho, antes de que se convierta en un error grave en " "una versión 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 "" "Además, a veces las API quedan obsoletas, por lo que su uso emitirá una " "advertencia donde\n" "antes no había ninguno." #: src\anti_patterns/deny-warnings.md:35 #, fuzzy msgid "" "All this conspires to potentially break the build whenever something changes." msgstr "" "Todo esto conspira para potencialmente romper la compilación cada vez que " "algo 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 "" "Además, las cajas que suministren pelusas adicionales (por ejemplo, " "[rust-clippy]) no pueden\n" "ya no se utilizará a menos que se elimine la anotación. Esto se mitiga con\n" "[--cap-pelusas]. El argumento de la línea de comando `--cap-lints=warn` " "convierte todo `deny`\n" "lint errores en advertencias." #: src\anti_patterns/deny-warnings.md:42 #: src\functional/generics-type-classes.md:227 #, fuzzy msgid "## Alternatives" msgstr "## Alternativas" #: 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 "" "Hay dos formas de abordar este problema: primero, podemos desacoplar la " "compilación\n" "configuración del código, y segundo, podemos nombrar las pelusas que " "queremos denegar\n" "explícitamente." #: src\anti_patterns/deny-warnings.md:48 #, fuzzy msgid "The following command line will build with all warnings set to `deny`:" msgstr "" "La siguiente línea de comando se construirá con todas las advertencias " "configuradas en \"denegar\":" #: src\anti_patterns/deny-warnings.md:50 #, fuzzy msgid "`RUSTFLAGS=\"-D warnings\" cargo build`" msgstr "`RUSTFLAGS=\"-D advertencias\" construcción de carga`" #: 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 "" "Esto lo puede hacer cualquier desarrollador individual (o se puede " "configurar en una herramienta de CI como\n" "Travis, pero recuerda que esto puede romper la compilación cuando algo " "cambia)\n" "sin requerir un cambio en el código." #: 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 "" "Alternativamente, podemos especificar los lints que queremos `denegar` en el " "código.\n" "Aquí hay una lista de pelusas de advertencia que (con suerte) son seguras de " "negar (a partir de 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 "" "Además, las siguientes pelusas \"permitidas\" pueden ser una buena idea para " "\"denegar\":" #: 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 "" "Algunos también pueden querer agregar \"implementaciones de copias " "faltantes\" a su 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 "" "Tenga en cuenta que no agregamos explícitamente la pelusa `obsoleta`, ya que " "es bastante\n" "seguro de que habrá más API obsoletas en el futuro." #: 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 colección de todas las pelusas cortadas] " "(https://rust-lang.github.io/rust-clippy/master)\n" "- Documentación de [atributo en desuso]\n" "- Escriba `rustc -W help` para obtener una lista de pelusas en su sistema. " "También escriba\n" " `rustc --help` para una lista general de opciones\n" "- [rust-clippy] es una colección de pelusas para mejorar el código de 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 "" "Usar incorrectamente el rasgo `Deref` para emular la herencia entre " "estructuras y, por lo tanto, reutilizar\n" "métodos." #: 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 veces queremos emular el siguiente patrón común de los lenguajes OO como\n" "como 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 "Podemos usar el antipatrón de polimorfismo deref para hacerlo:" #: 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 "" "No hay herencia de estructuras en Rust. En su lugar, usamos composición e " "incluimos\n" "una instancia de `Foo` en `Bar` (dado que el campo es un valor, se almacena " "en línea,\n" "entonces, si hubiera campos, tendrían el mismo diseño en la memoria que " "Java\n" "versión (probablemente, debería usar `#[repr(C)]` si quiere estar seguro))." #: 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 "" "Para hacer que la llamada al método funcione, implementamos `Deref` para " "`Bar` con `Foo`\n" "como objetivo (devolviendo el campo `Foo` incrustado). Eso significa que " "cuando nosotros\n" "desreferenciar una `Bar` (por ejemplo, usando `*`) entonces obtendremos un " "`Foo`. Eso es\n" "bastante raro. La desreferenciación generalmente da una `T` de una " "referencia a `T`, aquí\n" "tienen dos tipos no relacionados. Sin embargo, dado que el operador punto " "hace implícito\n" "desreferenciación, significa que la llamada al método buscará métodos en " "`Foo` como\n" "así como `Bar`." #: src\anti_patterns/deref.md:71 #, fuzzy msgid "You save a little boilerplate, e.g.," msgstr "Te ahorras un poco de texto repetitivo, por ejemplo," #: 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 "" "Lo más importante es que este es un idioma sorprendente: los futuros " "programadores que lean esto en\n" "el código no esperará que esto suceda. Eso es porque estamos haciendo un mal " "uso de `Deref`\n" "rasgo en lugar de usarlo según lo previsto (y documentado, etc.). también es " "porque\n" "el mecanismo aquí es completamente implícito." #: 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 "" "Este patrón no introduce subtipos entre `Foo` y `Bar` como\n" "la herencia en Java o C++ sí. Además, los rasgos implementados por `Foo` " "son\n" "no se implementa automáticamente para `Bar`, por lo que este patrón " "interactúa mal con\n" "verificación de límites y, por lo tanto, programación genérica." #: 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 "" "El uso de este patrón proporciona una semántica sutilmente diferente de la " "mayoría de los lenguajes OO con\n" "en lo que respecta a 'uno mismo'. Por lo general, sigue siendo una " "referencia a la subclase, con esto\n" "patrón será la 'clase' donde se define el método." #: 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 "" "Finalmente, este patrón solo admite herencia única y no tiene noción de\n" "interfaces, privacidad basada en clases u otras características relacionadas " "con la herencia. Por lo que\n" "brinda una experiencia que sorprenderá sutilmente a los programadores " "acostumbrados a Java\n" "herencia, etc" #: 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 "" "No hay una buena alternativa. Dependiendo de las circunstancias exactas, " "podría\n" "sería mejor volver a implementar usando rasgos o escribir los métodos de " "fachada para\n" "enviar a `Foo` manualmente. Tenemos la intención de agregar un mecanismo " "para la herencia.\n" "similar a esto para Rust, pero es probable que pase algún tiempo antes de " "que llegue\n" "Roya estable. Ver estos " "[blog](http://aturon.github.io/blog/2015/09/18/reuse/)\n" "[publicaciones] " "(http://smallcultfollowing.com/babysteps/blog/2015/10/08/virtual-structs-part-4-extended-enums-and-thin-traits/)\n" "y este [problema de RFC] (https://github.com/rust-lang/rfcs/issues/349) para " "obtener más detalles." #: 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 "" "El rasgo `Deref` está diseñado para la implementación de tipos de punteros " "personalizados.\n" "La intención es que tomará un puntero a `T` a `T`, no convertir\n" "entre diferentes tipos. Es una pena que esto no sea (probablemente no puede " "ser)\n" "reforzado por la definición de rasgo." #: 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 intenta lograr un equilibrio cuidadoso entre los mecanismos explícitos " "e implícitos,\n" "favoreciendo conversiones explícitas entre tipos. Eliminación automática de " "referencias en el punto\n" "operador es un caso donde la ergonomía favorece fuertemente un mecanismo " "implícito,\n" "pero la intención es que esto se limite a grados de indirección, no\n" "conversión entre tipos arbitrarios." #: 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 "" "- [Las colecciones son modismos de punteros " "inteligentes](../idioms/deref.md).\n" "- Cajas de delegación para menos repetitivo como " "[delegate](https://crates.io/crates/delegate)\n" " o [embajador](https://crates.io/crates/ambassador)\n" "- [Documentación para el rasgo " "`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html)." #: src\functional/index.md:1 #, fuzzy msgid "# Functional Usage of Rust" msgstr "# Uso funcional de 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 es un lenguaje imperativo, pero sigue muchos\n" "[programación " "funcional](https://en.wikipedia.org/wiki/Functional_programming) paradigmas." #: 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 "" "> En informática, la _programación funcional_ es un paradigma de " "programación donde\n" "> los programas se construyen aplicando y componiendo funciones.\n" "> Es un paradigma de programación declarativa en el que las definiciones de " "funciones son\n" "> árboles de expresiones que devuelven un valor, en lugar de una secuencia " "de\n" "> declaraciones imperativas que cambian el estado del programa." #: src\functional/paradigms.md:1 #, fuzzy msgid "# Programming paradigms" msgstr "# Paradigmas de programación" #: 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 de los mayores obstáculos para comprender los programas funcionales " "cuando se trata de\n" "desde un trasfondo imperativo es el cambio de pensamiento. programas " "imperativos\n" "describen **cómo** hacer algo, mientras que los programas declarativos " "describen\n" "**qué hacer. Sumemos los números del 1 al 10 para mostrar esto." #: 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 los programas imperativos, tenemos que jugar al compilador para ver qué " "está pasando.\n" "Aquí, comenzamos con una `suma` de `0`.\n" "A continuación, iteramos a través del rango de 1 a 10.\n" "Cada vez que recorremos el bucle, sumamos el valor correspondiente en el " "rango.\n" "Luego lo imprimimos." #: 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 "" "| `yo` | `suma` |\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 "" "Así es como la mayoría de nosotros empezamos a programar. Aprendemos que un " "programa es un conjunto\n" "de pasos" #: src\functional/paradigms.md:40 #, fuzzy msgid "## Declarative" msgstr "## Declarativo" #: 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 "" "¡Guau! ¡Esto es realmente diferente! ¿Que está pasando aqui?\n" "Recuerde que con los programas declarativos estamos describiendo **qué** " "hacer,\n" "en lugar de **cómo** hacerlo. `fold` es una función que [compone] " "(https://en.wikipedia.org/wiki/Function_composition)\n" "funciones El nombre es una convención de 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 "" "Aquí, estamos componiendo funciones de suma (este cierre: `|a, b| a + b`)\n" "con un rango de 1 a 10. El `0` es el punto de partida, por lo que `a` es `0` " "en\n" "primero. `b` es el primer elemento del rango, `1`. `0 + 1 = 1` es el " "resultado.\n" "Así que ahora 'doblamos' de nuevo, con 'a = 1', 'b = 2' y así '1 + 2 = 3' es " "el siguiente\n" "resultado. Este proceso continúa hasta que llegamos al último elemento del " "rango,\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` | resultado |\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 "# Genéricos como clases de tipos" #: 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 "" "El sistema de tipos de Rust está diseñado más como lenguajes funcionales " "(como Haskell)\n" "en lugar de lenguajes imperativos (como Java y C++). Como resultado, Rust " "puede convertir\n" "muchos tipos de problemas de programación en problemas de \"tipado " "estático\". Este es uno\n" "de las mayores ganancias de elegir un lenguaje funcional, y es fundamental " "para muchos\n" "de las garantías de tiempo de compilación de 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` and `vector` 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 clave de esta idea es la forma en que funcionan los tipos " "genéricos. En C++ y Java, por\n" "Por ejemplo, los tipos genéricos son una construcción de metaprogramación " "para el compilador.\n" "`vector` y `vector` en C++ son solo dos copias diferentes del\n" "mismo código repetitivo para un tipo `vector` (conocido como `plantilla`) " "con dos\n" "diferentes tipos rellenados." #: 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` and " "`Vec`\n" "_are two different types_, which are recognized as distinct by all parts of " "the\n" "type system." msgstr "" "En Rust, un parámetro de tipo genérico crea lo que se conoce en lenguajes " "funcionales\n" "como una \"restricción de clase de tipo\", y cada parámetro diferente " "completado por un extremo\n" "el usuario _realmente cambia el tipo_. En otras palabras, `Vec` y " "`Vec`\n" "_son dos tipos diferentes_, que son reconocidos como distintos por todas las " "partes del\n" "sistema de tipos." #: 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 "" "Esto se llama **monomorfización**, donde se crean diferentes tipos a partir " "de\n" "Código **polimórfico**. Este comportamiento especial requiere bloques `impl` " "para especificar\n" "parámetros genéricos. Diferentes valores para el tipo genérico causan " "diferentes tipos,\n" "y diferentes tipos pueden tener diferentes bloques `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 "" "En los lenguajes orientados a objetos, las clases pueden heredar el " "comportamiento de sus padres.\n" "Sin embargo, esto permite adjuntar no sólo un comportamiento adicional a\n" "miembros particulares de una clase de tipo, pero también comportamiento " "adicional." #: 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 "" "El equivalente más cercano es el polimorfismo en tiempo de ejecución en " "Javascript y Python,\n" "donde cualquier constructor puede agregar nuevos miembros a los objetos de " "cualquier manera.\n" "Sin embargo, a diferencia de esos lenguajes, todos los métodos adicionales " "de Rust se pueden escribir\n" "verificados cuando se usan, porque sus genéricos están definidos " "estáticamente. Eso\n" "los hace más utilizables sin dejar de ser seguros." #: 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 "" "Suponga que está diseñando un servidor de almacenamiento para una serie de " "máquinas de laboratorio.\n" "Debido al software involucrado, hay dos protocolos diferentes que necesita\n" "para admitir: BOOTP (para arranque de red PXE) y NFS (para almacenamiento de " "montaje 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 "" "Su objetivo es tener un programa, escrito en Rust, que pueda manejar ambos\n" "a ellos. Tendrá controladores de protocolo y escuchará ambos tipos de " "solicitudes. El\n" "La lógica de la aplicación principal permitirá que un administrador de " "laboratorio configure el almacenamiento\n" "y controles de seguridad para los archivos reales." #: 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 "" "Las solicitudes de archivos de las máquinas en el laboratorio contienen el " "mismo\n" "información, sin importar de qué protocolo provengan: un método de " "autenticación,\n" "y un nombre de archivo para recuperar. Una implementación sencilla se vería\n" "algo como esto:" #: 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 "" "Este diseño podría funcionar lo suficientemente bien. Pero ahora supongamos " "que necesita apoyo\n" "agregando metadatos que eran _específicos del protocolo_. Por ejemplo, con " "NFS, usted\n" "quería determinar cuál era su punto de montaje para hacer cumplir\n" "reglas de seguridad" #: 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 "" "La forma en que está diseñada la estructura actual deja la decisión del " "protocolo hasta\n" "tiempo de ejecución Eso significa cualquier método que se aplique a un " "protocolo y no al otro.\n" "requiere que el programador haga una verificación de tiempo de ejecución." #: src\functional/generics-type-classes.md:75 #, fuzzy msgid "Here is how getting an NFS mount point would look:" msgstr "Así es como se vería obtener un punto de montaje 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,\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 "" "Cada llamador de `mount_point()` debe buscar `Ninguno` y escribir código " "para manejar\n" "él. Esto es cierto incluso si saben que solo se usan solicitudes NFS en un " "determinado\n" "ruta de código!" #: 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 "" "Sería mucho más óptimo causar un error en tiempo de compilación si los " "diferentes\n" "los tipos de solicitud estaban confundidos. Después de todo, la ruta " "completa del código del usuario,\n" "incluidas las funciones de la biblioteca que utilizan, sabrán si una " "solicitud\n" "es una solicitud NFS o una solicitud 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 "" "¡En Rust, esto es realmente posible! La solución es _agregar un tipo " "genérico_ en\n" "para dividir la API." #: src\functional/generics-type-classes.md:107 #, fuzzy msgid "Here is what that looks like:" msgstr "Esto es lo que parece:" #: 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 {\n" " file_name: PathBuf,\n" " protocol: P,\n" "}\n" "\n" "// all common API parts go into a generic impl block\n" "impl FileDownloadRequest

{\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 {\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` does " "not\n" "implement `mount_point()`, only the type `FileDownloadRequest` does. " "And\n" "that is created by the NFS module, not the BOOTP module of course!" msgstr "" "Obtendrían un error de sintaxis. El tipo `FileDownloadRequest` no\n" "implementa `mount_point()`, solo lo hace el tipo `FileDownloadRequest`. " "Y\n" "eso lo crea el módulo NFS, ¡no el módulo BOOTP, por supuesto!" #: 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 "" "En primer lugar, permite eliminar la duplicación de campos que son comunes a " "varios estados.\n" "Al hacer que los campos no compartidos sean genéricos, se implementan una " "vez." #: 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 "" "En segundo lugar, hace que los bloques `impl` sean más fáciles de leer, " "porque están desglosados\n" "por estado Los métodos comunes a todos los estados se escriben una vez en un " "bloque y los métodos\n" "exclusivos de un estado están en un bloque separado." #: 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 "" "Ambos significan que hay menos líneas de código y están mejor organizados." #: 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 "" "Esto actualmente aumenta el tamaño del binario, debido a la forma en que se " "monomorfiza.\n" "se implementa en el compilador. Esperemos que la implementación pueda\n" "mejorar en el 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 "" "- Si un tipo parece necesitar una \"API dividida\" debido a la construcción " "o parcial\n" " inicialización, considere la\n" " [Patrón de constructor] (../patterns/creational/builder.md) en su lugar.\n" "\n" "- Si la API entre tipos no cambia, solo cambia el comportamiento, entonces\n" " el [Patrón de estrategia] (../patterns/behavioural/strategy.md) se usa " "mejor\n" " en cambio." #: src\functional/generics-type-classes.md:239 #, fuzzy msgid "This pattern is used throughout the standard library:" msgstr "Este patrón se utiliza en toda la biblioteca estándar:" #: src\functional/generics-type-classes.md:241 #, fuzzy msgid "" "- `Vec` can be cast from a String, unlike every other type of " "`Vec`.[^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` se puede convertir desde una cadena, a diferencia de cualquier " "otro tipo de `Vec`.[^1]\n" "- También se pueden convertir en un montón binario, pero solo si contienen " "un tipo\n" " que implementa el rasgo `Ord`.[^2]\n" "- El método `to_string` se especializó para `Vaca` solo del 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 "" "También lo utilizan varias cajas populares para permitir la flexibilidad de " "la 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` 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 "" "- El ecosistema `embedded-hal` utilizado para dispositivos integrados hace " "un uso extensivo de\n" " este patrón Por ejemplo, permite verificar estáticamente la configuración " "de\n" " registros de dispositivos utilizados para controlar pines incrustados. " "Cuando un pin se pone en un modo,\n" " devuelve una estructura `Pin`, cuyo genérico determina las " "funciones\n" " utilizables en ese modo, que no están en el propio `Pin`. [^4]\n" "\n" "- La biblioteca de cliente HTTP 'hiper' usa esto para exponer API " "enriquecidas para diferentes\n" " solicitudes conectables. Los clientes con diferentes conectores tienen " "diferentes métodos\n" " en ellos, así como diferentes implementaciones de rasgos, mientras que un " "conjunto básico de\n" " Los métodos se aplican a cualquier conector. [^5]\n" "\n" "- El patrón de \"estado de tipo\", donde un objeto gana y pierde API en " "función de un\n" " estado interno o invariante: se implementa en Rust utilizando el mismo\n" " concepto, y una técnica ligeramente diferente. [^6]" #: src\functional/generics-type-classes.md:263 #, fuzzy msgid "" "See: [impl From\\ for " "Vec\\](https://doc.rust-lang.org/1.59.0/src/std/ffi/c_str.rs.html#803-811)" msgstr "" "Ver: [impl From\\ for " "Vec\\](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\\ From\\\\> for " "BinaryHeap\\](https://doc.rust-lang.org/stable/src/alloc/collections/binary_heap.rs.html#1345-1354)" msgstr "" "Ver: [impl\\ From\\\\> for " "BinaryHeap\\](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 "" "Consulte: [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 "" "Ejemplo:\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 "" "Ver:\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 "" "Ver:\n" "[El caso del patrón de estado " "tipo](https://web.archive.org/web/20210325065112/https://www.novatec-gmbh.de/en/blog/the-case-for-the-typestate- " "patrón-el-tipo-estado-patrón-en-sí/)\n" "y\n" "[Serie Rusty Typestate (una tesis " "extensa)](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 "# Lentes y Prismas" #: 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 "" "Este es un concepto funcional puro que no se usa con frecuencia en Rust.\n" "Sin embargo, explorar el concepto puede ser útil para entender otros\n" "patrones en las API de Rust, como [visitantes] " "(../patterns/behavioural/visitor.md).\n" "También tienen casos de uso de nicho." #: src\functional/lenses.md:8 #, fuzzy msgid "## Lenses: Uniform Access Across Types" msgstr "## Lentes: acceso uniforme en todos los tipos" #: 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 es un concepto de los lenguajes de programación funcional que " "permite\n" "acceder a partes de un tipo de datos de forma abstracta y unificada.[^1]\n" "En concepto básico, es similar a la forma en que los rasgos de Rust " "funcionan con el borrado de tipos,\n" "pero tiene un poco más de potencia y flexibilidad." #: 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 "" "Por ejemplo, suponga que un banco contiene varios formatos JSON para " "clientes\n" "datos.\n" "Esto se debe a que provienen de diferentes bases de datos o sistemas " "heredados.\n" "Una base de datos contiene los datos necesarios para realizar verificaciones " "de crédito:" #: 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 "Otro contiene la información de la cuenta:" #: 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 "" "Tenga en cuenta que ambos tipos tienen un número de identificación de " "cliente que corresponde a una persona.\n" "¿Cómo manejaría una sola función ambos registros de diferentes tipos?" #: 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 "" "En Rust, una `estructura` podría representar cada uno de estos tipos, y un " "rasgo tendría\n" "una función `get_customer_id` que implementarían:" #: 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,\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(records: &[R]) -> HashSet {\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(iterator: I) -> HashSet\n" " where I: Iterator>\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 "" "Sin embargo, las lentes permiten que el código que respalda la " "identificación del cliente se mueva de la\n" "_type_ a la _función de acceso_.\n" "En lugar de implementar un rasgo en cada tipo, todas las estructuras " "coincidentes pueden\n" "simplemente se puede acceder de la misma manera." #: 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 "" "Si bien el lenguaje Rust en sí mismo no admite esto (el borrado de tipo es " "el\n" "solución preferida para este problema), [lens-rs " "crate](https://github.com/TOETOE55/lens-rs/blob/master/guide.md) permite " "código\n" "que se siente así para ser escrito con macros:" #: 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,\n" "}\n" "\n" "fn unique_ids_lens(iter: impl Iterator) -> HashSet\n" "where\n" " T: LensRef, // 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 versión de `unique_ids_lens` que se muestra aquí permite que cualquier " "tipo esté en el iterador,\n" "siempre que tenga un atributo llamado `customer_id` al que se pueda acceder " "mediante\n" "la función.\n" "Así es como la mayoría de los lenguajes de programación funcionales operan " "en lentes." #: 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 "" "En lugar de macros, lo logran con una técnica conocida como \"curring\".\n" "Es decir, \"construyen parcialmente\" la función, dejando el tipo de la\n" "parámetro final (el valor que se está operando) sin completar hasta que la " "función es\n" "llamado.\n" "Por lo tanto, se puede llamar con diferentes tipos dinámicamente incluso " "desde un lugar en\n" "el código.\n" "Eso es lo que simula `optics!` y `view_ref` en el ejemplo anterior." #: 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 "" "El enfoque funcional no tiene por qué limitarse a los miembros de acceso.\n" "Se pueden crear lentes más potentes que _configuran_ y _obtienen_ datos en " "un\n" "estructura.\n" "Pero el concepto realmente se vuelve interesante cuando se usa como un " "bloque de construcción para\n" "composición.\n" "Ahí es donde aparece más claro el concepto en Rust." #: src\functional/lenses.md:169 #, fuzzy msgid "## Prisms: A Higher-Order form of \"Optics\"" msgstr "## Prismas: una forma de \"óptica\" de orden superior" #: 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 función simple como `unique_ids_lens` anterior opera en una sola lente.\n" "Un _prisma_ es una función que opera en una _familia_ de lentes.\n" "Es un nivel conceptual más alto, usando lentes como bloque de construcción, " "y\n" "continuando con la metáfora, forma parte de una familia de \"ópticas\".\n" "Es el principal que es útil para comprender las API de Rust, por lo que será " "el\n" "enfócate aquí." #: 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 "" "De la misma manera que los rasgos permiten un diseño \"similar a una lente\" " "con polimorfismo estático y\n" "envío dinámico, los diseños de prisma aparecen en las API de Rust que " "dividen los problemas\n" "en múltiples tipos asociados para ser compuestos.\n" "Un buen ejemplo de esto son los rasgos en la caja de análisis _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 "" "Tratar de entender la forma en que funciona _Serde_ solo leyendo la API es " "un\n" "desafío, especialmente la primera vez.\n" "Considere el rasgo `Deserializer`, implementado por algún tipo en cualquier " "biblioteca\n" "que analiza un nuevo formato:" #: src\functional/lenses.md:188 msgid "" "```rust,ignore\n" "pub trait Deserializer<'de>: Sized {\n" " type Error: Error;\n" "\n" " fn deserialize_any(self, visitor: V) -> Result\n" " where\n" " V: Visitor<'de>;\n" "\n" " fn deserialize_bool(self, visitor: V) -> Result\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 "" "Para un rasgo que se supone que analiza datos de un formato y devuelve un\n" "valor, esto parece extraño." #: src\functional/lenses.md:207 #, fuzzy msgid "Why are all the return types type erased?" msgstr "¿Por qué se borran todos los tipos de devolución?" #: 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 "" "Para entender eso, necesitamos tener en mente el concepto de lente y " "observar\n" "la definición del tipo `Visitor` que se pasa genéricamente:" #: src\functional/lenses.md:212 msgid "" "```rust,ignore\n" "pub trait Visitor<'de>: Sized {\n" " type Value;\n" "\n" " fn visit_bool(self, v: bool) -> Result\n" " where\n" " E: Error;\n" "\n" " fn visit_u64(self, v: u64) -> Result\n" " where\n" " E: Error;\n" "\n" " fn visit_str(self, v: &str) -> Result\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 "" "El trabajo del tipo `Visitor` es construir valores en el modelo de datos " "_Serde_,\n" "que están representados por su tipo `Valor` asociado." #: 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 "" "Estos valores representan partes del valor de Rust que se está " "deserializando.\n" "Si esto falla, devuelve un tipo `Error` - un tipo de error determinado por " "el\n" "`Deserializer` cuando se llamaron sus métodos." #: 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 "" "Esto resalta que `Deserializer` es similar a `CustomerId` anterior,\n" "permitiendo que cualquier analizador de formato que lo implemente cree " "'Valores' basados en lo que\n" "analizó.\n" "El rasgo `Valor` está actuando como una lente en los lenguajes de " "programación funcionales." #: 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 "" "Pero a diferencia del rasgo `CustomerId`, los tipos de retorno de los " "métodos `Visitor` son\n" "_genérico_, y el tipo de `Valor` concreto es _determinado por el propio " "Visitante_." #: 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 "" "En lugar de actuar como una sola lente, actúa efectivamente como una familia " "de\n" "lentes, uno para cada tipo concreto de 'Visitante'." #: 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 "" "La API `Deserializer` se basa en tener un conjunto genérico de \"lentes\" " "que funcionan en\n" "un conjunto de otros tipos genéricos para \"observación\".\n" "Es un _prisma_." #: src\functional/lenses.md:254 #, fuzzy msgid "For example, consider the identity record from earlier but simplified:" msgstr "" "Por ejemplo, considere el registro de identidad anterior pero simplificado:" #: 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 "" "¿Cómo deserializaría la biblioteca _Serde_ este JSON en `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. El usuario llamaría a una función de biblioteca para deserializar los " "datos. Esto sería\n" " cree un `Deserializador` basado en el formato JSON.\n" "1. Según los campos de la estructura, se crearía un 'Visitante' (más sobre\n" " eso en un momento) que sabe cómo crear cada tipo en un data genérico\n" " modelo que se necesitaba para representarlo: `u64` y `String`.\n" "1. El deserializador haría llamadas al `Visitor` mientras analizaba los " "elementos.\n" "1. El `Visitante` indicaría si los artículos encontrados eran los esperados, " "y si no,\n" " genera un error para indicar que la deserialización ha fallado." #: src\functional/lenses.md:273 #, fuzzy msgid "For our very simple structure above, the expected pattern would be:" msgstr "Para nuestra estructura muy simple anterior, el patrón esperado sería:" #: 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. Visitar un mapa (equivalente de _Serde_ a `HashMap` o diccionario de " "JSON).\n" "1. Visite una clave de cadena llamada \"nombre\".\n" "1. Visite un valor de cadena, que irá al campo `nombre`.\n" "1. Visite una clave de cadena llamada \"customer_id\".\n" "1. Visite un valor de cadena, que irá al campo `customer_id`.\n" "1. Visita el final del mapa." #: src\functional/lenses.md:282 #, fuzzy msgid "But what determines which \"observation\" pattern is expected?" msgstr "Pero, ¿qué determina qué patrón de \"observación\" se espera?" #: 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 lenguaje de programación funcional sería capaz de usar curry para crear\n" "reflejo de cada tipo basado en el tipo mismo.\n" "Rust no admite eso, por lo que cada tipo debería tener su propio\n" "código escrito en base a sus campos y sus propiedades." #: src\functional/lenses.md:289 #, fuzzy msgid "_Serde_ solves this usability challenge with a derive macro:" msgstr "_Serde_ resuelve este desafío de usabilidad con una macro derivada:" #: 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 "" "Esa macro simplemente genera un bloque impl que hace que la estructura " "implemente un\n" "rasgo llamado `Deserializar`." #: src\functional/lenses.md:304 #, fuzzy msgid "It is defined this way:" msgstr "Se define de esta manera:" #: src\functional/lenses.md:306 msgid "" "```rust,ignore\n" "pub trait Deserialize<'de>: Sized {\n" " fn deserialize(deserializer: D) -> Result\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 "" "Esta es la función que determina cómo crear la estructura en sí.\n" "El código se genera en función de los campos de la estructura.\n" "Cuando se llama a la biblioteca de análisis, en nuestro ejemplo, una " "biblioteca de análisis JSON,\n" "crea un 'Deserializer' y llama a 'Type::deserialize' con él como un\n" "parámetro." #: 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 "" "El código `deserialize` creará un `Visitor` que tendrá sus llamadas\n" "\"refractado\" por el `Deserializador`.\n" "Si todo va bien, eventualmente ese 'Visitante' construirá un valor\n" "correspondiente al tipo que se está analizando y devolverlo." #: src\functional/lenses.md:325 #, fuzzy msgid "" "For a complete example, see the [_Serde_ " "documentation](https://serde.rs/deserialize-struct.html)." msgstr "" "Para ver un ejemplo completo, consulte la " "[documentación_Serde_](https://serde.rs/deserialize-struct.html)." #: src\functional/lenses.md:327 #, fuzzy msgid "To wrap up, this is the power of _Serde_:" msgstr "Para terminar, este es el poder de _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 estructura que se analiza está representada por un bloque `impl` para " "`Deserialize`\n" "1. El formato de datos de entrada (por ejemplo, JSON) está representado por " "un `Deserializador` llamado\n" " por `Deserializar`\n" "1. El 'Deserializador' actúa como un prisma que \"refracta\" al 'Visitor' " "similar a una lente\n" " llamadas que realmente construyen el valor de los datos" #: 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 "" "El resultado es que los tipos que se van a deserializar solo implementan la " "\"capa superior\" de\n" "la API y los formatos de archivo solo necesitan implementar la \"capa " "inferior\".\n" "Luego, cada pieza puede \"simplemente funcionar\" con el resto del " "ecosistema, ya que los genéricos\n" "los tipos los unirán." #: 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 "" "Para enfatizar, la única razón por la que este modelo funciona en cualquier " "formato y cualquier tipo es\n" "porque el tipo de salida del rasgo `Deserializer` ** está especificado por " "el\n" "implementador de `Visitor` se pasa **, en lugar de estar vinculado a un " "específico\n" "tipo.\n" "Esto no era cierto en el ejemplo de la cuenta anterior." #: 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 "" "El sistema de tipos de inspiración genérica de Rust puede acercarlo a estos " "conceptos y\n" "usa su poder, como se muestra en este diseño de API.\n" "Pero también puede necesitar macros de procedimiento para crear puentes para " "sus genéricos." #: src\functional/lenses.md:350 #, fuzzy msgid "## See Also" msgstr "## Ver también" #: 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 "" "- [caja de lentes-rs] (https://crates.io/crates/lens-rs) para lentes " "preconstruidos\n" " implementación, con una interfaz más limpia que estos ejemplos\n" "- [serde](https://serde.rs) en sí mismo, lo que hace que estos conceptos " "sean intuitivos para\n" " usuarios finales (es decir, definir las estructuras) sin necesidad de " "entender el\n" " detalles\n" "- [luminance](https://github.com/phaazon/luminance-rs) es una caja para " "dibujar\n" " gráficos por computadora que utilizan el diseño de la API de la lente, " "incluidas las macros procesales para\n" " crear prismas completos para búferes de diferentes tipos de píxeles que " "siguen siendo genéricos\n" "- [Un artículo sobre lentes en Scala] " "(https://web.archive.org/web/20221128185849/https://medium.com/zyseme-technology/function-references-lens-and-other-optics-in- " "scala-e5f7e2fdafe)\n" " eso es muy legible incluso sin experiencia en Scala.\n" "- [Papel: Óptica Profunctor: Datos Modulares\n" " " "Accesores](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 "" "[Escuela de Haskell: un pequeño tutorial para principiantes de lentes] " "la-semana/un-pequeño-lentes-inicio-tutorial)" #: src\additional_resources/index.md:1 #, fuzzy msgid "# Additional resources" msgstr "# Recursos adicionales" #: src\additional_resources/index.md:3 #, fuzzy msgid "A collection of complementary helpful content" msgstr "Una colección de contenido útil complementario" #: src\additional_resources/index.md:5 #, fuzzy msgid "## Talks" msgstr "## Negociaciones" #: 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 "" "- [Patrones de diseño en Rust](https://www.youtube.com/watch?v=Pm_oO0N5B9k) " "por\n" " Nicholas Cameron en el PDRust (2016)\n" "- [Escribir bibliotecas idiomáticas en " "Rust](https://www.youtube.com/watch?v=0zOg8_B71gE)\n" " por Pascal Hertleif en RustFest (2017)\n" "- [Técnicas de programación de óxido] " "(https://www.youtube.com/watch?v=vqavdUGKeb4) por\n" " Nicholas Cameron en LinuxConfAu (2018)" #: src\additional_resources/index.md:14 #, fuzzy msgid "## Books (Online)" msgstr "## Libros (en línea)" #: src\additional_resources/index.md:16 #, fuzzy msgid "- [The Rust API Guidelines](https://rust-lang.github.io/api-guidelines)" msgstr "" "- [Las pautas de la API de Rust] (https://rust-lang.github.io/api-guidelines)" #: src\additional_resources/design-principles.md:1 #, fuzzy msgid "# Design principles" msgstr "# Criterios de diseño" #: src\additional_resources/design-principles.md:3 #, fuzzy msgid "## A brief overview over common design principles" msgstr "## Una breve descripción de los principios de diseño comunes" #: src\additional_resources/design-principles.md:7 #, fuzzy msgid "## [SOLID](https://en.wikipedia.org/wiki/SOLID)" msgstr "## [SÓLIDO](https://en.wikipedia.org/wiki/SÓLIDO)" #: 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 de responsabilidad única (SRP)] " "(https://en.wikipedia.org/wiki/Single-responsibility_principle):\n" " Una clase solo debe tener una única responsabilidad, es decir, solo " "cambios a\n" " una parte de la especificación del software debería poder afectar la\n" " especificación de la clase.\n" "- [Principio abierto/cerrado " "(OCP)](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle):\n" " \"Las entidades de software... deberían estar abiertas para la extensión, " "pero cerradas para\n" " modificación.\"\n" "- [Principio de sustitución de Liskov (LSP)] " "(https://en.wikipedia.org/wiki/Liskov_substitution_principle):\n" " \"Los objetos en un programa deben ser reemplazables con instancias de sus " "subtipos\n" " sin alterar la corrección de ese programa\".\n" "- [Principio de segregación de interfaz (ISP)] " "(https://en.wikipedia.org/wiki/Interface_segregation_principle):\n" " \"Muchas interfaces específicas del cliente son mejores que una de " "propósito general\n" " interfaz.\"\n" "- [Principio de inversión de dependencia (DIP)] " "(https://en.wikipedia.org/wiki/Dependency_inversion_principle):\n" " Uno debe \"depender de abstracciones, [no] de concreciones\"." #: src\additional_resources/design-principles.md:25 #, fuzzy msgid "" "## [DRY (Don’t Repeat " "Yourself)](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)" msgstr "" "## [SECO (No te " "repitas)](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 "" "“Cada pieza de conocimiento debe tener un único, inequívoco, autorizado\n" "representación dentro de 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 "## [Ley de Deméter (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 objeto dado debe suponer lo menos posible acerca de la estructura o\n" "propiedades de cualquier otra cosa (incluidos sus subcomponentes), de " "acuerdo con\n" "el principio de \"ocultamiento de información\"" #: src\additional_resources/design-principles.md:42 #, fuzzy msgid "" "## [Design by contract " "(DbC)](https://en.wikipedia.org/wiki/Design_by_contract)" msgstr "" "## [Diseño por contrato " "(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 "" "los diseñadores de software deben definir una interfaz formal, precisa y " "verificable\n" "especificaciones para componentes de software, que amplían la definición " "ordinaria de\n" "tipos de datos abstractos con condiciones previas, condiciones posteriores e " "invariantes" #: src\additional_resources/design-principles.md:48 #, fuzzy msgid "" "## " "[Encapsulation](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming))" msgstr "" "## " "[Encapsulación](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 "" "agrupación de datos con los métodos que operan en esos datos, o la " "restricción\n" "de acceso directo a algunos de los componentes de un objeto. La " "encapsulación se utiliza para\n" "ocultar los valores o el estado de un objeto de datos estructurados dentro " "de una clase, evitando\n" "el acceso directo de terceros no autorizados a ellos." #: src\additional_resources/design-principles.md:55 #, fuzzy msgid "" "## " "[Command-Query-Separation(CQS)](https://en.wikipedia.org/wiki/Command%E2%80%93query_separation)" msgstr "" "## [Comando-Consulta-Separación " "(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 "" "“Las funciones no deben producir efectos secundarios abstractos... solo " "comandos\n" "(procedimientos) podrán producir efectos secundarios”. -Bertrand Meyer:\n" "Construcción de software orientada a objetos" #: 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 menor asombro " "(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 de un sistema debe comportarse de una manera que la mayoría de " "los usuarios esperarán\n" "a comportarse. El comportamiento no debe asombrar o sorprender a los " "usuarios." #: src\additional_resources/design-principles.md:66 #, fuzzy msgid "## Linguistic-Modular-Units" msgstr "## Unidades modulares lingüísticas" #: 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 "" "“Los módulos deben corresponder a unidades sintácticas en el idioma " "utilizado.” - Bertrand\n" "Meyer: Construcción de Software Orientado a Objetos" #: src\additional_resources/design-principles.md:71 #, fuzzy msgid "## Self-Documentation" msgstr "## Autodocumentación" #: 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 "" "“El diseñador de un módulo debe esforzarse por hacer que toda la información " "sobre el\n" "módulo parte del propio módulo.” - Bertrand Meyer: software orientado a " "objetos\n" "Construcción" #: src\additional_resources/design-principles.md:77 #, fuzzy msgid "## Uniform-Access" msgstr "## Acceso 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 "" "“Todos los servicios ofrecidos por un módulo deben estar disponibles a " "través de un\n" "notación, que no traiciona si se implementan a través del almacenamiento o\n" "a través de la computación.” - Bertrand Meyer: Construcción de Software " "Orientado a Objetos" #: src\additional_resources/design-principles.md:83 #, fuzzy msgid "## Single-Choice" msgstr "## Opción única" #: 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 "" "“Siempre que un sistema de software deba soportar un conjunto de " "alternativas, una y sólo\n" "un módulo en el sistema debe conocer su lista exhaustiva”. -Bertrand Meyer:\n" "Construcción de software orientada a objetos" #: src\additional_resources/design-principles.md:89 #, fuzzy msgid "## Persistence-Closure" msgstr "## Persistencia-Cierre" #: 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 "" "“Siempre que un mecanismo de almacenamiento almacena un objeto, debe " "almacenar con él el\n" "dependientes de ese objeto. Cada vez que un mecanismo de recuperación " "recupera un\n" "objeto previamente almacenado, también debe recuperar cualquier dependiente " "de ese objeto\n" "que aún no ha sido recuperado.” - Bertrand Meyer: software orientado a " "objetos\n" "Construcción" msgid "" msgstr "" msgid "" msgstr "" msgid "" msgstr "" msgid "" msgstr "" msgid "" msgstr "" msgid "" msgstr "" msgid "" msgstr "" msgid "" msgstr "" msgid "" msgstr "" msgid "" msgstr "" ================================================ FILE: po/it.po ================================================ 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: \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`, or `&T` over `&Box`." 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` o `&T` su `&Box`." #: 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` versus using a `&[T]` or using a `&Box` 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` rispetto all'utilizzo di un `&[T]` o all'utilizzo di un `&Box` " "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,\n" " // Vecs default to empty vector\n" " search_path: Vec,\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 {\n" " data: RawVec,\n" " //..\n" "}\n" "\n" "impl Deref for Vec {\n" " type Target = [T];\n" "\n" " fn deref(&self) -> &[T] {\n" " //..\n" " }\n" "}\n" "```" msgstr "" #: src\idioms/deref.md:28 #, fuzzy msgid "" "A `Vec` 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` 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` è 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` 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`) implement `Deref`. 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` " "can\n" "implement `Deref>` where `Bar` is a dynamically sized type " "and\n" "`&Bar` is a borrowed view of the data in `Foo`." msgstr "" "La maggior parte dei puntatori intelligenti (ad esempio, `Foo`) " "implementano `Deref`. 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` " "può\n" "implementa `Deref>` dove `Bar` è un tipo dimensionato " "dinamicamente e\n" "`&Bar` è una vista presa in prestito dei dati in `Foo`." #: 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`). 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`). 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> {\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 = 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` 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` 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 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 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 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>(\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 {\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>(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`](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`](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 {\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>,\n" "}\n" "\n" "impl Schema {\n" " fn new() -> Self {\n" " Self { commands: vec![] }\n" " }\n" "\n" " fn add_migration(&mut self, cmd: Box) {\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,\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 {\n" " self.commands.iter().map(|cmd| (cmd.execute)()).collect()\n" " }\n" " fn rollback(&self) -> Vec {\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 &'a str>;\n" "\n" "struct Schema<'a> {\n" " executes: Vec>,\n" " rollbacks: Vec>,\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(&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 {\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);\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 {\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 Mutex {\n" " fn lock(&self) -> MutexGuard {\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) {\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;\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(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(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, Box),\n" " Sub(Box, Box),\n" " }\n" "}\n" "\n" "// The abstract visitor\n" "mod visit {\n" " use ast::*;\n" "\n" " pub trait Visitor {\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 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),\n" " Let(Box, Box),\n" " }\n" "\n" " pub struct Name {\n" " value: String,\n" " }\n" "\n" " pub enum Expr {\n" " IntLit(i64),\n" " Add(Box, Box),\n" " Sub(Box, Box),\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) -> Box { n }\n" " // Create a new inner node by folding its children.\n" " fn fold_stmt(&mut self, s: Box) -> Box {\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) -> Box { ... }\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) -> Box {\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` 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` 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\n" " iterator: Option>>,\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` 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` è 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` 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` 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` documentation, which handles .clone() " "intelligently](http://doc.rust-lang.org/std/rc/)\n" "- [`Arc` 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`, che gestisce .clone() in modo " "intelligente](http://doc.rust-lang.org/std/rc/)\n" "- [documentazione `Arc`, 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` and `vector` 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` e `vector` 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` and " "`Vec`\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` e " "`Vec`\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,\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 {\n" " file_name: PathBuf,\n" " protocol: P,\n" "}\n" "\n" "// all common API parts go into a generic impl block\n" "impl FileDownloadRequest

{\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 {\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` does " "not\n" "implement `mount_point()`, only the type `FileDownloadRequest` 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` no\n" "implementa `mount_point()`, solo il tipo `FileDownloadRequest` 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` can be cast from a String, unlike every other type of " "`Vec`.[^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` può essere lanciato da una stringa, a differenza di ogni altro " "tipo di `Vec`.[^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` 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`, 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\\ for " "Vec\\](https://doc.rust-lang.org/1.59.0/src/std/ffi/c_str.rs.html#803-811)" msgstr "" "Vedere: [impl From\\ for " "Vec\\](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\\ From\\\\> for " "BinaryHeap\\](https://doc.rust-lang.org/stable/src/alloc/collections/binary_heap.rs.html#1345-1354)" msgstr "" "Vedere: [impl\\ From\\\\> for " "BinaryHeap\\](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,\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(records: &[R]) -> HashSet {\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(iterator: I) -> HashSet\n" " where I: Iterator>\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,\n" "}\n" "\n" "fn unique_ids_lens(iter: impl Iterator) -> HashSet\n" "where\n" " T: LensRef, // 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(self, visitor: V) -> Result\n" " where\n" " V: Visitor<'de>;\n" "\n" " fn deserialize_bool(self, visitor: V) -> Result\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(self, v: bool) -> Result\n" " where\n" " E: Error;\n" "\n" " fn visit_u64(self, v: u64) -> Result\n" " where\n" " E: Error;\n" "\n" " fn visit_str(self, v: &str) -> Result\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(deserializer: D) -> Result\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 "" ================================================ FILE: po/messages.pot ================================================ msgid "" msgstr "" "Project-Id-Version: Rust Design Patterns\n" "POT-Creation-Date: 2025-05-17T14:07:35+09:00\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: en\n" "Plural-Forms: nplurals=1; plural=0;\n" #: src/SUMMARY.md:1 msgid "Summary" msgstr "" #: src/SUMMARY.md:3 src/intro.md:1 msgid "Introduction" msgstr "" #: src/SUMMARY.md:4 src/translations.md:1 msgid "Translations" msgstr "" #: src/SUMMARY.md:5 src/idioms/index.md:1 msgid "Idioms" msgstr "" #: src/SUMMARY.md:6 src/idioms/coercion-arguments.md:1 msgid "Use borrowed types for arguments" msgstr "" #: src/SUMMARY.md:7 msgid "Concatenating Strings with format!" msgstr "" #: src/SUMMARY.md:8 msgid "Constructor" msgstr "" #: src/SUMMARY.md:9 msgid "The Default Trait" msgstr "" #: src/SUMMARY.md:10 msgid "Collections Are Smart Pointers" msgstr "" #: src/SUMMARY.md:11 msgid "Finalisation in Destructors" msgstr "" #: src/SUMMARY.md:12 msgid "`mem::{take(_), replace(_)}`" msgstr "" #: src/SUMMARY.md:13 src/idioms/on-stack-dyn-dispatch.md:1 msgid "On-Stack Dynamic Dispatch" msgstr "" #: src/SUMMARY.md:14 src/SUMMARY.md:40 msgid "Foreign function interface (FFI)" msgstr "" #: src/SUMMARY.md:15 msgid "Idiomatic Errors" msgstr "" #: src/SUMMARY.md:16 src/idioms/ffi/accepting-strings.md:1 msgid "Accepting Strings" msgstr "" #: src/SUMMARY.md:17 src/idioms/ffi/passing-strings.md:1 msgid "Passing Strings" msgstr "" #: src/SUMMARY.md:18 msgid "Iterating over an Option" msgstr "" #: src/SUMMARY.md:19 msgid "Pass Variables to Closure" msgstr "" #: src/SUMMARY.md:20 msgid "Privacy For Extensibility" msgstr "" #: src/SUMMARY.md:21 src/idioms/rustdoc-init.md:1 msgid "Easy doc initialization" msgstr "" #: src/SUMMARY.md:22 src/idioms/temporary-mutability.md:1 msgid "Temporary mutability" msgstr "" #: src/SUMMARY.md:23 msgid "Return consumed arg on error" msgstr "" #: src/SUMMARY.md:25 src/patterns/index.md:1 msgid "Design Patterns" msgstr "" #: src/SUMMARY.md:26 msgid "Behavioural" msgstr "" #: src/SUMMARY.md:27 src/patterns/behavioural/command.md:1 msgid "Command" msgstr "" #: src/SUMMARY.md:28 src/patterns/behavioural/interpreter.md:1 msgid "Interpreter" msgstr "" #: src/SUMMARY.md:29 src/patterns/behavioural/newtype.md:1 msgid "Newtype" msgstr "" #: src/SUMMARY.md:30 msgid "RAII Guards" msgstr "" #: src/SUMMARY.md:31 msgid "Strategy" msgstr "" #: src/SUMMARY.md:32 src/patterns/behavioural/visitor.md:1 msgid "Visitor" msgstr "" #: src/SUMMARY.md:33 msgid "Creational" msgstr "" #: src/SUMMARY.md:34 src/patterns/creational/builder.md:1 msgid "Builder" msgstr "" #: src/SUMMARY.md:35 src/patterns/creational/fold.md:1 msgid "Fold" msgstr "" #: src/SUMMARY.md:36 msgid "Structural" msgstr "" #: src/SUMMARY.md:37 msgid "Compose Structs" msgstr "" #: src/SUMMARY.md:38 msgid "Prefer Small Crates" msgstr "" #: src/SUMMARY.md:39 src/patterns/structural/unsafe-mods.md:1 msgid "Contain unsafety in small modules" msgstr "" #: src/SUMMARY.md:41 src/patterns/ffi/export.md:1 msgid "Object-Based APIs" msgstr "" #: src/SUMMARY.md:42 src/patterns/ffi/wrappers.md:1 msgid "Type Consolidation into Wrappers" msgstr "" #: src/SUMMARY.md:44 src/anti_patterns/index.md:1 msgid "Anti-patterns" msgstr "" #: src/SUMMARY.md:45 src/anti_patterns/borrow_clone.md:1 msgid "Clone to satisfy the borrow checker" msgstr "" #: src/SUMMARY.md:46 msgid "`#[deny(warnings)]`" msgstr "" #: src/SUMMARY.md:47 msgid "Deref Polymorphism" msgstr "" #: src/SUMMARY.md:49 msgid "Functional Programming" msgstr "" #: src/SUMMARY.md:50 src/functional/paradigms.md:1 msgid "Programming paradigms" msgstr "" #: src/SUMMARY.md:51 src/functional/generics-type-classes.md:1 msgid "Generics as Type Classes" msgstr "" #: src/SUMMARY.md:52 msgid "Functional Optics" msgstr "" #: src/SUMMARY.md:54 msgid "Additional Resources" msgstr "" #: src/SUMMARY.md:55 src/additional_resources/design-principles.md:1 msgid "Design principles" msgstr "" #: src/intro.md:3 msgid "Participation" msgstr "" #: src/intro.md:5 msgid "" "If you are interested in contributing to this book, check out the " "[contribution " "guidelines](https://github.com/rust-unofficial/patterns/blob/master/CONTRIBUTING.md)." msgstr "" #: src/intro.md:8 msgid "News" msgstr "" #: src/intro.md:10 msgid "" "**2024-03-17**: You can now download the book in PDF format from [this " "link](https://rust-unofficial.github.io/patterns/rust-design-patterns.pdf)." msgstr "" #: src/intro.md:13 msgid "Design patterns" msgstr "" #: src/intro.md:15 msgid "" "In software development, we often come across problems that share " "similarities regardless of the environment they appear in. Although the " "implementation details are crucial to solve the task at hand, we may " "abstract from these particularities to find the common practices that are " "generically applicable." msgstr "" #: src/intro.md:20 msgid "" "Design patterns are a collection of reusable and tested solutions to " "recurring problems in engineering. They make our software more modular, " "maintainable, and extensible. Moreover, these patterns provide a common " "language for developers, making them an excellent tool for effective " "communication when problem-solving in teams." msgstr "" #: src/intro.md:26 msgid "" "Keep in mind: Each pattern comes with its own set of trade-offs. It's " "crucial to focus on why you choose a particular pattern rather than just on " "how to implement it.[^1]" msgstr "" #: src/intro.md:30 src/patterns/index.md:14 msgid "Design patterns in Rust" msgstr "" #: src/intro.md:32 msgid "" "Rust is not object-oriented, and the combination of all its characteristics, " "such as functional elements, a strong type system, and the borrow checker, " "makes it unique. Because of this, Rust design patterns vary with respect to " "other traditional object-oriented programming languages. That's why we " "decided to write this book. We hope you enjoy reading it! The book is " "divided in three main chapters:" msgstr "" #: src/intro.md:39 msgid "" "[Idioms](./idioms/index.md): guidelines to follow when coding. They are the " "social norms of the community. You should break them only if you have a good " "reason for it." msgstr "" #: src/intro.md:42 msgid "" "[Design patterns](./patterns/index.md): methods to solve common problems " "when coding." msgstr "" #: src/intro.md:44 msgid "" "[Anti-patterns](./anti_patterns/index.md): methods to solve common problems " "when coding. However, while design patterns give us benefits, anti-patterns " "create more problems." msgstr "" #: src/intro.md:48 msgid "" "https://web.archive.org/web/20240124025806/https://www.infoq.com/podcasts/software-architecture-hard-parts/" msgstr "" #: src/translations.md:3 msgid "" "We are utilizing " "[mdbook-i18n-helper](https://github.com/google/mdbook-i18n-helpers). 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 "" #: src/translations.md:8 msgid "External translations" msgstr "" #: src/translations.md:10 msgid "[简体中文](https://fomalhauthmj.github.io/patterns/)" msgstr "" #: src/translations.md:12 msgid "" "If you want to add a translation, please open an issue in the [main " "repository](https://github.com/rust-unofficial/patterns)." msgstr "" #: src/idioms/index.md:3 msgid "" "[Idioms](https://en.wikipedia.org/wiki/Programming_idiom) are commonly used " "styles, guidelines and patterns largely agreed upon by a community. Writing " "idiomatic code allows other developers to understand better what is " "happening." msgstr "" #: src/idioms/index.md:7 msgid "" "After all, the computer only cares about the machine code that is generated " "by the compiler. Instead, the source code is mainly beneficial to the " "developer. So, since we have this abstraction layer, why not make it more " "readable?" msgstr "" #: src/idioms/index.md:11 msgid "" "Remember the [KISS principle](https://en.wikipedia.org/wiki/KISS_principle): " "\"Keep It Simple, Stupid\". It claims that \"most systems work best if they " "are kept simple rather than made complicated; therefore, simplicity should " "be a key goal in design, and unnecessary complexity should be avoided\"." msgstr "" #: src/idioms/index.md:16 msgid "Code is there for humans, not computers, to understand." msgstr "" #: src/idioms/coercion-arguments.md:3 src/idioms/concat-format.md:3 #: src/idioms/ctor.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/rustdoc-init.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:3 #: 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 msgid "Description" msgstr "" #: src/idioms/coercion-arguments.md:5 msgid "" "Using a target of a deref coercion can increase the flexibility of your code " "when you are deciding which argument type to use for a function argument. In " "this way, the function will accept more input types." msgstr "" #: src/idioms/coercion-arguments.md:9 msgid "" "This is not limited to slice-able or fat pointer types. In fact, you should " "always prefer using the **borrowed type** over **borrowing the owned type**. " "Such as `&str` over `&String`, `&[T]` over `&Vec`, or `&T` over `&Box`." msgstr "" #: src/idioms/coercion-arguments.md:13 msgid "" "Using borrowed types you can avoid layers of indirection for those instances " "where the owned type already provides a layer of indirection. For instance, " "a `String` has a layer of indirection, so a `&String` will have two layers " "of indirection. We can avoid this by using `&str` instead, and letting " "`&String` coerce to a `&str` whenever the function is invoked." msgstr "" #: src/idioms/coercion-arguments.md:19 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:19 #: src/idioms/rustdoc-init.md:45 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:12 #: src/patterns/behavioural/strategy.md:30 #: src/patterns/behavioural/visitor.md:13 src/patterns/creational/builder.md:7 #: src/patterns/creational/fold.md:12 #: src/patterns/structural/compose-structs.md:15 #: 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 msgid "Example" msgstr "" #: src/idioms/coercion-arguments.md:21 msgid "" "For this example, we will illustrate some differences for using `&String` as " "a function argument versus using a `&str`, but the ideas apply as well to " "using `&Vec` versus using a `&[T]` or using a `&Box` versus a `&T`." msgstr "" #: src/idioms/coercion-arguments.md:25 msgid "" "Consider an example where we wish to determine if a word contains three " "consecutive vowels. We don't need to own the string to determine this, so we " "will take a reference." msgstr "" #: src/idioms/coercion-arguments.md:29 msgid "The code might look something like this:" msgstr "" #: src/idioms/coercion-arguments.md:36 src/idioms/coercion-arguments.md:96 msgid "'a'" msgstr "" #: src/idioms/coercion-arguments.md:36 src/idioms/coercion-arguments.md:96 msgid "'e'" msgstr "" #: src/idioms/coercion-arguments.md:36 src/idioms/coercion-arguments.md:96 msgid "'i'" msgstr "" #: src/idioms/coercion-arguments.md:36 src/idioms/coercion-arguments.md:96 msgid "'o'" msgstr "" #: src/idioms/coercion-arguments.md:36 src/idioms/coercion-arguments.md:96 msgid "'u'" msgstr "" #: src/idioms/coercion-arguments.md:49 msgid "\"Ferris\"" msgstr "" #: src/idioms/coercion-arguments.md:50 msgid "\"Curious\"" msgstr "" #: src/idioms/coercion-arguments.md:51 src/idioms/coercion-arguments.md:52 msgid "\"{}: {}\"" msgstr "" #: src/idioms/coercion-arguments.md:54 msgid "" "// This works fine, but the following two lines would fail:\n" " // println!(\"Ferris: {}\", three_vowels(\"Ferris\"));\n" " // println!(\"Curious: {}\", three_vowels(\"Curious\"));\n" msgstr "" #: src/idioms/coercion-arguments.md:60 msgid "" "This works fine because we are passing a `&String` type as a parameter. If " "we remove the comments on the last two lines, the example will fail. This is " "because a `&str` type will not coerce to a `&String` type. We can fix this " "by simply modifying the type for our argument." msgstr "" #: src/idioms/coercion-arguments.md:65 msgid "For instance, if we change our function declaration to:" msgstr "" #: src/idioms/coercion-arguments.md:71 msgid "then both versions will compile and print the same output." msgstr "" #: src/idioms/coercion-arguments.md:78 msgid "" "But wait, that's not all! There is more to this story. It's likely that you " "may say to yourself: that doesn't matter, I will never be using a `&'static " "str` as an input anyways (as we did when we used `\"Ferris\"`). Even " "ignoring this special example, you may still find that using `&str` will " "give you more flexibility than using a `&String`." msgstr "" #: src/idioms/coercion-arguments.md:84 msgid "" "Let's now take an example where someone gives us a sentence, and we want to " "determine if any of the words in the sentence contain three consecutive " "vowels. We probably should make use of the function we have already defined " "and simply feed in each word from the sentence." msgstr "" #: src/idioms/coercion-arguments.md:89 msgid "An example of this could look like this:" msgstr "" #: src/idioms/coercion-arguments.md:110 msgid "\"Once upon a time, there was a friendly curious crab named Ferris\"" msgstr "" #: src/idioms/coercion-arguments.md:111 msgid "' '" msgstr "" #: src/idioms/coercion-arguments.md:113 msgid "\"{word} has three consecutive vowels!\"" msgstr "" #: src/idioms/coercion-arguments.md:119 msgid "" "Running this example using our function declared with an argument type " "`&str` will yield" msgstr "" #: src/idioms/coercion-arguments.md:126 msgid "" "However, this example will not run when our function is declared with an " "argument type `&String`. This is because string slices are a `&str` and not " "a `&String` which would require an allocation to be converted to `&String` " "which is not implicit, whereas converting from `String` to `&str` is cheap " "and implicit." msgstr "" #: src/idioms/coercion-arguments.md:132 src/idioms/ctor.md:101 #: src/idioms/default.md:58 src/idioms/deref.md:76 #: src/idioms/dtor-finally.md:93 src/idioms/mem-replace.md:116 #: src/idioms/on-stack-dyn-dispatch.md:80 src/idioms/option-iter.md:47 #: src/idioms/priv-extend.md:118 src/patterns/behavioural/command.md:218 #: src/patterns/behavioural/interpreter.md:144 #: src/patterns/behavioural/newtype.md:94 src/patterns/behavioural/RAII.md:112 #: src/patterns/behavioural/strategy.md:178 #: src/patterns/behavioural/visitor.md:108 #: src/patterns/creational/builder.md:109 src/patterns/creational/fold.md:109 #: src/patterns/structural/small-crates.md:45 #: src/patterns/structural/unsafe-mods.md:33 #: src/anti_patterns/borrow_clone.md:65 src/anti_patterns/deny-warnings.md:101 #: src/anti_patterns/deref.md:124 src/functional/generics-type-classes.md:236 msgid "See also" msgstr "" #: src/idioms/coercion-arguments.md:134 msgid "" "[Rust Language Reference on Type " "Coercions](https://doc.rust-lang.org/reference/type-coercions.html)" msgstr "" #: src/idioms/coercion-arguments.md:135 msgid "" "For more discussion on how to handle `String` and `&str` see [this blog " "series " "(2015)](https://web.archive.org/web/20201112023149/https://hermanradtke.com/2015/05/03/string-vs-str-in-rust-functions.html) " "by Herman J. Radtke III" msgstr "" #: src/idioms/coercion-arguments.md:138 msgid "" "[Steve Klabnik's Blogpost on 'When should I use String vs " "&str?'](https://archive.ph/LBpD0)" msgstr "" #: src/idioms/concat-format.md:1 msgid "Concatenating strings with `format!`" msgstr "" #: src/idioms/concat-format.md:5 msgid "" "It is possible to build up strings using the `push` and `push_str` methods " "on a mutable `String`, or using its `+` operator. However, it is often more " "convenient to use `format!`, especially where there is a mix of literal and " "non-literal strings." msgstr "" #: src/idioms/concat-format.md:14 msgid "" "// 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" msgstr "" #: src/idioms/concat-format.md:20 msgid "// But using format! is better.\n" msgstr "" #: src/idioms/concat-format.md:21 msgid "\"Hello {name}!\"" msgstr "" #: src/idioms/concat-format.md:25 src/idioms/deref.md:43 #: src/idioms/dtor-finally.md:46 src/idioms/mem-replace.md:91 #: src/idioms/on-stack-dyn-dispatch.md:43 src/idioms/ffi/errors.md:128 #: src/idioms/ffi/accepting-strings.md:65 src/idioms/ffi/passing-strings.md:66 #: src/idioms/pass-var-to-closure.md:48 src/idioms/rustdoc-init.md:77 #: src/idioms/temporary-mutability.md:38 #: src/idioms/return-consumed-arg-on-error.md:55 #: src/patterns/behavioural/newtype.md:55 src/patterns/behavioural/RAII.md:79 #: src/patterns/behavioural/strategy.md:98 #: src/patterns/creational/builder.md:68 #: src/patterns/structural/compose-structs.md:106 #: src/patterns/structural/small-crates.md:13 #: src/patterns/structural/unsafe-mods.md:12 src/patterns/ffi/export.md:113 #: src/patterns/ffi/wrappers.md:64 src/anti_patterns/deny-warnings.md:16 #: src/anti_patterns/deref.md:69 src/functional/generics-type-classes.md:209 msgid "Advantages" msgstr "" #: src/idioms/concat-format.md:27 msgid "" "Using `format!` is usually the most succinct and readable way to combine " "strings." msgstr "" #: src/idioms/concat-format.md:30 src/idioms/deref.md:50 #: src/idioms/dtor-finally.md:51 src/idioms/mem-replace.md:95 #: src/idioms/on-stack-dyn-dispatch.md:49 src/idioms/ffi/errors.md:133 #: src/idioms/ffi/accepting-strings.md:136 #: src/idioms/ffi/passing-strings.md:101 src/idioms/pass-var-to-closure.md:57 #: src/idioms/priv-extend.md:104 src/idioms/rustdoc-init.md:81 #: src/idioms/temporary-mutability.md:42 #: src/idioms/return-consumed-arg-on-error.md:59 #: src/patterns/behavioural/newtype.md:66 #: src/patterns/behavioural/strategy.md:107 #: src/patterns/creational/builder.md:76 #: src/patterns/structural/compose-structs.md:111 #: src/patterns/structural/small-crates.md:22 #: src/patterns/structural/unsafe-mods.md:18 src/patterns/ffi/export.md:236 #: src/patterns/ffi/wrappers.md:70 src/anti_patterns/deref.md:81 #: src/functional/generics-type-classes.md:220 msgid "Disadvantages" msgstr "" #: src/idioms/concat-format.md:32 msgid "" "It is usually not the most efficient way to combine strings - a series of " "`push` operations on a mutable string is usually the most efficient " "(especially if the string has been pre-allocated to the expected size)." msgstr "" #: src/idioms/ctor.md:1 msgid "Constructors" msgstr "" #: src/idioms/ctor.md:5 msgid "" "Rust does not have constructors as a language construct. Instead, the " "convention is to use an [associated " "function](https://doc.rust-lang.org/stable/book/ch05-03-method-syntax.html#associated-functions) " "`new` to create an object:" msgstr "" #: src/idioms/ctor.md:10 msgid "" "/// Time in seconds.\n" "///\n" "/// # Example\n" "///\n" "/// ```\n" "/// let s = Second::new(42);\n" "/// assert_eq!(42, s.value());\n" "/// ```\n" msgstr "" #: src/idioms/ctor.md:23 msgid "" "// Constructs a new instance of [`Second`].\n" " // Note this is an associated function - no self.\n" msgstr "" #: src/idioms/ctor.md:29 src/idioms/ctor.md:54 src/idioms/ctor.md:85 msgid "/// Returns the value in seconds.\n" msgstr "" #: src/idioms/ctor.md:36 msgid "Default Constructors" msgstr "" #: src/idioms/ctor.md:38 msgid "" "Rust supports default constructors with the " "[`Default`](https://doc.rust-lang.org/stable/std/default/trait.Default.html) " "trait:" msgstr "" #: src/idioms/ctor.md:41 src/idioms/ctor.md:71 msgid "" "/// Time in seconds.\n" "///\n" "/// # Example\n" "///\n" "/// ```\n" "/// let s = Second::default();\n" "/// assert_eq!(0, s.value());\n" "/// ```\n" msgstr "" #: src/idioms/ctor.md:67 msgid "" "`Default` can also be derived if all types of all fields implement " "`Default`, like they do with `Second`:" msgstr "" #: src/idioms/ctor.md:92 msgid "" "**Note:** It is common and expected for types to implement both `Default` " "and an empty `new` constructor. `new` is the constructor convention in Rust, " "and users expect it to exist, so if it is reasonable for the basic " "constructor to take no arguments, then it should, even if it is functionally " "identical to default." msgstr "" #: src/idioms/ctor.md:97 msgid "" "**Hint:** The advantage of implementing or deriving `Default` is that your " "type can now be used where a `Default` implementation is required, most " "prominently, any of the [`*or_default` functions in the standard " "library](https://doc.rust-lang.org/stable/std/?search=or_default)." msgstr "" #: src/idioms/ctor.md:103 msgid "" "The [default idiom](default.md) for a more in-depth description of the " "`Default` trait." msgstr "" #: src/idioms/ctor.md:106 msgid "" "The [builder pattern](../patterns/creational/builder.md) for constructing " "objects where there are multiple configurations." msgstr "" #: src/idioms/ctor.md:109 msgid "" "[API " "Guidelines/C-COMMON-TRAITS](https://rust-lang.github.io/api-guidelines/interoperability.html#types-eagerly-implement-common-traits-c-common-traits) " "for implementing both, `Default` and `new`." msgstr "" #: src/idioms/default.md:1 msgid "The `Default` Trait" msgstr "" #: src/idioms/default.md:5 msgid "" "Many types in Rust have a [constructor](ctor.md). However, this is " "_specific_ to the type; Rust cannot abstract over \"everything that has a " "`new()` method\". To allow this, the " "[`Default`](https://doc.rust-lang.org/stable/std/default/trait.Default.html) " "trait was conceived, which can be used with containers and other generic " "types (e.g. see " "[`Option::unwrap_or_default()`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.unwrap_or_default)). " "Notably, some containers already implement it where applicable." msgstr "" #: src/idioms/default.md:11 msgid "" "Not only do one-element containers like `Cow`, `Box` or `Arc` implement " "`Default` for contained `Default` types, one can automatically " "`#[derive(Default)]` for structs whose fields all implement it, so the more " "types implement `Default`, the more useful it becomes." msgstr "" #: src/idioms/default.md:16 msgid "" "On the other hand, constructors can take multiple arguments, while the " "`default()` method does not. There can even be multiple constructors with " "different names, but there can only be one `Default` implementation per type." msgstr "" #: src/idioms/default.md:24 msgid "// note that we can simply auto-derive Default here.\n" msgstr "" #: src/idioms/default.md:28 msgid "// Option defaults to None\n" msgstr "" #: src/idioms/default.md:30 msgid "// Vecs default to empty vector\n" msgstr "" #: src/idioms/default.md:32 msgid "// Duration defaults to zero time\n" msgstr "" #: src/idioms/default.md:34 msgid "// bool defaults to false\n" msgstr "" #: src/idioms/default.md:39 msgid "// add setters here\n" msgstr "" #: src/idioms/default.md:43 msgid "// construct a new instance with default values\n" msgstr "" #: src/idioms/default.md:45 msgid "// do something with conf here\n" msgstr "" #: src/idioms/default.md:47 msgid "\"conf = {conf:#?}\"" msgstr "" #: src/idioms/default.md:49 msgid "" "// partial initialization with default values, creates the same instance\n" msgstr "" #: src/idioms/default.md:60 msgid "" "The [constructor](ctor.md) idiom is another way to generate instances that " "may or may not be \"default\"" msgstr "" #: src/idioms/default.md:62 msgid "" "The " "[`Default`](https://doc.rust-lang.org/stable/std/default/trait.Default.html) " "documentation (scroll down for the list of implementors)" msgstr "" #: src/idioms/default.md:63 msgid "" "[`Option::unwrap_or_default()`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.unwrap_or_default)" msgstr "" #: src/idioms/default.md:64 msgid "[`derive(new)`](https://crates.io/crates/derive-new/)" msgstr "" #: src/idioms/deref.md:1 msgid "Collections are smart pointers" msgstr "" #: src/idioms/deref.md:5 msgid "" "Use the [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) trait " "to treat collections like smart pointers, offering owning and borrowed views " "of data." msgstr "" #: src/idioms/deref.md:16 src/idioms/deref.md:23 #: src/patterns/behavioural/RAII.md:29 src/patterns/behavioural/RAII.md:41 #: src/patterns/behavioural/RAII.md:100 src/anti_patterns/deref.md:35 msgid "//..\n" msgstr "" #: src/idioms/deref.md:28 msgid "" "A `Vec` is an owning collection of `T`s, while a slice (`&[T]`) is a " "borrowed collection of `T`s. Implementing `Deref` for `Vec` allows implicit " "dereferencing from `&Vec` to `&[T]` and includes the relationship in " "auto-dereferencing searches. Most methods you might expect to be implemented " "for `Vec`s are instead implemented for slices." msgstr "" #: src/idioms/deref.md:34 msgid "Also `String` and `&str` have a similar relation." msgstr "" #: src/idioms/deref.md:36 src/idioms/dtor-finally.md:36 #: src/idioms/mem-replace.md:63 src/idioms/on-stack-dyn-dispatch.md:32 #: src/idioms/ffi/accepting-strings.md:12 src/idioms/ffi/passing-strings.md:14 #: src/idioms/rustdoc-init.md:9 src/idioms/return-consumed-arg-on-error.md:45 #: src/patterns/behavioural/command.md:8 #: src/patterns/behavioural/interpreter.md:17 #: src/patterns/behavioural/newtype.md:45 src/patterns/behavioural/RAII.md:73 #: src/patterns/behavioural/strategy.md:21 #: src/patterns/behavioural/visitor.md:74 src/patterns/creational/builder.md:63 #: src/patterns/creational/fold.md:73 #: src/patterns/structural/compose-structs.md:100 src/patterns/ffi/export.md:16 #: src/anti_patterns/borrow_clone.md:30 msgid "Motivation" msgstr "" #: src/idioms/deref.md:38 msgid "" "Ownership and borrowing are key aspects of the Rust language. Data " "structures must account for these semantics properly to give a good user " "experience. When implementing a data structure that owns its data, offering " "a borrowed view of that data allows for more flexible APIs." msgstr "" #: src/idioms/deref.md:45 msgid "" "Most methods can be implemented only for the borrowed view, they are then " "implicitly available for the owning view." msgstr "" #: src/idioms/deref.md:48 msgid "Gives clients a choice between borrowing or taking ownership of data." msgstr "" #: src/idioms/deref.md:52 msgid "" "Methods and traits only available via dereferencing are not taken into " "account when bounds checking, so generic programming with data structures " "using this pattern can get complex (see the `Borrow` and `AsRef` traits, " "etc.)." msgstr "" #: src/idioms/deref.md:56 src/idioms/dtor-finally.md:66 #: src/idioms/mem-replace.md:105 src/idioms/on-stack-dyn-dispatch.md:66 #: src/idioms/priv-extend.md:87 src/idioms/rustdoc-init.md:88 #: src/patterns/behavioural/command.md:203 #: src/patterns/behavioural/interpreter.md:105 #: src/patterns/behavioural/newtype.md:74 src/patterns/behavioural/RAII.md:84 #: src/patterns/behavioural/strategy.md:113 #: src/patterns/behavioural/visitor.md:81 src/patterns/creational/builder.md:81 #: src/patterns/creational/fold.md:85 #: src/patterns/structural/compose-structs.md:117 #: src/anti_patterns/deref.md:102 msgid "Discussion" msgstr "" #: src/idioms/deref.md:58 msgid "" "Smart pointers and collections are analogous: a smart pointer points to a " "single object, whereas a collection points to many objects. From the point " "of view of the type system, there is little difference between the two. A " "collection owns its data if the only way to access each datum is via the " "collection and the collection is responsible for deleting the data (even in " "cases of shared ownership, some kind of borrowed view may be appropriate). " "If a collection owns its data, it is usually useful to provide a view of the " "data as borrowed so that it can be referenced multiple times." msgstr "" #: src/idioms/deref.md:67 msgid "" "Most smart pointers (e.g., `Foo`) implement `Deref`. However, " "collections will usually dereference to a custom type. `[T]` and `str` have " "some language support, but in the general case, this is not necessary. " "`Foo` can implement `Deref>` where `Bar` is a dynamically " "sized type and `&Bar` is a borrowed view of the data in `Foo`." msgstr "" #: src/idioms/deref.md:73 msgid "" "Commonly, ordered collections will implement `Index` for `Range`s to provide " "slicing syntax. The target will be the borrowed view." msgstr "" #: src/idioms/deref.md:78 msgid "[Deref polymorphism anti-pattern](../anti_patterns/deref.md)." msgstr "" #: src/idioms/deref.md:79 src/anti_patterns/deref.md:130 msgid "" "[Documentation for `Deref` " "trait](https://doc.rust-lang.org/std/ops/trait.Deref.html)." msgstr "" #: src/idioms/dtor-finally.md:1 msgid "Finalisation in destructors" msgstr "" #: src/idioms/dtor-finally.md:5 msgid "" "Rust does not provide the equivalent to `finally` blocks - code that will be " "executed no matter how a function is exited. Instead, an object's destructor " "can be used to run code that must be run before exit." msgstr "" #: src/idioms/dtor-finally.md:13 msgid "// some code\n" msgstr "" #: src/idioms/dtor-finally.md:17 msgid "// These don't need to be defined inside the function.\n" msgstr "" #: src/idioms/dtor-finally.md:20 msgid "// Implement a destructor for Foo.\n" msgstr "" #: src/idioms/dtor-finally.md:23 msgid "\"exit\"" msgstr "" #: src/idioms/dtor-finally.md:27 msgid "// The dtor of _exit will run however the function `bar` is exited.\n" msgstr "" #: src/idioms/dtor-finally.md:29 msgid "// Implicit return with `?` operator.\n" msgstr "" #: src/idioms/dtor-finally.md:31 msgid "// Normal return.\n" msgstr "" #: src/idioms/dtor-finally.md:38 msgid "" "If a function has multiple return points, then executing code on exit " "becomes difficult and repetitive (and thus bug-prone). This is especially " "the case where return is implicit due to a macro. A common case is the `?` " "operator which returns if the result is an `Err`, but continues if it is " "`Ok`. `?` is used as an exception handling mechanism, but unlike Java (which " "has `finally`), there is no way to schedule code to run in both the normal " "and exceptional cases. Panicking will also exit a function early." msgstr "" #: src/idioms/dtor-finally.md:48 msgid "" "Code in destructors will (nearly) always be run - copes with panics, early " "returns, etc." msgstr "" #: src/idioms/dtor-finally.md:53 msgid "" "It is not guaranteed that destructors will run. For example, if there is an " "infinite loop in a function or if running a function crashes before exit. " "Destructors are also not run in the case of a panic in an already panicking " "thread. Therefore, destructors cannot be relied on as finalizers where it is " "absolutely essential that finalisation happens." msgstr "" #: src/idioms/dtor-finally.md:59 msgid "" "This pattern introduces some hard to notice, implicit code. Reading a " "function gives no clear indication of destructors to be run on exit. This " "can make debugging tricky." msgstr "" #: src/idioms/dtor-finally.md:63 msgid "" "Requiring an object and `Drop` impl just for finalisation is heavy on " "boilerplate." msgstr "" #: src/idioms/dtor-finally.md:68 msgid "" "There is some subtlety about how exactly to store the object used as a " "finalizer. It must be kept alive until the end of the function and must then " "be destroyed. The object must always be a value or uniquely owned pointer " "(e.g., `Box`). If a shared pointer (such as `Rc`) is used, then the " "finalizer can be kept alive beyond the lifetime of the function. For similar " "reasons, the finalizer should not be moved or returned." msgstr "" #: src/idioms/dtor-finally.md:75 msgid "" "The finalizer must be assigned into a variable, otherwise it will be " "destroyed immediately, rather than when it goes out of scope. The variable " "name must start with `_` if the variable is only used as a finalizer, " "otherwise the compiler will warn that the finalizer is never used. However, " "do not call the variable `_` with no suffix - in that case it will be " "destroyed immediately." msgstr "" #: src/idioms/dtor-finally.md:81 msgid "" "In Rust, destructors are run when an object goes out of scope. This happens " "whether we reach the end of block, there is an early return, or the program " "panics. When panicking, Rust unwinds the stack running destructors for each " "object in each stack frame. So, destructors get called even if the panic " "happens in a function being called." msgstr "" #: src/idioms/dtor-finally.md:87 msgid "" "If a destructor panics while unwinding, there is no good action to take, so " "Rust aborts the thread immediately, without running further destructors. " "This means that destructors are not absolutely guaranteed to run. It also " "means that you must take extra care in your destructors not to panic, since " "it could leave resources in an unexpected state." msgstr "" #: src/idioms/dtor-finally.md:95 msgid "[RAII guards](../patterns/behavioural/RAII.md)." msgstr "" #: src/idioms/mem-replace.md:1 msgid "`mem::{take(_), replace(_)}` to keep owned values in changed enums" msgstr "" #: src/idioms/mem-replace.md:5 msgid "" "Say we have a `&mut MyEnum` which has (at least) two variants, `A { name: " "String, x: u8 }` and `B { name: String }`. Now we want to change `MyEnum::A` " "to a `B` if `x` is zero, while keeping `MyEnum::B` intact." msgstr "" #: src/idioms/mem-replace.md:9 msgid "We can do this without cloning the `name`." msgstr "" #: src/idioms/mem-replace.md:23 msgid "" "// This takes out our `name` and puts 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" msgstr "" #: src/idioms/mem-replace.md:34 msgid "This also works with more variants:" msgstr "" #: src/idioms/mem-replace.md:49 msgid "" "// 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" msgstr "" #: src/idioms/mem-replace.md:65 msgid "" "When working with enums, we may want to change an enum value in place, " "perhaps to another variant. This is usually done in two phases to keep the " "borrow checker happy. In the first phase, we observe the existing value and " "look at its parts to decide what to do next. In the second phase we may " "conditionally change the value (as in the example above)." msgstr "" #: src/idioms/mem-replace.md:71 msgid "" "The borrow checker won't allow us to take out `name` of the enum (because " "_something_ must be there.) We could of course `.clone()` name and put the " "clone 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 can avoid the extra allocation by changing `e` with only a " "mutable borrow." msgstr "" #: src/idioms/mem-replace.md:78 msgid "" "`mem::take` lets us swap out the value, replacing it with its default value, " "and returning the previous value. For `String`, the default value is an " "empty `String`, which does not need to allocate. As a result, we get the " "original `name` _as an owned value_. We can then wrap this in another enum." msgstr "" #: src/idioms/mem-replace.md:83 msgid "" "**NOTE:** `mem::replace` is very similar, but allows us to specify what to " "replace the value with. An equivalent to our `mem::take` line would be " "`mem::replace(name, String::new())`." msgstr "" #: src/idioms/mem-replace.md:87 msgid "" "Note, however, that if we are using an `Option` and want to replace its " "value with a `None`, `Option`’s `take()` method provides a shorter and more " "idiomatic alternative." msgstr "" #: src/idioms/mem-replace.md:93 msgid "" "Look ma, no allocation! Also you may feel like Indiana Jones while doing it." msgstr "" #: src/idioms/mem-replace.md:97 msgid "" "This gets a bit wordy. Getting it wrong repeatedly will make you hate the " "borrow checker. The compiler may fail to optimize away the double store, " "resulting in reduced performance as opposed to what you'd do in unsafe " "languages." msgstr "" #: src/idioms/mem-replace.md:101 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 " "implement this, you can instead use `mem::replace`." msgstr "" #: src/idioms/mem-replace.md:107 msgid "" "This pattern is only of interest in Rust. In GC'd languages, you'd take the " "reference to the value by default (and the GC would keep track of refs), and " "in other low-level languages like C you'd simply alias the pointer and fix " "things later." msgstr "" #: src/idioms/mem-replace.md:112 msgid "" "However, in Rust, we have to do a little more work to do this. An owned " "value may only have one owner, so to take it out, we need to put something " "back in – like Indiana Jones, replacing the artifact with a bag of sand." msgstr "" #: src/idioms/mem-replace.md:118 msgid "" "This gets rid of the [Clone to satisfy the borrow " "checker](../anti_patterns/borrow_clone.md) anti-pattern in a specific case." msgstr "" #: src/idioms/on-stack-dyn-dispatch.md:5 msgid "" "We can dynamically dispatch over multiple values, however, to do so, we need " "to declare multiple variables to bind differently-typed objects. To extend " "the lifetime as necessary, we can use deferred conditional initialization, " "as seen below:" msgstr "" #: src/idioms/on-stack-dyn-dispatch.md:17 #: src/idioms/on-stack-dyn-dispatch.md:20 #: src/idioms/on-stack-dyn-dispatch.md:56 msgid "\"-\"" msgstr "" #: src/idioms/on-stack-dyn-dispatch.md:18 msgid "// We need to describe the type to get dynamic dispatch.\n" msgstr "" #: src/idioms/on-stack-dyn-dispatch.md:25 #: src/idioms/on-stack-dyn-dispatch.md:60 msgid "// Read from `readable` here.\n" msgstr "" #: src/idioms/on-stack-dyn-dispatch.md:34 msgid "" "Rust monomorphises code by default. This means a copy of the code will be " "generated for each type it is used with and optimized independently. While " "this allows for very fast code on the hot path, it also bloats the code in " "places where performance is not of the essence, thus costing compile time " "and cache usage." msgstr "" #: src/idioms/on-stack-dyn-dispatch.md:40 msgid "" "Luckily, Rust allows us to use dynamic dispatch, but we have to explicitly " "ask for it." msgstr "" #: src/idioms/on-stack-dyn-dispatch.md:45 msgid "" "We do not need to allocate anything on the heap. Neither do we need to " "initialize something we won't use later, nor do we need to monomorphize the " "whole code that follows to work with both `File` or `Stdin`." msgstr "" #: src/idioms/on-stack-dyn-dispatch.md:51 msgid "" "Before Rust 1.79.0, the code needed two `let` bindings with deferred " "initialization, which made up more moving parts than the `Box`\\-based " "version:" msgstr "" #: src/idioms/on-stack-dyn-dispatch.md:55 msgid "// We still need to ascribe the type for dynamic dispatch.\n" msgstr "" #: src/idioms/on-stack-dyn-dispatch.md:64 msgid "Luckily, this disadvantage is now gone. Yay!" msgstr "" #: src/idioms/on-stack-dyn-dispatch.md:68 msgid "" "Since Rust 1.79.0, the compiler will automatically extend the lifetimes of " "temporary values within `&` or `&mut` as long as possible within the scope " "of the function." msgstr "" #: src/idioms/on-stack-dyn-dispatch.md:72 msgid "" "This means we can simply use a `&mut` value here without worrying about " "placing the contents into some `let` binding (which would have been needed " "for deferred initialization, which was the solution used before that change)." msgstr "" #: src/idioms/on-stack-dyn-dispatch.md:76 msgid "" "We still have a place for each value (even if that place is temporary), the " "compiler knows the size of each value and each borrowed value outlives all " "references borrowed from it." msgstr "" #: src/idioms/on-stack-dyn-dispatch.md:82 msgid "" "[Finalisation in destructors](dtor-finally.md) and [RAII " "guards](../patterns/behavioural/RAII.md) can benefit from tight control over " "lifetimes." msgstr "" #: src/idioms/on-stack-dyn-dispatch.md:85 msgid "" "For conditionally filled `Option<&T>`s of (mutable) references, one can " "initialize an `Option` directly and use its " "[`.as_ref()`](https://doc.rust-lang.org/std/option/enum.Option.html#method.as_ref) " "method to get an optional reference." msgstr "" #: src/idioms/ffi/intro.md:1 msgid "FFI Idioms" msgstr "" #: src/idioms/ffi/intro.md:3 msgid "" "Writing FFI code is an entire course in itself. However, there are several " "idioms here that can act as pointers, and avoid traps for inexperienced " "users of `unsafe` Rust." msgstr "" #: src/idioms/ffi/intro.md:7 msgid "This section contains idioms that may be useful when doing FFI." msgstr "" #: src/idioms/ffi/intro.md:9 msgid "" "[Idiomatic Errors](./errors.md) - Error handling with integer codes and " "sentinel return values (such as `NULL` pointers)" msgstr "" #: src/idioms/ffi/intro.md:12 msgid "[Accepting Strings](./accepting-strings.md) with minimal unsafe code" msgstr "" #: src/idioms/ffi/intro.md:14 msgid "[Passing Strings](./passing-strings.md) to FFI functions" msgstr "" #: src/idioms/ffi/errors.md:1 msgid "Error Handling in FFI" msgstr "" #: src/idioms/ffi/errors.md:5 msgid "" "In foreign languages like C, errors are represented by return codes. " "However, Rust's type system allows much more rich error information to be " "captured and propagated through a full type." msgstr "" #: src/idioms/ffi/errors.md:9 msgid "" "This best practice shows different kinds of error codes, and how to expose " "them in a usable way:" msgstr "" #: src/idioms/ffi/errors.md:12 msgid "Flat Enums should be converted to integers and returned as codes." msgstr "" #: src/idioms/ffi/errors.md:13 msgid "" "Structured Enums should be converted to an integer code with a string error " "message for detail." msgstr "" #: src/idioms/ffi/errors.md:15 msgid "" "Custom Error Types should become \"transparent\", with a C representation." msgstr "" #: 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:44 #: src/patterns/ffi/wrappers.md:24 msgid "Code Example" msgstr "" #: src/idioms/ffi/errors.md:19 msgid "Flat Enums" msgstr "" #: src/idioms/ffi/errors.md:23 msgid "// user attempted a write operation\n" msgstr "" #: src/idioms/ffi/errors.md:24 msgid "// user should read the C errno() for what it was\n" msgstr "" #: src/idioms/ffi/errors.md:25 msgid "// user should run a repair tool to recover it\n" msgstr "" #: src/idioms/ffi/errors.md:35 msgid "Structured Enums" msgstr "" #: src/idioms/ffi/errors.md:42 msgid "// message describing the issue\n" msgstr "" #: src/idioms/ffi/errors.md:61 src/idioms/ffi/accepting-strings.md:47 #: src/idioms/ffi/accepting-strings.md:79 src/idioms/ffi/passing-strings.md:33 #: src/patterns/ffi/export.md:154 src/patterns/ffi/export.md:158 #: src/patterns/ffi/export.md:165 msgid "\"C\"" msgstr "" #: src/idioms/ffi/errors.md:64 msgid "" "// SAFETY: we assume that the lifetime of `e` is greater than\n" " // the current stack frame.\n" msgstr "" #: src/idioms/ffi/errors.md:70 msgid "\"cannot write to read-only database\"" msgstr "" #: src/idioms/ffi/errors.md:73 msgid "\"I/O Error: {e}\"" msgstr "" #: src/idioms/ffi/errors.md:76 msgid "\"File corrupted, run repair: {}\"" msgstr "" #: src/idioms/ffi/errors.md:83 msgid "" "// SAFETY: copying error_bytes to an allocated buffer with a '\\0'\n" " // byte at the end.\n" msgstr "" #: src/idioms/ffi/errors.md:99 msgid "Custom Error Types" msgstr "" #: src/idioms/ffi/errors.md:109 src/idioms/ffi/accepting-strings.md:48 #: src/idioms/ffi/accepting-strings.md:83 src/patterns/creational/builder.md:30 #: src/patterns/ffi/export.md:137 src/patterns/ffi/export.md:139 msgid "/* ... */" msgstr "" #: src/idioms/ffi/errors.md:111 msgid "/* Create a second version which is exposed as a C structure */" msgstr "" #: src/idioms/ffi/errors.md:130 msgid "" "This ensures that the foreign language has clear access to error information " "while not compromising the Rust code's API at all." msgstr "" #: src/idioms/ffi/errors.md:135 msgid "" "It's a lot of typing, and some types may not be able to be converted easily " "to C." msgstr "" #: src/idioms/ffi/accepting-strings.md:5 msgid "" "When accepting strings via FFI through pointers, there are two principles " "that should be followed:" msgstr "" #: src/idioms/ffi/accepting-strings.md:8 msgid "Keep foreign strings \"borrowed\", rather than copying them directly." msgstr "" #: src/idioms/ffi/accepting-strings.md:9 msgid "" "Minimize the amount of complexity and `unsafe` code involved in converting " "from a C-style string to native Rust strings." msgstr "" #: src/idioms/ffi/accepting-strings.md:14 msgid "" "The strings used in C have different behaviours to those used in Rust, " "namely:" msgstr "" #: src/idioms/ffi/accepting-strings.md:16 msgid "C strings are null-terminated while Rust strings store their length" msgstr "" #: src/idioms/ffi/accepting-strings.md:17 msgid "" "C strings can contain any arbitrary non-zero byte while Rust strings must be " "UTF-8" msgstr "" #: src/idioms/ffi/accepting-strings.md:19 msgid "" "C strings are accessed and manipulated using `unsafe` pointer operations " "while interactions with Rust strings go through safe methods" msgstr "" #: src/idioms/ffi/accepting-strings.md:22 msgid "" "The Rust standard library comes with C equivalents of Rust's `String` and " "`&str` called `CString` and `&CStr`, that allow us to avoid a lot of the " "complexity and `unsafe` code involved in converting between C strings and " "Rust strings." msgstr "" #: src/idioms/ffi/accepting-strings.md:26 msgid "" "The `&CStr` type also allows us to work with borrowed data, meaning passing " "strings between Rust and C is a zero-cost operation." msgstr "" #: src/idioms/ffi/accepting-strings.md:34 #: src/idioms/ffi/accepting-strings.md:77 src/idioms/ffi/passing-strings.md:31 #: src/idioms/ffi/passing-strings.md:80 src/patterns/ffi/wrappers.md:114 msgid "// other module content\n" msgstr "" #: src/idioms/ffi/accepting-strings.md:36 msgid "" "/// 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" msgstr "" #: src/idioms/ffi/accepting-strings.md:50 msgid "" "// SAFETY: The caller has already guaranteed this is okay (see the\n" " // `# Safety` section of the doc-comment).\n" msgstr "" #: src/idioms/ffi/accepting-strings.md:55 #: src/idioms/ffi/accepting-strings.md:105 msgid "\"FFI string conversion failed\"" msgstr "" #: src/idioms/ffi/accepting-strings.md:67 msgid "The example is written to ensure that:" msgstr "" #: src/idioms/ffi/accepting-strings.md:69 src/idioms/ffi/passing-strings.md:70 msgid "The `unsafe` block is as small as possible." msgstr "" #: src/idioms/ffi/accepting-strings.md:70 msgid "" "The pointer with an \"untracked\" lifetime becomes a \"tracked\" shared " "reference" msgstr "" #: src/idioms/ffi/accepting-strings.md:72 msgid "Consider an alternative, where the string is actually copied:" msgstr "" #: src/idioms/ffi/accepting-strings.md:80 msgid "" "// DO NOT USE THIS CODE.\n" " // IT IS UGLY, VERBOSE, AND CONTAINS A SUBTLE BUG.\n" msgstr "" #: src/idioms/ffi/accepting-strings.md:85 msgid "/* SAFETY: strlen is what it is, I guess? */" msgstr "" #: src/idioms/ffi/accepting-strings.md:92 msgid "" "// SAFETY: copying from a foreign pointer expected to live\n" " // for the entire stack frame into owned memory\n" msgstr "" #: src/idioms/ffi/accepting-strings.md:116 msgid "This code is inferior to the original in two respects:" msgstr "" #: src/idioms/ffi/accepting-strings.md:118 msgid "" "There is much more `unsafe` code, and more importantly, more invariants it " "must uphold." msgstr "" #: src/idioms/ffi/accepting-strings.md:120 msgid "" "Due to the extensive arithmetic required, there is a bug in this version " "that cases Rust `undefined behaviour`." msgstr "" #: src/idioms/ffi/accepting-strings.md:123 msgid "" "The bug here is a simple mistake in pointer arithmetic: the string was " "copied, all `msg_len` bytes of it. However, the `NUL` terminator at the end " "was not." msgstr "" #: src/idioms/ffi/accepting-strings.md:126 msgid "" "The Vector then had its size _set_ to the length of the _zero padded string_ " "-- rather than _resized_ to it, which could have added a zero at the end. As " "a result, the last byte in the Vector is uninitialized memory. When the " "`CString` is created at the bottom of the block, its read of the Vector will " "cause `undefined behaviour`!" msgstr "" #: src/idioms/ffi/accepting-strings.md:132 msgid "" "Like many such issues, this would be difficult issue to track down. " "Sometimes it would panic because the string was not `UTF-8`, sometimes it " "would put a weird character at the end of the string, sometimes it would " "just completely crash." msgstr "" #: src/idioms/ffi/accepting-strings.md:138 #: src/idioms/ffi/passing-strings.md:103 msgid "None?" msgstr "" #: src/idioms/ffi/passing-strings.md:5 msgid "" "When passing strings to FFI functions, there are four principles that should " "be followed:" msgstr "" #: src/idioms/ffi/passing-strings.md:8 msgid "Make the lifetime of owned strings as long as possible." msgstr "" #: src/idioms/ffi/passing-strings.md:9 msgid "Minimize `unsafe` code during the conversion." msgstr "" #: src/idioms/ffi/passing-strings.md:10 msgid "If the C code can modify the string data, use `Vec` instead of `CString`." msgstr "" #: src/idioms/ffi/passing-strings.md:11 msgid "" "Unless the Foreign Function API requires it, the ownership of the string " "should not transfer to the callee." msgstr "" #: src/idioms/ffi/passing-strings.md:16 msgid "" "Rust has built-in support for C-style strings with its `CString` and `CStr` " "types. However, there are different approaches one can take with strings " "that are being sent to a foreign function call from a Rust function." msgstr "" #: src/idioms/ffi/passing-strings.md:20 msgid "" "The best practice is simple: use `CString` in such a way as to minimize " "`unsafe` code. However, a secondary caveat is that _the object must live " "long enough_, meaning the lifetime should be maximized. In addition, the " "documentation explains that \"round-tripping\" a `CString` after " "modification is UB, so additional work is necessary in that case." msgstr "" #: src/idioms/ffi/passing-strings.md:42 msgid "" "// SAFETY: calling an FFI whose documentation says the pointer is\n" " // const, so no modification should occur\n" msgstr "" #: src/idioms/ffi/passing-strings.md:48 msgid "// The lifetime of c_err continues until here\n" msgstr "" #: src/idioms/ffi/passing-strings.md:54 msgid "" "// SAFETY: calling an FFI whose documentation implies\n" " // that the input need only live as long as the call\n" msgstr "" #: src/idioms/ffi/passing-strings.md:68 msgid "The example is written in a way to ensure that:" msgstr "" #: src/idioms/ffi/passing-strings.md:71 msgid "The `CString` lives long enough." msgstr "" #: src/idioms/ffi/passing-strings.md:72 msgid "Errors with typecasts are always propagated when possible." msgstr "" #: src/idioms/ffi/passing-strings.md:74 msgid "" "A common mistake (so common it's in the documentation) is to not use the " "variable in the first block:" msgstr "" #: src/idioms/ffi/passing-strings.md:84 msgid "// SAFETY: whoops, this contains a dangling pointer!\n" msgstr "" #: src/idioms/ffi/passing-strings.md:92 msgid "" "This code will result in a dangling pointer, because the lifetime of the " "`CString` is not extended by the pointer creation, unlike if a reference " "were created." msgstr "" #: src/idioms/ffi/passing-strings.md:96 msgid "" "Another issue frequently raised is that the initialization of a 1k vector of " "zeroes is \"slow\". However, recent versions of Rust actually optimize that " "particular macro to a call to `zmalloc`, meaning it is as fast as the " "operating system's ability to return zeroed memory (which is quite fast)." msgstr "" #: src/idioms/option-iter.md:1 msgid "Iterating over an `Option`" msgstr "" #: src/idioms/option-iter.md:5 msgid "" "`Option` can be viewed as a container that contains either zero or one " "element. In particular, it implements the `IntoIterator` trait, and as such " "can be used with generic code that needs such a type." msgstr "" #: src/idioms/option-iter.md:9 src/patterns/structural/small-crates.md:34 #: src/patterns/structural/unsafe-mods.md:23 msgid "Examples" msgstr "" #: src/idioms/option-iter.md:11 msgid "" "Since `Option` implements `IntoIterator`, it can be used as an argument to " "[`.extend()`](https://doc.rust-lang.org/std/iter/trait.Extend.html#tymethod.extend):" msgstr "" #: src/idioms/option-iter.md:15 src/idioms/option-iter.md:31 msgid "\"Turing\"" msgstr "" #: src/idioms/option-iter.md:16 src/idioms/option-iter.md:32 msgid "\"Curry\"" msgstr "" #: src/idioms/option-iter.md:16 src/idioms/option-iter.md:32 msgid "\"Kleene\"" msgstr "" #: src/idioms/option-iter.md:16 src/idioms/option-iter.md:32 msgid "\"Markov\"" msgstr "" #: src/idioms/option-iter.md:19 msgid "// equivalent to\n" msgstr "" #: src/idioms/option-iter.md:26 msgid "" "If you need to tack an `Option` to the end of an existing iterator, you can " "pass it to " "[`.chain()`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.chain):" msgstr "" #: src/idioms/option-iter.md:35 msgid "\"{logician} is a logician\"" msgstr "" #: src/idioms/option-iter.md:39 msgid "" "Note that if the `Option` is always `Some`, then it is more idiomatic to use " "[`std::iter::once`](https://doc.rust-lang.org/std/iter/fn.once.html) on the " "element instead." msgstr "" #: src/idioms/option-iter.md:43 msgid "" "Also, since `Option` implements `IntoIterator`, it's possible to iterate " "over it using a `for` loop. This is equivalent to matching it with `if let " "Some(..)`, and in most cases you should prefer the latter." msgstr "" #: src/idioms/option-iter.md:49 msgid "" "[`std::iter::once`](https://doc.rust-lang.org/std/iter/fn.once.html) is an " "iterator which yields exactly one element. It's a more readable alternative " "to `Some(foo).into_iter()`." msgstr "" #: src/idioms/option-iter.md:53 msgid "" "[`Iterator::filter_map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter_map) " "is a version of " "[`Iterator::map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map), " "specialized to mapping functions which return `Option`." msgstr "" #: src/idioms/option-iter.md:58 msgid "" "The [`ref_slice`](https://crates.io/crates/ref_slice) crate provides " "functions for converting an `Option` to a zero- or one-element slice." msgstr "" #: src/idioms/option-iter.md:61 msgid "" "[Documentation for " "`Option`](https://doc.rust-lang.org/std/option/enum.Option.html)" msgstr "" #: src/idioms/pass-var-to-closure.md:1 msgid "Pass variables to closure" msgstr "" #: src/idioms/pass-var-to-closure.md:5 msgid "" "By default, closures capture their environment by borrowing. Or you can use " "a `move`\\-closure to move the whole environment. However, often you want to " "move just some variables to the closure, give it a copy of some data, pass " "by reference, or perform some other transformation." msgstr "" #: src/idioms/pass-var-to-closure.md:10 msgid "Use variable rebinding in a separate scope for that." msgstr "" #: src/idioms/pass-var-to-closure.md:14 msgid "Use" msgstr "" #: src/idioms/pass-var-to-closure.md:23 msgid "// `num1` is moved\n" msgstr "" #: src/idioms/pass-var-to-closure.md:24 msgid "// `num2` is cloned\n" msgstr "" #: src/idioms/pass-var-to-closure.md:25 msgid "// `num3` is borrowed\n" msgstr "" #: src/idioms/pass-var-to-closure.md:32 msgid "instead of" msgstr "" #: src/idioms/pass-var-to-closure.md:50 msgid "" "Copied data are grouped together with the closure definition, so their " "purpose is more clear, and they will be dropped immediately even if they are " "not consumed by the closure." msgstr "" #: src/idioms/pass-var-to-closure.md:54 msgid "" "The closure uses the same variable names as the surrounding code, whether " "data are copied or moved." msgstr "" #: src/idioms/pass-var-to-closure.md:59 msgid "Additional indentation of the closure body." msgstr "" #: src/idioms/priv-extend.md:1 msgid "`#[non_exhaustive]` and private fields for extensibility" msgstr "" #: src/idioms/priv-extend.md:5 msgid "" "A small set of scenarios exist where a library author may want to add public " "fields to a public struct or new variants to an enum without breaking " "backwards compatibility." msgstr "" #: src/idioms/priv-extend.md:9 msgid "Rust offers two solutions to this problem:" msgstr "" #: src/idioms/priv-extend.md:11 msgid "" "Use `#[non_exhaustive]` on `struct`s, `enum`s, and `enum` variants. For " "extensive documentation on all the places where `#[non_exhaustive]` can be " "used, see [the " "docs](https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute)." msgstr "" #: src/idioms/priv-extend.md:16 msgid "" "You may add a private field to a struct to prevent it from being directly " "instantiated or matched against (see Alternative)" msgstr "" #: src/idioms/priv-extend.md:23 msgid "// Public struct.\n" msgstr "" #: src/idioms/priv-extend.md:41 msgid "" "// Because S is `#[non_exhaustive]`, it cannot be named here and\n" " // we must use `..` in the pattern.\n" msgstr "" #: src/idioms/priv-extend.md:47 msgid "\"it's an A\"" msgstr "" #: src/idioms/priv-extend.md:48 msgid "\"it's a b\"" msgstr "" #: src/idioms/priv-extend.md:50 msgid "// .. required because this variant is non-exhaustive as well\n" msgstr "" #: src/idioms/priv-extend.md:51 msgid "\"it's a c\"" msgstr "" #: src/idioms/priv-extend.md:53 msgid "" "// The wildcard match is required because more variants may be\n" " // added in the future\n" msgstr "" #: src/idioms/priv-extend.md:55 msgid "\"it's a new variant\"" msgstr "" #: src/idioms/priv-extend.md:60 msgid "Alternative: `Private fields` for structs" msgstr "" #: src/idioms/priv-extend.md:62 msgid "" "`#[non_exhaustive]` only works across crate boundaries. Within a crate, the " "private field method may be used." msgstr "" #: src/idioms/priv-extend.md:65 msgid "" "Adding a field to a struct is a mostly backwards compatible change. However, " "if a client uses a pattern to deconstruct a struct instance, they might name " "all the fields in the struct and adding a new one would break that pattern. " "The client could name some fields and use `..` in the pattern, in which case " "adding another field is backwards compatible. Making at least one of the " "struct's fields private forces clients to use the latter form of patterns, " "ensuring that the struct is future-proof." msgstr "" #: src/idioms/priv-extend.md:73 msgid "" "The downside of this approach is that you might need to add an otherwise " "unneeded field to the struct. You can use the `()` type so that there is no " "runtime overhead and prepend `_` to the field name to avoid the unused field " "warning." msgstr "" #: src/idioms/priv-extend.md:81 msgid "" "// Because `b` is private, you cannot match on `S` without using `..` and " "`S`\n" " // cannot be directly instantiated or matched against\n" msgstr "" #: src/idioms/priv-extend.md:89 msgid "" "On `struct`s, `#[non_exhaustive]` allows adding additional fields in a " "backwards compatible way. It will also prevent clients from using the struct " "constructor, even if all the fields are public. This may be helpful, but " "it's worth considering if you _want_ an additional field to be found by " "clients as a compiler error rather than something that may be silently " "undiscovered." msgstr "" #: src/idioms/priv-extend.md:95 msgid "" "`#[non_exhaustive]` can be applied to enum variants as well. A " "`#[non_exhaustive]` variant behaves in the same way as a `#[non_exhaustive]` " "struct." msgstr "" #: src/idioms/priv-extend.md:99 msgid "" "Use this deliberately and with caution: incrementing the major version when " "adding fields or variants is often a better option. `#[non_exhaustive]` may " "be appropriate in scenarios where you're modeling an external resource that " "may change out-of-sync with your library, but is not a general purpose tool." msgstr "" #: src/idioms/priv-extend.md:106 msgid "" "`#[non_exhaustive]` can make your code much less ergonomic to use, " "especially when forced to handle unknown enum variants. It should only be " "used when these sorts of evolutions are required **without** incrementing " "the major version." msgstr "" #: src/idioms/priv-extend.md:110 msgid "" "When `#[non_exhaustive]` is applied to `enum`s, it forces clients to handle " "a wildcard variant. If there is no sensible action to take in this case, " "this may lead to awkward code and code paths that are only executed in " "extremely rare circumstances. If a client decides to `panic!()` in this " "scenario, it may have been better to expose this error at compile time. In " "fact, `#[non_exhaustive]` forces clients to handle the \"Something else\" " "case; there is rarely a sensible action to take in this scenario." msgstr "" #: src/idioms/priv-extend.md:120 msgid "" "[RFC introducing #\\[non_exhaustive\\] attribute for enums and " "structs](https://github.com/rust-lang/rfcs/blob/master/text/2008-non-exhaustive.md)" msgstr "" #: src/idioms/rustdoc-init.md:5 msgid "" "If a struct takes significant effort to initialize when writing docs, it can " "be quicker to wrap your example with a helper function which takes the " "struct as an argument." msgstr "" #: src/idioms/rustdoc-init.md:11 msgid "" "Sometimes there is a struct with multiple or complicated parameters and " "several methods. Each of these methods should have examples." msgstr "" #: src/idioms/rustdoc-init.md:14 msgid "For example:" msgstr "" #: src/idioms/rustdoc-init.md:23 msgid "" "/// Sends a request over the connection.\n" " ///\n" " /// # Example\n" " /// ```no_run\n" " /// # // Boilerplate are required to get an example working.\n" " /// # let stream = TcpStream::connect(\"127.0.0.1:34254\");\n" " /// # let connection = Connection { name: \"foo\".to_owned(), stream };\n" " /// # let request = Request::new(\"RequestId\", RequestType::Get, " "\"payload\");\n" " /// let response = connection.send_request(request);\n" " /// assert!(response.is_ok());\n" " /// ```\n" msgstr "" #: src/idioms/rustdoc-init.md:35 src/idioms/rustdoc-init.md:40 #: src/idioms/rustdoc-init.md:68 msgid "// ...\n" msgstr "" #: src/idioms/rustdoc-init.md:38 msgid "/// Oh no, all that boilerplate needs to be repeated here!\n" msgstr "" #: src/idioms/rustdoc-init.md:47 msgid "" "Instead of typing all of this boilerplate to create a `Connection` and " "`Request`, it is easier to just create a wrapping helper function which " "takes them as arguments:" msgstr "" #: src/idioms/rustdoc-init.md:58 msgid "" "/// Sends a request over the connection.\n" " ///\n" " /// # Example\n" " /// ```\n" " /// # fn call_send(connection: Connection, request: Request) {\n" " /// let response = connection.send_request(request);\n" " /// assert!(response.is_ok());\n" " /// # }\n" " /// ```\n" msgstr "" #: src/idioms/rustdoc-init.md:73 msgid "" "**Note** in the above example the line `assert!(response.is_ok());` will not " "actually run while testing because it is inside a function which is never " "invoked." msgstr "" #: src/idioms/rustdoc-init.md:79 msgid "This is much more concise and avoids repetitive code in examples." msgstr "" #: src/idioms/rustdoc-init.md:83 msgid "" "As example is in a function, the code will not be tested. Though it will " "still be checked to make sure it compiles when running a `cargo test`. So " "this pattern is most useful when you need `no_run`. With this, you do not " "need to add `no_run`." msgstr "" #: src/idioms/rustdoc-init.md:90 msgid "If assertions are not required this pattern works well." msgstr "" #: src/idioms/rustdoc-init.md:92 msgid "" "If they are, an alternative can be to create a public method to create a " "helper instance which is annotated with `#[doc(hidden)]` (so that users " "won't see it). Then this method can be called inside of rustdoc because it " "is part of the crate's public API." msgstr "" #: src/idioms/temporary-mutability.md:5 msgid "" "Often it is necessary to prepare and process some data, but after that data " "are only inspected and never modified. The intention can be made explicit by " "redefining the mutable variable as immutable." msgstr "" #: src/idioms/temporary-mutability.md:9 msgid "" "It can be done either by processing data within a nested block or by " "redefining the variable." msgstr "" #: src/idioms/temporary-mutability.md:14 msgid "Say, vector must be sorted before usage." msgstr "" #: src/idioms/temporary-mutability.md:16 msgid "Using nested block:" msgstr "" #: src/idioms/temporary-mutability.md:24 src/idioms/temporary-mutability.md:34 msgid "// Here `data` is immutable.\n" msgstr "" #: src/idioms/temporary-mutability.md:28 msgid "Using variable rebinding:" msgstr "" #: src/idioms/temporary-mutability.md:40 msgid "" "Compiler ensures that you don't accidentally mutate data after some point." msgstr "" #: src/idioms/temporary-mutability.md:44 msgid "" "Nested block requires additional indentation of block body. One more line to " "return data from block or redefine variable." msgstr "" #: src/idioms/return-consumed-arg-on-error.md:1 msgid "Return consumed argument on error" msgstr "" #: src/idioms/return-consumed-arg-on-error.md:5 msgid "" "If a fallible function consumes (moves) an argument, return that argument " "back inside an error." msgstr "" #: src/idioms/return-consumed-arg-on-error.md:12 msgid "\"using {value} in a meaningful way\"" msgstr "" #: src/idioms/return-consumed-arg-on-error.md:13 msgid "// Simulate non-deterministic fallible action.\n" msgstr "" #: src/idioms/return-consumed-arg-on-error.md:28 msgid "\"imagine this is very long string\"" msgstr "" #: src/idioms/return-consumed-arg-on-error.md:31 msgid "// Try to send value two times.\n" msgstr "" #: src/idioms/return-consumed-arg-on-error.md:41 msgid "\"success: {success}\"" msgstr "" #: src/idioms/return-consumed-arg-on-error.md:47 msgid "" "In case of error you may want to try some alternative way or to retry action " "in case of non-deterministic function. But if the argument is always " "consumed, you are forced to clone it on every call, which is not very " "efficient." msgstr "" #: src/idioms/return-consumed-arg-on-error.md:51 msgid "" "The standard library uses this approach in e.g. `String::from_utf8` method. " "When given a vector that doesn't contain valid UTF-8, a `FromUtf8Error` is " "returned. You can get original vector back using `FromUtf8Error::into_bytes` " "method." msgstr "" #: src/idioms/return-consumed-arg-on-error.md:57 msgid "Better performance because of moving arguments whenever possible." msgstr "" #: src/idioms/return-consumed-arg-on-error.md:61 msgid "Slightly more complex error types." msgstr "" #: src/patterns/index.md:3 msgid "" "[Design patterns](https://en.wikipedia.org/wiki/Software_design_pattern) are " "\"general reusable solutions to a commonly occurring problem within a given " "context in software design\". Design patterns are a great way to describe " "the culture of a programming language. Design patterns are very " "language-specific - what is a pattern in one language may be unnecessary in " "another due to a language feature, or impossible to express due to a missing " "feature." msgstr "" #: src/patterns/index.md:10 msgid "" "If overused, design patterns can add unnecessary complexity to programs. " "However, they are a great way to share intermediate and advanced level " "knowledge about a programming language." msgstr "" #: src/patterns/index.md:16 msgid "" "Rust has many unique features. These features give us great benefit by " "removing whole classes of problems. Some of them are also patterns that are " "_unique_ to Rust." msgstr "" #: src/patterns/index.md:20 msgid "YAGNI" msgstr "" #: src/patterns/index.md:22 msgid "" "YAGNI is an acronym that stands for `You Aren't Going to Need It`. It's a " "vital software design principle to apply as you write code." msgstr "" #: src/patterns/index.md:25 msgid "The best code I ever wrote was code I never wrote." msgstr "" #: src/patterns/index.md:27 msgid "" "If we apply YAGNI to design patterns, we see that the features of Rust allow " "us to throw out many patterns. For instance, there is no need for the " "[strategy pattern](https://en.wikipedia.org/wiki/Strategy_pattern) in Rust " "because we can just use [traits](https://doc.rust-lang.org/book/traits.html)." msgstr "" #: src/patterns/behavioural/intro.md:1 msgid "Behavioural Patterns" msgstr "" #: src/patterns/behavioural/intro.md:3 msgid "From [Wikipedia](https://en.wikipedia.org/wiki/Behavioral_pattern):" msgstr "" #: src/patterns/behavioural/intro.md:5 msgid "" "Design patterns that identify common communication patterns among objects. " "By doing so, these patterns increase flexibility in carrying out " "communication." msgstr "" #: src/patterns/behavioural/command.md:5 msgid "" "The basic idea of the Command pattern is to separate out actions into its " "own objects and pass them as parameters." msgstr "" #: src/patterns/behavioural/command.md:10 msgid "" "Suppose we have a sequence of actions or transactions encapsulated as " "objects. We want these actions or commands to be executed or invoked in some " "order later at different time. These commands may also be triggered as a " "result of some event. For example, when a user pushes a button, or on " "arrival of a data packet. In addition, these commands might be undoable. " "This may come in useful for operations of an editor. We might want to store " "logs of executed commands so that we could reapply the changes later if the " "system crashes." msgstr "" #: src/patterns/behavioural/command.md:20 msgid "" "Define two database operations `create table` and `add field`. Each of these " "operations is a command which knows how to undo the command, e.g., `drop " "table` and `remove field`. When a user invokes a database migration " "operation then each command is executed in the defined order, and when the " "user invokes the rollback operation then the whole set of commands is " "invoked in reverse order." msgstr "" #: src/patterns/behavioural/command.md:26 msgid "Approach: Using trait objects" msgstr "" #: src/patterns/behavioural/command.md:28 msgid "" "We define a common trait which encapsulates our command with two operations " "`execute` and `rollback`. All command `structs` must implement this trait." msgstr "" #: src/patterns/behavioural/command.md:40 #: src/patterns/behavioural/command.md:90 #: src/patterns/behavioural/command.md:143 #: src/patterns/behavioural/command.md:145 #: src/patterns/behavioural/command.md:196 #: src/patterns/behavioural/command.md:198 msgid "\"create table\"" msgstr "" #: src/patterns/behavioural/command.md:43 #: src/patterns/behavioural/command.md:91 #: src/patterns/behavioural/command.md:143 #: src/patterns/behavioural/command.md:146 #: src/patterns/behavioural/command.md:196 #: src/patterns/behavioural/command.md:199 msgid "\"drop table\"" msgstr "" #: src/patterns/behavioural/command.md:50 #: src/patterns/behavioural/command.md:90 #: src/patterns/behavioural/command.md:134 #: src/patterns/behavioural/command.md:145 #: src/patterns/behavioural/command.md:187 #: src/patterns/behavioural/command.md:198 msgid "\"add field\"" msgstr "" #: src/patterns/behavioural/command.md:53 #: src/patterns/behavioural/command.md:91 #: src/patterns/behavioural/command.md:138 #: src/patterns/behavioural/command.md:146 #: src/patterns/behavioural/command.md:191 #: src/patterns/behavioural/command.md:199 msgid "\"remove field\"" msgstr "" #: src/patterns/behavioural/command.md:76 msgid "// reverse iterator's direction\n" msgstr "" #: src/patterns/behavioural/command.md:95 msgid "Approach: Using function pointers" msgstr "" #: src/patterns/behavioural/command.md:97 msgid "" "We could follow another approach by creating each individual command as a " "different function and store function pointers to invoke these functions " "later at a different time. Since function pointers implement all three " "traits `Fn`, `FnMut`, and `FnOnce` we could as well pass and store closures " "instead of function pointers." msgstr "" #: src/patterns/behavioural/command.md:150 msgid "Approach: Using `Fn` trait objects" msgstr "" #: src/patterns/behavioural/command.md:152 msgid "" "Finally, instead of defining a common command trait we could store each " "command implementing the `Fn` trait separately in vectors." msgstr "" #: src/patterns/behavioural/command.md:205 msgid "" "If our commands are small and may be defined as functions or passed as a " "closure then using function pointers might be preferable since it does not " "exploit dynamic dispatch. But if our command is a whole struct with a bunch " "of functions and variables defined as separated module then using trait " "objects would be more suitable. A case of application can be found in " "[`actix`](https://actix.rs/), which uses trait objects when it registers a " "handler function for routes. In case of using `Fn` trait objects we can " "create and use commands in the same way as we used in case of function " "pointers." msgstr "" #: src/patterns/behavioural/command.md:214 msgid "" "As performance, there is always a trade-off between performance and code " "simplicity and organisation. Static dispatch gives faster performance, while " "dynamic dispatch provides flexibility when we structure our application." msgstr "" #: src/patterns/behavioural/command.md:220 msgid "[Command pattern](https://en.wikipedia.org/wiki/Command_pattern)" msgstr "" #: src/patterns/behavioural/command.md:222 msgid "" "[Another example for the `command` " "pattern](https://web.archive.org/web/20210223131236/https://chercher.tech/rust/command-design-pattern-rust)" msgstr "" #: src/patterns/behavioural/interpreter.md:5 msgid "" "If a problem occurs very often and requires long and repetitive steps to " "solve it, then the problem instances might be expressed in a simple language " "and an interpreter object could solve it by interpreting the sentences " "written in this simple language." msgstr "" #: src/patterns/behavioural/interpreter.md:10 msgid "Basically, for any kind of problems we define:" msgstr "" #: src/patterns/behavioural/interpreter.md:12 msgid "" "A [domain specific " "language](https://en.wikipedia.org/wiki/Domain-specific_language)," msgstr "" #: src/patterns/behavioural/interpreter.md:14 msgid "A grammar for this language," msgstr "" #: src/patterns/behavioural/interpreter.md:15 msgid "An interpreter that solves the problem instances." msgstr "" #: src/patterns/behavioural/interpreter.md:19 msgid "" "Our goal is to translate simple mathematical expressions into postfix " "expressions (or [Reverse Polish " "notation](https://en.wikipedia.org/wiki/Reverse_Polish_notation)) For " "simplicity, our expressions consist of ten digits `0`, ..., `9` and two " "operations `+`, `-`. For example, the expression `2 + 4` is translated into " "`2 4 +`." msgstr "" #: src/patterns/behavioural/interpreter.md:26 msgid "Context Free Grammar for our problem" msgstr "" #: src/patterns/behavioural/interpreter.md:28 msgid "" "Our task is translating infix expressions into postfix ones. Let's define a " "context free grammar for a set of infix expressions over `0`, ..., `9`, `+`, " "and `-`, where:" msgstr "" #: src/patterns/behavioural/interpreter.md:32 msgid "Terminal symbols: `0`, `...`, `9`, `+`, `-`" msgstr "" #: src/patterns/behavioural/interpreter.md:33 msgid "Non-terminal symbols: `exp`, `term`" msgstr "" #: src/patterns/behavioural/interpreter.md:34 msgid "Start symbol is `exp`" msgstr "" #: src/patterns/behavioural/interpreter.md:35 msgid "And the following are production rules" msgstr "" #: src/patterns/behavioural/interpreter.md:44 msgid "" "**NOTE:** This grammar should be further transformed depending on what we " "are going to do with it. For example, we might need to remove left " "recursion. For more details please see [Compilers: Principles,Techniques, " "and " "Tools](https://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools) " "(aka Dragon Book)." msgstr "" #: src/patterns/behavioural/interpreter.md:50 msgid "Solution" msgstr "" #: src/patterns/behavioural/interpreter.md:52 msgid "" "We simply implement a recursive descent parser. For simplicity's sake, the " "code panics when an expression is syntactically wrong (for example `2-34` or " "`2+5-` are wrong according to the grammar definition)." msgstr "" #: src/patterns/behavioural/interpreter.md:74 msgid "'+'" msgstr "" #: src/patterns/behavioural/interpreter.md:74 msgid "'-'" msgstr "" #: src/patterns/behavioural/interpreter.md:78 msgid "\"Unexpected symbol '{op}'\"" msgstr "" #: src/patterns/behavioural/interpreter.md:86 msgid "\"Unexpected symbol '{ch}'\"" msgstr "" #: src/patterns/behavioural/interpreter.md:87 msgid "\"Unexpected end of string\"" msgstr "" #: src/patterns/behavioural/interpreter.md:93 msgid "\"2+3\"" msgstr "" #: src/patterns/behavioural/interpreter.md:96 msgid "\"23+\"" msgstr "" #: src/patterns/behavioural/interpreter.md:98 msgid "\"1-2+3-4\"" msgstr "" #: src/patterns/behavioural/interpreter.md:101 msgid "\"12-3+4-\"" msgstr "" #: src/patterns/behavioural/interpreter.md:107 msgid "" "There may be a wrong perception that the Interpreter design pattern is about " "design grammars for formal languages and implementation of parsers for these " "grammars. In fact, this pattern is about expressing problem instances in a " "more specific way and implementing functions/classes/structs that solve " "these problem instances. Rust language has `macro_rules!` that allow us to " "define special syntax and rules on how to expand this syntax into source " "code." msgstr "" #: src/patterns/behavioural/interpreter.md:114 msgid "" "In the following example we create a simple `macro_rules!` that computes " "[Euclidean length](https://en.wikipedia.org/wiki/Euclidean_distance) of `n` " "dimensional vectors. Writing `norm!(x,1,2)` might be easier to express and " "more efficient than packing `x,1,2` into a `Vec` and calling a function " "computing the length." msgstr "" #: src/patterns/behavioural/interpreter.md:146 msgid "[Interpreter pattern](https://en.wikipedia.org/wiki/Interpreter_pattern)" msgstr "" #: src/patterns/behavioural/interpreter.md:147 msgid "" "[Context free grammar](https://en.wikipedia.org/wiki/Context-free_grammar)" msgstr "" #: src/patterns/behavioural/interpreter.md:148 msgid "[macro_rules!](https://doc.rust-lang.org/rust-by-example/macros.html)" msgstr "" #: src/patterns/behavioural/newtype.md:3 msgid "" "What if in some cases we want a type to behave similar to another type or " "enforce some behaviour at compile time when using only type aliases would " "not be enough?" msgstr "" #: src/patterns/behavioural/newtype.md:7 msgid "" "For example, if we want to create a custom `Display` implementation for " "`String` due to security considerations (e.g. passwords)." msgstr "" #: src/patterns/behavioural/newtype.md:10 msgid "" "For such cases we could use the `Newtype` pattern to provide **type safety** " "and **encapsulation**." msgstr "" #: src/patterns/behavioural/newtype.md:15 msgid "" "Use a tuple struct with a single field to make an opaque wrapper for a type. " "This creates a new type, rather than an alias to a type (`type` items)." msgstr "" #: src/patterns/behavioural/newtype.md:22 msgid "// Create Newtype Password to override the Display trait for String\n" msgstr "" #: src/patterns/behavioural/newtype.md:28 msgid "\"****************\"" msgstr "" #: src/patterns/behavioural/newtype.md:33 msgid "\"ThisIsMyPassword\"" msgstr "" #: src/patterns/behavioural/newtype.md:35 msgid "\"unsecured_password: {unsecured_password}\"" msgstr "" #: src/patterns/behavioural/newtype.md:36 msgid "\"secured_password: {secured_password}\"" msgstr "" #: src/patterns/behavioural/newtype.md:47 msgid "" "The primary motivation for newtypes is abstraction. It allows you to share " "implementation details between types while precisely controlling the " "interface. By using a newtype rather than exposing the implementation type " "as part of an API, it allows you to change implementation backwards " "compatibly." msgstr "" #: src/patterns/behavioural/newtype.md:52 msgid "" "Newtypes can be used for distinguishing units, e.g., wrapping `f64` to give " "distinguishable `Miles` and `Kilometres`." msgstr "" #: src/patterns/behavioural/newtype.md:57 msgid "" "The wrapped and wrapper types are not type compatible (as opposed to using " "`type`), so users of the newtype will never 'confuse' the wrapped and " "wrapper types." msgstr "" #: src/patterns/behavioural/newtype.md:61 msgid "Newtypes are a zero-cost abstraction - there is no runtime overhead." msgstr "" #: src/patterns/behavioural/newtype.md:63 msgid "" "The privacy system ensures that users cannot access the wrapped type (if the " "field is private, which it is by default)." msgstr "" #: src/patterns/behavioural/newtype.md:68 msgid "" "The downside of newtypes (especially compared with type aliases), is that " "there is no special language support. This means there can be _a lot_ of " "boilerplate. You need a 'pass through' method for every method you want to " "expose on the wrapped type, and an impl for every trait you want to also be " "implemented for the wrapper type." msgstr "" #: src/patterns/behavioural/newtype.md:76 msgid "" "Newtypes are very common in Rust code. Abstraction or representing units are " "the most common uses, but they can be used for other reasons:" msgstr "" #: src/patterns/behavioural/newtype.md:79 msgid "" "restricting functionality (reduce the functions exposed or traits " "implemented)," msgstr "" #: src/patterns/behavioural/newtype.md:81 msgid "making a type with copy semantics have move semantics," msgstr "" #: src/patterns/behavioural/newtype.md:82 msgid "" "abstraction by providing a more concrete type and thus hiding internal " "types, e.g.," msgstr "" #: src/patterns/behavioural/newtype.md:89 msgid "" "Here, `Bar` might be some public, generic type and `T1` and `T2` are some " "internal types. Users of our module shouldn't know that we implement `Foo` " "by using a `Bar`, but what we're really hiding here is the types `T1` and " "`T2`, and how they are used with `Bar`." msgstr "" #: src/patterns/behavioural/newtype.md:96 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)" msgstr "" #: src/patterns/behavioural/newtype.md:97 msgid "[Newtypes in Haskell](https://wiki.haskell.org/Newtype)" msgstr "" #: src/patterns/behavioural/newtype.md:98 msgid "" "[Type " "aliases](https://doc.rust-lang.org/stable/book/ch19-04-advanced-types.html#creating-type-synonyms-with-type-aliases)" msgstr "" #: src/patterns/behavioural/newtype.md:99 msgid "" "[derive_more](https://crates.io/crates/derive_more), a crate for deriving " "many builtin traits on newtypes." msgstr "" #: src/patterns/behavioural/newtype.md:101 msgid "" "[The Newtype Pattern In " "Rust](https://web.archive.org/web/20230519162111/https://www.worthe-it.co.za/blog/2020-10-31-newtype-pattern-in-rust.html)" msgstr "" #: src/patterns/behavioural/RAII.md:1 msgid "RAII with guards" msgstr "" #: src/patterns/behavioural/RAII.md:5 msgid "" "[RAII](https://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization) " "stands for \"Resource Acquisition is Initialisation\" which is a terrible " "name. The essence of the pattern is that resource initialisation is done in " "the constructor of an object and finalisation in the destructor. This " "pattern is extended in Rust by using a RAII object as a guard of some " "resource and relying on the type system to ensure that access is always " "mediated by the guard object." msgstr "" #: src/patterns/behavioural/RAII.md:14 msgid "" "Mutex guards are the classic example of this pattern from the std library " "(this is a simplified version of the real implementation):" msgstr "" #: src/patterns/behavioural/RAII.md:23 msgid "" "// We keep a reference to our data: T here.\n" " //..\n" msgstr "" #: src/patterns/behavioural/RAII.md:31 msgid "// Locking the mutex is explicit.\n" msgstr "" #: src/patterns/behavioural/RAII.md:35 msgid "" "// Lock the underlying OS mutex.\n" " //..\n" msgstr "" #: src/patterns/behavioural/RAII.md:38 msgid "// MutexGuard keeps a reference to self\n" msgstr "" #: src/patterns/behavioural/RAII.md:45 msgid "// Destructor for unlocking the mutex.\n" msgstr "" #: src/patterns/behavioural/RAII.md:49 msgid "" "// Unlock the underlying OS mutex.\n" " //..\n" msgstr "" #: src/patterns/behavioural/RAII.md:53 msgid "" "// Implementing Deref means we can treat MutexGuard like a pointer to T.\n" msgstr "" #: src/patterns/behavioural/RAII.md:65 msgid "" "// 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" msgstr "" #: src/patterns/behavioural/RAII.md:69 msgid "" "// x is unlocked when we exit this function and xx's destructor is " "executed.\n" msgstr "" #: src/patterns/behavioural/RAII.md:75 msgid "" "Where a resource must be finalised after use, RAII can be used to do this " "finalisation. If it is an error to access that resource after finalisation, " "then this pattern can be used to prevent such errors." msgstr "" #: src/patterns/behavioural/RAII.md:81 msgid "" "Prevents errors where a resource is not finalised and where a resource is " "used after finalisation." msgstr "" #: src/patterns/behavioural/RAII.md:86 msgid "" "RAII is a useful pattern for ensuring resources are properly deallocated or " "finalised. We can make use of the borrow checker in Rust to statically " "prevent errors stemming from using resources after finalisation takes place." msgstr "" #: src/patterns/behavioural/RAII.md:90 msgid "" "The core aim of the borrow checker is to ensure that references to data do " "not outlive that data. The RAII guard pattern works because the guard object " "contains a reference to the underlying resource and only exposes such " "references. Rust ensures that the guard cannot outlive the underlying " "resource and that references to the resource mediated by the guard cannot " "outlive the guard. To see how this works it is helpful to examine the " "signature of `deref` without lifetime elision:" msgstr "" #: src/patterns/behavioural/RAII.md:104 msgid "" "The returned reference to the resource has the same lifetime as `self` " "(`'a`). The borrow checker therefore ensures that the lifetime of the " "reference to `T` is shorter than the lifetime of `self`." msgstr "" #: src/patterns/behavioural/RAII.md:108 msgid "" "Note that implementing `Deref` is not a core part of this pattern, it only " "makes using the guard object more ergonomic. Implementing a `get` method on " "the guard works just as well." msgstr "" #: src/patterns/behavioural/RAII.md:114 msgid "[Finalisation in destructors idiom](../../idioms/dtor-finally.md)" msgstr "" #: src/patterns/behavioural/RAII.md:116 msgid "" "RAII is a common pattern in C++: " "[cppreference.com](http://en.cppreference.com/w/cpp/language/raii), " "[wikipedia](https://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization)." msgstr "" #: src/patterns/behavioural/RAII.md:122 msgid "" "[Style guide " "entry](https://doc.rust-lang.org/1.0.0/style/ownership/raii.html) (currently " "just a placeholder)." msgstr "" #: src/patterns/behavioural/strategy.md:1 msgid "Strategy (aka Policy)" msgstr "" #: src/patterns/behavioural/strategy.md:5 msgid "" "The [Strategy design " "pattern](https://en.wikipedia.org/wiki/Strategy_pattern) is a technique that " "enables separation of concerns. It also allows to decouple software modules " "through [Dependency " "Inversion](https://en.wikipedia.org/wiki/Dependency_inversion_principle)." msgstr "" #: src/patterns/behavioural/strategy.md:10 msgid "" "The basic idea behind the Strategy pattern is that, given an algorithm " "solving a particular problem, we define only the skeleton of the algorithm " "at an abstract level, and we separate the specific algorithm’s " "implementation into different parts." msgstr "" #: src/patterns/behavioural/strategy.md:15 msgid "" "In this way, a client using the algorithm may choose a specific " "implementation, while the general algorithm workflow remains the same. In " "other words, the abstract specification of the class does not depend on the " "specific implementation of the derived class, but specific implementation " "must adhere to the abstract specification. This is why we call it " "\"Dependency Inversion\"." msgstr "" #: src/patterns/behavioural/strategy.md:23 msgid "" "Imagine we are working on a project that generates reports every month. We " "need the reports to be generated in different formats (strategies), e.g., in " "`JSON` or `Plain Text` formats. But things vary over time, and we don't know " "what kind of requirement we may get in the future. For example, we may need " "to generate our report in a completely new format, or just modify one of the " "existing formats." msgstr "" #: src/patterns/behavioural/strategy.md:32 msgid "" "In this example our invariants (or abstractions) are `Formatter` and " "`Report`, while `Text` and `Json` are our strategy structs. These strategies " "have to implement the `Formatter` trait." msgstr "" #: src/patterns/behavioural/strategy.md:48 msgid "" "// Write should be used but we kept it as String to ignore error handling\n" msgstr "" #: src/patterns/behavioural/strategy.md:50 msgid "// backend operations...\n" msgstr "" #: src/patterns/behavioural/strategy.md:52 msgid "\"one\"" msgstr "" #: src/patterns/behavioural/strategy.md:53 msgid "\"two\"" msgstr "" #: src/patterns/behavioural/strategy.md:54 msgid "// generate report\n" msgstr "" #: src/patterns/behavioural/strategy.md:63 msgid "\"{k} {v}\\n\"" msgstr "" #: src/patterns/behavioural/strategy.md:72 msgid "'['" msgstr "" #: src/patterns/behavioural/strategy.md:74 msgid "r#\"{{\"{}\":\"{}\"}}\"#" msgstr "" #: src/patterns/behavioural/strategy.md:76 msgid "','" msgstr "" #: src/patterns/behavioural/strategy.md:79 msgid "// remove extra , at the end\n" msgstr "" #: src/patterns/behavioural/strategy.md:81 msgid "']'" msgstr "" #: src/patterns/behavioural/strategy.md:86 msgid "\"\"" msgstr "" #: src/patterns/behavioural/strategy.md:88 msgid "\"one 1\"" msgstr "" #: src/patterns/behavioural/strategy.md:89 msgid "\"two 2\"" msgstr "" #: src/patterns/behavioural/strategy.md:91 msgid "// reuse the same buffer\n" msgstr "" #: src/patterns/behavioural/strategy.md:93 msgid "r#\"{\"one\":\"1\"}\"#" msgstr "" #: src/patterns/behavioural/strategy.md:94 msgid "r#\"{\"two\":\"2\"}\"#" msgstr "" #: src/patterns/behavioural/strategy.md:100 msgid "" "The main advantage is separation of concerns. For example, in this case " "`Report` does not know anything about specific implementations of `Json` and " "`Text`, whereas the output implementations does not care about how data is " "preprocessed, stored, and fetched. The only thing they have to know is a " "specific trait to implement and its method defining the concrete algorithm " "implementation processing the result, i.e., `Formatter` and `format(...)`." msgstr "" #: src/patterns/behavioural/strategy.md:109 msgid "" "For each strategy there must be implemented at least one module, so number " "of modules increases with number of strategies. If there are many strategies " "to choose from then users have to know how strategies differ from one " "another." msgstr "" #: src/patterns/behavioural/strategy.md:115 msgid "" "In the previous example all strategies are implemented in a single file. " "Ways of providing different strategies includes:" msgstr "" #: src/patterns/behavioural/strategy.md:118 msgid "" "All in one file (as shown in this example, similar to being separated as " "modules)" msgstr "" #: src/patterns/behavioural/strategy.md:120 msgid "" "Separated as modules, E.g. `formatter::json` module, `formatter::text` module" msgstr "" #: src/patterns/behavioural/strategy.md:121 msgid "Use compiler feature flags, E.g. `json` feature, `text` feature" msgstr "" #: src/patterns/behavioural/strategy.md:122 msgid "Separated as crates, E.g. `json` crate, `text` crate" msgstr "" #: src/patterns/behavioural/strategy.md:124 msgid "" "Serde crate is a good example of the `Strategy` pattern in action. Serde " "allows [full customization](https://serde.rs/custom-serialization.html) of " "the serialization behavior by manually implementing `Serialize` and " "`Deserialize` traits for our type. For example, we could easily swap " "`serde_json` with `serde_cbor` since they expose similar methods. Having " "this makes the helper crate `serde_transcode` much more useful and ergonomic." msgstr "" #: src/patterns/behavioural/strategy.md:131 msgid "" "However, we don't need to use traits in order to design this pattern in Rust." msgstr "" #: src/patterns/behavioural/strategy.md:133 msgid "" "The following toy example demonstrates the idea of the Strategy pattern " "using Rust `closures`:" msgstr "" #: src/patterns/behavioural/strategy.md:164 msgid "In fact, Rust already uses this idea for `Options`'s `map` method:" msgstr "" #: src/patterns/behavioural/strategy.md:168 msgid "\"Rust\"" msgstr "" #: src/patterns/behavioural/strategy.md:180 msgid "[Strategy Pattern](https://en.wikipedia.org/wiki/Strategy_pattern)" msgstr "" #: src/patterns/behavioural/strategy.md:181 msgid "" "[Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection)" msgstr "" #: src/patterns/behavioural/strategy.md:182 msgid "" "[Policy Based " "Design](https://en.wikipedia.org/wiki/Modern_C++_Design#Policy-based_design)" msgstr "" #: src/patterns/behavioural/strategy.md:183 msgid "" "[Implementing a TCP server for Space Applications in Rust using the Strategy " "Pattern](https://web.archive.org/web/20231003171500/https://robamu.github.io/posts/rust-strategy-pattern/)" msgstr "" #: src/patterns/behavioural/visitor.md:5 msgid "" "A visitor encapsulates an algorithm that operates over a heterogeneous " "collection of objects. It allows multiple different algorithms to be written " "over the same data without having to modify the data (or their primary " "behaviour)." msgstr "" #: src/patterns/behavioural/visitor.md:10 msgid "" "Furthermore, the visitor pattern allows separating the traversal of a " "collection of objects from the operations performed on each object." msgstr "" #: src/patterns/behavioural/visitor.md:16 msgid "// The data we will visit\n" msgstr "" #: src/patterns/behavioural/visitor.md:33 msgid "// The abstract visitor\n" msgstr "" #: src/patterns/behavioural/visitor.md:47 msgid "" "// An example concrete implementation - walks the AST interpreting it as " "code.\n" msgstr "" #: src/patterns/behavioural/visitor.md:71 msgid "" "One could implement further visitors, for example a type checker, without " "having to modify the AST data." msgstr "" #: src/patterns/behavioural/visitor.md:76 msgid "" "The visitor pattern is useful anywhere that you want to apply an algorithm " "to heterogeneous data. If data is homogeneous, you can use an iterator-like " "pattern. Using a visitor object (rather than a functional approach) allows " "the visitor to be stateful and thus communicate information between nodes." msgstr "" #: src/patterns/behavioural/visitor.md:83 msgid "" "It is common for the `visit_*` methods to return void (as opposed to in the " "example). In that case it is possible to factor out the traversal code and " "share it between algorithms (and also to provide noop default methods). In " "Rust, the common way to do this is to provide `walk_*` functions for each " "datum. For example," msgstr "" #: src/patterns/behavioural/visitor.md:105 msgid "" "In other languages (e.g., Java) it is common for data to have an `accept` " "method which performs the same duty." msgstr "" #: src/patterns/behavioural/visitor.md:110 msgid "The visitor pattern is a common pattern in most OO languages." msgstr "" #: src/patterns/behavioural/visitor.md:112 msgid "[Wikipedia article](https://en.wikipedia.org/wiki/Visitor_pattern)" msgstr "" #: src/patterns/behavioural/visitor.md:114 msgid "" "The [fold](../creational/fold.md) pattern is similar to visitor but produces " "a new version of the visited data structure." msgstr "" #: src/patterns/creational/intro.md:1 msgid "Creational Patterns" msgstr "" #: src/patterns/creational/intro.md:3 msgid "From [Wikipedia](https://en.wikipedia.org/wiki/Creational_pattern):" msgstr "" #: src/patterns/creational/intro.md:5 msgid "" "Design patterns that deal with object creation mechanisms, trying to create " "objects in a manner suitable to the situation. The basic form of object " "creation could result in design problems or in added complexity to the " "design. Creational design patterns solve this problem by somehow controlling " "this object creation." msgstr "" #: src/patterns/creational/builder.md:5 msgid "Construct an object with calls to a builder helper." msgstr "" #: src/patterns/creational/builder.md:12 msgid "// Lots of complicated fields.\n" msgstr "" #: src/patterns/creational/builder.md:17 msgid "// This method will help users to discover the builder\n" msgstr "" #: src/patterns/creational/builder.md:25 msgid "// Probably lots of optional fields.\n" msgstr "" #: src/patterns/creational/builder.md:31 msgid "// Set the minimally required fields of Foo.\n" msgstr "" #: src/patterns/creational/builder.md:33 msgid "\"X\"" msgstr "" #: src/patterns/creational/builder.md:38 msgid "// Set the name on the builder itself, and return the builder by value.\n" msgstr "" #: src/patterns/creational/builder.md:43 msgid "" "// 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" msgstr "" #: src/patterns/creational/builder.md:47 msgid "" "// Create a Foo from the FooBuilder, applying all settings in FooBuilder\n" " // to Foo.\n" msgstr "" #: src/patterns/creational/builder.md:56 src/patterns/creational/builder.md:58 msgid "\"Y\"" msgstr "" #: src/patterns/creational/builder.md:65 msgid "" "Useful when you would otherwise require many constructors or where " "construction has side effects." msgstr "" #: src/patterns/creational/builder.md:70 msgid "Separates methods for building from other methods." msgstr "" #: src/patterns/creational/builder.md:72 msgid "Prevents proliferation of constructors." msgstr "" #: src/patterns/creational/builder.md:74 msgid "" "Can be used for one-liner initialisation as well as more complex " "construction." msgstr "" #: src/patterns/creational/builder.md:78 msgid "" "More complex than creating a struct object directly, or a simple constructor " "function." msgstr "" #: src/patterns/creational/builder.md:83 msgid "" "This pattern is seen more frequently in Rust (and for simpler objects) than " "in many other languages because Rust lacks overloading. Since you can only " "have a single method with a given name, having multiple constructors is less " "nice in Rust than in C++, Java, or others." msgstr "" #: src/patterns/creational/builder.md:88 msgid "" "This pattern is often used where the builder object is useful in its own " "right, rather than being just a builder. For example, see " "[`std::process::Command`](https://doc.rust-lang.org/std/process/struct.Command.html) " "is a builder for " "[`Child`](https://doc.rust-lang.org/std/process/struct.Child.html) (a " "process). In these cases, the `T` and `TBuilder` naming pattern is not used." msgstr "" #: src/patterns/creational/builder.md:95 msgid "" "The example takes and returns the builder by value. It is often more " "ergonomic (and more efficient) to take and return the builder as a mutable " "reference. The borrow checker makes this work naturally. This approach has " "the advantage that one can write code like" msgstr "" #: src/patterns/creational/builder.md:107 msgid "as well as the `FooBuilder::new().a().b().build()` style." msgstr "" #: src/patterns/creational/builder.md:111 msgid "" "[Description in the style " "guide](https://web.archive.org/web/20210104103100/https://doc.rust-lang.org/1.12.0/style/ownership/builders.html)" msgstr "" #: src/patterns/creational/builder.md:112 msgid "" "[derive_builder](https://crates.io/crates/derive_builder), a crate for " "automatically implementing this pattern while avoiding the boilerplate." msgstr "" #: src/patterns/creational/builder.md:114 msgid "" "[Constructor pattern](../../idioms/ctor.md) for when construction is simpler." msgstr "" #: src/patterns/creational/builder.md:115 msgid "" "[Builder pattern (wikipedia)](https://en.wikipedia.org/wiki/Builder_pattern)" msgstr "" #: src/patterns/creational/builder.md:116 msgid "" "[Construction of complex " "values](https://web.archive.org/web/20210104103000/https://rust-lang.github.io/api-guidelines/type-safety.html#c-builder)" msgstr "" #: src/patterns/creational/fold.md:5 msgid "" "Run an algorithm over each item in a collection of data to create a new " "item, thus creating a whole new collection." msgstr "" #: src/patterns/creational/fold.md:8 msgid "" "The etymology here is unclear to me. The terms 'fold' and 'folder' are used " "in the Rust compiler, although it appears to me to be more like a map than a " "fold in the usual sense. See the discussion below for more details." msgstr "" #: src/patterns/creational/fold.md:15 msgid "// The data we will fold, a simple AST.\n" msgstr "" #: src/patterns/creational/fold.md:32 msgid "// The abstract folder\n" msgstr "" #: src/patterns/creational/fold.md:38 msgid "" "// A leaf node just returns the node itself. In some cases, we can do this\n" " // to inner nodes too.\n" msgstr "" #: src/patterns/creational/fold.md:41 msgid "// Create a new inner node by folding its children.\n" msgstr "" #: src/patterns/creational/fold.md:54 msgid "// An example concrete implementation - renames every name to 'foo'.\n" msgstr "" #: src/patterns/creational/fold.md:59 msgid "\"foo\"" msgstr "" #: src/patterns/creational/fold.md:61 msgid "// Use the default methods for the other nodes.\n" msgstr "" #: src/patterns/creational/fold.md:65 msgid "" "The result of running the `Renamer` on an AST is a new AST identical to the " "old one, but with every name changed to `foo`. A real life folder might have " "some state preserved between nodes in the struct itself." msgstr "" #: src/patterns/creational/fold.md:69 msgid "" "A folder can also be defined to map one data structure to a different (but " "usually similar) data structure. For example, we could fold an AST into a " "HIR tree (HIR stands for high-level intermediate representation)." msgstr "" #: src/patterns/creational/fold.md:75 msgid "" "It is common to want to map a data structure by performing some operation on " "each node in the structure. For simple operations on simple data structures, " "this can be done using `Iterator::map`. For more complex operations, perhaps " "where earlier nodes can affect the operation on later nodes, or where " "iteration over the data structure is non-trivial, using the fold pattern is " "more appropriate." msgstr "" #: src/patterns/creational/fold.md:82 msgid "" "Like the visitor pattern, the fold pattern allows us to separate traversal " "of a data structure from the operations performed to each node." msgstr "" #: src/patterns/creational/fold.md:87 msgid "" "Mapping data structures in this fashion is common in functional languages. " "In OO languages, it would be more common to mutate the data structure in " "place. The 'functional' approach is common in Rust, mostly due to the " "preference for immutability. Using fresh data structures, rather than " "mutating old ones, makes reasoning about the code easier in most " "circumstances." msgstr "" #: src/patterns/creational/fold.md:93 msgid "" "The trade-off between efficiency and reusability can be tweaked by changing " "how nodes are accepted by the `fold_*` methods." msgstr "" #: src/patterns/creational/fold.md:96 msgid "" "In the above example we operate on `Box` pointers. Since these own their " "data exclusively, the original copy of the data structure cannot be re-used. " "On the other hand if a node is not changed, reusing it is very efficient." msgstr "" #: src/patterns/creational/fold.md:100 msgid "" "If we were to operate on borrowed references, the original data structure " "can be reused; however, a node must be cloned even if unchanged, which can " "be expensive." msgstr "" #: src/patterns/creational/fold.md:104 msgid "" "Using a reference counted pointer gives the best of both worlds - we can " "reuse the original data structure, and we don't need to clone unchanged " "nodes. However, they are less ergonomic to use and mean that the data " "structures cannot be mutable." msgstr "" #: src/patterns/creational/fold.md:111 msgid "" "Iterators have a `fold` method, however this folds a data structure into a " "value, rather than into a new data structure. An iterator's `map` is more " "like this fold pattern." msgstr "" #: src/patterns/creational/fold.md:115 msgid "" "In other languages, fold is usually used in the sense of Rust's iterators, " "rather than this pattern. Some functional languages have powerful constructs " "for performing flexible maps over data structures." msgstr "" #: src/patterns/creational/fold.md:119 msgid "" "The [visitor](../behavioural/visitor.md) pattern is closely related to fold. " "They share the concept of walking a data structure performing an operation " "on each node. However, the visitor does not create a new data structure nor " "consume the old one." msgstr "" #: src/patterns/structural/intro.md:1 msgid "Structural Patterns" msgstr "" #: src/patterns/structural/intro.md:3 msgid "From [Wikipedia](https://en.wikipedia.org/wiki/Structural_pattern):" msgstr "" #: src/patterns/structural/intro.md:5 msgid "" "Design patterns that ease the design by identifying a simple way to realize " "relationships among entities." msgstr "" #: src/patterns/structural/compose-structs.md:1 msgid "Struct decomposition for independent borrowing" msgstr "" #: src/patterns/structural/compose-structs.md:5 msgid "" "Sometimes a large struct will cause issues with the borrow checker - " "although fields can be borrowed independently, sometimes the whole struct " "ends up being used at once, preventing other uses. A solution might be to " "decompose the struct into several smaller structs. Then compose these " "together into the original struct. Then each struct can be borrowed " "separately and have more flexible behaviour." msgstr "" #: src/patterns/structural/compose-structs.md:12 msgid "" "This will often lead to a better design in other ways: applying this design " "pattern often reveals smaller units of functionality." msgstr "" #: src/patterns/structural/compose-structs.md:17 msgid "" "Here is a contrived example of where the borrow checker foils us in our plan " "to use a struct:" msgstr "" #: src/patterns/structural/compose-structs.md:28 msgid "\"Connection string: {}\"" msgstr "" #: src/patterns/structural/compose-structs.md:29 msgid "\"Timeout: {}\"" msgstr "" #: src/patterns/structural/compose-structs.md:30 msgid "\"Pool size: {}\"" msgstr "" #: src/patterns/structural/compose-structs.md:35 msgid "\"initial string\"" msgstr "" #: src/patterns/structural/compose-structs.md:42 #: src/patterns/structural/compose-structs.md:96 msgid "\"new string\"" msgstr "" #: src/patterns/structural/compose-structs.md:46 msgid "The compiler throws following errors:" msgstr "" #: src/patterns/structural/compose-structs.md:48 msgid "" "```ignore\n" "let connection_string = &mut db.connection_string;\n" " ------------------------- mutable borrow occurs " "here\n" "print_database(&db);\n" " ^^^ immutable borrow occurs here\n" "*connection_string = \"new string\".to_string();\n" "------------------ mutable borrow later used here\n" "```" msgstr "" #: src/patterns/structural/compose-structs.md:57 msgid "" "We can apply this design pattern and refactor `Database` into three smaller " "structs, thus solving the borrow checking issue:" msgstr "" #: src/patterns/structural/compose-structs.md:61 msgid "" "// Database is now composed of three structs - ConnectionString, Timeout and " "PoolSize.\n" "// Let's decompose it into smaller structs\n" msgstr "" #: src/patterns/structural/compose-structs.md:71 msgid "// We then compose these smaller structs back into `Database`\n" msgstr "" #: src/patterns/structural/compose-structs.md:78 msgid "" "// print_database can then take ConnectionString, Timeout and Poolsize " "struct instead\n" msgstr "" #: src/patterns/structural/compose-structs.md:81 msgid "\"Connection string: {connection_str:?}\"" msgstr "" #: src/patterns/structural/compose-structs.md:82 msgid "\"Timeout: {timeout:?}\"" msgstr "" #: src/patterns/structural/compose-structs.md:83 msgid "\"Pool size: {pool_size:?}\"" msgstr "" #: src/patterns/structural/compose-structs.md:87 msgid "// Initialize the Database with the three structs\n" msgstr "" #: src/patterns/structural/compose-structs.md:89 msgid "\"localhost\"" msgstr "" #: src/patterns/structural/compose-structs.md:102 msgid "" "This pattern is most useful, when you have a struct that ended up with a lot " "of fields that you want to borrow independently. Thus having a more flexible " "behaviour in the end." msgstr "" #: src/patterns/structural/compose-structs.md:108 msgid "" "Decomposition of structs lets you work around limitations in the borrow " "checker. And it often produces a better design." msgstr "" #: src/patterns/structural/compose-structs.md:113 msgid "" "It can lead to more verbose code. And sometimes, the smaller structs are not " "good abstractions, and so we end up with a worse design. That is probably a " "'code smell', indicating that the program should be refactored in some way." msgstr "" #: src/patterns/structural/compose-structs.md:119 msgid "" "This pattern is not required in languages that don't have a borrow checker, " "so in that sense is unique to Rust. However, making smaller units of " "functionality often leads to cleaner code: a widely acknowledged principle " "of software engineering, independent of the language." msgstr "" #: src/patterns/structural/compose-structs.md:124 msgid "" "This pattern relies on Rust's borrow checker to be able to borrow fields " "independently of each other. In the example, the borrow checker knows that " "`a.b` and `a.c` are distinct and can be borrowed independently, it does not " "try to borrow all of `a`, which would make this pattern useless." msgstr "" #: src/patterns/structural/small-crates.md:1 msgid "Prefer small crates" msgstr "" #: src/patterns/structural/small-crates.md:5 msgid "Prefer small crates that do one thing well." msgstr "" #: src/patterns/structural/small-crates.md:7 msgid "" "Cargo and crates.io make it easy to add third-party libraries, much more so " "than in say C or C++. Moreover, since packages on crates.io cannot be edited " "or removed after publication, any build that works now should continue to " "work in the future. We should take advantage of this tooling, and use " "smaller, more fine-grained dependencies." msgstr "" #: src/patterns/structural/small-crates.md:15 msgid "Small crates are easier to understand, and encourage more modular code." msgstr "" #: src/patterns/structural/small-crates.md:16 msgid "" "Crates allow for re-using code between projects. For example, the `url` " "crate was developed as part of the Servo browser engine, but has since found " "wide use outside the project." msgstr "" #: src/patterns/structural/small-crates.md:19 msgid "" "Since the compilation unit of Rust is the crate, splitting a project into " "multiple crates can allow more of the code to be built in parallel." msgstr "" #: src/patterns/structural/small-crates.md:24 msgid "" "This can lead to \"dependency hell\", when a project depends on multiple " "conflicting versions of a crate at the same time. For example, the `url` " "crate has both versions 1.0 and 0.5. Since the `Url` from `url:1.0` and the " "`Url` from `url:0.5` are different types, an HTTP client that uses `url:0.5` " "would not accept `Url` values from a web scraper that uses `url:1.0`." msgstr "" #: src/patterns/structural/small-crates.md:29 msgid "" "Packages on crates.io are not curated. A crate may be poorly written, have " "unhelpful documentation, or be outright malicious." msgstr "" #: src/patterns/structural/small-crates.md:31 msgid "" "Two small crates may be less optimized than one large one, since the " "compiler does not perform link-time optimization (LTO) by default." msgstr "" #: src/patterns/structural/small-crates.md:36 msgid "" "The [`url`](https://crates.io/crates/url) crate provides tools for working " "with URLs." msgstr "" #: src/patterns/structural/small-crates.md:39 msgid "" "The [`num_cpus`](https://crates.io/crates/num_cpus) crate provides a " "function to query the number of CPUs on a machine." msgstr "" #: src/patterns/structural/small-crates.md:42 msgid "" "The [`ref_slice`](https://crates.io/crates/ref_slice) crate provides " "functions for converting `&T` to `&[T]`. (Historical example)" msgstr "" #: src/patterns/structural/small-crates.md:47 msgid "[crates.io: The Rust community crate host](https://crates.io/)" msgstr "" #: src/patterns/structural/unsafe-mods.md:5 msgid "" "If you have `unsafe` code, create the smallest possible module that can " "uphold the needed invariants to build a minimal safe interface upon the " "unsafety. Embed this into a larger module that contains only safe code and " "presents an ergonomic interface. Note that the outer module can contain " "unsafe functions and methods that call directly into the unsafe code. Users " "may use this to gain speed benefits." msgstr "" #: src/patterns/structural/unsafe-mods.md:14 msgid "This restricts the unsafe code that must be audited" msgstr "" #: src/patterns/structural/unsafe-mods.md:15 msgid "" "Writing the outer module is much easier, since you can count on the " "guarantees of the inner module" msgstr "" #: src/patterns/structural/unsafe-mods.md:20 msgid "Sometimes, it may be hard to find a suitable interface." msgstr "" #: src/patterns/structural/unsafe-mods.md:21 msgid "The abstraction may introduce inefficiencies." msgstr "" #: src/patterns/structural/unsafe-mods.md:25 msgid "" "The [`toolshed`](https://docs.rs/toolshed) crate contains its unsafe " "operations in submodules, presenting a safe interface to users." msgstr "" #: src/patterns/structural/unsafe-mods.md:27 msgid "" "`std`'s `String` class is a wrapper over `Vec` with the added invariant " "that the contents must be valid UTF-8. The operations on `String` ensure " "this behavior. However, users have the option of using an `unsafe` method to " "create a `String`, in which case the onus is on them to guarantee the " "validity of the contents." msgstr "" #: src/patterns/structural/unsafe-mods.md:35 msgid "" "[Ralf Jung's Blog about invariants in unsafe " "code](https://www.ralfj.de/blog/2018/08/22/two-kinds-of-invariants.html)" msgstr "" #: src/patterns/ffi/intro.md:1 msgid "FFI Patterns" msgstr "" #: src/patterns/ffi/intro.md:3 msgid "" "Writing FFI code is an entire course in itself. However, there are several " "idioms here that can act as pointers, and avoid traps for inexperienced " "users of unsafe Rust." msgstr "" #: src/patterns/ffi/intro.md:7 msgid "This section contains design patterns that may be useful when doing FFI." msgstr "" #: src/patterns/ffi/intro.md:9 msgid "" "[Object-Based API](./export.md) design that has good memory safety " "characteristics, and a clean boundary of what is safe and what is unsafe" msgstr "" #: src/patterns/ffi/intro.md:12 msgid "" "[Type Consolidation into Wrappers](./wrappers.md) - group multiple Rust " "types together into an opaque \"object\"" msgstr "" #: src/patterns/ffi/export.md:5 msgid "" "When designing APIs in Rust which are exposed to other languages, there are " "some important design principles which are contrary to normal Rust API " "design:" msgstr "" #: src/patterns/ffi/export.md:8 msgid "" "All Encapsulated types should be _owned_ by Rust, _managed_ by the user, and " "_opaque_." msgstr "" #: src/patterns/ffi/export.md:10 msgid "" "All Transactional data types should be _owned_ by the user, and " "_transparent_." msgstr "" #: src/patterns/ffi/export.md:12 msgid "All library behavior should be functions acting upon Encapsulated types." msgstr "" #: src/patterns/ffi/export.md:13 msgid "" "All library behavior should be encapsulated into types not based on " "structure, but _provenance/lifetime_." msgstr "" #: src/patterns/ffi/export.md:18 msgid "" "Rust has built-in FFI support to other languages. It does this by providing " "a way for crate authors to provide C-compatible APIs through different ABIs " "(though that is unimportant to this practice)." msgstr "" #: src/patterns/ffi/export.md:22 msgid "" "Well-designed Rust FFI follows C API design principles, while compromising " "the design in Rust as little as possible. There are three goals with any " "foreign API:" msgstr "" #: src/patterns/ffi/export.md:26 msgid "Make it easy to use in the target language." msgstr "" #: src/patterns/ffi/export.md:27 msgid "" "Avoid the API dictating internal unsafety on the Rust side as much as " "possible." msgstr "" #: src/patterns/ffi/export.md:29 msgid "" "Keep the potential for memory unsafety and Rust `undefined behaviour` as " "small as possible." msgstr "" #: src/patterns/ffi/export.md:32 msgid "" "Rust code must trust the memory safety of the foreign language beyond a " "certain point. However, every bit of `unsafe` code on the Rust side is an " "opportunity for bugs, or to exacerbate `undefined behaviour`." msgstr "" #: src/patterns/ffi/export.md:36 msgid "" "For example, if a pointer provenance is wrong, that may be a segfault due to " "invalid memory access. But if it is manipulated by unsafe code, it could " "become full-blown heap corruption." msgstr "" #: src/patterns/ffi/export.md:40 msgid "" "The Object-Based API design allows for writing shims that have good memory " "safety characteristics, and a clean boundary of what is safe and what is " "`unsafe`." msgstr "" #: src/patterns/ffi/export.md:46 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). " "It is an excellent example of an \"object-based\" API." msgstr "" #: src/patterns/ffi/export.md:50 msgid "" "Here is the definition in C, which hopefully should be easy to read for " "those involved in FFI. The commentary below should help explain it for those " "who miss the subtleties." msgstr "" #: src/patterns/ffi/export.md:69 msgid "This API defines two types: `DBM` and `datum`." msgstr "" #: src/patterns/ffi/export.md:71 msgid "" "The `DBM` type was called an \"encapsulated\" type above. It is designed to " "contain internal state, and acts as an entry point for the library's " "behavior." msgstr "" #: src/patterns/ffi/export.md:74 msgid "" "It is completely opaque to the user, who cannot create a `DBM` themselves " "since they don't know its size or layout. Instead, they must call " "`dbm_open`, and that only gives them _a pointer to one_." msgstr "" #: src/patterns/ffi/export.md:78 msgid "" "This means all `DBM`s are \"owned\" by the library in a Rust sense. The " "internal state of unknown size is kept in memory controlled by the library, " "not the user. The user can only manage its life cycle with `open` and " "`close`, and perform operations on it with the other functions." msgstr "" #: src/patterns/ffi/export.md:83 msgid "" "The `datum` type was called a \"transactional\" type above. It is designed " "to facilitate the exchange of information between the library and its user." msgstr "" #: src/patterns/ffi/export.md:86 msgid "" "The database is designed to store \"unstructured data\", with no pre-defined " "length or meaning. As a result, the `datum` is the C equivalent of a Rust " "slice: a bunch of bytes, and a count of how many there are. The main " "difference is that there is no type information, which is what `void` " "indicates." msgstr "" #: src/patterns/ffi/export.md:91 msgid "" "Keep in mind that this header is written from the library's point of view. " "The user likely has some type they are using, which has a known size. But " "the library does not care, and by the rules of C casting, any type behind a " "pointer can be cast to `void`." msgstr "" #: src/patterns/ffi/export.md:96 msgid "" "As noted earlier, this type is _transparent_ to the user. But also, this " "type is _owned_ by the user. This has subtle ramifications, due to that " "pointer inside it. The question is, who owns the memory that pointer points " "to?" msgstr "" #: src/patterns/ffi/export.md:100 msgid "" "The answer for best memory safety is, \"the user\". But in cases such as " "retrieving a value, the user does not know how to allocate it correctly " "(since they don't know how long the value is). In this case, the library " "code is expected to use the heap that the user has access to -- such as the " "C library `malloc` and `free` -- and then _transfer ownership_ in the Rust " "sense." msgstr "" #: src/patterns/ffi/export.md:106 msgid "" "This may all seem speculative, but this is what a pointer means in C. It " "means the same thing as Rust: \"user defined lifetime.\" The user of the " "library needs to read the documentation in order to use it correctly. That " "said, there are some decisions that have fewer or greater consequences if " "users do it wrong. Minimizing those are what this best practice is about, " "and the key is to _transfer ownership of everything that is transparent_." msgstr "" #: src/patterns/ffi/export.md:115 msgid "" "This minimizes the number of memory safety guarantees the user must uphold " "to a relatively small number:" msgstr "" #: src/patterns/ffi/export.md:118 msgid "" "Do not call any function with a pointer not returned by `dbm_open` (invalid " "access or corruption)." msgstr "" #: src/patterns/ffi/export.md:120 msgid "Do not call any function on a pointer after close (use after free)." msgstr "" #: src/patterns/ffi/export.md:121 msgid "" "The `dptr` on any `datum` must be `NULL`, or point to a valid slice of " "memory at the advertised length." msgstr "" #: src/patterns/ffi/export.md:124 msgid "" "In addition, it avoids a lot of pointer provenance issues. To understand " "why, let us consider an alternative in some depth: key iteration." msgstr "" #: src/patterns/ffi/export.md:127 msgid "" "Rust is well known for its iterators. When implementing one, the programmer " "makes a separate type with a bounded lifetime to its owner, and implements " "the `Iterator` trait." msgstr "" #: src/patterns/ffi/export.md:131 msgid "Here is how iteration would be done in Rust for `DBM`:" msgstr "" #: src/patterns/ffi/export.md:149 msgid "" "This is clean, idiomatic, and safe. thanks to Rust's guarantees. However, " "consider what a straightforward API translation would look like:" msgstr "" #: src/patterns/ffi/export.md:155 src/patterns/ffi/export.md:162 #: src/patterns/ffi/export.md:166 msgid "" "// THIS API IS A BAD IDEA! For real applications, use object-based design " "instead.\n" msgstr "" #: src/patterns/ffi/export.md:170 msgid "" "This API loses a key piece of information: the lifetime of the iterator must " "not exceed the lifetime of the `Dbm` object that owns it. A user of the " "library could use it in a way which causes the iterator to outlive the data " "it is iterating on, resulting in reading uninitialized memory." msgstr "" #: src/patterns/ffi/export.md:175 msgid "" "This example written in C contains a bug that will be explained afterwards:" msgstr "" #: src/patterns/ffi/export.md:179 msgid "// DO NOT USE THIS FUNCTION. IT HAS A SUBTLE BUT SERIOUS BUG!\n" msgstr "" #: src/patterns/ffi/export.md:189 msgid "// an error is indicated by -1\n" msgstr "" #: src/patterns/ffi/export.md:192 msgid "// end of the iterator\n" msgstr "" #: src/patterns/ffi/export.md:204 msgid "" "This bug is a classic. Here's what happens when the iterator returns the " "end-of-iteration marker:" msgstr "" #: src/patterns/ffi/export.md:207 msgid "" "The loop condition sets `l` to zero, and enters the loop because `0 >= 0`." msgstr "" #: src/patterns/ffi/export.md:208 msgid "The length is incremented, in this case by zero." msgstr "" #: src/patterns/ffi/export.md:209 msgid "" "The if statement is true, so the database is closed. There should be a break " "statement here." msgstr "" #: src/patterns/ffi/export.md:211 msgid "" "The loop condition executes again, causing a `next` call on the closed " "object." msgstr "" #: src/patterns/ffi/export.md:214 msgid "" "The worst part about this bug? If the Rust implementation was careful, this " "code will work most of the time! If the memory for the `Dbm` object is not " "immediately reused, an internal check will almost certainly fail, resulting " "in the iterator returning a `-1` indicating an error. But occasionally, it " "will cause a segmentation fault, or even worse, nonsensical memory " "corruption!" msgstr "" #: src/patterns/ffi/export.md:220 msgid "" "None of this can be avoided by Rust. From its perspective, it put those " "objects on its heap, returned pointers to them, and gave up control of their " "lifetimes. The C code simply must \"play nice\"." msgstr "" #: src/patterns/ffi/export.md:224 msgid "" "The programmer must read and understand the API documentation. While some " "consider that par for the course in C, a good API design can mitigate this " "risk. The POSIX API for `DBM` did this by _consolidating the ownership_ of " "the iterator with its parent:" msgstr "" #: src/patterns/ffi/export.md:234 msgid "" "Thus, all the lifetimes were bound together, and such unsafety was prevented." msgstr "" #: src/patterns/ffi/export.md:238 msgid "" "However, this design choice also has a number of drawbacks, which should be " "considered as well." msgstr "" #: src/patterns/ffi/export.md:241 msgid "" "First, the API itself becomes less expressive. With POSIX DBM, there is only " "one iterator per object, and every call changes its state. This is much more " "restrictive than iterators in almost any language, even though it is safe. " "Perhaps with other related objects, whose lifetimes are less hierarchical, " "this limitation is more of a cost than the safety." msgstr "" #: src/patterns/ffi/export.md:247 msgid "" "Second, depending on the relationships of the API's parts, significant " "design effort may be involved. Many of the easier design points have other " "patterns associated with them:" msgstr "" #: src/patterns/ffi/export.md:251 msgid "" "[Wrapper Type Consolidation](./wrappers.md) groups multiple Rust types " "together into an opaque \"object\"" msgstr "" #: src/patterns/ffi/export.md:254 msgid "" "[FFI Error Passing](../../idioms/ffi/errors.md) explains error handling with " "integer codes and sentinel return values (such as `NULL` pointers)" msgstr "" #: src/patterns/ffi/export.md:257 msgid "" "[Accepting Foreign Strings](../../idioms/ffi/accepting-strings.md) allows " "accepting strings with minimal unsafe code, and is easier to get right than " "[Passing Strings to FFI](../../idioms/ffi/passing-strings.md)" msgstr "" #: src/patterns/ffi/export.md:261 msgid "" "However, not every API can be done this way. It is up to the best judgement " "of the programmer as to who their audience is." msgstr "" #: src/patterns/ffi/wrappers.md:5 msgid "" "This pattern is designed to allow gracefully handling multiple related " "types, while minimizing the surface area for memory unsafety." msgstr "" #: src/patterns/ffi/wrappers.md:8 msgid "" "One of the cornerstones of Rust's aliasing rules is lifetimes. This ensures " "that many patterns of access between types can be memory safe, data race " "safety included." msgstr "" #: src/patterns/ffi/wrappers.md:12 msgid "" "However, when Rust types are exported to other languages, they are usually " "transformed into pointers. In Rust, a pointer means \"the user manages the " "lifetime of the pointee.\" It is their responsibility to avoid memory " "unsafety." msgstr "" #: src/patterns/ffi/wrappers.md:16 msgid "" "Some level of trust in the user code is thus required, notably around " "use-after-free which Rust can do nothing about. However, some API designs " "place higher burdens than others on the code written in the other language." msgstr "" #: src/patterns/ffi/wrappers.md:20 msgid "" "The lowest risk API is the \"consolidated wrapper\", where all possible " "interactions with an object are folded into a \"wrapper type\", while " "keeping the Rust API clean." msgstr "" #: src/patterns/ffi/wrappers.md:26 msgid "" "To understand this, let us look at a classic example of an API to export: " "iteration through a collection." msgstr "" #: src/patterns/ffi/wrappers.md:29 msgid "That API looks like this:" msgstr "" #: src/patterns/ffi/wrappers.md:31 msgid "The iterator is initialized with `first_key`." msgstr "" #: src/patterns/ffi/wrappers.md:32 msgid "Each call to `next_key` will advance the iterator." msgstr "" #: src/patterns/ffi/wrappers.md:33 msgid "Calls to `next_key` if the iterator is at the end will do nothing." msgstr "" #: src/patterns/ffi/wrappers.md:34 msgid "" "As noted above, the iterator is \"wrapped into\" the collection (unlike the " "native Rust API)." msgstr "" #: src/patterns/ffi/wrappers.md:37 msgid "" "If the iterator implements `nth()` efficiently, then it is possible to make " "it ephemeral to each function call:" msgstr "" #: src/patterns/ffi/wrappers.md:62 msgid "As a result, the wrapper is simple and contains no `unsafe` code." msgstr "" #: src/patterns/ffi/wrappers.md:66 msgid "" "This makes APIs safer to use, avoiding issues with lifetimes between types. " "See [Object-Based APIs](./export.md) for more on the advantages and pitfalls " "this avoids." msgstr "" #: src/patterns/ffi/wrappers.md:72 msgid "" "Often, wrapping types is quite difficult, and sometimes a Rust API " "compromise would make things easier." msgstr "" #: src/patterns/ffi/wrappers.md:75 msgid "" "As an example, consider an iterator which does not efficiently implement " "`nth()`. It would definitely be worth putting in special logic to make the " "object handle iteration internally, or to support a different access pattern " "efficiently that only the Foreign Function API will use." msgstr "" #: src/patterns/ffi/wrappers.md:80 msgid "Trying to Wrap Iterators (and Failing)" msgstr "" #: src/patterns/ffi/wrappers.md:82 msgid "" "To wrap any type of iterator into the API correctly, the wrapper would need " "to do what a C version of the code would do: erase the lifetime of the " "iterator, and manage it manually." msgstr "" #: src/patterns/ffi/wrappers.md:86 msgid "Suffice it to say, this is _incredibly_ difficult." msgstr "" #: src/patterns/ffi/wrappers.md:88 msgid "Here is an illustration of just _one_ pitfall." msgstr "" #: src/patterns/ffi/wrappers.md:90 msgid "A first version of `MySetWrapper` would look like this:" msgstr "" #: src/patterns/ffi/wrappers.md:96 msgid "// created from a transmuted Box\n" msgstr "" #: src/patterns/ffi/wrappers.md:101 msgid "" "With `transmute` being used to extend a lifetime, and a pointer to hide it, " "it's ugly already. But it gets even worse: _any other operation can cause " "Rust `undefined behaviour`_." msgstr "" #: src/patterns/ffi/wrappers.md:105 msgid "" "Consider that the `MySet` in the wrapper could be manipulated by other " "functions during iteration, such as storing a new value to the key it was " "iterating over. The API doesn't discourage this, and in fact some similar C " "libraries expect it." msgstr "" #: src/patterns/ffi/wrappers.md:109 msgid "A simple implementation of `myset_store` would be:" msgstr "" #: src/patterns/ffi/wrappers.md:117 msgid "// DO NOT USE THIS CODE. IT IS UNSAFE TO DEMONSTRATE A PROBLEM.\n" msgstr "" #: src/patterns/ffi/wrappers.md:120 msgid "// SAFETY: whoops, UB occurs in here!\n" msgstr "" #: src/patterns/ffi/wrappers.md:124 msgid "/* ...check and cast key and value data... */" msgstr "" #: src/patterns/ffi/wrappers.md:134 msgid "" "If the iterator exists when this function is called, we have violated one of " "Rust's aliasing rules. According to Rust, the mutable reference in this " "block must have _exclusive_ access to the object. If the iterator simply " "exists, it's not exclusive, so we have `undefined behaviour`! [^1]" msgstr "" #: src/patterns/ffi/wrappers.md:139 msgid "" "To avoid this, we must have a way of ensuring that mutable reference really " "is exclusive. That basically means clearing out the iterator's shared " "reference while it exists, and then reconstructing it. In most cases, that " "will still be less efficient than the C version." msgstr "" #: src/patterns/ffi/wrappers.md:144 msgid "" "Some may ask: how can C do this more efficiently? The answer is, it cheats. " "Rust's aliasing rules are the problem, and C simply ignores them for its " "pointers. In exchange, it is common to see code that is declared in the " "manual as \"not thread safe\" under some or all circumstances. In fact, the " "[GNU C " "library](https://manpages.debian.org/buster/manpages/attributes.7.en.html) " "has an entire lexicon dedicated to concurrent behavior!" msgstr "" #: src/patterns/ffi/wrappers.md:151 msgid "" "Rust would rather make everything memory safe all the time, for both safety " "and optimizations that C code cannot attain. Being denied access to certain " "shortcuts is the price Rust programmers need to pay." msgstr "" #: src/patterns/ffi/wrappers.md:155 msgid "" "For the C programmers out there scratching their heads, the iterator need " "not be read _during_ this code to cause the UB. The exclusivity rule also " "enables compiler optimizations which may cause inconsistent observations by " "the iterator's shared reference (e.g. stack spills or reordering " "instructions for efficiency). These observations may happen _any time after_ " "the mutable reference is created." msgstr "" #: src/anti_patterns/index.md:3 msgid "" "An [anti-pattern](https://en.wikipedia.org/wiki/Anti-pattern) is a solution " "to a \"recurring problem that is usually ineffective and risks being highly " "counterproductive\". Just as valuable as knowing how to solve a problem, is " "knowing how _not_ to solve it. Anti-patterns give us great counter-examples " "to consider relative to design patterns. Anti-patterns are not confined to " "code. For example, a process can be an anti-pattern, too." msgstr "" #: src/anti_patterns/borrow_clone.md:5 msgid "" "The borrow checker prevents Rust users from developing otherwise unsafe code " "by ensuring that either: only one mutable reference exists, or potentially " "many but all immutable references exist. If the code written does not hold " "true to these conditions, this anti-pattern arises when the developer " "resolves the compiler error by cloning the variable." msgstr "" #: src/anti_patterns/borrow_clone.md:14 msgid "// define any variable\n" msgstr "" #: src/anti_patterns/borrow_clone.md:16 msgid "// Borrow `x` -- but clone it first\n" msgstr "" #: src/anti_patterns/borrow_clone.md:19 msgid "" "// 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" msgstr "" #: src/anti_patterns/borrow_clone.md:23 msgid "\"{x}\"" msgstr "" #: src/anti_patterns/borrow_clone.md:24 msgid "" "// perform some action on the borrow to prevent rust from optimizing this\n" "//out of existence\n" msgstr "" #: src/anti_patterns/borrow_clone.md:32 msgid "" "It is tempting, particularly for beginners, to use this pattern to resolve " "confusing issues with the borrow checker. However, there are serious " "consequences. Using `.clone()` causes a copy of the data to be made. Any " "changes between the two are not synchronized -- as if two completely " "separate variables exist." msgstr "" #: src/anti_patterns/borrow_clone.md:38 msgid "" "There are special cases -- `Rc` is designed to handle clones " "intelligently. It internally manages exactly one copy of the data. Invoking " "`.clone()` on `Rc` produces a new `Rc` instance, which points to the same " "data as the source `Rc`, while increasing a reference count. The same " "applies to `Arc`, the thread-safe counterpart of `Rc`." msgstr "" #: src/anti_patterns/borrow_clone.md:44 msgid "" "In general, clones should be deliberate, with full understanding of the " "consequences. If a clone is used to make a borrow checker error disappear, " "that's a good indication this anti-pattern may be in use." msgstr "" #: src/anti_patterns/borrow_clone.md:48 msgid "" "Even though `.clone()` is an indication of a bad pattern, sometimes **it is " "fine to write inefficient code**, in cases such as when:" msgstr "" #: src/anti_patterns/borrow_clone.md:51 msgid "the developer is still new to ownership" msgstr "" #: src/anti_patterns/borrow_clone.md:52 msgid "" "the code doesn't have great speed or memory constraints (like hackathon " "projects or prototypes)" msgstr "" #: src/anti_patterns/borrow_clone.md:54 msgid "" "satisfying the borrow checker is really complicated, and you prefer to " "optimize readability over performance" msgstr "" #: src/anti_patterns/borrow_clone.md:57 msgid "" "If an unnecessary clone is suspected, The [Rust Book's chapter on " "Ownership](https://doc.rust-lang.org/book/ownership.html) should be " "understood fully before assessing whether the clone is required or not." msgstr "" #: src/anti_patterns/borrow_clone.md:62 msgid "" "Also be sure to always run `cargo clippy` in your project, which will detect " "some cases in which `.clone()` is not necessary." msgstr "" #: src/anti_patterns/borrow_clone.md:67 msgid "" "[`mem::{take(_), replace(_)}` to keep owned values in changed " "enums](../idioms/mem-replace.md)" msgstr "" #: src/anti_patterns/borrow_clone.md:68 msgid "" "[`Rc` documentation, which handles .clone() " "intelligently](http://doc.rust-lang.org/std/rc/)" msgstr "" #: src/anti_patterns/borrow_clone.md:69 msgid "" "[`Arc` documentation, a thread-safe reference-counting " "pointer](https://doc.rust-lang.org/std/sync/struct.Arc.html)" msgstr "" #: src/anti_patterns/borrow_clone.md:70 msgid "" "[Tricks with ownership in " "Rust](https://web.archive.org/web/20210120233744/https://xion.io/post/code/rust-borrowchk-tricks.html)" msgstr "" #: src/anti_patterns/deny-warnings.md:1 msgid "`#![deny(warnings)]`" msgstr "" #: src/anti_patterns/deny-warnings.md:5 msgid "" "A well-intentioned crate author wants to ensure their code builds without " "warnings. So they annotate their crate root with the following:" msgstr "" #: src/anti_patterns/deny-warnings.md:12 msgid "// All is well.\n" msgstr "" #: src/anti_patterns/deny-warnings.md:18 msgid "It is short and will stop the build if anything is amiss." msgstr "" #: src/anti_patterns/deny-warnings.md:20 msgid "Drawbacks" msgstr "" #: src/anti_patterns/deny-warnings.md:22 msgid "" "By disallowing the compiler to build with warnings, a crate author opts out " "of Rust's famed stability. Sometimes new features or old misfeatures need a " "change in how things are done, thus lints are written that `warn` for a " "certain grace period before being turned to `deny`." msgstr "" #: src/anti_patterns/deny-warnings.md:27 msgid "" "For example, it was discovered that a type could have two `impl`s with the " "same method. This was deemed a bad idea, but in order to make the transition " "smooth, the `overlapping-inherent-impls` lint was introduced to give a " "warning to those stumbling on this fact, before it becomes a hard error in a " "future release." msgstr "" #: src/anti_patterns/deny-warnings.md:32 msgid "" "Also sometimes APIs get deprecated, so their use will emit a warning where " "before there was none." msgstr "" #: src/anti_patterns/deny-warnings.md:35 msgid "" "All this conspires to potentially break the build whenever something changes." msgstr "" #: src/anti_patterns/deny-warnings.md:37 msgid "" "Furthermore, crates that supply additional lints (e.g. " "[rust-clippy](https://github.com/rust-lang/rust-clippy)) can no longer be " "used unless the annotation is removed. This is mitigated with " "[\\--cap-lints](https://doc.rust-lang.org/rustc/lints/levels.html#capping-lints). " "The `--cap-lints=warn` command line argument, turns all `deny` lint errors " "into warnings." msgstr "" #: src/anti_patterns/deny-warnings.md:42 #: src/functional/generics-type-classes.md:226 msgid "Alternatives" msgstr "" #: src/anti_patterns/deny-warnings.md:44 msgid "" "There are two ways of tackling this problem: First, we can decouple the " "build setting from the code, and second, we can name the lints we want to " "deny explicitly." msgstr "" #: src/anti_patterns/deny-warnings.md:48 msgid "The following command line will build with all warnings set to `deny`:" msgstr "" #: src/anti_patterns/deny-warnings.md:50 msgid "`RUSTFLAGS=\"-D warnings\" cargo build`" msgstr "" #: src/anti_patterns/deny-warnings.md:52 msgid "" "This can be done by any individual developer (or be set in a CI tool like " "Travis, but remember that this may break the build when something changes) " "without requiring a change to the code." msgstr "" #: src/anti_patterns/deny-warnings.md:56 msgid "" "Alternatively, we can specify the lints that we want to `deny` in the code. " "Here is a list of warning lints that is (hopefully) safe to deny (as of " "rustc 1.48.0):" msgstr "" #: src/anti_patterns/deny-warnings.md:81 msgid "In addition, the following `allow`ed lints may be a good idea to `deny`:" msgstr "" #: src/anti_patterns/deny-warnings.md:96 msgid "Some may also want to add `missing-copy-implementations` to their list." msgstr "" #: src/anti_patterns/deny-warnings.md:98 msgid "" "Note that we explicitly did not add the `deprecated` lint, as it is fairly " "certain that there will be more deprecated APIs in the future." msgstr "" #: src/anti_patterns/deny-warnings.md:103 msgid "" "[A collection of all clippy " "lints](https://rust-lang.github.io/rust-clippy/master)" msgstr "" #: src/anti_patterns/deny-warnings.md:104 msgid "" "[deprecate " "attribute](https://doc.rust-lang.org/reference/attributes.html#deprecation) " "documentation" msgstr "" #: src/anti_patterns/deny-warnings.md:105 msgid "" "Type `rustc -W help` for a list of lints on your system. Also type `rustc " "--help` for a general list of options" msgstr "" #: src/anti_patterns/deny-warnings.md:107 msgid "" "[rust-clippy](https://github.com/rust-lang/rust-clippy) is a collection of " "lints for better Rust code" msgstr "" #: src/anti_patterns/deref.md:1 msgid "`Deref` polymorphism" msgstr "" #: src/anti_patterns/deref.md:5 msgid "" "Misuse the `Deref` trait to emulate inheritance between structs, and thus " "reuse methods." msgstr "" #: src/anti_patterns/deref.md:10 msgid "" "Sometimes we want to emulate the following common pattern from OO languages " "such as Java:" msgstr "" #: src/anti_patterns/deref.md:26 msgid "We can use the deref polymorphism anti-pattern to do so:" msgstr "" #: src/anti_patterns/deref.md:56 msgid "" "There is no struct inheritance in Rust. Instead we use composition and " "include an instance of `Foo` in `Bar` (since the field is a value, it is " "stored inline, so if there were fields, they would have the same layout in " "memory as the Java version (probably, you should use `#[repr(C)]` if you " "want to be sure))." msgstr "" #: src/anti_patterns/deref.md:61 msgid "" "In order to make the method call work we implement `Deref` for `Bar` with " "`Foo` as the target (returning the embedded `Foo` field). That means that " "when we dereference a `Bar` (for example, using `*`) then we will get a " "`Foo`. That is pretty weird. Dereferencing usually gives a `T` from a " "reference to `T`, here we have two unrelated types. However, since the dot " "operator does implicit dereferencing, it means that the method call will " "search for methods on `Foo` as well as `Bar`." msgstr "" #: src/anti_patterns/deref.md:71 msgid "You save a little boilerplate, e.g.," msgstr "" #: src/anti_patterns/deref.md:83 msgid "" "Most importantly this is a surprising idiom - future programmers reading " "this in code will not expect this to happen. That's because we are misusing " "the `Deref` trait rather than using it as intended (and documented, etc.). " "It's also because the mechanism here is completely implicit." msgstr "" #: src/anti_patterns/deref.md:88 msgid "" "This pattern does not introduce subtyping between `Foo` and `Bar` like " "inheritance in Java or C++ does. Furthermore, traits implemented by `Foo` " "are not automatically implemented for `Bar`, so this pattern interacts badly " "with bounds checking and thus generic programming." msgstr "" #: src/anti_patterns/deref.md:93 msgid "" "Using this pattern gives subtly different semantics from most OO languages " "with regards to `self`. Usually it remains a reference to the sub-class, " "with this pattern it will be the 'class' where the method is defined." msgstr "" #: src/anti_patterns/deref.md:97 msgid "" "Finally, this pattern only supports single inheritance, and has no notion of " "interfaces, class-based privacy, or other inheritance-related features. So, " "it gives an experience that will be subtly surprising to programmers used to " "Java inheritance, etc." msgstr "" #: src/anti_patterns/deref.md:104 msgid "" "There is no one good alternative. Depending on the exact circumstances it " "might be better to re-implement using traits or to write out the facade " "methods to dispatch to `Foo` manually. We do intend to add a mechanism for " "inheritance similar to this to Rust, but it is likely to be some time before " "it reaches stable Rust. See these " "[blog](http://aturon.github.io/blog/2015/09/18/reuse/) " "[posts](http://smallcultfollowing.com/babysteps/blog/2015/10/08/virtual-structs-part-4-extended-enums-and-thin-traits/) " "and this [RFC issue](https://github.com/rust-lang/rfcs/issues/349) for more " "details." msgstr "" #: src/anti_patterns/deref.md:113 msgid "" "The `Deref` trait is designed for the implementation of custom pointer " "types. The intention is that it will take a pointer-to-`T` to a `T`, not " "convert between different types. It is a shame that this isn't (probably " "cannot be) enforced by the trait definition." msgstr "" #: src/anti_patterns/deref.md:118 msgid "" "Rust tries to strike a careful balance between explicit and implicit " "mechanisms, favouring explicit conversions between types. Automatic " "dereferencing in the dot operator is a case where the ergonomics strongly " "favour an implicit mechanism, but the intention is that this is limited to " "degrees of indirection, not conversion between arbitrary types." msgstr "" #: src/anti_patterns/deref.md:126 msgid "[Collections are smart pointers idiom](../idioms/deref.md)." msgstr "" #: src/anti_patterns/deref.md:127 msgid "" "Delegation crates for less boilerplate like " "[delegate](https://crates.io/crates/delegate) or " "[ambassador](https://crates.io/crates/ambassador)" msgstr "" #: src/functional/index.md:1 msgid "Functional Usage of Rust" msgstr "" #: src/functional/index.md:3 msgid "" "Rust is an imperative language, but it follows many [functional " "programming](https://en.wikipedia.org/wiki/Functional_programming) paradigms." msgstr "" #: src/functional/index.md:7 msgid "" "In computer science, _functional programming_ is a programming paradigm " "where programs are constructed by applying and composing functions. It is a " "declarative programming paradigm in which function definitions are trees of " "expressions that each return a value, rather than a sequence of imperative " "statements which change the state of the program." msgstr "" #: src/functional/paradigms.md:3 msgid "" "One of the biggest hurdles to understanding functional programs when coming " "from an imperative background is the shift in thinking. Imperative programs " "describe **how** to do something, whereas declarative programs describe " "**what** to do. Let's sum the numbers from 1 to 10 to show this." msgstr "" #: src/functional/paradigms.md:8 msgid "Imperative" msgstr "" #: src/functional/paradigms.md:15 msgid "\"{sum}\"" msgstr "" #: src/functional/paradigms.md:18 msgid "" "With imperative programs, we have to play compiler to see what is happening. " "Here, we start with a `sum` of `0`. Next, we iterate through the range from " "1 to 10. Each time through the loop, we add the corresponding value in the " "range. Then we print it out." msgstr "" #: src/functional/paradigms.md:23 msgid "`i`" msgstr "" #: src/functional/paradigms.md:23 msgid "`sum`" msgstr "" #: src/functional/paradigms.md:25 src/functional/paradigms.md:59 #: src/functional/paradigms.md:60 msgid "1" msgstr "" #: src/functional/paradigms.md:26 src/functional/paradigms.md:60 msgid "2" msgstr "" #: src/functional/paradigms.md:26 src/functional/paradigms.md:27 #: src/functional/paradigms.md:60 src/functional/paradigms.md:61 msgid "3" msgstr "" #: src/functional/paradigms.md:27 src/functional/paradigms.md:30 #: src/functional/paradigms.md:61 src/functional/paradigms.md:62 #: src/functional/paradigms.md:64 msgid "6" msgstr "" #: src/functional/paradigms.md:28 src/functional/paradigms.md:62 msgid "4" msgstr "" #: src/functional/paradigms.md:28 src/functional/paradigms.md:34 #: src/functional/paradigms.md:62 src/functional/paradigms.md:63 #: src/functional/paradigms.md:68 msgid "10" msgstr "" #: src/functional/paradigms.md:29 src/functional/paradigms.md:63 msgid "5" msgstr "" #: src/functional/paradigms.md:29 src/functional/paradigms.md:63 #: src/functional/paradigms.md:64 msgid "15" msgstr "" #: src/functional/paradigms.md:30 src/functional/paradigms.md:64 #: src/functional/paradigms.md:65 msgid "21" msgstr "" #: src/functional/paradigms.md:31 src/functional/paradigms.md:65 msgid "7" msgstr "" #: src/functional/paradigms.md:31 src/functional/paradigms.md:65 #: src/functional/paradigms.md:66 msgid "28" msgstr "" #: src/functional/paradigms.md:32 src/functional/paradigms.md:66 msgid "8" msgstr "" #: src/functional/paradigms.md:32 src/functional/paradigms.md:66 #: src/functional/paradigms.md:67 msgid "36" msgstr "" #: src/functional/paradigms.md:33 src/functional/paradigms.md:67 msgid "9" msgstr "" #: src/functional/paradigms.md:33 src/functional/paradigms.md:67 #: src/functional/paradigms.md:68 msgid "45" msgstr "" #: src/functional/paradigms.md:34 src/functional/paradigms.md:68 msgid "55" msgstr "" #: src/functional/paradigms.md:36 msgid "" "This is how most of us start out programming. We learn that a program is a " "set of steps." msgstr "" #: src/functional/paradigms.md:39 msgid "Declarative" msgstr "" #: src/functional/paradigms.md:42 msgid "\"{}\"" msgstr "" #: src/functional/paradigms.md:45 msgid "" "Whoa! This is really different! What's going on here? Remember that with " "declarative programs we are describing **what** to do, rather than **how** " "to do it. `fold` is a function that " "[composes](https://en.wikipedia.org/wiki/Function_composition) functions. " "The name is a convention from Haskell." msgstr "" #: src/functional/paradigms.md:51 msgid "" "Here, we are composing functions of addition (this closure: `|a, b| a + b`) " "with a range from 1 to 10. The `0` is the starting point, so `a` is `0` at " "first. `b` is the first element of the range, `1`. `0 + 1 = 1` is the " "result. So now we `fold` again, with `a = 1`, `b = 2` and so `1 + 2 = 3` is " "the next result. This process continues until we get to the last element in " "the range, `10`." msgstr "" #: src/functional/paradigms.md:57 msgid "`a`" msgstr "" #: src/functional/paradigms.md:57 msgid "`b`" msgstr "" #: src/functional/paradigms.md:57 msgid "result" msgstr "" #: src/functional/paradigms.md:59 msgid "0" msgstr "" #: src/functional/generics-type-classes.md:5 msgid "" "Rust's type system is designed more like functional languages (like Haskell) " "rather than imperative languages (like Java and C++). As a result, Rust can " "turn many kinds of programming problems into \"static typing\" problems. " "This is one of the biggest wins of choosing a functional language, and is " "critical to many of Rust's compile time guarantees." msgstr "" #: src/functional/generics-type-classes.md:11 msgid "" "A key part of this idea is the way generic types work. In C++ and Java, for " "example, generic types are a meta-programming construct for the compiler. " "`vector` and `vector` in C++ are just two different copies of the " "same boilerplate code for a `vector` type (known as a `template`) with two " "different types filled in." msgstr "" #: src/functional/generics-type-classes.md:17 msgid "" "In Rust, a generic type parameter creates what is known in functional " "languages as a \"type class constraint\", and each different parameter " "filled in by an end user _actually changes the type_. In other words, " "`Vec` and `Vec` _are two different types_, which are recognized " "as distinct by all parts of the type system." msgstr "" #: src/functional/generics-type-classes.md:23 msgid "" "This is called **monomorphization**, where different types are created from " "**polymorphic** code. This special behavior requires `impl` blocks to " "specify generic parameters. Different values for the generic type cause " "different types, and different types can have different `impl` blocks." msgstr "" #: src/functional/generics-type-classes.md:28 msgid "" "In object-oriented languages, classes can inherit behavior from their " "parents. However, this allows the attachment of not only additional behavior " "to particular members of a type class, but extra behavior as well." msgstr "" #: src/functional/generics-type-classes.md:32 msgid "" "The nearest equivalent is the runtime polymorphism in Javascript and Python, " "where new members can be added to objects willy-nilly by any constructor. " "However, unlike those languages, all of Rust's additional methods can be " "type checked when they are used, because their generics are statically " "defined. That makes them more usable while remaining safe." msgstr "" #: src/functional/generics-type-classes.md:40 msgid "" "Suppose you are designing a storage server for a series of lab machines. " "Because of the software involved, there are two different protocols you need " "to support: BOOTP (for PXE network boot), and NFS (for remote mount storage)." msgstr "" #: src/functional/generics-type-classes.md:44 msgid "" "Your goal is to have one program, written in Rust, which can handle both of " "them. It will have protocol handlers and listen for both kinds of requests. " "The main application logic will then allow a lab administrator to configure " "storage and security controls for the actual files." msgstr "" #: src/functional/generics-type-classes.md:49 msgid "" "The requests from machines in the lab for files contain the same basic " "information, no matter what protocol they came from: an authentication " "method, and a file name to retrieve. A straightforward implementation would " "look something like this:" msgstr "" #: src/functional/generics-type-classes.md:66 msgid "" "This design might work well enough. But now suppose you needed to support " "adding metadata that was _protocol specific_. For example, with NFS, you " "wanted to determine what their mount point was in order to enforce " "additional security rules." msgstr "" #: src/functional/generics-type-classes.md:71 msgid "" "The way the current struct is designed leaves the protocol decision until " "runtime. That means any method that applies to one protocol and not the " "other requires the programmer to do a runtime check." msgstr "" #: src/functional/generics-type-classes.md:75 msgid "Here is how getting an NFS mount point would look:" msgstr "" #: src/functional/generics-type-classes.md:85 msgid "// ... other methods ...\n" msgstr "" #: src/functional/generics-type-classes.md:87 msgid "" "/// Gets an NFS mount point if this is an NFS request. Otherwise,\n" " /// return None.\n" msgstr "" #: src/functional/generics-type-classes.md:95 msgid "" "Every caller of `mount_point()` must check for `None` and write code to " "handle it. This is true even if they know only NFS requests are ever used in " "a given code path!" msgstr "" #: src/functional/generics-type-classes.md:99 msgid "" "It would be far more optimal to cause a compile-time error if the different " "request types were confused. After all, the entire path of the user's code, " "including what functions from the library they use, will know whether a " "request is an NFS request or a BOOTP request." msgstr "" #: src/functional/generics-type-classes.md:104 msgid "" "In Rust, this is actually possible! The solution is to _add a generic type_ " "in order to split the API." msgstr "" #: src/functional/generics-type-classes.md:107 msgid "Here is what that looks like:" msgstr "" #: src/functional/generics-type-classes.md:114 msgid "// NFS session management omitted\n" msgstr "" #: src/functional/generics-type-classes.md:118 msgid "// no authentication in bootp\n" msgstr "" #: src/functional/generics-type-classes.md:120 msgid "// private module, lest outside users invent their own protocol kinds!\n" msgstr "" #: src/functional/generics-type-classes.md:149 msgid "// no additional metadata\n" msgstr "" #: src/functional/generics-type-classes.md:159 msgid "// keep internal to prevent impls\n" msgstr "" #: src/functional/generics-type-classes.md:160 msgid "// re-export so callers can see them\n" msgstr "" #: src/functional/generics-type-classes.md:166 msgid "// all common API parts go into a generic impl block\n" msgstr "" #: src/functional/generics-type-classes.md:177 msgid "// all protocol-specific impls go into their own block\n" msgstr "" #: src/functional/generics-type-classes.md:186 msgid "// your code here\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 " "type;" msgstr "" #: src/functional/generics-type-classes.md:197 msgid "\"/secure\"" msgstr "" #: src/functional/generics-type-classes.md:197 msgid "\"Access denied\"" msgstr "" #: src/functional/generics-type-classes.md:198 msgid "// continue on...\n" msgstr "" #: src/functional/generics-type-classes.md:200 msgid "// Rest of the code here\n" msgstr "" #: src/functional/generics-type-classes.md:205 msgid "" "They would get a syntax error. The type `FileDownloadRequest` does " "not implement `mount_point()`, only the type `FileDownloadRequest` " "does. And that is created by the NFS module, not the BOOTP module of course!" msgstr "" #: src/functional/generics-type-classes.md:211 msgid "" "First, it allows fields that are common to multiple states to be " "de-duplicated. By making the non-shared fields generic, they are implemented " "once." msgstr "" #: src/functional/generics-type-classes.md:214 msgid "" "Second, it makes the `impl` blocks easier to read, because they are broken " "down by state. Methods common to all states are typed once in one block, and " "methods unique to one state are in a separate block." msgstr "" #: src/functional/generics-type-classes.md:218 msgid "" "Both of these mean there are fewer lines of code, and they are better " "organized." msgstr "" #: src/functional/generics-type-classes.md:222 msgid "" "This currently increases the size of the binary, due to the way " "monomorphization is implemented in the compiler. Hopefully the " "implementation will be able to improve in the future." msgstr "" #: src/functional/generics-type-classes.md:228 msgid "" "If a type seems to need a \"split API\" due to construction or partial " "initialization, consider the [Builder " "Pattern](../patterns/creational/builder.md) instead." msgstr "" #: src/functional/generics-type-classes.md:232 msgid "" "If the API between types does not change -- only the behavior does -- then " "the [Strategy Pattern](../patterns/behavioural/strategy.md) is better used " "instead." msgstr "" #: src/functional/generics-type-classes.md:238 msgid "This pattern is used throughout the standard library:" msgstr "" #: src/functional/generics-type-classes.md:240 msgid "" "`Vec` can be cast from a String, unlike every other type of `Vec`.[^1]" msgstr "" #: src/functional/generics-type-classes.md:241 msgid "" "Iterators can be cast into a binary heap, but only if they contain a type " "that implements the `Ord` trait.[^2]" msgstr "" #: src/functional/generics-type-classes.md:243 msgid "The `to_string` method was specialized for `Cow` only of type `str`.[^3]" msgstr "" #: src/functional/generics-type-classes.md:245 msgid "It is also used by several popular crates to allow API flexibility:" msgstr "" #: src/functional/generics-type-classes.md:247 msgid "" "The `embedded-hal` ecosystem used for embedded devices makes extensive use " "of this pattern. For example, it allows statically verifying the " "configuration of device registers used to control embedded pins. When a pin " "is put into a mode, it returns a `Pin` struct, whose generic " "determines the functions usable in that mode, which are not on the `Pin` " "itself. [^4]" msgstr "" #: src/functional/generics-type-classes.md:253 msgid "" "The `hyper` HTTP client library uses this to expose rich APIs for different " "pluggable requests. Clients with different connectors have different methods " "on them as well as different trait implementations, while a core set of " "methods apply to any connector. [^5]" msgstr "" #: src/functional/generics-type-classes.md:258 msgid "" "The \"type state\" pattern -- where an object gains and loses API based on " "an internal state or invariant -- is implemented in Rust using the same " "basic concept, and a slightly different technique. [^6]" msgstr "" #: src/functional/generics-type-classes.md:262 msgid "" "See: [impl From\\ for " "Vec\\](https://doc.rust-lang.org/1.59.0/src/std/ffi/c_str.rs.html#803-811)" msgstr "" #: src/functional/generics-type-classes.md:265 msgid "" "See: [impl\\ FromIterator\\ for " "BinaryHeap\\](https://web.archive.org/web/20201030132806/https://doc.rust-lang.org/stable/src/alloc/collections/binary_heap.rs.html#1330-1335)" msgstr "" #: src/functional/generics-type-classes.md:268 msgid "" "See: [impl\\<'\\_\\> ToString for Cow\\<'\\_, " "str>](https://doc.rust-lang.org/stable/src/alloc/string.rs.html#2235-2240)" msgstr "" #: src/functional/generics-type-classes.md:271 msgid "" "Example: " "[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 "" #: src/functional/generics-type-classes.md:274 msgid "" "See: " "[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 "" #: src/functional/generics-type-classes.md:277 msgid "" "See: [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/) " "and [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 "" #: src/functional/optics.md:1 msgid "Functional Language Optics" msgstr "" #: src/functional/optics.md:3 msgid "" "Optics is a type of API design that is common to functional languages. This " "is a pure functional concept that is not frequently used in Rust." msgstr "" #: src/functional/optics.md:6 msgid "" "Nevertheless, exploring the concept may be helpful to understand other " "patterns in Rust APIs, such as " "[visitors](../patterns/behavioural/visitor.md). They also have niche use " "cases." msgstr "" #: src/functional/optics.md:10 msgid "" "This is quite a large topic, and would require actual books on language " "design to fully get into its abilities. However their applicability in Rust " "is much simpler." msgstr "" #: src/functional/optics.md:14 msgid "" "To explain the relevant parts of the concept, the `Serde`\\-API will be used " "as an example, as it is one that is difficult for many to understand from " "simply the API documentation." msgstr "" #: src/functional/optics.md:18 msgid "" "In the process, different specific patterns, called Optics, will be covered. " "These are _The Iso_, _The Poly Iso_, and _The Prism_." msgstr "" #: src/functional/optics.md:21 msgid "An API Example: Serde" msgstr "" #: src/functional/optics.md:23 msgid "" "Trying to understand the way _Serde_ works by only reading the API is a " "challenge, especially the first time. Consider the `Deserializer` trait, " "implemented by any library which parses a new data format:" msgstr "" #: src/functional/optics.md:39 src/functional/optics.md:61 #: src/functional/optics.md:379 src/functional/optics.md:401 msgid "// remainder omitted\n" msgstr "" #: src/functional/optics.md:43 msgid "And here's the definition of the `Visitor` trait passed in generically:" msgstr "" #: src/functional/optics.md:65 msgid "" "There is a lot of type erasure going on here, with multiple levels of " "associated types being passed back and forth." msgstr "" #: src/functional/optics.md:68 msgid "" "But what is the big picture? Why not just have the `Visitor` return the " "pieces the caller needs in a streaming API, and call it a day? Why all the " "extra pieces?" msgstr "" #: src/functional/optics.md:72 msgid "" "One way to understand it is to look at a functional languages concept called " "_optics_." msgstr "" #: src/functional/optics.md:75 msgid "" "This is a way to do composition of behavior and proprieties that is designed " "to facilitate patterns common to Rust: failure, type transformation, etc.[^1]" msgstr "" #: src/functional/optics.md:78 msgid "" "The Rust language does not have very good support for these directly. " "However, they appear in the design of the language itself, and their " "concepts can help to understand some of Rust's APIs. As a result, this " "attempts to explain the concepts with the way Rust does it." msgstr "" #: src/functional/optics.md:83 msgid "" "This will perhaps shed light on what those APIs are achieving: specific " "properties of composability." msgstr "" #: src/functional/optics.md:86 msgid "Basic Optics" msgstr "" #: src/functional/optics.md:88 msgid "The Iso" msgstr "" #: src/functional/optics.md:90 msgid "" "The Iso is a value transformer between two types. It is extremely simple, " "but a conceptually important building block." msgstr "" #: src/functional/optics.md:93 msgid "" "As an example, suppose that we have a custom Hash table structure used as a " "concordance for a document.[^2] It uses strings for keys (words) and a list " "of indexes for values (file offsets, for instance)." msgstr "" #: src/functional/optics.md:97 msgid "" "A key feature is the ability to serialize this format to disk. A \"quick and " "dirty\" approach would be to implement a conversion to and from a string in " "JSON format. (Errors are ignored for the time being, they will be handled " "later.)" msgstr "" #: src/functional/optics.md:101 msgid "To write it in a normal form expected by functional language users:" msgstr "" #: src/functional/optics.md:110 msgid "" "The Iso is thus a pair of functions which convert values of different types: " "`serialize` and `deserialize`." msgstr "" #: src/functional/optics.md:113 msgid "A straightforward implementation:" msgstr "" #: src/functional/optics.md:129 msgid "// invalid concordances are empty\n" msgstr "" #: src/functional/optics.md:136 msgid "" "This may seem rather silly. In Rust, this type of behavior is typically done " "with traits. After all, the standard library has `FromStr` and `ToString` in " "it." msgstr "" #: src/functional/optics.md:139 msgid "But that is where our next subject comes in: Poly Isos." msgstr "" #: src/functional/optics.md:141 msgid "Poly Isos" msgstr "" #: src/functional/optics.md:143 msgid "" "The previous example was simply converting between values of two fixed " "types. This next block builds upon it with generics, and is more interesting." msgstr "" #: src/functional/optics.md:146 msgid "" "Poly Isos allow an operation to be generic over any type while returning a " "single type." msgstr "" #: src/functional/optics.md:149 msgid "" "This brings us closer to parsing. Consider what a basic parser would do " "ignoring error cases. Again, this is its normal form:" msgstr "" #: src/functional/optics.md:159 msgid "Here we have our first generic, the type `T` being converted." msgstr "" #: src/functional/optics.md:161 msgid "" "In Rust, this could be implemented with a pair of traits in the standard " "library: `FromStr` and `ToString`. The Rust version even handles errors:" msgstr "" #: src/functional/optics.md:176 msgid "" "Unlike the Iso, the Poly Iso allows application of multiple types, and " "returns them generically. This is what you would want for a basic string " "parser." msgstr "" #: src/functional/optics.md:179 msgid "" "At first glance, this seems like a good option for writing a parser. Let's " "see it in action:" msgstr "" #: src/functional/optics.md:208 src/functional/optics.md:282 msgid "\"hello\"" msgstr "" #: src/functional/optics.md:210 msgid "\"Our Test Struct as JSON: {}\"" msgstr "" #: src/functional/optics.md:214 msgid "That seems quite logical. However, there are two problems with this." msgstr "" #: src/functional/optics.md:216 msgid "" "First, `to_string` does not indicate to API users, \"this is JSON.\" Every " "type would need to agree on a JSON representation, and many of the types in " "the Rust standard library already don't. Using this is a poor fit. This can " "easily be resolved with our own trait." msgstr "" #: src/functional/optics.md:221 msgid "But there is a second, subtler problem: scaling." msgstr "" #: src/functional/optics.md:223 msgid "" "When every type writes `to_string` by hand, this works. But if every single " "person who wants their type to be serializable has to write a bunch of code " "-- and possibly different JSON libraries -- to do it themselves, it will " "turn into a mess very quickly!" msgstr "" #: src/functional/optics.md:228 msgid "" "The answer is one of Serde's two key innovations: an independent data model " "to represent Rust data in structures common to data serialization languages. " "The result is that it can use Rust's code generation abilities to create an " "intermediary conversion type it calls a `Visitor`." msgstr "" #: src/functional/optics.md:233 msgid "" "This means, in normal form (again, skipping error handling for simplicity):" msgstr "" #: src/functional/optics.md:247 msgid "" "The result is one Poly Iso and one Iso (respectively). Both of these can be " "implemented with traits:" msgstr "" #: src/functional/optics.md:263 msgid "" "Because there is a uniform set of rules to transform Rust structures to the " "independent form, it is even possible to have code generation creating the " "`Visitor` associated with type `T`:" msgstr "" #: src/functional/optics.md:268 msgid "// the \"Serde\" derive creates the trait impl block\n" msgstr "" #: src/functional/optics.md:273 msgid "// user writes this macro to generate an associated visitor type\n" msgstr "" #: src/functional/optics.md:278 msgid "But let's actually try that approach." msgstr "" #: src/functional/optics.md:284 msgid "\"Our Test Struct as JSON: {a_data}\"" msgstr "" #: src/functional/optics.md:290 msgid "" "It turns out that the conversion isn't symmetric after all! On paper it is, " "but with the auto-generated code the name of the actual type necessary to " "convert all the way from `String` is hidden. We'd need some kind of " "`generated_visitor_for!` macro to obtain the type name." msgstr "" #: src/functional/optics.md:295 msgid "It's wonky, but it works... until we get to the elephant in the room." msgstr "" #: src/functional/optics.md:297 msgid "" "The only format currently supported is JSON. How would we support more " "formats?" msgstr "" #: src/functional/optics.md:299 msgid "" "The current design requires completely re-writing all of the code generation " "and creating a new Serde trait. That is quite terrible and not extensible at " "all!" msgstr "" #: src/functional/optics.md:302 msgid "In order to solve that, we need something more powerful." msgstr "" #: src/functional/optics.md:304 msgid "Prism" msgstr "" #: src/functional/optics.md:306 msgid "To take format into account, we need something in normal form like this:" msgstr "" #: src/functional/optics.md:315 msgid "" "This construct is called a Prism. It is \"one level higher\" in generics " "than Poly Isos (in this case, the \"intersecting\" type F is the key)." msgstr "" #: src/functional/optics.md:318 msgid "" "Unfortunately because `Visitor` is a trait (since each incarnation requires " "its own custom code), this would require a kind of generic type boundary " "that Rust does not support." msgstr "" #: src/functional/optics.md:322 msgid "" "Fortunately, we still have that `Visitor` type from before. What is the " "`Visitor` doing? It is attempting to allow each data structure to define the " "way it is itself parsed." msgstr "" #: src/functional/optics.md:326 msgid "" "Well what if we could add one more interface for the generic format? Then " "the `Visitor` is just an implementation detail, and it would \"bridge\" the " "two APIs." msgstr "" #: src/functional/optics.md:329 msgid "In normal form:" msgstr "" #: src/functional/optics.md:348 msgid "" "And what do you know, a pair of Poly Isos at the bottom which can be " "implemented as traits!" msgstr "" #: src/functional/optics.md:351 msgid "Thus we have the Serde API:" msgstr "" #: src/functional/optics.md:353 msgid "" "Each type to be serialized implements `Deserialize` or `Serialize`, " "equivalent to the `Serde` class" msgstr "" #: src/functional/optics.md:355 msgid "" "They get a type (well two, one for each direction) implementing the " "`Visitor` trait, which is usually (but not always) done through code " "generated by a derive macro. This contains the logic to construct or " "destruct between the data type and the format of the Serde data model." msgstr "" #: src/functional/optics.md:359 msgid "" "The type implementing the `Deserializer` trait handles all details specific " "to the format, being \"driven by\" the `Visitor`." msgstr "" #: src/functional/optics.md:362 msgid "" "This splitting and Rust type erasure is really to achieve a Prism through " "indirection." msgstr "" #: src/functional/optics.md:365 msgid "You can see it on the `Deserializer` trait" msgstr "" #: src/functional/optics.md:383 msgid "And the visitor:" msgstr "" #: src/functional/optics.md:405 msgid "And the trait `Deserialize` implemented by the macros:" msgstr "" #: src/functional/optics.md:415 msgid "This has been abstract, so let's look at a concrete example." msgstr "" #: src/functional/optics.md:417 msgid "" "How does actual Serde deserialize a bit of JSON into `struct Concordance` " "from earlier?" msgstr "" #: src/functional/optics.md:420 msgid "" "The user would call a library function to deserialize the data. This would " "create a `Deserializer` based on the JSON format." msgstr "" #: src/functional/optics.md:422 msgid "" "Based on the fields in the struct, a `Visitor` would be created (more on " "that in a moment) which knows how to create each type in a generic data " "model that was needed to represent it: `Vec` (list), `u64` and `String`." msgstr "" #: src/functional/optics.md:425 msgid "The deserializer would make calls to the `Visitor` as it parsed items." msgstr "" #: src/functional/optics.md:426 msgid "" "The `Visitor` would indicate if the items found were expected, and if not, " "raise an error to indicate deserialization has failed." msgstr "" #: src/functional/optics.md:429 msgid "For our very simple structure above, the expected pattern would be:" msgstr "" #: src/functional/optics.md:431 msgid "" "Begin visiting a map (_Serde_'s equivalent to `HashMap` or JSON's " "dictionary)." msgstr "" #: src/functional/optics.md:433 msgid "Visit a string key called \"keys\"." msgstr "" #: src/functional/optics.md:434 msgid "Begin visiting a map value." msgstr "" #: src/functional/optics.md:435 msgid "For each item, visit a string key then an integer value." msgstr "" #: src/functional/optics.md:436 src/functional/optics.md:443 msgid "Visit the end of the map." msgstr "" #: src/functional/optics.md:437 msgid "Store the map into the `keys` field of the data structure." msgstr "" #: src/functional/optics.md:438 msgid "Visit a string key called \"value_table\"." msgstr "" #: src/functional/optics.md:439 msgid "Begin visiting a list value." msgstr "" #: src/functional/optics.md:440 msgid "For each item, visit an integer." msgstr "" #: src/functional/optics.md:441 msgid "Visit the end of the list" msgstr "" #: src/functional/optics.md:442 msgid "Store the list into the `value_table` field." msgstr "" #: src/functional/optics.md:445 msgid "But what determines which \"observation\" pattern is expected?" msgstr "" #: src/functional/optics.md:447 msgid "" "A functional programming language would be able to use currying to create " "reflection of each type based on the type itself. Rust does not support " "that, so every single type would need to have its own code written based on " "its fields and their properties." msgstr "" #: src/functional/optics.md:452 msgid "_Serde_ solves this usability challenge with a derive macro:" msgstr "" #: src/functional/optics.md:464 msgid "" "That macro simply generates an impl block causing the struct to implement a " "trait called `Deserialize`." msgstr "" #: src/functional/optics.md:467 msgid "" "This is the function that determines how to create the struct itself. Code " "is generated based on the struct's fields. When the parsing library is " "called - in our example, a JSON parsing library - it creates a " "`Deserializer` and calls `Type::deserialize` with it as a parameter." msgstr "" #: src/functional/optics.md:472 msgid "" "The `deserialize` code will then create a `Visitor` which will have its " "calls \"refracted\" by the `Deserializer`. If everything goes well, " "eventually that `Visitor` will construct a value corresponding to the type " "being parsed and return it." msgstr "" #: src/functional/optics.md:477 msgid "" "For a complete example, see the [_Serde_ " "documentation](https://serde.rs/deserialize-struct.html)." msgstr "" #: src/functional/optics.md:480 msgid "" "The result is that types to be deserialized only implement the \"top layer\" " "of the API, and file formats only need to implement the \"bottom layer\". " "Each piece can then \"just work\" with the rest of the ecosystem, since " "generic types will bridge them." msgstr "" #: src/functional/optics.md:485 msgid "" "In conclusion, Rust's generic-inspired type system can bring it close to " "these concepts and use their power, as shown in this API design. But it may " "also need procedural macros to create bridges for its generics." msgstr "" #: src/functional/optics.md:489 msgid "" "If you are interested in learning more about this topic, please check the " "following section." msgstr "" #: src/functional/optics.md:492 msgid "See Also" msgstr "" #: src/functional/optics.md:494 msgid "" "[lens-rs crate](https://crates.io/crates/lens-rs) for a pre-built lenses " "implementation, with a cleaner interface than these examples" msgstr "" #: src/functional/optics.md:496 msgid "" "[Serde](https://serde.rs) itself, which makes these concepts intuitive for " "end users (i.e. defining the structs) without needing to understand the " "details" msgstr "" #: src/functional/optics.md:498 msgid "" "[luminance](https://github.com/phaazon/luminance-rs) is a crate for drawing " "computer graphics that uses similar API design, including procedural macros " "to create full prisms for buffers of different pixel types that remain " "generic" msgstr "" #: src/functional/optics.md:501 msgid "" "[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) " "that is very readable even without Scala expertise." msgstr "" #: src/functional/optics.md:503 msgid "" "[Paper: Profunctor Optics: Modular Data " "Accessors](https://web.archive.org/web/20220701102832/https://arxiv.org/ftp/arxiv/papers/1703/1703.10857.pdf)" msgstr "" #: src/functional/optics.md:505 msgid "" "[Musli](https://github.com/udoprog/musli) is a library which attempts to use " "a similar structure with a different approach, e.g. doing away with the " "visitor" msgstr "" #: src/functional/optics.md:508 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 "" #: src/functional/optics.md:510 msgid "" "[Concordance on " "Wikipedia](https://en.wikipedia.org/wiki/Concordance_(publishing))" msgstr "" #: src/additional_resources/index.md:1 msgid "Additional resources" msgstr "" #: src/additional_resources/index.md:3 msgid "A collection of complementary helpful content" msgstr "" #: src/additional_resources/index.md:5 msgid "Talks" msgstr "" #: src/additional_resources/index.md:7 msgid "" "[Design Patterns in Rust](https://www.youtube.com/watch?v=Pm_oO0N5B9k) by " "Nicholas Cameron at the PDRust (2016)" msgstr "" #: src/additional_resources/index.md:9 msgid "" "[Writing Idiomatic Libraries in " "Rust](https://www.youtube.com/watch?v=0zOg8_B71gE) by Pascal Hertleif at " "RustFest (2017)" msgstr "" #: src/additional_resources/index.md:11 msgid "" "[Rust Programming Techniques](https://www.youtube.com/watch?v=vqavdUGKeb4) " "by Nicholas Cameron at LinuxConfAu (2018)" msgstr "" #: src/additional_resources/index.md:14 msgid "Books (Online)" msgstr "" #: src/additional_resources/index.md:16 msgid "[The Rust API Guidelines](https://rust-lang.github.io/api-guidelines)" msgstr "" #: src/additional_resources/design-principles.md:3 msgid "A brief overview over common design principles" msgstr "" #: src/additional_resources/design-principles.md:7 msgid "[SOLID](https://en.wikipedia.org/wiki/SOLID)" msgstr "" #: src/additional_resources/design-principles.md:9 msgid "" "[Single Responsibility Principle " "(SRP)](https://en.wikipedia.org/wiki/Single-responsibility_principle): A " "class should only have a single responsibility, that is, only changes to one " "part of the software's specification should be able to affect the " "specification of the class." msgstr "" #: src/additional_resources/design-principles.md:13 msgid "" "[Open/Closed Principle " "(OCP)](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle): " "\"Software entities ... should be open for extension, but closed for " "modification.\"" msgstr "" #: src/additional_resources/design-principles.md:16 msgid "" "[Liskov Substitution Principle " "(LSP)](https://en.wikipedia.org/wiki/Liskov_substitution_principle): " "\"Objects in a program should be replaceable with instances of their " "subtypes without altering the correctness of that program.\"" msgstr "" #: src/additional_resources/design-principles.md:19 msgid "" "[Interface Segregation Principle " "(ISP)](https://en.wikipedia.org/wiki/Interface_segregation_principle): " "\"Many client-specific interfaces are better than one general-purpose " "interface.\"" msgstr "" #: src/additional_resources/design-principles.md:22 msgid "" "[Dependency Inversion Principle " "(DIP)](https://en.wikipedia.org/wiki/Dependency_inversion_principle): One " "should \"depend upon abstractions, \\[not\\] concretions.\"" msgstr "" #: src/additional_resources/design-principles.md:25 msgid "" "[CRP (Composite Reuse Principle) or Composition over " "inheritance](https://en.wikipedia.org/wiki/Composition_over_inheritance)" msgstr "" #: src/additional_resources/design-principles.md:27 msgid "" "“a the principle that classes should favor polymorphic behavior and code " "reuse by their composition (by containing instances of other classes that " "implement the desired functionality) over inheritance from a base or parent " "class” - Knoernschild, Kirk (2002). Java Design - Objects, UML, and Process" msgstr "" #: src/additional_resources/design-principles.md:32 msgid "" "[DRY (Don’t Repeat " "Yourself)](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)" msgstr "" #: src/additional_resources/design-principles.md:34 msgid "" "\"Every piece of knowledge must have a single, unambiguous, authoritative " "representation within a system\"" msgstr "" #: src/additional_resources/design-principles.md:37 msgid "[KISS principle](https://en.wikipedia.org/wiki/KISS_principle)" msgstr "" #: src/additional_resources/design-principles.md:39 msgid "" "most systems work best if they are kept simple rather than made complicated; " "therefore, simplicity should be a key goal in design, and unnecessary " "complexity should be avoided" msgstr "" #: src/additional_resources/design-principles.md:43 msgid "[Law of Demeter (LoD)](https://en.wikipedia.org/wiki/Law_of_Demeter)" msgstr "" #: src/additional_resources/design-principles.md:45 msgid "" "a given object should assume as little as possible about the structure or " "properties of anything else (including its subcomponents), in accordance " "with the principle of \"information hiding\"" msgstr "" #: src/additional_resources/design-principles.md:49 msgid "" "[Design by contract (DbC)](https://en.wikipedia.org/wiki/Design_by_contract)" msgstr "" #: src/additional_resources/design-principles.md:51 msgid "" "software designers should define formal, precise and verifiable interface " "specifications for software components, which extend the ordinary definition " "of abstract data types with preconditions, postconditions and invariants" msgstr "" #: src/additional_resources/design-principles.md:55 msgid "" "[Encapsulation](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming))" msgstr "" #: src/additional_resources/design-principles.md:57 msgid "" "bundling of data with the methods that operate on that data, or the " "restricting of direct access to some of an object's components. " "Encapsulation is used to hide the values or state of a structured data " "object inside a class, preventing unauthorized parties' direct access to " "them." msgstr "" #: src/additional_resources/design-principles.md:62 msgid "" "[Command-Query-Separation " "(CQS)](https://en.wikipedia.org/wiki/Command%E2%80%93query_separation)" msgstr "" #: src/additional_resources/design-principles.md:64 msgid "" "“Functions should not produce abstract side effects...only commands " "(procedures) will be permitted to produce side effects.” - Bertrand Meyer: " "Object-Oriented Software Construction" msgstr "" #: src/additional_resources/design-principles.md:68 msgid "" "[Principle of least astonishment " "(POLA)](https://en.wikipedia.org/wiki/Principle_of_least_astonishment)" msgstr "" #: src/additional_resources/design-principles.md:70 msgid "" "a component of a system should behave in a way that most users will expect " "it to behave. The behavior should not astonish or surprise users" msgstr "" #: src/additional_resources/design-principles.md:73 msgid "Linguistic-Modular-Units" msgstr "" #: src/additional_resources/design-principles.md:75 msgid "" "“Modules must correspond to syntactic units in the language used.” - " "Bertrand Meyer: Object-Oriented Software Construction" msgstr "" #: src/additional_resources/design-principles.md:78 msgid "Self-Documentation" msgstr "" #: src/additional_resources/design-principles.md:80 msgid "" "“The designer of a module should strive to make all information about the " "module part of the module itself.” - Bertrand Meyer: Object-Oriented " "Software Construction" msgstr "" #: src/additional_resources/design-principles.md:84 msgid "Uniform-Access" msgstr "" #: src/additional_resources/design-principles.md:86 msgid "" "“All services offered by a module should be available through a uniform " "notation, which does not betray whether they are implemented through storage " "or through computation.” - Bertrand Meyer: Object-Oriented Software " "Construction" msgstr "" #: src/additional_resources/design-principles.md:90 msgid "Single-Choice" msgstr "" #: src/additional_resources/design-principles.md:92 msgid "" "“Whenever a software system must support a set of alternatives, one and only " "one module in the system should know their exhaustive list.” - Bertrand " "Meyer: Object-Oriented Software Construction" msgstr "" #: src/additional_resources/design-principles.md:96 msgid "Persistence-Closure" msgstr "" #: src/additional_resources/design-principles.md:98 msgid "" "“Whenever a storage mechanism stores an object, it must store with it the " "dependents of that object. Whenever a retrieval mechanism retrieves a " "previously stored object, it must also retrieve any dependent of that object " "that has not yet been retrieved.” - Bertrand Meyer: Object-Oriented Software " "Construction" msgstr "" ================================================ FILE: po/pt-BR.po ================================================ msgid "" msgstr "" "Project-Id-Version: Rust Design Patterns\n" "POT-Creation-Date: \n" "PO-Revision-Date: 2023-04-08 21:56+0200\n" "Last-Translator: \n" "Language-Team: Language pt-BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pt-BR\n" "Plural-Forms: nplurals=1; plural=0;\n" #: src\SUMMARY.md:3 #, fuzzy msgid "Introduction" msgstr "Introdução" #: src\SUMMARY.md:4 #, fuzzy msgid "Translations" msgstr "Traduções" #: src\SUMMARY.md:5 #, fuzzy msgid "Idioms" msgstr "expressões idiomáticas" #: src\SUMMARY.md:6 #, fuzzy msgid "Use borrowed types for arguments" msgstr "Use tipos emprestados para argumentos" #: src\SUMMARY.md:7 #, fuzzy msgid "Concatenating Strings with format!" msgstr "Concatenando Strings com formato!" #: src\SUMMARY.md:8 #, fuzzy msgid "Constructor" msgstr "Construtor" #: src\SUMMARY.md:9 #, fuzzy msgid "The Default Trait" msgstr "A característica padrão" #: src\SUMMARY.md:10 #, fuzzy msgid "Collections Are Smart Pointers" msgstr "Coleções são ponteiros inteligentes" #: src\SUMMARY.md:11 #, fuzzy msgid "Finalisation in Destructors" msgstr "Finalização em Destruidores" #: src\SUMMARY.md:12 #, fuzzy msgid "mem::{take(_), replace(_)}" msgstr "mem::{pegar(_), substituir(_)}" #: src\SUMMARY.md:13 #, fuzzy msgid "On-Stack Dynamic Dispatch" msgstr "Despacho dinâmico na pilha" #: src\SUMMARY.md:14 src\SUMMARY.md:40 #, fuzzy msgid "Foreign function interface (FFI)" msgstr "Interface de função externa (FFI)" #: src\SUMMARY.md:15 #, fuzzy msgid "Idiomatic Errors" msgstr "Erros idiomáticos" #: src\SUMMARY.md:16 #, fuzzy msgid "Accepting Strings" msgstr "Aceitando Strings" #: src\SUMMARY.md:17 #, fuzzy msgid "Passing Strings" msgstr "Cordas de passagem" #: src\SUMMARY.md:18 #, fuzzy msgid "Iterating over an Option" msgstr "Iterando sobre uma opção" #: src\SUMMARY.md:19 #, fuzzy msgid "Pass Variables to Closure" msgstr "Passar Variáveis para Encerramento" #: src\SUMMARY.md:20 #, fuzzy msgid "Privacy For Extensibility" msgstr "Privacidade para Extensibilidade" #: src\SUMMARY.md:21 #, fuzzy msgid "Easy doc initialization" msgstr "Fácil inicialização do documento" #: src\SUMMARY.md:22 #, fuzzy msgid "Temporary mutability" msgstr "Mutabilidade temporária" #: src\SUMMARY.md:23 #, fuzzy msgid "Return consumed arg on error" msgstr "Retorno arg consumido em caso de erro" #: src\SUMMARY.md:25 #, fuzzy msgid "Design Patterns" msgstr "Padrões de design" #: src\SUMMARY.md:26 #, fuzzy msgid "Behavioural" msgstr "Comportamental" #: src\SUMMARY.md:27 #, fuzzy msgid "Command" msgstr "Comando" #: src\SUMMARY.md:28 #, fuzzy msgid "Interpreter" msgstr "Intérprete" #: src\SUMMARY.md:29 #, fuzzy msgid "Newtype" msgstr "Newtype" #: src\SUMMARY.md:30 #, fuzzy msgid "RAII Guards" msgstr "Guardas RAII" #: src\SUMMARY.md:31 #, fuzzy msgid "Strategy" msgstr "Estratégia" #: src\SUMMARY.md:32 #, fuzzy msgid "Visitor" msgstr "Visitante" #: src\SUMMARY.md:33 #, fuzzy msgid "Creational" msgstr "criacional" #: src\SUMMARY.md:34 #, fuzzy msgid "Builder" msgstr "Construtor" #: src\SUMMARY.md:35 #, fuzzy msgid "Fold" msgstr "Dobrar" #: src\SUMMARY.md:36 #, fuzzy msgid "Structural" msgstr "Estrutural" #: src\SUMMARY.md:37 #, fuzzy msgid "Compose Structs" msgstr "Compor Estruturas" #: src\SUMMARY.md:38 #, fuzzy msgid "Prefer Small Crates" msgstr "Prefira caixas pequenas" #: src\SUMMARY.md:39 #, fuzzy msgid "Contain unsafety in small modules" msgstr "Contenha a insegurança em pequenos módulos" #: src\SUMMARY.md:41 #, fuzzy msgid "Object-Based APIs" msgstr "APIs baseadas em objetos" #: src\SUMMARY.md:42 #, fuzzy msgid "Type Consolidation into Wrappers" msgstr "Digite a consolidação em wrappers" #: src\SUMMARY.md:44 #, fuzzy msgid "Anti-patterns" msgstr "Antipadrões" #: src\SUMMARY.md:45 #, fuzzy msgid "Clone to satisfy the borrow checker" msgstr "Clone para satisfazer o verificador de empréstimo" #: src\SUMMARY.md:46 #, fuzzy msgid "#[deny(warnings)]" msgstr "#[negar(avisos)]" #: src\SUMMARY.md:47 #, fuzzy msgid "Deref Polymorphism" msgstr "Polimorfismo Deref" #: src\SUMMARY.md:49 #, fuzzy msgid "Functional Programming" msgstr "Programação Funcional" #: src\SUMMARY.md:50 #, fuzzy msgid "Programming paradigms" msgstr "Paradigmas de programação" #: src\SUMMARY.md:51 #, fuzzy msgid "Generics as Type Classes" msgstr "Genéricos como Classes de Tipo" #: src\SUMMARY.md:52 #, fuzzy msgid "Lenses and Prisms" msgstr "Lentes e Prismas" #: src\SUMMARY.md:54 #, fuzzy msgid "Additional Resources" msgstr "Recursos adicionais" #: src\SUMMARY.md:55 #, fuzzy msgid "Design principles" msgstr "Princípios de design" #: src\intro.md:1 #, fuzzy msgid "# Introduction" msgstr "# Introdução" #: src\intro.md:3 #, fuzzy msgid "## Participation" msgstr "## Participação" #: 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 você estiver interessado em contribuir para este livro, confira o\n" "[diretrizes de " "contribuição](https://github.com/rust-unofficial/patterns/blob/master/CONTRIBUTING.md)." #: src\intro.md:8 #, fuzzy msgid "## Design patterns" msgstr "## Padrões de design" #: 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 "" "No desenvolvimento de software, muitas vezes nos deparamos com problemas que " "compartilham\n" "semelhanças independentemente do ambiente em que aparecem.\n" "detalhes de implementação são cruciais para resolver a tarefa em mãos, " "podemos\n" "abstrair dessas particularidades para encontrar as práticas comuns que\n" "são genericamente aplicáveis." #: 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 "" "Padrões de projeto são uma coleção de soluções reutilizáveis e testadas " "para\n" "problemas recorrentes na engenharia. Eles tornam nosso software mais " "modular,\n" "sustentável e extensível. Além disso, esses padrões fornecem uma\n" "linguagem para desenvolvedores, tornando-os uma excelente ferramenta para\n" "comunicação na solução de problemas em equipes." #: src\intro.md:22 src\patterns/index.md:14 #, fuzzy msgid "## Design patterns in Rust" msgstr "## Padrões de design em 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 não é orientado a objetos, e a combinação de todas as suas " "características,\n" "como elementos funcionais, um sistema de tipo forte e o verificador de " "empréstimo,\n" "torna único.\n" "Por causa disso, os padrões de projeto do Rust variam em relação a outros\n" "linguagens de programação tradicionais orientadas a objetos.\n" "É por isso que decidimos escrever este livro. Esperamos que você goste de " "lê-lo!\n" "O livro está dividido em três capítulos principais:" #: 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): orientações a seguir ao codificar.\n" " Eles são as normas sociais da comunidade.\n" " Você deve quebrá-los apenas se tiver um bom motivo para isso.\n" "- [Padrões de design](./patterns/index.md): métodos para resolver problemas " "comuns\n" " ao codificar.\n" "- [Anti-padrões](./anti_patterns/index.md): métodos para resolver problemas " "comuns\n" " ao codificar.\n" " No entanto, embora os padrões de projeto nos tragam benefícios,\n" " antipadrões criam mais problemas." #: src\translations.md:1 #, fuzzy msgid "# Translations" msgstr "# Traduções" #: 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 "" "Estamos utilizando " "[mdbook-i18n-helper](https://github.com/google/mdbook-i18n-helpers).\n" "Leia sobre como _adicionar_ e _atualizar_ traduções em [seu " "repositório](https://github.com/google/mdbook-i18n-helpers#creating-and-updating-translations)" #: src\translations.md:6 #, fuzzy msgid "## External translations" msgstr "## Traduções externas" #: 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 você quiser adicionar uma tradução, abra um problema no\n" "[repositório principal](https://github.com/rust-unofficial/patterns)." #: src\idioms/index.md:1 #, fuzzy msgid "# Idioms" msgstr "# expressões idiomáticas" #: 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 "" "[idiomas](https://en.wikipedia.org/wiki/Programming_idiom) são comumente " "usados\n" "estilos, diretrizes e padrões amplamente aceitos por uma comunidade.\n" "Escrever código idiomático permite que outros desenvolvedores entendam " "melhor o que é\n" "acontecendo." #: 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 "" "Afinal, o computador só se preocupa com o código de máquina que é gerado\n" "pelo compilador.\n" "Em vez disso, o código-fonte é benéfico principalmente para o " "desenvolvedor.\n" "Então, já que temos essa camada de abstração, por que não torná-la mais " "legível?" #: 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 "> O código existe para ser entendido por humanos, não por computadores." #: src\idioms/coercion-arguments.md:1 #, fuzzy msgid "# Use borrowed types for arguments" msgstr "# Use tipos emprestados para argumentos" #: 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 "## Descrição" #: 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 "" "Usar um alvo de uma coerção deref pode aumentar a flexibilidade do seu " "código\n" "quando você está decidindo qual tipo de argumento usar para um argumento de " "função.\n" "Dessa forma, a função aceitará mais tipos de entrada." #: 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`, or `&T` over `&Box`." msgstr "" "Isso não se limita aos tipos de ponteiro fat ou fat.\n" "Na verdade, você deve sempre preferir usar o **tipo emprestado** em vez de\n" "**emprestar o tipo próprio**.\n" "Como `&str` sobre `&String`, `&[T]` sobre `&Vec` ou `&T` sobre `&Box`." #: 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 "" "Usando tipos emprestados, você pode evitar camadas de indireção para essas " "instâncias\n" "onde o tipo de propriedade já fornece uma camada de indireção. Por exemplo, " "um\n" "`String` tem uma camada de indireção, então um `&String` terá duas camadas " "de\n" "indireção. Podemos evitar isso usando `&str` e deixando `&String`\n" "coagir a um `&str` sempre que a função for invocada." #: 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 "## Exemplo" #: 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` versus using a `&[T]` or using a `&Box` versus a `&T`." msgstr "" "Para este exemplo, vamos ilustrar algumas diferenças para usar `&String` " "como um\n" "argumento de função versus usar um `&str`, mas as ideias também se aplicam " "ao uso\n" "`&Vec` versus usar um `&[T]` ou usar um `&Box` versus um `&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 "" "Considere um exemplo em que desejamos determinar se uma palavra contém três\n" "vogais consecutivas. Não precisamos ser os donos da string para determinar " "isso, então\n" "vai pegar uma referência." #: src\idioms/coercion-arguments.md:30 #, fuzzy msgid "The code might look something like this:" msgstr "O código pode ser algo como isto:" #: 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 "" "Isso funciona bem porque estamos passando um tipo `&String` como parâmetro.\n" "Se removermos os comentários nas duas últimas linhas, o exemplo falhará. " "Esse\n" "é porque um tipo `&str` não será forçado a um tipo `&String`. Nós podemos " "consertar isso\n" "simplesmente modificando o tipo do nosso argumento." #: src\idioms/coercion-arguments.md:67 #, fuzzy msgid "For instance, if we change our function declaration to:" msgstr "Por exemplo, se mudarmos nossa declaração de função para:" #: 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 "então ambas as versões irão compilar e imprimir a mesma saída." #: 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 "" "Mas espere, isso não é tudo! Há mais nesta história.\n" "É provável que você diga a si mesmo: isso não importa, eu nunca serei\n" "usando um `&'static str` como uma entrada de qualquer maneira (como fizemos " "quando usamos `\"Ferris\"`).\n" "Mesmo ignorando este exemplo especial, você ainda pode achar que usar " "`&str`\n" "dar-lhe mais flexibilidade do que usar um `&String`." #: 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 "" "Vamos agora dar um exemplo onde alguém nos dá uma frase, e queremos\n" "determine se alguma das palavras da frase contém três vogais consecutivas.\n" "Provavelmente devemos usar a função que já definimos e simplesmente\n" "alimente cada palavra da frase." #: src\idioms/coercion-arguments.md:91 #, fuzzy msgid "An example of this could look like this:" msgstr "Um exemplo disso poderia ser assim:" #: 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 "" "Executando este exemplo usando nossa função declarada com um tipo de " "argumento `&str`\n" "vai render" #: 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 "" "No entanto, este exemplo não será executado quando nossa função for " "declarada com um\n" "tipo de argumento `&String`. Isso ocorre porque as fatias de string são um " "`&str` e não um\n" "`&String` que exigiria uma alocação para ser convertida em `&String` que\n" "não é implícito, enquanto a conversão de `String` para `&str` é barata e " "implícita." #: 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 "## Veja também" #: 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 "" "- [Rust Language Reference on Type " "Coercions](https://doc.rust-lang.org/reference/type-coercions.html)\n" "- Para mais discussões sobre como lidar com `String` e `&str` veja\n" " [esta série de blogs " "(2015)](https://web.archive.org/web/20201112023149/https://hermanradtke.com/2015/05/03/string-vs-str-in-rust-functions.html " ")\n" " por Herman J. Radtke III" #: src\idioms/concat-format.md:1 #, fuzzy msgid "# Concatenating strings with `format!`" msgstr "# Concatenando strings com `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 "" "É possível construir strings usando os métodos `push` e `push_str` em um\n" "`String` mutável, ou usando seu operador `+`. No entanto, muitas vezes é " "mais\n" "conveniente usar `format!`, especialmente onde há uma mistura de literal e\n" "strings não literais." #: 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 "## Vantagens" #: src\idioms/concat-format.md:27 #, fuzzy msgid "" "Using `format!` is usually the most succinct and readable way to combine " "strings." msgstr "" "Usar `format!` geralmente é a maneira mais sucinta e legível de combinar " "strings." #: 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 "## Desvantagens" #: 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 "" "Geralmente não é a maneira mais eficiente de combinar strings - uma série de " "`push`\n" "operações em uma string mutável é geralmente a mais eficiente (especialmente " "se o\n" "string foi pré-alocada para o tamanho esperado)." #: src\idioms/ctor.md:1 #, fuzzy msgid "# Constructors\r" msgstr "# Construtores\r" #: src\idioms/ctor.md:3 src\idioms/rustdoc-init.md:3 #, fuzzy msgid "## Description\r" msgstr "## Descrição\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 não possui construtores como uma construção de linguagem. Em vez disso, " "o\r\n" "A convenção é usar uma [função associada][função associada] `new` para criar " "um objeto:" #: 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 "## Construtores Padrão\r" #: src\idioms/ctor.md:37 #, fuzzy msgid "" "Rust supports default constructors with the [`Default`][std-default] trait:" msgstr "" "Rust suporta construtores padrão com o atributo [`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 "" "`Padrão` também pode ser derivado se todos os tipos de todos os campos " "implementarem `Padrão`,\r\n" "como eles fazem com `Second`:" #: 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 "" "**Observação:** é comum e esperado que os tipos implementem ambos\r\n" "`Default` e um construtor `new` vazio. `new` é o construtor\r\n" "convenção em Rust, e os usuários esperam que ela exista, então se for\r\n" "razoável para o construtor básico não receber argumentos, então\r\n" "deve, mesmo que seja funcionalmente idêntico ao padrão." #: 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 "" "**Dica:** A vantagem de implementar ou derivar `Default` é que seu tipo\r\n" "agora pode ser usado onde uma implementação `Padrão` é necessária, " "principalmente,\r\n" "qualquer uma das funções [`*or_default` na biblioteca " "padrão][std-or-default]." #: src\idioms/ctor.md:101 #, fuzzy msgid "## See also\r" msgstr "## Veja também\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 "" "- O [idioma padrão](default.md) para uma descrição mais detalhada do\r\n" " Traço `Padrão`.\r\n" "\r\n" "- O [padrão de construtor](../patterns/creational/builder.md) para " "construir\r\n" " objetos onde existem múltiplas configurações.\r\n" "\r\n" "- [Diretrizes de API/C-COMMON-TRAITS][Diretrizes de API/C-COMMON-TRAITS] " "para\r\n" " implementando ambos, `Default` e `new`.\r\n" "\r" #: src\idioms/default.md:1 #, fuzzy msgid "# The `Default` Trait" msgstr "# A Característica `Padrão`" #: 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 "" "Não apenas contêineres de um elemento como `Cow`, `Box` ou `Arc` " "implementam\n" "`Default` para tipos `Default` contidos, pode-se automaticamente\n" "`#[derive(Default)]` para structs cujos campos todos o implementam, então " "quanto mais\n" "tipos implementam `Padrão`, mais útil ele se torna." #: 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 "" "Por outro lado, os construtores podem receber vários argumentos, enquanto " "os\n" "O método `default()` não. Pode até haver vários construtores com\n" "nomes diferentes, mas só pode haver uma implementação `Padrão` por 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,\n" " // Vecs default to empty vector\n" " search_path: Vec,\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 "" "- O idioma [constructor] é outra maneira de gerar instâncias que podem ou " "podem\n" " não ser \"padrão\"\n" "- A documentação [`Padrão`] (role para baixo para ver a lista de " "implementadores)\n" "- [`Option::unwrap_or_default()`]\n" "- [`derivar(novo)`]" #: src\idioms/deref.md:1 #, fuzzy msgid "# Collections are smart pointers" msgstr "# Coleções são ponteiros inteligentes" #: 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 "" "Use o [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html)\n" "característica para tratar coleções como ponteiros inteligentes, oferecendo " "propriedade\n" "e visualizações de dados emprestadas." #: src\idioms/deref.md:11 msgid "" "```rust,ignore\n" "use std::ops::Deref;\n" "\n" "struct Vec {\n" " data: RawVec,\n" " //..\n" "}\n" "\n" "impl Deref for Vec {\n" " type Target = [T];\n" "\n" " fn deref(&self) -> &[T] {\n" " //..\n" " }\n" "}\n" "```" msgstr "" #: src\idioms/deref.md:28 #, fuzzy msgid "" "A `Vec` 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` 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 "" "Um `Vec` é uma coleção proprietária de `T`s, enquanto uma fatia (`&[T]`) " "é um empréstimo\n" "coleção de `T`s. A implementação de `Deref` para `Vec` permite a " "desreferência implícita\n" "de `&Vec` para `&[T]` e inclui o relacionamento na desativação " "automática\n" "pesquisas. A maioria dos métodos que você pode esperar que sejam " "implementados para `Vec`s são\n" "implementado para fatias." #: src\idioms/deref.md:34 #, fuzzy msgid "Also `String` and `&str` have a similar relation." msgstr "Além disso, `String` e `&str` têm uma relação semelhante." #: 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 "## Motivação" #: 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 "" "Propriedade e empréstimo são aspectos-chave da linguagem Rust. Estruturas de " "dados\n" "deve levar em conta essas semânticas adequadamente para dar a um bom " "usuário\n" "experiência. Ao implementar uma estrutura de dados proprietária de seus " "dados, oferecendo uma\n" "A visão emprestada desses dados permite APIs mais flexíveis." #: 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 "" "A maioria dos métodos pode ser implementada apenas para a visão emprestada, " "eles são então\n" "implicitamente disponível para a exibição proprietária." #: src\idioms/deref.md:48 #, fuzzy msgid "Gives clients a choice between borrowing or taking ownership of data." msgstr "" "Dá aos clientes a escolha entre tomar emprestado ou se apropriar dos dados." #: 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 "" "Métodos e características disponíveis apenas por desreferenciação não são " "levados em consideração\n" "ao verificar limites, então programação genérica com estruturas de dados " "usando este\n" "padrão pode se tornar complexo (veja as características `Borrow` e `AsRef`, " "etc.)." #: 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 "## Discussão" #: 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 "" "Ponteiros inteligentes e coleções são análogos: um ponteiro inteligente " "aponta para um único\n" "objeto, enquanto uma coleção aponta para muitos objetos. Do ponto de vista " "de\n" "o sistema de tipo, há pouca diferença entre os dois. Uma coleção possui\n" "seus dados se a única forma de acesso a cada dado for através da coleta e " "do\n" "coleta é responsável por excluir os dados (mesmo em casos de " "compartilhamento\n" "propriedade, algum tipo de visão emprestada pode ser apropriada). Se uma " "coleção possui\n" "seus dados, geralmente é útil fornecer uma visão dos dados como emprestados " "para que\n" "pode ser referenciado várias vezes." #: src\idioms/deref.md:67 #, fuzzy msgid "" "Most smart pointers (e.g., `Foo`) implement `Deref`. 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` " "can\n" "implement `Deref>` where `Bar` is a dynamically sized type " "and\n" "`&Bar` is a borrowed view of the data in `Foo`." msgstr "" "A maioria dos ponteiros inteligentes (por exemplo, `Foo`) implementam " "`Deref`. No entanto,\n" "as coleções geralmente desreferenciarão a um tipo personalizado. `[T]` e " "`str` têm alguns\n" "suporte a idiomas, mas no caso geral, isso não é necessário. `Foo` pode\n" "implemente `Deref>` onde `Bar` é um tipo de tamanho dinâmico " "e\n" "`&Bar` é uma visão emprestada dos dados em `Foo`." #: 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 "" "Normalmente, coleções ordenadas irão implementar `Index` para `Range`s para " "fornecer\n" "sintaxe de corte. O alvo será a visão emprestada." #: 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-padrão](../anti_patterns/deref.md).\n" "- [Documentação para o trait " "`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html)." #: src\idioms/dtor-finally.md:1 #, fuzzy msgid "# Finalisation in destructors" msgstr "# Finalização em destrutores" #: 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 não fornece o equivalente aos blocos `finally` - código que será\n" "executado, não importa como uma função é encerrada. Em vez disso, o " "destruidor de um objeto pode\n" "ser usado para executar o código que deve ser executado antes da saída." #: 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 uma função tiver vários pontos de retorno, a execução do código na saída " "torna-se\n" "difícil e repetitivo (e, portanto, propenso a erros). Este é especialmente o " "caso onde\n" "o retorno é implícito devido a uma macro. Um caso comum é o operador `?` " "que\n" "retorna se o resultado for um `Err`, mas continua se for `Ok`. `?` é usado " "como\n" "um mecanismo de manipulação de exceção, mas ao contrário de Java (que tem " "`finally`), há\n" "não há como agendar o código para execução em casos normais e excepcionais.\n" "Entrar em pânico também sairá de uma função mais cedo." #: src\idioms/dtor-finally.md:44 #, fuzzy msgid "" "Code in destructors will (nearly) always be run - copes with panics, early\n" "returns, etc." msgstr "" "O código em destruidores será (quase) sempre executado - lida com pânicos,\n" "devoluções, etc" #: 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 "" "Não é garantido que os destruidores serão executados. Por exemplo, se houver " "um\n" "loop infinito em uma função ou se a execução de uma função falhar antes de " "sair.\n" "Os destruidores também não são executados no caso de um pânico em um já em " "pânico\n" "fio. Portanto, os destruidores não podem ser usados como finalizadores onde " "é\n" "absolutamente essencial que a finalização aconteça." #: 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 "" "Esse padrão introduz algum código implícito difícil de perceber. Lendo uma " "função\n" "não dá nenhuma indicação clara de destruidores a serem executados na saída. " "isso pode fazer\n" "depuração complicada." #: src\idioms/dtor-finally.md:59 #, fuzzy msgid "" "Requiring an object and `Drop` impl just for finalisation is heavy on " "boilerplate." msgstr "" "Exigir um objeto e impl `Drop` apenas para finalização é pesado em clichê." #: 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`). 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 "" "Existe alguma sutileza sobre como exatamente armazenar o objeto usado como " "um\n" "finalizador. Deve ser mantido vivo até o final da função e deve então ser\n" "destruído. O objeto deve ser sempre um valor ou um ponteiro de propriedade " "exclusiva (por exemplo,\n" "`Box`). Se um ponteiro compartilhado (como `Rc`) for usado, o " "finalizador pode\n" "ser mantido vivo além do tempo de vida da função. Por razões semelhantes, o\n" "finalizer não deve ser movido ou retornado." #: 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 "" "O finalizador deve ser atribuído a uma variável, caso contrário, será " "destruído\n" "imediatamente, em vez de quando sai do escopo. O nome da variável deve " "começar\n" "com `_` se a variável for usada apenas como finalizador, caso contrário, o " "compilador\n" "avisará que o finalizador nunca é usado. No entanto, não chame a variável\n" "`_` sem sufixo - nesse caso será destruído imediatamente." #: 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 "" "No Rust, os destruidores são executados quando um objeto sai do escopo. Isto " "acontece\n" "se chegamos ao final do bloco, há um retorno antecipado ou o programa\n" "pânico. Ao entrar em pânico, Rust desenrola a pilha executando destruidores " "para cada\n" "objeto em cada quadro de pilha. Assim, os destruidores são chamados mesmo " "que o pânico aconteça\n" "em uma função que está sendo chamada." #: 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 um destruidor entrar em pânico enquanto desenrola, não há nenhuma boa " "ação a ser tomada, então Rust\n" "aborta o thread imediatamente, sem executar mais destruidores. Isso " "significa\n" "que os destruidores não são absolutamente garantidos para serem executados. " "Também significa que você\n" "deve tomar cuidado extra em seus destruidores para não entrar em pânico, " "pois pode deixar\n" "recursos em um estado inesperado." #: src\idioms/dtor-finally.md:90 #, fuzzy msgid "[RAII guards](../patterns/behavioural/RAII.md)." msgstr "[guardas 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(_)}` para manter os valores de propriedade em " "enums alterados" #: 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 "" "Digamos que temos um `&mut MyEnum` que tem (pelo menos) duas variantes,\n" "`A { nome: String, x: u8 }` e `B { nome: String }`. Agora queremos mudar\n" "`MyEnum::A` para um `B` se `x` for zero, enquanto mantém `MyEnum::B` intacto." #: src\idioms/mem-replace.md:9 #, fuzzy msgid "We can do this without cloning the `name`." msgstr "Podemos fazer isso sem clonar o `name`." #: 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 "Isso também funciona com mais variantes:" #: 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 "" "Ao trabalhar com enums, podemos querer alterar um valor de enum no lugar, " "talvez\n" "para outra variante. Isso geralmente é feito em duas fases para manter o " "empréstimo\n" "verificador feliz. Na primeira fase, observamos o valor existente e " "procuramos\n" "suas partes para decidir o que fazer a seguir. Na segunda fase, podemos " "condicionalmente\n" "altere o valor (como no exemplo acima)." #: 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 "" "O verificador de empréstimo não nos permitirá remover `name` do enum " "(porque\n" "_algo_ deve estar lá.) É claro que poderíamos nomear `.clone()` e colocar o " "clone\n" "em nosso `MyEnum::B`, mas isso seria uma instância do anti-padrão [Clone " "para satisfazer o verificador de " "empréstimo](../anti_patterns/borrow_clone.md). De qualquer forma, nós\n" "pode evitar a alocação extra alterando `e` apenas com um empréstimo mutável." #: 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` nos permite trocar o valor, substituindo-o por seu valor " "padrão,\n" "e retornando o valor anterior. Para `String`, o valor padrão é um vazio\n" "`String`, que não precisa alocar. Como resultado, obtemos o original\n" "`name` _como um valor de propriedade_. Podemos então envolver isso em outro " "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` é muito semelhante, mas nos permite especificar o " "que\n" "substitua o valor por. Um equivalente à nossa linha `mem::take` seria\n" "`mem::replace(nome, 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 "" "Observe, no entanto, que se estivermos usando uma `Option` e quisermos " "substituir sua\n" "valor com um `None`, o método `take()` de `Option` fornece um valor mais " "curto e\n" "alternativa mais idiomática." #: src\idioms/mem-replace.md:85 #, fuzzy msgid "" "Look ma, no allocation! Also you may feel like Indiana Jones while doing it." msgstr "" "Olha ma, sem alocação! Além disso, você pode se sentir como Indiana Jones ao " "fazê-lo." #: 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 "" "Isso fica um pouco prolixo. Errar repetidamente fará com que você odeie o\n" "verificador de empréstimo. O compilador pode falhar ao otimizar o " "armazenamento duplo,\n" "resultando em desempenho reduzido em oposição ao que você faria em ambientes " "inseguros\n" "línguas." #: 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 "" "Além disso, o tipo que você está tomando precisa implementar o [traço " "`Default`](./default.md). No entanto, se o tipo com o qual você está " "trabalhando não\n" "implementar isso, você pode usar `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 "" "Esse padrão é interessante apenas no Rust. Em idiomas GC'd, você pegaria o\n" "referência ao valor por padrão (e o GC manteria o controle de refs), e em\n" "outras linguagens de baixo nível, como C, você simplesmente criaria um alias " "para o ponteiro e consertaria as coisas\n" "mais tarde." #: 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 "" "No entanto, no Rust, temos que trabalhar um pouco mais para fazer isso. Um " "valor de propriedade\n" "pode ter apenas um dono, então, para retirá-lo, precisamos colocar algo de " "volta –\n" "como Indiana Jones, substituindo o artefato por um saco de areia." #: 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 "" "Isso elimina o [Clone para satisfazer o verificador de " "empréstimo](../anti_patterns/borrow_clone.md)\n" "antipadrão em um caso específico." #: src\idioms/on-stack-dyn-dispatch.md:1 #, fuzzy msgid "# On-Stack Dynamic Dispatch" msgstr "# Despacho Dinâmico On-Stack" #: 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 "" "Podemos despachar dinamicamente vários valores, no entanto, para fazer isso, " "precisamos\n" "para declarar várias variáveis para vincular objetos de tipos diferentes. " "Para estender o\n" "tempo de vida conforme necessário, podemos usar a inicialização condicional " "adiada, como visto\n" "abaixo:" #: src\idioms/on-stack-dyn-dispatch.md:12 msgid "" "```rust\n" "use std::io;\n" "use std::fs;\n" "\n" "# fn main() -> Result<(), Box> {\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 monomorfiza o código por padrão. Isso significa que uma cópia do código " "será\n" "gerado para cada tipo com o qual é usado e otimizado independentemente. " "Enquanto isso\n" "permite um código muito rápido no hot path, também incha o código em locais\n" "onde o desempenho não é essencial, custando assim tempo de compilação e " "cache\n" "uso." #: 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 "" "Felizmente, o Rust nos permite usar o dispatch dinâmico, mas temos que " "perguntar explicitamente\n" "para isso." #: 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 "" "Não precisamos alocar nada no heap. Nem nós precisamos\n" "inicializar algo que não usaremos mais tarde, nem precisamos monomorfizar o\n" "todo o código que segue para funcionar com `File` ou `Stdin`." #: src\idioms/on-stack-dyn-dispatch.md:56 #, fuzzy msgid "The code needs more moving parts than the `Box`-based version:" msgstr "O código precisa de mais partes móveis do que a versão baseada em `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 = 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 "" "Os recém-chegados ao Rust geralmente aprenderão que o Rust exige que todas " "as variáveis sejam\n" "inicializado _antes de usar_, então é fácil ignorar o fato de que _não " "usado_\n" "as variáveis podem muito bem ser não inicializadas. Rust trabalha bastante " "para garantir que este\n" "funciona bem e apenas os valores inicializados são descartados no final de " "sua\n" "escopo." #: src\idioms/on-stack-dyn-dispatch.md:76 #, fuzzy msgid "The example meets all the constraints Rust places on us:" msgstr "O exemplo atende a todas as restrições que Rust nos impõe:" #: 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 "" "- Todas as variáveis são inicializadas antes de serem usadas (neste caso, " "emprestadas)\n" "- Cada variável contém apenas valores de um único tipo. Em nosso exemplo, " "`stdin` é\n" " do tipo `Stdin`, `file` é do tipo `File` e `readable` é do tipo `&mut dyn " "Read`\n" "- Cada valor emprestado sobrevive a todas as referências emprestadas dele" #: 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` directly and use its [`.as_ref()`] method to get " "an\n" " optional reference." msgstr "" "- [Finalização em destruidores](dtor-finally.md) e\n" " [guardas RAII](../patterns/behavioural/RAII.md) podem se beneficiar de um " "controle rígido sobre\n" " vidas.\n" "- Para `Option<&T>`s de referências (mutáveis) preenchidas condicionalmente, " "pode-se\n" " inicialize um `Option` diretamente e use seu método [`.as_ref()`] para " "obter um\n" " referência opcional." #: src\idioms/ffi/intro.md:1 #, fuzzy msgid "# FFI Idioms" msgstr "# Idiomas 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 "" "Escrever código FFI é um curso completo em si.\n" "No entanto, existem vários idiomas aqui que podem atuar como ponteiros e " "evitar\n" "armadilhas para usuários inexperientes de Rust `inseguro`." #: src\idioms/ffi/intro.md:7 #, fuzzy msgid "This section contains idioms that may be useful when doing FFI." msgstr "" "Esta seção contém expressões idiomáticas que podem ser úteis ao fazer 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. [Erros idiomáticos](./errors.md) - Tratamento de erros com códigos " "inteiros e\n" " valores de retorno do sentinela (como ponteiros `NULL`)\n" "\n" "2. [Accepting Strings](./accepting-strings.md) com o mínimo de código " "inseguro\n" "\n" "3. [Passing Strings](./passing-strings.md) para funções FFI" #: src\idioms/ffi/errors.md:1 #, fuzzy msgid "# Error Handling in FFI" msgstr "# Tratamento de erros no 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 "" "Em idiomas estrangeiros como C, os erros são representados por códigos de " "retorno.\n" "No entanto, o sistema de tipos do Rust permite que informações de erro muito " "mais ricas sejam\n" "capturado e propagado através de um 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 "" "Esta prática recomendada mostra diferentes tipos de códigos de erro e como " "expô-los\n" "de forma utilizável:" #: 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. Flat Enums devem ser convertidos em inteiros e retornados como códigos.\n" "2. Enums estruturados devem ser convertidos em um código inteiro com um erro " "de string\n" " mensagem para detalhes.\n" "3. Tipos de erro personalizados devem se tornar \"transparentes\", com uma " "representação em 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 "## Exemplo de Código" #: src\idioms/ffi/errors.md:19 #, fuzzy msgid "### Flat Enums" msgstr "### Enums Simples" #: 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 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 "### Enums estruturados" #: 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 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 "### Tipos de erro personalizados" #: 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 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 "" "Isso garante que o idioma estrangeiro tenha acesso claro às informações de " "erro\n" "sem comprometer a API do código 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 "" "É muita digitação e alguns tipos podem não ser convertidos facilmente\n" "para C." #: src\idioms/ffi/accepting-strings.md:1 #, fuzzy msgid "# Accepting Strings" msgstr "# Aceitando Strings" #: 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 "" "Ao aceitar strings via FFI por meio de ponteiros, existem dois princípios " "que\n" "deve ser seguido:" #: 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. Mantenha strings estrangeiras \"emprestadas\", em vez de copiá-las " "diretamente.\n" "2. Minimize a complexidade e o código \"inseguro\" envolvido na conversão\n" " de uma string estilo C para strings Rust nativas." #: src\idioms/ffi/accepting-strings.md:14 #, fuzzy msgid "" "The strings used in C have different behaviours to those used in Rust, " "namely:" msgstr "" "As strings usadas em C possuem comportamentos diferentes das usadas em Rust, " "a saber:" #: 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 "" "- As strings C são terminadas em nulo, enquanto as strings Rust armazenam " "seu comprimento\n" "- As strings C podem conter qualquer byte arbitrário diferente de zero, " "enquanto as strings Rust devem ser\n" " UTF-8\n" "- Strings C são acessadas e manipuladas usando operações de ponteiro " "`inseguras`\n" " enquanto as interações com strings Rust passam por métodos seguros" #: 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 "" "A biblioteca padrão do Rust vem com equivalentes em C de `String` e `&str` " "do Rust\n" "chamados `CString` e `&CStr`, que nos permitem evitar muita complexidade\n" "e código `inseguro` envolvido na conversão entre strings C e strings 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 "" "O tipo `&CStr` também nos permite trabalhar com dados emprestados, ou seja, " "passar\n" "strings entre Rust e C é uma operação de custo 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 "O exemplo foi escrito para garantir que:" #: 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. O bloco `unsafe` é o menor possível.\n" "2. O ponteiro com um tempo de vida \"não rastreado\" torna-se um " "\"rastreado\" compartilhado\n" " referência" #: src\idioms/ffi/accepting-strings.md:76 #, fuzzy msgid "Consider an alternative, where the string is actually copied:" msgstr "Considere uma alternativa, onde a string é realmente copiada:" #: 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 "Este código é inferior ao original em dois aspectos:" #: 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. Há muito mais código \"inseguro\" e, mais importante, mais invariantes\n" " deve sustentar.\n" "2. Devido à extensa aritmética necessária, há um bug nesta versão\n" " que casos Rust `comportamento indefinido`." #: 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 "" "O bug aqui é um erro simples na aritmética do ponteiro: a string foi " "copiada,\n" "todos os bytes `msg_len` dele. No entanto, o terminador `NUL` no final não " "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 "" "O vetor então teve seu tamanho _definido_ para o comprimento da _string " "preenchida com zero_ --\n" "em vez de _redimensionado_ a ele, o que poderia ter adicionado um zero no " "final.\n" "Como resultado, o último byte no Vector é memória não inicializada.\n" "Quando o `CString` é criado na parte inferior do bloco, sua leitura do\n" "O vetor causará `comportamento indefinido`!" #: 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 "" "Como muitos desses problemas, esse seria um problema difícil de rastrear.\n" "Às vezes entrava em pânico porque a string não era `UTF-8`, às vezes\n" "colocar um caractere estranho no final da string, às vezes seria apenas\n" "travar completamente." #: src\idioms/ffi/accepting-strings.md:143 #: src\idioms/ffi/passing-strings.md:105 #, fuzzy msgid "None?" msgstr "Nenhum?" #: src\idioms/ffi/passing-strings.md:1 #, fuzzy msgid "# Passing Strings" msgstr "# Passando Cordas" #: 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 "" "Ao passar strings para funções FFI, existem quatro princípios que devem ser\n" "seguido:" #: 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. Faça com que a vida útil das strings próprias seja a maior possível.\n" "2. Minimize o código `inseguro` durante a conversão.\n" "3. Se o código C puder modificar os dados da string, use `Vec` em vez de " "`CString`.\n" "4. A menos que a API de função externa exija, a propriedade da string\n" " não deve transferir para o receptor." #: 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 tem suporte embutido para strings no estilo C com seus `CString` e " "`CStr`\n" "tipos. No entanto, existem diferentes abordagens que podem ser adotadas com " "strings que\n" "estão sendo enviados para uma chamada de função estrangeira de uma função " "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 "" "A melhor prática é simples: use `CString` de forma a minimizar\n" "código `inseguro`. No entanto, uma advertência secundária é que\n" "_o objeto deve viver o suficiente_, o que significa que o tempo de vida deve " "ser maximizado.\n" "Além disso, a documentação explica que \"transmitir\" um `CString` após\n" "modificação é UB, então trabalho adicional é necessário nesse caso." #: 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>(\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 {\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 "O exemplo é escrito de forma a garantir que:" #: 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. O bloco `unsafe` é o menor possível.\n" "2. O `CString` vive o suficiente.\n" "3. Erros com typecasts são sempre propagados quando possível." #: 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 "" "Um erro comum (tão comum que está na documentação) é não usar o\n" "variável no primeiro bloco:" #: 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>(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 "" "Este código resultará em um ponteiro pendente, porque o tempo de vida do\n" "`CString` não é estendido pela criação do ponteiro, ao contrário de uma " "referência\n" "criada." #: 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 "" "Outra questão frequentemente levantada é que a inicialização de um vetor 1k " "de\n" "zeros é \"lento\". No entanto, versões recentes do Rust realmente otimizam " "isso\n" "macro específica para uma chamada para `zmalloc`, o que significa que é tão " "rápido quanto a operação\n" "a capacidade do sistema de retornar memória zerada (o que é bastante rápido)." #: src\idioms/option-iter.md:1 #, fuzzy msgid "# Iterating over an `Option`" msgstr "# Iterando sobre uma `Option`" #: 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` pode ser visto como um contêiner que contém zero ou um\n" "elemento. Em particular, ele implementa o recurso `IntoIterator` e, como " "tal,\n" "pode ser usado com código genérico que precisa desse 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 "## Exemplos" #: 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 "" "Como `Option` implementa `IntoIterator`, ele pode ser usado como um " "argumento para\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 você precisar adicionar uma `Option` ao final de um iterador existente, " "você pode\n" "passe para " "[`.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 "" "Note que se `Option` for sempre `Some`, então é mais idiomático usar\n" "[`std::iter::once`](https://doc.rust-lang.org/std/iter/fn.once.html) no\n" "elemento em vez disso." #: 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 "" "Além disso, como `Option` implementa `IntoIterator`, é possível iterar " "sobre\n" "usando um loop `for`. Isso é equivalente a combiná-lo com `if let " "Some(..)`,\n" "e na maioria dos casos você deve preferir o último." #: 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`](https://doc.rust-lang.org/std/option/enum.Option.html)" msgstr "" "- [`std::iter::once`](https://doc.rust-lang.org/std/iter/fn.once.html) é um\n" " iterator que produz exatamente um elemento. É uma alternativa mais legível " "para\n" " `Some(foo).into_iter()`.\n" "\n" "- " "[`Iterator::filter_map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter_map)\n" " é uma versão do " "[`Iterator::map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map),\n" " especializado para funções de mapeamento que retornam `Option`.\n" "\n" "- A caixa [`ref_slice`](https://crates.io/crates/ref_slice) fornece funções\n" " para converter uma `Opção` em uma fatia de zero ou um elemento.\n" "\n" "- [Documentação para " "`Option`](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 variáveis para encerramento" #: 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 "" "Por padrão, os fechamentos capturam seu ambiente por empréstimo. Ou você " "pode usar\n" "fechamento `move` para mover todo o ambiente. No entanto, muitas vezes você " "deseja mover apenas\n" "algumas variáveis para fechamento, dar-lhe cópia de alguns dados, passá-lo " "por referência ou\n" "realizar alguma outra transformação." #: src\idioms/pass-var-to-closure.md:10 #, fuzzy msgid "Use variable rebinding in separate scope for that." msgstr "Use a religação de variável em escopo separado para isso." #: src\idioms/pass-var-to-closure.md:14 #, fuzzy msgid "Use" msgstr "Usar" #: 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 "em vez de" #: 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 "" "Os dados copiados são agrupados com a definição de fechamento, portanto, sua " "finalidade é\n" "mais claros, e eles serão descartados imediatamente, mesmo que não sejam " "consumidos\n" "por fechamento." #: 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 "" "Closure usa os mesmos nomes de variáveis que o código ao redor, sejam os " "dados copiados ou\n" "mudou-se." #: src\idioms/pass-var-to-closure.md:59 #, fuzzy msgid "Additional indentation of closure body." msgstr "Recuo adicional do corpo da tampa." #: src\idioms/priv-extend.md:1 #, fuzzy msgid "# `#[non_exhaustive]` and private fields for extensibility" msgstr "# `#[non_exhaustive]` e campos privados para extensibilidade" #: 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 "" "Existe um pequeno conjunto de cenários em que um autor de biblioteca pode " "querer adicionar\n" "campos para uma estrutura pública ou novas variantes para uma enumeração sem " "quebrar para trás\n" "compatibilidade." #: src\idioms/priv-extend.md:9 #, fuzzy msgid "Rust offers two solutions to this problem:" msgstr "Rust oferece duas soluções para este 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 "" "- Use `#[non_exhaustive]` nas variantes `struct`s, `enum`s e `enum`.\n" " Para documentação extensa sobre todos os lugares onde `#[non_exhaustive]` " "pode ser\n" " usado, consulte [os " "documentos](https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute).\n" "\n" "- Você pode adicionar um campo privado a uma estrutura para evitar que ela " "seja diretamente\n" " instanciado ou comparado (ver 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: `Campos privados` para structs" #: 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]` só funciona além dos limites da caixa.\n" "Dentro de uma caixa, o método de campo privado pode ser usado." #: 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 "" "Adicionar um campo a uma estrutura é uma alteração compatível com versões " "anteriores.\n" "No entanto, se um cliente usar um padrão para desconstruir uma instância " "struct, ele\n" "pode nomear todos os campos na estrutura e adicionar um novo quebraria isso\n" "padrão.\n" "O cliente pode nomear alguns campos e usar `..` no padrão, caso em que " "adicionar\n" "outro campo é compatível com versões anteriores.\n" "Tornar privado pelo menos um dos campos da estrutura obriga os clientes a " "usar o último\n" "forma de padrões, garantindo que a estrutura seja à prova de 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 "" "A desvantagem dessa abordagem é que você pode precisar adicionar um\n" "campo para a estrutura.\n" "Você pode usar o tipo `()` para que não haja sobrecarga de tempo de execução " "e anexar `_` para\n" "o nome do campo para evitar o aviso de campo não utilizado." #: 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 "" "Em `struct`s, `#[non_exhaustive]` permite adicionar campos adicionais de " "forma inversa\n" "maneira compatível.\n" "Também impedirá que os clientes usem o construtor struct, mesmo que todos " "os\n" "campos são públicos.\n" "Isso pode ser útil, mas vale a pena considerar se você _quer_ um campo " "adicional\n" "ser encontrado pelos clientes como um erro do compilador em vez de algo que " "pode ser silenciosamente\n" "não descoberto." #: 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]` também pode ser aplicado a variantes de enumeração.\n" "Uma variante `#[non_exhaustive]` se comporta da mesma forma que uma " "estrutura `#[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 "" "Use isso deliberadamente e com cautela: incrementando a versão principal ao " "adicionar\n" "campos ou variantes geralmente é uma opção melhor.\n" "`#[non_exhaustive]` pode ser apropriado em cenários onde você está modelando " "um externo\n" "recurso que pode ficar fora de sincronia com sua biblioteca, mas não é um " "propósito geral\n" "ferramenta." #: src\idioms/priv-extend.md:104 #, fuzzy msgid "### Disadvantages" msgstr "### Desvantagens" #: 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]` pode tornar seu código muito menos ergonômico de usar, " "especialmente quando\n" "forçado a lidar com variantes de enumeração desconhecidas.\n" "Só deve ser usado quando esses tipos de evoluções são necessários **sem**\n" "incrementando a versão principal." #: 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 introduzindo o atributo #[non_exhaustive] para enums e " "structs](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 "# Fácil inicialização do documento\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 uma estrutura requer um esforço significativo para inicializar ao " "escrever documentos, pode ser\r\n" "mais rápido para agrupar seu exemplo com uma função auxiliar que usa a " "estrutura como um\r\n" "argumento." #: src\idioms/rustdoc-init.md:9 #, fuzzy msgid "## Motivation\r" msgstr "## Motivação\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 "" "Às vezes, há uma estrutura com parâmetros múltiplos ou complicados e " "vários\r\n" "métodos. Cada um desses métodos deve ter exemplos." #: src\idioms/rustdoc-init.md:14 #, fuzzy msgid "For example:" msgstr "Por exemplo:" #: 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 {\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 "## Exemplo\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 "" "Em vez de digitar todo esse clichê para criar uma `Conexão` e\r\n" "`Request`, é mais fácil apenas criar uma função auxiliar de empacotamento " "que leva\r\n" "como argumentos:" #: 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 "## Vantagens\r" #: src\idioms/rustdoc-init.md:79 #, fuzzy msgid "This is much more concise and avoids repetitive code in examples." msgstr "Isso é muito mais conciso e evita código repetitivo em exemplos." #: src\idioms/rustdoc-init.md:81 #, fuzzy msgid "## Disadvantages\r" msgstr "## Desvantagens\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 "" "Como o exemplo está em uma função, o código não será testado. Embora ainda " "seja\r\n" "verificado para garantir que ele compila ao executar um `teste de carga`. " "Então esse padrão é\r\n" "mais útil quando você precisa de `no_run`. Com isso, você não precisa " "adicionar `no_run`." #: src\idioms/rustdoc-init.md:87 #, fuzzy msgid "## Discussion\r" msgstr "## Discussão\r" #: src\idioms/rustdoc-init.md:89 #, fuzzy msgid "If assertions are not required this pattern works well." msgstr "Se as asserções não forem necessárias, esse padrão funcionará bem." #: 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 forem, uma alternativa pode ser criar um método público para criar um " "auxiliar\r\n" "instância que é anotada com `#[doc(hidden)]` (para que os usuários não a " "vejam).\r\n" "Então este método pode ser chamado dentro do rustdoc porque faz parte do\r\n" "API pública da caixa." #: src\idioms/temporary-mutability.md:1 #, fuzzy msgid "# Temporary mutability" msgstr "# Mutabilidade temporária" #: 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 "" "Muitas vezes é necessário preparar e processar alguns dados, mas depois " "disso os dados são\n" "apenas inspecionado e nunca modificado. A intenção pode ser tornada " "explícita redefinindo\n" "a variável mutável como imutável." #: 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 "" "Isso pode ser feito processando dados dentro de um bloco aninhado ou " "redefinindo\n" "a variável." #: src\idioms/temporary-mutability.md:14 #, fuzzy msgid "Say, vector must be sorted before usage." msgstr "Diga, o vetor deve ser classificado antes do uso." #: src\idioms/temporary-mutability.md:16 #, fuzzy msgid "Using nested block:" msgstr "Usando bloco aninhado:" #: 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 "Usando religação de variável:" #: 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 "" "O compilador garante que você não modifique dados acidentalmente após algum " "ponto." #: 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 "" "O bloco aninhado requer recuo adicional do corpo do bloco.\n" "Mais uma linha para retornar dados do bloco ou redefinir variável." #: src\idioms/return-consumed-arg-on-error.md:1 #, fuzzy msgid "# Return consumed argument on error" msgstr "# Retorna o argumento consumido em caso de erro" #: 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 uma função falível consumir (mover) um argumento, retorne esse argumento " "para dentro\n" "um erro." #: 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 "" "Em caso de erro, você pode querer tentar alguma forma alternativa ou\n" "repetir a ação em caso de função não determinística. Mas se o argumento\n" "é sempre consumido, você é forçado a cloná-lo em todas as chamadas, o que\n" "não é muito eficiente." #: 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 "" "A biblioteca padrão usa esta abordagem em, por exemplo, Método " "`String::from_utf8`.\n" "Quando dado um vetor que não contém UTF-8 válido, um `FromUtf8Error`\n" "é devolvido.\n" "Você pode recuperar o vetor original usando o método " "`FromUtf8Error::into_bytes`." #: src\idioms/return-consumed-arg-on-error.md:57 #, fuzzy msgid "Better performance because of moving arguments whenever possible." msgstr "Melhor desempenho devido a argumentos em movimento sempre que possível." #: src\idioms/return-consumed-arg-on-error.md:61 #, fuzzy msgid "Slightly more complex error types." msgstr "Tipos de erro um pouco mais complexos." #: src\patterns/index.md:1 #, fuzzy msgid "# Design Patterns" msgstr "# Padrões de design" #: 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 "" "[Padrões de design](https://en.wikipedia.org/wiki/Software_design_pattern) " "são\n" "“soluções gerais reutilizáveis para um problema que ocorre comumente dentro " "de um determinado\n" "contexto no design de software\". Os padrões de design são uma ótima maneira " "de descrever o\n" "cultura de uma linguagem de programação. Os padrões de design são muito " "específicos da linguagem -\n" "o que é um padrão em um idioma pode ser desnecessário em outro devido a uma\n" "recurso de linguagem ou impossível de expressar devido a um recurso ausente." #: 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 usados em excesso, os padrões de projeto podem adicionar complexidade " "desnecessária aos programas.\n" "No entanto, eles são uma ótima maneira de compartilhar conhecimentos de " "nível intermediário e avançado\n" "sobre uma linguagem de programação." #: 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 tem muitos recursos exclusivos. Esses recursos nos dão grande benefício " "ao remover\n" "classes inteiras de problemas. Alguns deles também são padrões _exclusivos_ " "do 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 é um acrônimo que significa `You Are not Going to Need It`.\n" "É um princípio de design de software vital a ser aplicado enquanto você " "escreve o código." #: src\patterns/index.md:24 #, fuzzy msgid "> The best code I ever wrote was code I never wrote." msgstr "> O melhor código que já escrevi foi um código que nunca escrevi." #: 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 aplicarmos o YAGNI aos padrões de projeto, veremos que os recursos do " "Rust nos permitem\n" "jogue fora muitos padrões. Por exemplo, não há necessidade do [padrão de " "estratégia](https://en.wikipedia.org/wiki/Strategy_pattern)\n" "em Rust porque podemos usar apenas " "[traits](https://doc.rust-lang.org/book/traits.html)." #: src\patterns/behavioural/intro.md:1 #, fuzzy msgid "# Behavioural Patterns" msgstr "# Padrões Comportamentais" #: 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 "" "> Padrões de design que identificam padrões comuns de comunicação entre " "objetos.\n" "> Ao fazer isso, esses padrões aumentam a flexibilidade na realização da " "comunicação." #: 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 "" "A ideia básica do padrão Command é separar as ações em seu próprio\n" "objetos e passá-los como parâmetros." #: 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 "" "Suponha que tenhamos uma sequência de ações ou transações encapsuladas como " "objetos.\n" "Queremos que essas ações ou comandos sejam executados ou invocados em alguma " "ordem posteriormente\n" "em tempo diferente. Esses comandos também podem ser acionados como resultado " "de algum evento.\n" "Por exemplo, quando um usuário pressiona um botão ou na chegada de um pacote " "de dados.\n" "Além disso, esses comandos podem ser desfeitos. Isso pode ser útil para\n" "operações de um editor. Podemos querer armazenar logs de comandos executados " "para que\n" "poderíamos reaplicar as alterações mais tarde se o sistema travar." #: 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 "" "Defina duas operações de banco de dados `create table` e `add field`. Cada " "um desses\n" "operações é um comando que sabe como desfazer o comando, por exemplo, `drop " "table`\n" "e `remover campo`. Quando um usuário invoca uma operação de migração de " "banco de dados, cada\n" "comando é executado na ordem definida e quando o usuário invoca o rollback\n" "operação, então todo o conjunto de comandos é invocado na ordem inversa." #: src\patterns/behavioural/command.md:26 #, fuzzy msgid "## Approach: Using trait objects" msgstr "## Abordagem: Usando objetos de característica" #: 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 "" "Definimos uma característica comum que encapsula nosso comando com duas " "operações\n" "`execute` e `rollback`. Todos os `structs` de comando devem implementar esta " "característica." #: 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>,\n" "}\n" "\n" "impl Schema {\n" " fn new() -> Self {\n" " Self { commands: vec![] }\n" " }\n" "\n" " fn add_migration(&mut self, cmd: Box) {\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 "## Abordagem: Usando ponteiros de função" #: 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 "" "Poderíamos seguir outra abordagem criando cada comando individual como\n" "uma função diferente e armazenar ponteiros de função para invocar essas " "funções mais tarde\n" "em um momento diferente. Como os ponteiros de função implementam todas as " "três características `Fn`,\n" "`FnMut` e `FnOnce`, poderíamos passar e armazenar encerramentos em vez de\n" "ponteiros de função." #: 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,\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 {\n" " self.commands.iter().map(|cmd| (cmd.execute)()).collect()\n" " }\n" " fn rollback(&self) -> Vec {\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 "## Abordagem: Usando objetos de característica `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 "" "Finalmente, em vez de definir um traço de comando comum, poderíamos " "armazenar\n" "cada comando implementando o traço `Fn` separadamente em vetores." #: src\patterns/behavioural/command.md:155 msgid "" "```rust\n" "type Migration<'a> = Box &'a str>;\n" "\n" "struct Schema<'a> {\n" " executes: Vec>,\n" " rollbacks: Vec>,\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(&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 nossos comandos são pequenos e podem ser definidos como funções ou " "passados como encerramento\n" "usar ponteiros de função pode ser preferível, pois não explora\n" "despacho dinâmico. Mas se nosso comando for uma estrutura inteira com um " "monte de funções\n" "e variáveis definidas como módulo separado, então usar objetos de " "característica seria\n" "mais adequado. Um caso de aplicação pode ser encontrado em " "[`actix`](https://actix.rs/),\n" "que usa objetos trait quando registra uma função de manipulador para rotas.\n" "No caso de usar objetos de característica `Fn`, podemos criar e usar " "comandos no mesmo\n" "maneira como usamos no caso de ponteiros de função." #: 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 "" "Como desempenho, sempre há uma troca entre desempenho e código\n" "simplicidade e organização. O despacho estático oferece desempenho mais " "rápido, enquanto\n" "o despacho dinâmico fornece flexibilidade quando estruturamos nosso " "aplicativo." #: 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 "" "- [Padrão de comando](https://en.wikipedia.org/wiki/Command_pattern)\n" "\n" "- [Outro exemplo para o padrão " "`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 "# Intérprete" #: 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 um problema ocorre com muita frequência e requer etapas longas e " "repetitivas para resolver\n" "isso, então as instâncias do problema podem ser expressas em uma linguagem " "simples e um\n" "objeto intérprete poderia resolvê-lo interpretando as frases escritas neste\n" "linguagem simples." #: src\patterns/behavioural/interpreter.md:10 #, fuzzy msgid "Basically, for any kind of problems we define:" msgstr "Basicamente, para qualquer tipo de problema definimos:" #: 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 "" "- Um [idioma específico do " "domínio](https://en.wikipedia.org/wiki/Domain-specific_language),\n" "- Uma gramática para esta linguagem,\n" "- Um interpretador que resolve as instâncias do 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 "" "Nosso objetivo é traduzir expressões matemáticas simples em expressões " "pós-fixadas\n" "(ou [notação polonesa " "reversa](https://en.wikipedia.org/wiki/Reverse_Polish_notation))\n" "Para simplificar, nossas expressões consistem em dez dígitos `0`, ..., `9` e " "dois\n" "operações `+`, `-`. Por exemplo, a expressão `2 + 4` é traduzida para\n" "`2 4 +`." #: src\patterns/behavioural/interpreter.md:24 #, fuzzy msgid "## Context Free Grammar for our problem" msgstr "## Gramática livre de contexto para o nosso 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 "" "Nossa tarefa é traduzir expressões infixas em pós-fixadas. Vamos definir um " "contexto\n" "gramática livre para um conjunto de expressões infixas sobre `0`, ..., `9`, " "`+` e `-`,\n" "onde:" #: 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 "" "- Símbolos de terminais: `0`, `...`, `9`, `+`, `-`\n" "- Símbolos não terminais: `exp`, `term`\n" "- O símbolo inicial é `exp`\n" "- E as seguintes são regras de produção" #: 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:** Esta gramática deve ser transformada dependendo do que vamos\n" "fazer com isso. Por exemplo, podemos precisar remover a recursão à esquerda. " "Para mais\n" "detalhes, consulte [Compilers: Principles,Techniques, and " "Tools](https://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools)\n" "(também conhecido como Livro do Dragão)." #: src\patterns/behavioural/interpreter.md:47 #, fuzzy msgid "## Solution" msgstr "## Solução" #: 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 "" "Simplesmente implementamos um analisador descendente recursivo. Para " "simplificar, o código\n" "entra em pânico quando uma expressão está sintaticamente errada (por exemplo " "`2-34` ou `2+5-`\n" "estão errados de acordo com a definição gramatical)." #: 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 {\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 "" "Pode haver uma percepção errada de que o padrão de projeto Interpreter é " "sobre design\n" "gramáticas para linguagens formais e implementação de parsers para essas " "gramáticas.\n" "Na verdade, esse padrão é sobre expressar instâncias de problemas de uma " "forma mais específica.\n" "maneira e implementando funções/classes/estruturas que resolvem essas " "instâncias do problema.\n" "A linguagem Rust tem `macro_rules!` que nos permite definir sintaxe e regras " "especiais\n" "sobre como expandir essa sintaxe no código-fonte." #: 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 "" "No exemplo a seguir, criamos um `macro_rules!` simples que calcula\n" "[Comprimento euclidiano](https://en.wikipedia.org/wiki/Euclidean_distance) " "de `n`\n" "vetores dimensionais. Escrever `norma!(x,1,2)` pode ser mais fácil de " "expressar e mais\n" "eficiente do que empacotar `x,1,2` em um `Vec` e chamar uma função de " "computação\n" "O comprimento." #: 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 "" "- [Padrão de intérprete](https://en.wikipedia.org/wiki/Interpreter_pattern)\n" "- [Gramática livre de " "contexto](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 "# Novotipo" #: 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 "" "E se em alguns casos quisermos que um tipo se comporte de maneira semelhante " "a outro tipo ou\n" "impor algum comportamento em tempo de compilação ao usar apenas aliases de " "tipo\n" "não ser suficiente?" #: 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 "" "Por exemplo, se quisermos criar uma implementação `Display` personalizada " "para `String`\n" "devido a considerações de segurança (por exemplo, senhas)." #: 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 "" "Para tais casos, poderíamos usar o padrão `Newtype` para fornecer ** " "segurança de tipo **\n" "e **encapsulamento**." #: 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 "" "Use uma estrutura de tupla com um único campo para criar um wrapper opaco " "para um tipo.\n" "Isso cria um novo tipo, em vez de um alias para um tipo (itens `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 "" "A principal motivação para newtypes é a abstração. Ele permite que você " "compartilhe\n" "detalhes de implementação entre tipos enquanto controla com precisão a " "interface.\n" "Usando um newtype em vez de expor o tipo de implementação como parte de um\n" "API, permite que você altere a implementação de forma compatível com versões " "anteriores." #: 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 "" "Newtypes podem ser usados para distinguir unidades, por exemplo, agrupando " "`f64` para dar\n" "distinguíveis 'Milhas' e 'Quilômetros'." #: 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 "" "Os tipos wrapper e wrapper não são compatíveis (ao contrário de usar\n" "`type`), então os usuários do newtype nunca irão 'confundir' o wrapper e o " "wrapper\n" "tipos." #: src\patterns/behavioural/newtype.md:72 #, fuzzy msgid "Newtypes are a zero-cost abstraction - there is no runtime overhead." msgstr "" "Newtypes são uma abstração de custo zero - não há sobrecarga de tempo de " "execução." #: 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 "" "O sistema de privacidade garante que os usuários não possam acessar o tipo " "encapsulado (se o\n" "campo é privado, o que é por padrão)." #: 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 "" "A desvantagem de newtypes (especialmente em comparação com aliases de tipo) " "é que há\n" "não há suporte de idioma especial. Isso significa que pode haver _muito_ " "clichê.\n" "Você precisa de um método 'pass through' para cada método que deseja expor " "no\n" "tipo embrulhado e um impl para cada característica que você deseja que " "também seja implementado para\n" "o tipo de invólucro." #: 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 "" "Newtypes são muito comuns em código Rust. Unidades de abstração ou " "representação são as\n" "usos mais comuns, mas podem ser usados por outros motivos:" #: 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 "" "- funcionalidade restritiva (reduzir as funções expostas ou características " "implementadas),\n" "- fazer um tipo com semântica de cópia tem semântica de movimento,\n" "- abstração ao fornecer um tipo mais concreto e, assim, ocultar os tipos " "internos,\n" " por exemplo.," #: src\patterns/behavioural/newtype.md:95 msgid "" "```rust,ignore\n" "pub struct Foo(Bar);\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 "" "Aqui, `Bar` pode ser algum tipo público e genérico e `T1` e `T2` são alguns " "tipos internos\n" "tipos. Os usuários do nosso módulo não devem saber que implementamos `Foo` " "usando um `Bar`,\n" "mas o que realmente estamos escondendo aqui são os tipos `T1` e `T2`, e como " "eles são usados\n" "com '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 "" "- [Tipos avançados no " "livro](https://doc.rust-lang.org/book/ch19-04-advanced-types.html?highlight=newtype#using-the-newtype-pattern-for-type-safety " "-e-abstração)\n" "- [Novos tipos em Haskell](https://wiki.haskell.org/Newtype)\n" "- [aliases de " "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), uma caixa para " "derivar muitos\n" " traços embutidos em novos tipos.\n" "- [O padrão Newtype em " "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 com guardas" #: 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] significa \"Resource Acquisition is Initialisation\" que é " "um\n" "nome terrível. A essência do padrão é que a inicialização do recurso é " "feita\n" "no construtor de um objeto e a finalização no destruidor. Esse padrão\n" "é estendido em Rust usando um objeto RAII como guarda de algum recurso e " "contando\n" "no sistema de tipos para garantir que o acesso seja sempre mediado pelo " "objeto de guarda." #: 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 "" "Mutex guards são o exemplo clássico deste padrão da biblioteca std (este\n" "é uma versão simplificada da implementação real):" #: src\patterns/behavioural/RAII.md:16 msgid "" "```rust,ignore\n" "use std::ops::Deref;\n" "\n" "struct Foo {}\n" "\n" "struct Mutex {\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 Mutex {\n" " fn lock(&self) -> MutexGuard {\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) {\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 "" "Onde um recurso deve ser finalizado após o uso, o RAII pode ser usado para " "fazer isso\n" "finalização. Se for um erro acessar esse recurso após a finalização, então\n" "esse padrão pode ser usado para evitar tais erros." #: 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 "" "Evita erros onde um recurso não é finalizado e onde um recurso é usado\n" "após a finalização." #: 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 é um padrão útil para garantir que os recursos sejam devidamente " "desalocados ou\n" "finalizado. Podemos usar o verificador de empréstimo no Rust para prevenir " "estaticamente\n" "erros decorrentes do uso de recursos após a finalização." #: 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 "" "O principal objetivo do verificador de empréstimos é garantir que as " "referências aos dados não\n" "sobreviver a esses dados. O padrão de guarda RAII funciona porque o objeto " "de guarda\n" "contém uma referência ao recurso subjacente e apenas expõe tal\n" "referências. A ferrugem garante que o guarda não sobreviva ao recurso " "subjacente\n" "e que as referências ao recurso mediado pela guarda não podem sobreviver ao\n" "guarda. Para ver como isso funciona, é útil examinar a assinatura de " "`deref`\n" "sem elisão vitalícia:" #: 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 "" "A referência retornada ao recurso tem o mesmo tempo de vida que `self` " "(`'a`).\n" "O verificador de empréstimo, portanto, garante que o tempo de vida da " "referência a `T`\n" "é mais curto que o tempo de vida de `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 "" "Observe que a implementação de `Deref` não é uma parte essencial desse " "padrão, apenas torna\n" "usando o objeto de guarda mais ergonômico. Implementando um método `get` no " "guarda\n" "funciona tão bem." #: src\patterns/behavioural/RAII.md:113 #, fuzzy msgid "[Finalisation in destructors idiom](../../idioms/dtor-finally.md)" msgstr "[Finalização no idioma dos destruidores](../../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 é um padrão comum em 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 "" "[Entrada do guia de " "estilo](https://doc.rust-lang.org/1.0.0/style/ownership/raii.html)\n" "(atualmente apenas um espaço reservado)." #: src\patterns/behavioural/strategy.md:1 #, fuzzy msgid "# Strategy (aka Policy)" msgstr "# Estratégia (também conhecida como Política)" #: 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 "" "O [padrão de design de " "estratégia](https://en.wikipedia.org/wiki/Strategy_pattern)\n" "é uma técnica que permite a separação de preocupações.\n" "Também permite desacoplar módulos de software por meio de [Inversão de " "dependência](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 "" "A ideia básica por trás do padrão Strategy é que, dado um algoritmo " "resolvendo\n" "um problema particular, definimos apenas o esqueleto do algoritmo em um " "resumo\n" "nível, e separamos a implementação do algoritmo específico em diferentes " "partes." #: 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 "" "Desta forma, um cliente usando o algoritmo pode escolher uma implementação " "específica,\n" "enquanto o fluxo de trabalho do algoritmo geral permanece o mesmo. Em outras " "palavras, o resumo\n" "especificação da classe não depende da implementação específica do\n" "classe derivada, mas a implementação específica deve aderir à especificação " "abstrata.\n" "É por isso que chamamos de \"Inversão de Dependência\"." #: 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 "" "Imagine que estamos trabalhando em um projeto que gera relatórios todos os " "meses.\n" "Precisamos que os relatórios sejam gerados em diferentes formatos " "(estratégias), por exemplo,\n" "nos formatos `JSON` ou `Texto Simples`.\n" "Mas as coisas variam ao longo do tempo e não sabemos que tipo de exigência " "podemos obter\n" "no futuro. Por exemplo, podemos precisar gerar nosso relatório em um formato " "completamente novo\n" "formato, ou apenas modifique um dos formatos existentes." #: 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 "" "Neste exemplo, nossas invariantes (ou abstrações) são `Context`, " "`Formatter`,\n" "e `Report`, enquanto `Text` e `Json` são nossas estruturas de estratégia. " "Essas estratégias\n" "tem que implementar o trait `Formatter`." #: src\patterns/behavioural/strategy.md:34 msgid "" "```rust\n" "use std::collections::HashMap;\n" "\n" "type Data = HashMap;\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(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 "" "A principal vantagem é a separação de interesses. Por exemplo, neste caso " "`Relatório`\n" "não sabe nada sobre implementações específicas de `Json` e `Text`,\n" "considerando que as implementações de saída não se preocupam com a forma " "como os dados são pré-processados,\n" "armazenado e obtido. A única coisa que eles precisam saber é o contexto e " "um\n" "trait e método para implementar, ou seja, `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 "" "Para cada estratégia deve ser implementado pelo menos um módulo, então o " "número de módulos\n" "aumenta com o número de estratégias. Se houver muitas estratégias para " "escolher\n" "então os usuários precisam saber como as estratégias diferem umas das outras." #: 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 "" "No exemplo anterior todas as estratégias são implementadas em um único " "arquivo.\n" "Formas de fornecer diferentes estratégias incluem:" #: 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 "" "- Tudo em um arquivo (conforme mostrado neste exemplo, semelhante a ser " "separado como módulos)\n" "- Separados como módulos, por ex. módulo `formatter::json`, módulo " "`formatter::text`\n" "- Use sinalizadores de recursos do compilador, por exemplo recurso `json`, " "recurso `texto`\n" "- Separados como caixotes, por ex. caixa `json`, caixa `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 é um bom exemplo do padrão `Strategy` em ação. Serde permite\n" "[customização completa](https://serde.rs/custom-serialization.html) da " "serialização\n" "comportamento implementando manualmente as características `Serialize` e " "`Deserialize` para o nosso\n" "tipo. Por exemplo, poderíamos facilmente trocar `serde_json` por " "`serde_cbor` já que eles\n" "expor métodos semelhantes. Ter isso faz com que o auxiliar crie " "`serde_transcode` muito\n" "mais útil e ergonômico." #: 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 "" "No entanto, não precisamos usar traits para projetar esse padrão no 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 "" "O exemplo de brinquedo a seguir demonstra a ideia do padrão Strategy usando " "Rust\n" "`encerramentos`:" #: src\patterns/behavioural/strategy.md:132 msgid "" "```rust\n" "struct Adder;\n" "impl Adder {\n" " pub fn add(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 "Na verdade, Rust já usa essa ideia para o método `map` de `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 "" "- [Padrão de Estratégia](https://en.wikipedia.org/wiki/Strategy_pattern)\n" "- [Injeção de " "dependência](https://en.wikipedia.org/wiki/Dependency_injection)\n" "- [Design baseado em " "políticas](https://en.wikipedia.org/wiki/Modern_C++_Design#Policy-based_design)" #: src\patterns/behavioural/visitor.md:1 #, fuzzy msgid "# Visitor" msgstr "# Visitante" #: 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 "" "Um visitante encapsula um algoritmo que opera em uma rede heterogênea\n" "coleção de objetos. Ele permite que vários algoritmos diferentes sejam " "escritos\n" "sobre os mesmos dados sem ter que modificar os dados (ou seus principais\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 "" "Além disso, o padrão do visitante permite separar a travessia de\n" "uma coleção de objetos das operações executadas em cada objeto." #: 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, Box),\n" " Sub(Box, Box),\n" " }\n" "}\n" "\n" "// The abstract visitor\n" "mod visit {\n" " use ast::*;\n" "\n" " pub trait Visitor {\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 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 "" "Pode-se implementar mais visitantes, por exemplo, um verificador de tipo, " "sem ter\n" "para modificar os dados 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 "" "O padrão do visitante é útil em qualquer lugar que você deseja aplicar um " "algoritmo para\n" "dados heterogêneos. Se os dados forem homogêneos, você pode usar um padrão " "do tipo iterador.\n" "O uso de um objeto de visitante (em vez de uma abordagem funcional) permite " "que o visitante\n" "ser stateful e, assim, comunicar informações entre os nós." #: 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 "" "É comum que os métodos `visit_*` retornem void (em oposição ao método\n" "exemplo). Nesse caso, é possível fatorar o código de travessia e " "compartilhar\n" "entre algoritmos (e também para fornecer métodos padrão noop). Em Ferrugem, " "o\n" "A maneira comum de fazer isso é fornecer funções `walk_*` para cada dado. " "Para\n" "exemplo," #: 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 "" "Em outras linguagens (por exemplo, Java) é comum que os dados tenham um " "método `accept`\n" "que cumpre a mesma função." #: src\patterns/behavioural/visitor.md:108 #, fuzzy msgid "The visitor pattern is a common pattern in most OO languages." msgstr "" "O padrão de visitante é um padrão comum na maioria das linguagens orientadas " "a objetos." #: src\patterns/behavioural/visitor.md:110 #, fuzzy msgid "[Wikipedia article](https://en.wikipedia.org/wiki/Visitor_pattern)" msgstr "[Artigo da Wikipédia](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 "" "O padrão [fold](../creational/fold.md) é semelhante ao do visitante, mas " "produz\n" "uma nova versão da estrutura de dados visitada." #: src\patterns/creational/intro.md:1 #, fuzzy msgid "# Creational Patterns" msgstr "# Padrões Criacionais" #: 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 "" "> Padrões de design que lidam com mecanismos de criação de objetos, tentando " "criar objetos\n" "> de forma adequada à situação. A forma básica de criação de objetos " "poderia\n" "> resultar em problemas de projeto ou em complexidade adicional ao projeto. " "design criacional\n" "> os padrões resolvem esse problema controlando de alguma forma a criação " "desse objeto." #: src\patterns/creational/builder.md:1 #, fuzzy msgid "# Builder" msgstr "# Construtor" #: src\patterns/creational/builder.md:5 #, fuzzy msgid "Construct an object with calls to a builder helper." msgstr "Construa um objeto com chamadas para um auxiliar de construtor." #: 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 "" "Útil quando você precisaria de muitos construtores ou onde\n" "construção tem efeitos colaterais." #: src\patterns/creational/builder.md:70 #, fuzzy msgid "Separates methods for building from other methods." msgstr "Separa métodos para construção de outros métodos." #: src\patterns/creational/builder.md:72 #, fuzzy msgid "Prevents proliferation of constructors." msgstr "Previne a proliferação de construtores." #: src\patterns/creational/builder.md:74 #, fuzzy msgid "" "Can be used for one-liner initialisation as well as more complex " "construction." msgstr "" "Pode ser usado para inicialização de uma linha, bem como construções mais " "complexas." #: src\patterns/creational/builder.md:78 #, fuzzy msgid "" "More complex than creating a struct object directly, or a simple " "constructor\n" "function." msgstr "" "Mais complexo do que criar um objeto struct diretamente ou um construtor " "simples\n" "função." #: 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 "" "Esse padrão é visto com mais frequência em Rust (e para objetos mais " "simples) do que em\n" "muitas outras linguagens porque Rust não tem sobrecarga. Como você só pode " "ter um\n" "método único com um determinado nome, ter vários construtores é menos " "agradável em\n" "Rust do que em C++, Java ou outros." #: 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 "" "Esse padrão é frequentemente usado onde o objeto construtor é útil por si " "só,\n" "em vez de ser apenas um construtor. Por exemplo, veja\n" "[`std::process::Command`](https://doc.rust-lang.org/std/process/struct.Command.html)\n" "é um construtor para " "[`Child`](https://doc.rust-lang.org/std/process/struct.Child.html)\n" "(um processo). Nesses casos, o padrão de nomenclatura `T` e `TBuilder` não é " "usado." #: 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 "" "O exemplo pega e retorna o construtor por valor. Muitas vezes é mais " "ergonômico\n" "(e mais eficiente) para obter e retornar o construtor como uma referência " "mutável. O\n" "o verificador de empréstimo faz isso funcionar naturalmente. Esta abordagem " "tem a vantagem de\n" "pode-se escrever código como" #: 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 "assim como o estilo `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 "" "- [Descrição no guia de " "estilo](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), uma caixa para " "automaticamente\n" " implementando esse padrão enquanto evita o clichê.\n" "- [Padrão construtor](../../idioms/ctor.md) para quando a construção é mais " "simples.\n" "- [Padrão do construtor " "(wikipedia)](https://en.wikipedia.org/wiki/Builder_pattern)\n" "- [Construção de valores " "complexos](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 "# Dobrar" #: 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 "" "Execute um algoritmo sobre cada item em uma coleção de dados para criar um " "novo item,\n" "criando assim uma coleção totalmente nova." #: 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 "" "A etimologia aqui não é clara para mim. Os termos 'dobrar' e 'pasta' são " "usados\n" "no compilador Rust, embora me pareça mais um mapa do que um\n" "dobrar no sentido usual. Veja a discussão abaixo para mais detalhes." #: 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),\n" " Let(Box, Box),\n" " }\n" "\n" " pub struct Name {\n" " value: String,\n" " }\n" "\n" " pub enum Expr {\n" " IntLit(i64),\n" " Add(Box, Box),\n" " Sub(Box, Box),\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) -> Box { n }\n" " // Create a new inner node by folding its children.\n" " fn fold_stmt(&mut self, s: Box) -> Box {\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) -> Box { ... }\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) -> Box {\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 "" "O resultado da execução do `Renamer` em um AST é um novo AST idêntico ao " "antigo\n" "um, mas com todos os nomes alterados para `foo`. Uma pasta da vida real pode " "ter alguns\n" "estado preservado entre nós na própria estrutura." #: 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 "" "Uma pasta também pode ser definida para mapear uma estrutura de dados para " "outra (mas\n" "geralmente semelhante) estrutura de dados. Por exemplo, poderíamos dobrar um " "AST em um HIR\n" "árvore (HIR significa representação intermediária de alto nível)." #: 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 "" "É comum querer mapear uma estrutura de dados realizando alguma operação em\n" "cada nó da estrutura. Para operações simples em estruturas de dados " "simples,\n" "isso pode ser feito usando `Iterator::map`. Para operações mais complexas, " "talvez\n" "onde nós anteriores podem afetar a operação em nós posteriores, ou onde a " "iteração\n" "sobre a estrutura de dados não é trivial, usar o padrão de dobra é mais\n" "apropriado." #: 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 "" "Assim como o padrão Visitor, o padrão Fold nos permite separar a travessia " "de um\n" "estrutura de dados das operações realizadas para cada nó." #: 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 "" "Mapear estruturas de dados dessa maneira é comum em linguagens funcionais. " "Eu não\n" "idiomas, seria mais comum alterar a estrutura de dados no local. O\n" "abordagem 'funcional' é comum em Rust, principalmente devido à preferência " "por\n" "imutabilidade. Usar novas estruturas de dados, em vez de modificar " "estruturas antigas, torna\n" "Raciocinar sobre o código é mais fácil na maioria das circunstâncias." #: 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 "" "A compensação entre eficiência e reutilização pode ser ajustada alterando a " "forma como\n" "nós são aceitos pelos métodos `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 "" "No exemplo acima, operamos em ponteiros `Box`. Uma vez que estes possuem " "seus dados\n" "exclusivamente, a cópia original da estrutura de dados não pode ser " "reutilizada. No\n" "por outro lado, se um nó não for alterado, reutilizá-lo é muito eficiente." #: 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 "" "Usar um ponteiro de contagem de referência oferece o melhor dos dois mundos " "- podemos reutilizar\n" "a estrutura de dados original e não precisamos clonar nós inalterados. No " "entanto,\n" "eles são menos ergonômicos de usar e significam que as estruturas de dados " "não podem ser\n" "mutável." #: 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 "" "Os iteradores têm um método `fold`, no entanto, isso dobra uma estrutura de " "dados em um\n" "valor, em vez de em uma nova estrutura de dados. O `map` de um iterador é " "mais parecido com\n" "este padrão de dobra." #: 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 "" "Em outras linguagens, fold é geralmente usado no sentido dos iteradores do " "Rust,\n" "em vez deste padrão. Algumas linguagens funcionais têm construções poderosas " "para\n" "realizando mapas flexíveis sobre estruturas de dados." #: 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 "" "O padrão [visitor](../behavioural/visitor.md) está intimamente relacionado à " "dobra.\n" "Eles compartilham o conceito de percorrer uma estrutura de dados realizando " "uma operação em\n" "cada nó. No entanto, o visitante não cria uma nova estrutura de dados nem " "consome\n" "o antigo." #: src\patterns/structural/intro.md:1 #, fuzzy msgid "# Structural Patterns" msgstr "# Padrões Estruturais" #: 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 "" "> Padrões de design que facilitam o design identificando uma maneira simples " "de realizar relacionamentos\n" "> entre entidades." #: src\patterns/structural/compose-structs.md:1 #, fuzzy msgid "# Compose structs together for better borrowing" msgstr "# Compor estruturas juntas para melhor empréstimo" #: src\patterns/structural/compose-structs.md:3 #, fuzzy msgid "TODO - this is not a very snappy name" msgstr "TODO - este não é um nome muito rápido" #: 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 "" "Às vezes, uma estrutura grande causará problemas com o verificador de " "empréstimo - embora\n" "campos podem ser emprestados de forma independente, às vezes toda a " "estrutura acaba sendo\n" "usados de uma só vez, impedindo outros usos. Uma solução pode ser decompor a " "estrutura\n" "em várias estruturas menores. Em seguida, componha-os juntos no original\n" "struct. Em seguida, cada struct pode ser emprestado separadamente e ter mais " "flexibilidade\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 "" "Isso geralmente leva a um design melhor de outras maneiras: aplicando esse " "design\n" "padrão geralmente revela unidades menores de funcionalidade." #: 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 "" "Aqui está um exemplo forjado de onde o verificador de empréstimos nos " "frustra em nosso plano de\n" "use uma estrutura:" #: 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 "" "Podemos aplicar esse padrão de design e refatorar `A` em duas estruturas " "menores, assim\n" "resolvendo o problema de verificação de empréstimo:" #: 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 Por que e onde você deve usar o padrão" #: src\patterns/structural/compose-structs.md:77 #, fuzzy msgid "Lets you work around limitations in the borrow checker." msgstr "Permite contornar as limitações no verificador de empréstimos." #: src\patterns/structural/compose-structs.md:79 #, fuzzy msgid "Often produces a better design." msgstr "Muitas vezes produz um design melhor." #: src\patterns/structural/compose-structs.md:83 #, fuzzy msgid "Leads to more verbose code." msgstr "Leva a um código mais detalhado." #: 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 "" "Às vezes, as estruturas menores não são boas abstrações e, portanto, " "acabamos com\n" "um projeto pior. Isso é provavelmente um 'cheiro de código', indicando que o " "programa\n" "deve ser refatorado de alguma forma." #: 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 "" "Esse padrão não é necessário em idiomas que não possuem um verificador de " "empréstimo, então\n" "nesse sentido, é exclusivo do Rust. No entanto, fazer unidades menores de " "funcionalidade\n" "muitas vezes leva a um código mais limpo: um princípio de software " "amplamente reconhecido\n" "engenharia, independente do idioma." #: 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 "" "Esse padrão depende do verificador de empréstimo do Rust para poder " "emprestar campos\n" "independentemente um do outro. No exemplo, o verificador de empréstimo sabe " "que `a.b`\n" "e `a.c` são distintos e podem ser emprestados independentemente, ele não " "tenta\n" "pegue emprestado todo `a`, o que tornaria esse padrão inútil." #: src\patterns/structural/small-crates.md:1 #, fuzzy msgid "# Prefer small crates" msgstr "# Prefira caixotes pequenos" #: src\patterns/structural/small-crates.md:5 #, fuzzy msgid "Prefer small crates that do one thing well." msgstr "Prefira caixas pequenas que façam uma coisa bem." #: 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 facilitam a adição de bibliotecas de terceiros, muito mais " "do que\n" "digamos em C ou C++. Além disso, como os pacotes no crates.io não podem ser " "editados ou removidos\n" "após a publicação, qualquer compilação que funcione agora deve continuar " "funcionando no futuro.\n" "Devemos aproveitar essas ferramentas e usar dependências menores e mais " "refinadas." #: 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 "" "- Caixas pequenas são mais fáceis de entender e incentivam um código mais " "modular.\n" "- As caixas permitem a reutilização de código entre projetos.\n" " Por exemplo, a caixa `url` foi desenvolvida como parte do mecanismo do " "navegador Servo,\n" " mas desde então encontrou amplo uso fora do projeto.\n" "- Desde a unidade de compilação\n" " de Rust é a caixa, dividir um projeto em várias caixas pode permitir mais\n" " o código a ser construído em paralelo." #: 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 "" "- Isso pode levar ao \"inferno da dependência\", quando um projeto depende " "de vários\n" " versões de uma caixa ao mesmo tempo. Por exemplo, a caixa `url` tem ambas " "as versões\n" " 1,0 e 0,5. Como o `Url` de `url:1.0` e o `Url` de `url:0.5` são\n" " tipos diferentes, um cliente HTTP que usa `url:0.5` não aceitaria valores " "`Url`\n" " de um web scraper que usa `url:1.0`.\n" "- Pacotes em crates.io não são selecionados. Uma caixa pode estar mal " "escrita, ter\n" " documentação inútil ou totalmente malicioso.\n" "- Duas caixas pequenas podem ser menos otimizadas do que uma grande, pois o " "compilador\n" " não executa otimização de tempo de link (LTO) por padrão." #: 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 "" "A caixa [`ref_slice`](https://crates.io/crates/ref_slice) fornece funções\n" "para converter `&T` em `&[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 "" "A caixa [`url`](https://crates.io/crates/url) fornece ferramentas para " "trabalhar com\n" "URLs." #: 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 "" "A caixa [`num_cpus`](https://crates.io/crates/num_cpus) fornece uma função " "para\n" "consultar o número de CPUs em uma máquina." #: src\patterns/structural/small-crates.md:47 #, fuzzy msgid "- [crates.io: The Rust community crate host](https://crates.io/)" msgstr "- [crates.io: o host de caixas da comunidade Rust](https://crates.io/)" #: src\patterns/structural/unsafe-mods.md:1 #, fuzzy msgid "# Contain unsafety in small modules" msgstr "# Conter a insegurança em pequenos módulos" #: 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 você tiver um código `inseguro`, crie o menor módulo possível que possa " "suportar\n" "as invariantes necessárias para construir uma interface segura mínima sobre " "a insegurança. Embutir\n" "isso em um módulo maior que contém apenas código seguro e apresenta um " "design ergonômico\n" "interface. Observe que o módulo externo pode conter funções e métodos " "inseguros\n" "que chamam diretamente para o código inseguro. Os usuários podem usar isso " "para obter benefícios de velocidade." #: 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 "" "- Isso restringe o código inseguro que deve ser auditado\n" "- Escrever o módulo externo é muito mais fácil, pois você pode contar com as " "garantias\n" " do módulo 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 "" "- Às vezes, pode ser difícil encontrar uma interface adequada.\n" "- A abstração pode introduzir ineficiências." #: 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` 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 "" "- A caixa [`toolshed`](https://docs.rs/toolshed) contém suas operações " "inseguras\n" " em submódulos, apresentando uma interface segura aos usuários.\n" "- A classe `String` de `std` é um wrapper sobre `Vec` com a invariante " "adicionada\n" " que o conteúdo deve ser UTF-8 válido. As operações em `String` garantem " "isso\n" " comportamento.\n" " No entanto, os usuários têm a opção de usar um método `inseguro` para " "criar uma `String`,\n" " neste caso, cabe a eles o ônus de garantir a validade do conteúdo." #: 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 de Ralf Jung sobre invariantes em código " "inseguro](https://www.ralfj.de/blog/2018/08/22/two-kinds-of-invariants.html)" #: src\patterns/ffi/intro.md:1 #, fuzzy msgid "# FFI Patterns" msgstr "# Padrões 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 "" "Escrever código FFI é um curso completo em si.\n" "No entanto, existem vários idiomas aqui que podem atuar como ponteiros e " "evitar armadilhas\n" "para usuários inexperientes de Rust inseguro." #: src\patterns/ffi/intro.md:7 #, fuzzy msgid "This section contains design patterns that may be useful when doing FFI." msgstr "Esta seção contém padrões de projeto que podem ser úteis ao fazer 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. Design de [API baseada em objeto](./export.md) que possui boas " "características de segurança de memória,\n" " e um limite claro do que é seguro e do que não é seguro\n" "\n" "2. [Digite Consolidação em Wrappers](./wrappers.md) - agrupe vários tipos de " "Rust\n" " juntos em um \"objeto\" opaco" #: src\patterns/ffi/export.md:1 #, fuzzy msgid "# Object-Based APIs" msgstr "# APIs baseadas em objetos" #: 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 "" "Ao projetar APIs em Rust expostas a outras linguagens, existem algumas\n" "princípios de design importantes que são contrários ao design normal da Rust " "API:" #: 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. Todos os tipos encapsulados devem ser _propriedade_ da Rust, " "_gerenciados_ pelo usuário,\n" " e _opaco_.\n" "2. Todos os tipos de dados transacionais devem ser _propriedade_ do usuário " "e _transparentes_.\n" "3. Todo o comportamento da biblioteca deve ser funções agindo sobre tipos " "encapsulados.\n" "4. Todo o comportamento da biblioteca deve ser encapsulado em tipos não " "baseados em estrutura,\n" " mas _proveniência/tempo de vida_." #: 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 possui suporte FFI integrado para outros idiomas.\n" "Ele faz isso fornecendo uma maneira para os autores de caixas fornecerem " "APIs compatíveis com C\n" "através de diferentes ABIs (embora isso não seja importante para esta " "prática)." #: 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 "" "O Rust FFI bem projetado segue os princípios de design da API C, ao mesmo " "tempo em que compromete o\n" "projete em Rust o mínimo possível. Existem três objetivos com qualquer API " "estrangeira:" #: 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. Facilite o uso no idioma de destino.\n" "2. Evite o máximo possível a API ditando a insegurança interna no lado da " "Rust.\n" "3. Mantenha o potencial de insegurança de memória e \"comportamento " "indefinido\" Rust como pequeno\n" " que possível." #: 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 "" "O código Rust deve confiar na segurança da memória do idioma estrangeiro " "além de um certo\n" "apontar. No entanto, cada pedaço de código `inseguro` no lado do Rust é uma " "oportunidade para\n" "bugs, ou para exacerbar `comportamento indefinido`." #: 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 "" "Por exemplo, se a proveniência de um ponteiro estiver errada, isso pode ser " "uma falha de segmentação devido a\n" "acesso inválido à memória. Mas se for manipulado por código inseguro, pode " "tornar-se\n" "corrupção total da pilha." #: 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 "" "O design da API baseada em objeto permite escrever shims com boa segurança " "de memória\n" "características e um limite claro do que é seguro e do que é 'inseguro'." #: 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 "" "O padrão POSIX define a API para acessar um banco de dados on-file, " "conhecido como " "[DBM](https://web.archive.org/web/20210105035602/https://www.mankier.com/0p/ndbm.h) " ".\n" "É um excelente exemplo de uma API \"baseada em objeto\"." #: 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 "" "Aqui está a definição em C, que deve ser fácil de ler para aqueles\n" "envolvidos no FFI. O comentário abaixo deve ajudar a explicá-lo para aqueles " "que\n" "perca as sutilezas." #: 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 "Esta API define dois tipos: `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 "" "O tipo `DBM` foi chamado de tipo \"encapsulado\" acima.\n" "Ele é projetado para conter o estado interno e atua como um ponto de entrada " "para o\n" "comportamento da 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 para o usuário, que não pode criar um `DBM` por conta " "própria, pois\n" "eles não sabem seu tamanho ou layout. Em vez disso, eles devem chamar " "`dbm_open`, e isso\n" "apenas dá a eles _um ponteiro para um_." #: 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 "" "Isso significa que todos os `DBM`s são \"propriedade\" da biblioteca no " "sentido Rust.\n" "O estado interno de tamanho desconhecido é mantido na memória controlada " "pela biblioteca,\n" "não o usuário. O usuário só pode gerenciar seu ciclo de vida com 'abrir' e " "'fechar',\n" "e executar operações nele com as outras funções." #: 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 "" "O tipo `datum` foi chamado de tipo \"transacional\" acima.\n" "Ele é projetado para facilitar a troca de informações entre a biblioteca e " "os\n" "seu usuário." #: 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 "" "O banco de dados é projetado para armazenar \"dados não estruturados\", sem " "comprimento pré-definido\n" "ou significado. Como resultado, o `datum` é o equivalente em C de uma fatia " "Rust: um monte\n" "de bytes e uma contagem de quantos existem. A principal diferença é que " "existe\n" "nenhuma informação de tipo, que é o que `void` indica." #: 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 "" "Tenha em mente que este cabeçalho foi escrito do ponto de vista da " "biblioteca.\n" "O usuário provavelmente tem algum tipo que está usando, que tem um tamanho " "conhecido.\n" "Mas a biblioteca não se importa, e pelas regras do C casting, qualquer tipo " "por trás de um\n" "ponteiro pode ser convertido em `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 "" "Conforme observado anteriormente, esse tipo é _transparent_ para o usuário. " "Mas também, este tipo é\n" "_propriedade_ do usuário.\n" "Isso tem ramificações sutis, devido ao ponteiro dentro dele.\n" "A questão é: a quem pertence a memória para a qual o ponteiro aponta?" #: 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 "" "A resposta para a melhor segurança de memória é \"o usuário\".\n" "Mas em casos como recuperar um valor, o usuário não sabe como alocar\n" "corretamente (já que eles não sabem quanto tempo é o valor). Neste caso, a " "biblioteca\n" "espera-se que o código use o heap ao qual o usuário tem acesso -- como a " "biblioteca C\n" "`malloc` e `free` -- e então _transferir propriedade_ no sentido 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 "" "Tudo isso pode parecer especulativo, mas é isso que um ponteiro significa em " "C.\n" "Significa a mesma coisa que Rust: \"tempo de vida definido pelo usuário\".\n" "O usuário da biblioteca precisa ler a documentação para utilizá-la " "corretamente.\n" "Dito isso, há algumas decisões que têm menos ou mais consequências se os " "usuários\n" "faça errado. Minimizá-los é o objetivo desta melhor prática, e a chave\n" "é _transferir a propriedade de tudo que é transparente_." #: 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 "" "Isso minimiza o número de garantias de segurança de memória que o usuário " "deve manter a um\n" "número relativamente pequeno:" #: 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. Não chame nenhuma função com um ponteiro não retornado por `dbm_open` " "(inválido\n" " acesso ou corrupção).\n" "2. Não chame nenhuma função em um ponteiro depois de fechar (use depois de " "liberar).\n" "3. O `dptr` em qualquer `datum` deve ser `NULL` ou apontar para uma parte " "válida da memória\n" " no comprimento anunciado." #: 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 "" "Além disso, evita muitos problemas de proveniência do ponteiro.\n" "Para entender o porquê, vamos considerar uma alternativa com alguma " "profundidade: iteração de chave." #: 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 é bem conhecido por seus iteradores.\n" "Ao implementar um, o programador cria um tipo separado com um tempo de vida " "limitado\n" "ao seu proprietário e implementa a característica `Iterator`." #: src\patterns/ffi/export.md:129 #, fuzzy msgid "Here is how iteration would be done in Rust for `DBM`:" msgstr "Aqui está como a iteração seria feita em Rust para `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 "" "Isso é limpo, idiomático e seguro. graças às garantias de Rust.\n" "No entanto, considere como seria uma tradução direta da 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 "" "Essa API perde uma informação importante: o tempo de vida do iterador não " "deve\n" "exceder o tempo de vida do objeto `Dbm` que o possui. Um usuário da " "biblioteca pode\n" "usá-lo de uma maneira que faça com que o iterador sobreviva aos dados em que " "está iterando,\n" "resultando na leitura de memória não inicializada." #: src\patterns/ffi/export.md:173 #, fuzzy msgid "" "This example written in C contains a bug that will be explained afterwards:" msgstr "Este exemplo escrito em C contém um bug que será explicado a seguir:" #: 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 "" "Este erro é um clássico. Aqui está o que acontece quando o iterador retorna " "o\n" "marcador de fim de iteração:" #: 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. A condição do loop define `l` como zero e entra no loop porque `0 >= 0`.\n" "2. O comprimento é incrementado, neste caso por zero.\n" "3. A instrução if é verdadeira, então o banco de dados está fechado. Deve " "haver uma pausa\n" " declaração aqui.\n" "4. A condição do loop é executada novamente, causando uma chamada `next` no " "objeto fechado." #: 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 "" "A pior parte desse bug?\n" "Se a implementação do Rust for cuidadosa, esse código funcionará na maioria " "das vezes!\n" "Se a memória para o objeto `Dbm` não for reutilizada imediatamente, uma " "verificação interna\n" "quase certamente falhará, resultando no iterador retornando um `-1` " "indicando\n" "um erro. Mas, ocasionalmente, causará uma falha de segmentação ou, pior " "ainda,\n" "corrupção de memória sem sentido!" #: 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 "" "Nada disso pode ser evitado por Rust.\n" "De sua perspectiva, ele colocou esses objetos em sua pilha, retornou " "ponteiros para eles,\n" "e desistiram do controle de suas vidas. O código C simplesmente deve \"jogar " "bem\"." #: 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 "" "O programador deve ler e entender a documentação da API.\n" "Enquanto alguns consideram esse par para o curso em C, um bom design de API " "pode atenuar\n" "este risco. A API POSIX para `DBM` fez isso _consolidando a propriedade_ de\n" "o iterador com seu pai:" #: 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 "Assim, todas as vidas foram unidas e tal insegurança foi evitada." #: 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 "" "No entanto, esta escolha de design também tem uma série de desvantagens, que " "devem ser\n" "considerado também." #: 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 "" "Primeiro, a própria API se torna menos expressiva.\n" "Com POSIX DBM, há apenas um iterador por objeto e cada chamada muda\n" "seu estado. Isso é muito mais restritivo do que iteradores em quase qualquer " "idioma,\n" "mesmo que seja seguro. Talvez com outros objetos relacionados, cujas vidas " "são\n" "menos hierárquica, essa limitação é mais um custo do que a segurança." #: 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 "" "Em segundo lugar, dependendo das relações das partes da API, um esforço de " "design significativo\n" "pode estar envolvido. Muitos dos pontos de design mais fáceis têm outros " "padrões associados\n" "com eles:" #: 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 "" "- [Consolidação de tipo de wrapper](./wrappers.md) agrupa vários tipos de " "Rust\n" " em um \"objeto\" opaco\n" "\n" "- [FFI Error Passing](../../idioms/ffi/errors.md) explica o tratamento de " "erros com número inteiro\n" " códigos e valores de retorno do sentinela (como ponteiros `NULL`)\n" "\n" "- [Accepting Foreign Strings](../../idioms/ffi/accepting-strings.md) permite " "aceitar\n" " strings com código inseguro mínimo e é mais fácil de acertar do que\n" " [Passando Strings para 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 "" "No entanto, nem toda API pode ser feita dessa maneira.\n" "Cabe ao melhor julgamento do programador saber quem é seu público." #: src\patterns/ffi/wrappers.md:1 #, fuzzy msgid "# Type Consolidation into Wrappers" msgstr "# Digite a consolidação em wrappers" #: 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 "" "Esse padrão foi projetado para permitir o manuseio elegante de vários tipos " "relacionados,\n" "enquanto minimiza a área de superfície para insegurança de memória." #: 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 "" "Um dos pilares das regras de aliasing de Rust são os tempos de vida.\n" "Isso garante que muitos padrões de acesso entre os tipos possam ser seguros " "para a memória,\n" "segurança de corrida de dados incluída." #: 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 "" "No entanto, quando os tipos Rust são exportados para outros idiomas, eles " "geralmente são transformados\n" "em ponteiros. Em Rust, um ponteiro significa \"o usuário gerencia o tempo de " "vida da ponta\".\n" "É sua responsabilidade evitar a insegurança da memória." #: 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 "" "Algum nível de confiança no código do usuário é, portanto, necessário, " "principalmente em torno do use-after-free\n" "sobre o qual Rust não pode fazer nada. No entanto, alguns designs de API " "impõem cargas maiores\n" "do que outros no código escrito no outro idioma." #: 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 "" "A API de menor risco é o \"wrapper consolidado\", onde todas as interações " "possíveis\n" "com um objeto são dobrados em um \"tipo wrapper\", mantendo a API Rust limpa." #: 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 "" "Para entender isso, vejamos um exemplo clássico de uma API para exportar: " "iteração\n" "através de uma coleção." #: src\patterns/ffi/wrappers.md:28 #, fuzzy msgid "That API looks like this:" msgstr "Essa API se parece com isso:" #: 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. O iterador é inicializado com `first_key`.\n" "2. Cada chamada para `next_key` avançará o iterador.\n" "3. Chamadas para `next_key` se o iterador estiver no final não farão nada.\n" "4. Conforme observado acima, o iterador é \"envolto\" na coleção (ao " "contrário do nativo\n" " API de ferrugem)." #: 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 o iterador implementa `nth()` de forma eficiente, então é possível " "torná-lo\n" "efêmero para cada chamada de função:" #: 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 "" "Como resultado, o wrapper é simples e não contém nenhum código `inseguro`." #: 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 "" "Isso torna as APIs mais seguras de usar, evitando problemas com tempos de " "vida entre os tipos.\n" "Consulte [APIs baseadas em objetos](./export.md) para saber mais sobre as " "vantagens e armadilhas\n" "isso 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 "" "Freqüentemente, os tipos de empacotamento são bastante difíceis e, às vezes, " "um comprometimento da Rust API\n" "facilitaria as coisas." #: 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 "" "Como exemplo, considere um iterador que não implementa eficientemente " "`nth()`.\n" "Definitivamente valeria a pena colocar uma lógica especial para fazer o " "objeto manipular\n" "iteração internamente, ou para suportar um padrão de acesso diferente de " "forma eficiente que\n" "somente a API de Função Estrangeira usará." #: src\patterns/ffi/wrappers.md:79 #, fuzzy msgid "### Trying to Wrap Iterators (and Failing)" msgstr "### Tentando agrupar iteradores (e falhando)" #: 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 "" "Para agrupar qualquer tipo de iterador na API corretamente, o empacotador " "precisaria\n" "fazer o que uma versão C do código faria: apagar o tempo de vida do " "iterador,\n" "e gerenciá-lo manualmente." #: src\patterns/ffi/wrappers.md:85 #, fuzzy msgid "Suffice it to say, this is _incredibly_ difficult." msgstr "Basta dizer que isso é _incrivelmente_ difícil." #: src\patterns/ffi/wrappers.md:87 #, fuzzy msgid "Here is an illustration of just _one_ pitfall." msgstr "Aqui está uma ilustração de apenas uma armadilha." #: src\patterns/ffi/wrappers.md:89 #, fuzzy msgid "A first version of `MySetWrapper` would look like this:" msgstr "Uma primeira versão de `MySetWrapper` ficaria assim:" #: 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\n" " iterator: Option>>,\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 "" "Com `transmutar` sendo usado para estender uma vida, e um ponteiro para " "ocultá-lo,\n" "já está feio. Mas fica ainda pior: _qualquer outra operação pode causar\n" "Rust `comportamento indefinido`_." #: 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 "" "Considere que o `MySet` no wrapper pode ser manipulado por outros\n" "funções durante a iteração, como armazenar um novo valor na chave que foi\n" "iterando. A API não desencoraja isso e, de fato, alguns C semelhantes\n" "as bibliotecas esperam isso." #: src\patterns/ffi/wrappers.md:109 #, fuzzy msgid "A simple implementation of `myset_store` would be:" msgstr "Uma implementação simples de `myset_store` seria:" #: 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 o iterador existir quando esta função for chamada, violamos uma das " "regras do Rust\n" "regras de alias. De acordo com Rust, a referência mutável neste bloco deve " "ter\n" "acesso _exclusivo_ ao objeto. Se o iterador simplesmente existir, não é " "exclusivo,\n" "então temos `comportamento indefinido`!" #: 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 "" "Para evitar isso, devemos ter uma maneira de garantir que a referência " "mutável seja realmente exclusiva.\n" "Isso basicamente significa limpar a referência compartilhada do iterador " "enquanto ela existe,\n" "e depois reconstruí-lo. Na maioria dos casos, isso ainda será menos " "eficiente do que\n" "a versão 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 "" "Alguns podem perguntar: como C pode fazer isso de forma mais eficiente?\n" "A resposta é: engana. As regras de aliasing do Rust são o problema, e C " "simplesmente ignora\n" "eles por seus ponteiros. Em troca, é comum ver código declarado\n" "no manual como \"não thread-safe\" em algumas ou todas as circunstâncias. Na " "verdade,\n" "a [biblioteca GNU " "C](https://manpages.debian.org/buster/manpages/attributes.7.en.html)\n" "tem todo um léxico dedicado ao comportamento simultâneo!" #: 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 prefere tornar tudo seguro para a memória o tempo todo, tanto para " "segurança quanto para\n" "otimizações que o código C não pode atingir. Ser negado o acesso a certos " "atalhos\n" "é o preço que os programadores Rust precisam pagar." #: 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 "" "Para os programadores C que estão coçando a cabeça, o iterador precisa\n" "não ser lido _durante_ este código causa o UB. A regra de exclusividade " "também permite\n" "otimizações do compilador que podem causar observações inconsistentes por " "parte do iterador\n" "referência compartilhada (por exemplo, derramamentos de pilha ou " "reordenamento de instruções para eficiência).\n" "Essas observações podem acontecer _a qualquer momento após_ a referência " "mutável ser criada." #: src\anti_patterns/index.md:1 #, fuzzy msgid "# Anti-patterns" msgstr "# Antipadrões" #: 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 "" "Um [anti-padrão](https://en.wikipedia.org/wiki/Anti-padrão) é uma solução " "para\n" "um \"problema recorrente que geralmente é ineficaz e corre o risco de ser " "altamente\n" "contraproducente\". Tão valioso quanto saber resolver um problema, é\n" "sabendo _não_ resolvê-lo. Os antipadrões nos dão ótimos contra-exemplos " "para\n" "considerar em relação aos padrões de projeto. Os antipadrões não estão " "confinados ao código.\n" "Por exemplo, um processo também pode ser um antipadrão." #: src\anti_patterns/borrow_clone.md:1 #, fuzzy msgid "# Clone to satisfy the borrow checker" msgstr "# Clone para satisfazer o verificador de empréstimo" #: 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 "" "O verificador de empréstimo impede que os usuários do Rust desenvolvam " "códigos inseguros,\n" "garantindo que: apenas uma referência mutável existe, ou potencialmente " "muitas, mas\n" "todas as referências imutáveis existem. Se o código escrito não for fiel a " "essas\n" "condições, esse antipadrão surge quando o desenvolvedor resolve o problema " "do compilador\n" "erro ao clonar a variável." #: 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 "" "É tentador, principalmente para iniciantes, usar esse padrão para resolver\n" "questões confusas com o verificador de empréstimo. No entanto, existem " "graves\n" "consequências. O uso de `.clone()` faz com que uma cópia dos dados seja " "feita. Qualquer alteração\n" "entre os dois não estão sincronizados - como se duas variáveis completamente " "separadas\n" "existir." #: src\anti_patterns/borrow_clone.md:38 #, fuzzy msgid "" "There are special cases -- `Rc` 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 "" "Existem casos especiais -- `Rc` é projetado para lidar com clones de " "forma inteligente.\n" "Ele gerencia internamente exatamente uma cópia dos dados e a clonagem só\n" "clonar a referência." #: src\anti_patterns/borrow_clone.md:42 #, fuzzy msgid "" "There is also `Arc` 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 "" "Há também `Arc` que fornece propriedade compartilhada de um valor do tipo " "T\n" "que está alocado no heap. Invocar `.clone()` em `Arc` produz um novo `Arc`\n" "instância, que aponta para a mesma alocação no heap que a origem `Arc`,\n" "enquanto aumenta uma contagem de referência." #: 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 "" "Em geral, os clones devem ser deliberados, com total compreensão do\n" "consequências. Se um clone for usado para fazer desaparecer um erro do " "verificador de empréstimo,\n" "essa é uma boa indicação de que esse antipadrão pode estar em 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 "" "Mesmo que `.clone()` seja uma indicação de um padrão ruim, às vezes\n" "**é bom escrever código ineficiente**, em casos como 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 "" "- o desenvolvedor ainda é novo na propriedade\n" "- o código não tem grandes restrições de velocidade ou memória\n" " (como projetos ou protótipos de hackathon)\n" "- satisfazer o verificador de empréstimo é realmente complicado e você " "prefere\n" " otimizar a legibilidade sobre o desempenho" #: 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 houver suspeita de um clone desnecessário, o [capítulo do Rust Book sobre " "propriedade](https://doc.rust-lang.org/book/ownership.html)\n" "deve ser totalmente compreendido antes de avaliar se o clone é necessário ou " "não." #: 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 "" "Certifique-se também de sempre executar `cargo clippy` em seu projeto, o que " "detectará alguns\n" "casos em que `.clone()` não é necessário, como " "[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) ou " "[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` documentation, which handles .clone() " "intelligently](http://doc.rust-lang.org/std/rc/)\n" "- [`Arc` 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(_)}` para manter os valores de propriedade em " "enums alterados](../idioms/mem-replace.md)\n" "- [documentação `Rc`, que lida com .clone() de forma " "inteligente](http://doc.rust-lang.org/std/rc/)\n" "- [Documentação do `Arc`, um ponteiro de contagem de referência " "thread-safe](https://doc.rust-lang.org/std/sync/struct.Arc.html)\n" "- [Truques com propriedade em " "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 "# `#![negar(avisos)]`" #: 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 "" "Um criador de caixas bem-intencionado quer garantir que seu código seja " "construído sem\n" "avisos. Então, eles anotam a raiz da caixa com o seguinte:" #: 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 "É curto e interromperá a construção se algo estiver errado." #: src\anti_patterns/deny-warnings.md:20 #, fuzzy msgid "## Drawbacks" msgstr "## Desvantagens" #: 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 "" "Ao não permitir que o compilador construa com avisos, um autor de caixa opta " "por não\n" "A famosa estabilidade de Rust. Às vezes, novos recursos ou antigos erros " "precisam de uma mudança\n" "em como as coisas são feitas, assim são escritos lints que 'advertem' para " "uma certa graça\n" "período antes de ser transformado em `negar`." #: 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 "" "Por exemplo, descobriu-se que um tipo poderia ter dois `impl`s com o mesmo\n" "método. Isso foi considerado uma má ideia, mas para tornar a transição " "suave,\n" "o lint `overlapping-inherent-impls` foi introduzido para dar um aviso " "àqueles\n" "tropeçando nesse fato, antes que se torne um erro grave em uma versão 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 "" "Às vezes, as APIs ficam obsoletas, portanto, seu uso emitirá um aviso onde\n" "antes não havia nenhum." #: src\anti_patterns/deny-warnings.md:35 #, fuzzy msgid "" "All this conspires to potentially break the build whenever something changes." msgstr "" "Tudo isso conspira para potencialmente quebrar a construção sempre que algo " "mudar." #: 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 "" "Além disso, as caixas que fornecem fiapos adicionais (por exemplo, " "[ferrugem-clippy]) não podem\n" "não será mais usado, a menos que a anotação seja removida. Isso é mitigado " "com\n" "[--cap-lints]. O argumento de linha de comando `--cap-lints=warn` transforma " "todos os `deny`\n" "erros lint em avisos." #: src\anti_patterns/deny-warnings.md:42 #: src\functional/generics-type-classes.md:227 #, fuzzy msgid "## Alternatives" msgstr "## Alternativas" #: 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 "" "Existem duas maneiras de lidar com esse problema: primeiro, podemos " "desacoplar a construção\n" "configuração do código e, segundo, podemos nomear os lints que queremos " "negar\n" "explicitamente." #: src\anti_patterns/deny-warnings.md:48 #, fuzzy msgid "The following command line will build with all warnings set to `deny`:" msgstr "" "A linha de comando a seguir será criada com todos os avisos definidos como " "`deny`:" #: src\anti_patterns/deny-warnings.md:50 #, fuzzy msgid "`RUSTFLAGS=\"-D warnings\" cargo build`" msgstr "`RUSTFLAGS=\"-D warnings\" construção de carga`" #: 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 "" "Isso pode ser feito por qualquer desenvolvedor individual (ou pode ser " "configurado em uma ferramenta CI como\n" "Travis, mas lembre-se que isso pode quebrar a construção quando algo mudar)\n" "sem exigir alteração no código." #: 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 "" "Como alternativa, podemos especificar os lints que queremos `negar` no " "código.\n" "Aqui está uma lista de lints de aviso que é (espero) seguro negar (a partir " "de 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 "" "Além disso, os seguintes lints permitidos podem ser uma boa ideia para negar:" #: 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 "" "Alguns também podem querer adicionar `missing-copy-implementations` à sua " "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 "" "Observe que não adicionamos explicitamente o lint `obsoleto`, pois é " "bastante\n" "certo de que haverá mais APIs obsoletas no futuro." #: 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 "" "- [Uma coleção de todos os lints " "clippy](https://rust-lang.github.io/rust-clippy/master)\n" "- [atributo obsoleto] documentação\n" "- Digite `rustc -W help` para obter uma lista de lints em seu sistema. " "Digite também\n" " `rustc --help` para uma lista geral de opções\n" "- [rust-clippy] é uma coleção de lints para melhorar o código 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 "" "Use mal o trait `Deref` para emular a herança entre structs e, assim, " "reutilizar\n" "métodos." #: 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 "" "Às vezes, queremos emular o seguinte padrão comum de linguagens OO, como\n" "como 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 "Podemos usar o antipadrão de polimorfismo deref para fazer isso:" #: 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 "" "Não há herança de struct no Rust. Em vez disso, usamos composição e " "incluímos\n" "uma instância de `Foo` em `Bar` (como o campo é um valor, ele é armazenado " "em linha,\n" "portanto, se houvesse campos, eles teriam o mesmo layout na memória que o " "Java\n" "versão (provavelmente, você deve usar `#[repr(C)]` se quiser ter certeza))." #: 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 "" "Para fazer a chamada do método funcionar, implementamos `Deref` para `Bar` " "com `Foo`\n" "como o destino (retornando o campo `Foo` incorporado). Isso significa que " "quando nós\n" "desreferenciar um `Bar` (por exemplo, usando `*`) então obteremos um `Foo`. " "Aquilo é\n" "bem estranho. Desreferenciar geralmente dá um `T` de uma referência a `T`, " "aqui nós\n" "têm dois tipos não relacionados. No entanto, como o operador ponto " "implícito\n" "desreferenciação, isso significa que a chamada do método irá procurar " "métodos em `Foo` como\n" "bem como 'Bar'." #: src\anti_patterns/deref.md:71 #, fuzzy msgid "You save a little boilerplate, e.g.," msgstr "Você economiza um pouco clichê, por exemplo," #: 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 "" "Mais importante, este é um idioma surpreendente - futuros programadores " "lendo isso em\n" "código não espera que isso aconteça. Isso porque estamos usando mal o " "`Deref`\n" "traço em vez de usá-lo como pretendido (e documentado, etc.). é também " "porque\n" "o mecanismo aqui é completamente implícito." #: 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 "" "Este padrão não introduz subtipagem entre `Foo` e `Bar` como\n" "herança em Java ou C++ faz. Além disso, as características implementadas por " "`Foo` são\n" "não implementado automaticamente para `Bar`, então este padrão interage mal " "com\n" "verificação de limites e, portanto, programação genérica." #: 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 "" "O uso desse padrão fornece uma semântica sutilmente diferente da maioria das " "linguagens OO com\n" "diz respeito a 'eu'. Normalmente permanece uma referência à subclasse, com " "este\n" "pattern será a 'classe' onde o método é definido." #: 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 "" "Por fim, esse padrão suporta apenas herança única e não tem noção de\n" "interfaces, privacidade baseada em classe ou outros recursos relacionados à " "herança. Então, é\n" "oferece uma experiência que surpreenderá sutilmente os programadores " "acostumados com Java\n" "herança, etc" #: 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 "" "Não há uma boa alternativa. Dependendo das circunstâncias exatas, pode\n" "seria melhor reimplementar usando traits ou escrever os métodos de fachada " "para\n" "despachar para `Foo` manualmente. Pretendemos adicionar um mecanismo para " "herança\n" "semelhante a isso para Rust, mas é provável que demore algum tempo antes de " "atingir\n" "ferrugem estável. Veja estes " "[blog](http://aturon.github.io/blog/2015/09/18/reuse/)\n" "[postagens](http://smallcultfollowing.com/babysteps/blog/2015/10/08/virtual-structs-part-4-extended-enums-and-thin-traits/)\n" "e este [problema RFC](https://github.com/rust-lang/rfcs/issues/349) para " "mais detalhes." #: 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 "" "O trait `Deref` é projetado para a implementação de tipos de ponteiro " "personalizados.\n" "A intenção é que ele leve um ponteiro para `T` para um `T`, não converta\n" "entre diferentes tipos. É uma pena que isso não seja (provavelmente não pode " "ser)\n" "imposta pela definição do traço." #: 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 tenta encontrar um equilíbrio cuidadoso entre mecanismos explícitos e " "implícitos,\n" "favorecendo conversões explícitas entre tipos. Desreferenciamento automático " "no ponto\n" "operador é um caso onde a ergonomia favorece fortemente um mecanismo " "implícito,\n" "mas a intenção é que isso seja limitado a graus de indireção, não\n" "conversão entre tipos arbitrários." #: 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 "" "- [Coleções são idiomas de ponteiros inteligentes](../idioms/deref.md).\n" "- Caixas de delegação por menos padrão como " "[delegate](https://crates.io/crates/delegate)\n" " ou [embaixador](https://crates.io/crates/ambassador)\n" "- [Documentação para o trait " "`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html)." #: src\functional/index.md:1 #, fuzzy msgid "# Functional Usage of Rust" msgstr "# Uso Funcional de 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 "" "A ferrugem é uma linguagem imperativa, mas segue muitas\n" "[programação " "funcional](https://en.wikipedia.org/wiki/Functional_programming) paradigmas." #: 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 "" "> Em ciência da computação, _programação funcional_ é um paradigma de " "programação onde\n" "> os programas são construídos aplicando e compondo funções.\n" "> É um paradigma de programação declarativa em que as definições de funções " "são\n" "> árvores de expressões que retornam um valor, em vez de uma sequência de\n" "> declarações imperativas que mudam o estado do programa." #: src\functional/paradigms.md:1 #, fuzzy msgid "# Programming paradigms" msgstr "# Paradigmas de programação" #: 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 "" "Um dos maiores obstáculos para a compreensão dos programas funcionais ao " "chegar\n" "de um fundo imperativo é a mudança no pensamento. programas imperativos\n" "descrevem **como** fazer algo, enquanto os programas declarativos descrevem\n" "**o que fazer. Vamos somar os números de 1 a 10 para mostrar isso." #: 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 "" "Com programas imperativos, temos que jogar compilador para ver o que está " "acontecendo.\n" "Aqui, começamos com uma `soma` de `0`.\n" "Em seguida, iteramos pelo intervalo de 1 a 10.\n" "Cada vez que passamos pelo loop, adicionamos o valor correspondente no " "intervalo.\n" "Depois imprimimos." #: 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 "" "| `eu` | `soma` |\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 "" "É assim que a maioria de nós começa a programar. Aprendemos que um programa " "é um conjunto\n" "de passos." #: src\functional/paradigms.md:40 #, fuzzy msgid "## Declarative" msgstr "## Declarativo" #: 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 "" "Uau! Isso é realmente diferente! O que está acontecendo aqui?\n" "Lembre-se que com programas declarativos estamos descrevendo **o que** " "fazer,\n" "em vez de **como** fazer. `fold` é uma função que " "[compõe](https://en.wikipedia.org/wiki/Function_composition)\n" "funções. O nome é uma convenção de 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 "" "Aqui, estamos compondo funções de adição (este fechamento: `|a, b| a + b`)\n" "com um intervalo de 1 a 10. O `0` é o ponto de partida, então `a` é `0` em\n" "primeiro. `b` é o primeiro elemento do intervalo, `1`. `0 + 1 = 1` é o " "resultado.\n" "Então agora nós `fold` novamente, com `a = 1`, `b = 2` e então `1 + 2 = 3` é " "o próximo\n" "resultado. Esse processo continua até chegarmos ao último elemento do " "intervalo,\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` | resultado |\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 as Type Classes" #: 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 "" "O sistema de tipos do Rust é projetado mais como linguagens funcionais (como " "Haskell)\n" "em vez de linguagens imperativas (como Java e C++). Como resultado, Rust " "pode transformar\n" "muitos tipos de problemas de programação em problemas de \"digitação " "estática\". Isso é um\n" "das maiores vitórias de escolher uma linguagem funcional, e é fundamental " "para muitos\n" "das garantias de tempo de compilação do 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` and `vector` 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 "" "Uma parte fundamental dessa ideia é a maneira como os tipos genéricos " "funcionam. Em C++ e Java, por\n" "Por exemplo, os tipos genéricos são uma construção de metaprogramação para o " "compilador.\n" "`vector` e `vector` em C++ são apenas duas cópias diferentes do\n" "mesmo código clichê para um tipo `vector` (conhecido como `template`) com " "dois\n" "diferentes tipos preenchidos." #: 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` and " "`Vec`\n" "_are two different types_, which are recognized as distinct by all parts of " "the\n" "type system." msgstr "" "No Rust, um parâmetro de tipo genérico cria o que é conhecido em linguagens " "funcionais\n" "como uma \"restrição de classe de tipo\", e cada parâmetro diferente " "preenchido por um final\n" "o usuário _realmente muda o tipo_. Em outras palavras, `Vec` e " "`Vec`\n" "_são dois tipos diferentes_, que são reconhecidos como distintos por todas " "as partes do\n" "tipo de sistema." #: 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 "" "Isso é chamado de **monomorfização**, onde diferentes tipos são criados a " "partir de\n" "Código **polimórfico**. Este comportamento especial requer blocos `impl` " "para especificar\n" "parâmetros genéricos. Valores diferentes para o tipo genérico causam tipos " "diferentes,\n" "e diferentes tipos podem ter diferentes blocos `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 "" "Em linguagens orientadas a objetos, as classes podem herdar o comportamento " "de seus pais.\n" "No entanto, isso permite a anexação não apenas de comportamento adicional a\n" "membros particulares de uma classe de tipo, mas comportamento extra também." #: 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 "" "O equivalente mais próximo é o polimorfismo de tempo de execução em " "Javascript e Python,\n" "onde novos membros podem ser adicionados a objetos por qualquer construtor.\n" "No entanto, ao contrário dessas linguagens, todos os métodos adicionais do " "Rust podem ser digitados\n" "verificados quando são usados, porque seus genéricos são definidos " "estaticamente. Que\n" "torna-os mais utilizáveis enquanto permanecem seguros." #: 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 "" "Suponha que você esteja projetando um servidor de armazenamento para uma " "série de máquinas de laboratório.\n" "Devido ao software envolvido, existem dois protocolos diferentes que você " "precisa\n" "para suportar: BOOTP (para inicialização de rede PXE) e NFS (para " "armazenamento de montagem remota)." #: 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 "" "Seu objetivo é ter um programa, escrito em Rust, que possa lidar com ambos\n" "eles. Ele terá manipuladores de protocolo e escutará ambos os tipos de " "solicitações. O\n" "a lógica do aplicativo principal permitirá que um administrador de " "laboratório configure o armazenamento\n" "e controles de segurança para os arquivos reais." #: 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 "" "As solicitações de máquinas no laboratório para arquivos contêm o mesmo " "básico\n" "informações, independentemente do protocolo de onde vieram: um método de " "autenticação,\n" "e um nome de arquivo para recuperar. Uma implementação direta pareceria\n" "algo assim:" #: 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 "" "Este design pode funcionar bem o suficiente. Mas agora suponha que você " "precise apoiar\n" "adicionando metadados que eram _protocolos específicos_. Por exemplo, com o " "NFS, você\n" "queria determinar qual era o seu ponto de montagem para impor\n" "regras de segurança." #: 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 "" "A maneira como a estrutura atual é projetada deixa a decisão do protocolo " "até\n" "tempo de execução. Isso significa qualquer método que se aplique a um " "protocolo e não ao outro\n" "requer que o programador faça uma verificação de tempo de execução." #: src\functional/generics-type-classes.md:75 #, fuzzy msgid "Here is how getting an NFS mount point would look:" msgstr "Aqui está como obter um ponto de montagem NFS seria:" #: src\functional/generics-type-classes.md:77 msgid "" "```rust,ignore\n" "struct FileDownloadRequest {\n" " file_name: PathBuf,\n" " authentication: AuthInfo,\n" " mount_point: Option,\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 "" "Todo chamador de `mount_point()` deve verificar `None` e escrever o código " "para manipular\n" "isto. Isso é verdade mesmo que eles saibam que apenas solicitações NFS são " "usadas em um determinado\n" "caminho do código!" #: 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 "" "Seria muito mais ideal causar um erro de tempo de compilação se os " "diferentes\n" "os tipos de solicitação eram confusos. Afinal, todo o caminho do código do " "usuário,\n" "incluindo quais funções da biblioteca eles usam, saberão se uma solicitação\n" "é uma solicitação NFS ou uma solicitação 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 "" "No Rust, isso é realmente possível! A solução é _adicionar um tipo genérico_ " "em\n" "para dividir a API." #: src\functional/generics-type-classes.md:107 #, fuzzy msgid "Here is what that looks like:" msgstr "Aqui está o que parece:" #: 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 {\n" " file_name: PathBuf,\n" " protocol: P,\n" "}\n" "\n" "// all common API parts go into a generic impl block\n" "impl FileDownloadRequest

{\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 {\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` does " "not\n" "implement `mount_point()`, only the type `FileDownloadRequest` does. " "And\n" "that is created by the NFS module, not the BOOTP module of course!" msgstr "" "Eles receberiam um erro de sintaxe. O tipo `FileDownloadRequest` não\n" "implementar `mount_point()`, apenas o tipo `FileDownloadRequest` o faz. " "E\n" "que é criado pelo módulo NFS, não pelo módulo BOOTP, é claro!" #: 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 "" "Primeiro, permite que os campos comuns a vários estados sejam " "desduplicados.\n" "Ao tornar os campos não compartilhados genéricos, eles são implementados uma " "vez." #: 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 "" "Em segundo lugar, torna os blocos `impl` mais fáceis de ler, porque eles são " "divididos\n" "por estado. Os métodos comuns a todos os estados são digitados uma vez em um " "bloco e os métodos\n" "exclusivos para um estado estão em um bloco separado." #: 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 "" "Ambos significam que há menos linhas de código e são mais bem organizados." #: 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 "" "Isso atualmente aumenta o tamanho do binário, devido à forma como a " "monomorfização\n" "é implementado no compilador. Esperamos que a implementação seja capaz de\n" "melhorar no 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 um tipo parecer precisar de uma \"API dividida\" devido à construção " "ou\n" " inicialização, considere o\n" " [Padrão do construtor](../patterns/creational/builder.md) em vez disso.\n" "\n" "- Se a API entre os tipos não mudar -- apenas o comportamento muda -- então\n" " o [Padrão de Estratégia](../patterns/behavioural/strategy.md) é melhor " "usado\n" " em vez de." #: src\functional/generics-type-classes.md:239 #, fuzzy msgid "This pattern is used throughout the standard library:" msgstr "Este padrão é usado em toda a biblioteca padrão:" #: src\functional/generics-type-classes.md:241 #, fuzzy msgid "" "- `Vec` can be cast from a String, unlike every other type of " "`Vec`.[^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` pode ser lançado a partir de uma String, ao contrário de " "qualquer outro tipo de `Vec`.[^1]\n" "- Eles também podem ser lançados em um heap binário, mas apenas se " "contiverem um tipo\n" " que implementa o traço `Ord`.[^2]\n" "- O método `to_string` foi especializado para `Cow` apenas do 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 "" "Ele também é usado por várias caixas populares para permitir a flexibilidade " "da 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` 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 "" "- O ecossistema `embedded-hal` usado para dispositivos embarcados faz uso " "extensivo de\n" " esse padrão. Por exemplo, permite verificar estaticamente a configuração " "de\n" " registradores de dispositivos usados para controlar pinos embutidos. " "Quando um pino é colocado em um modo,\n" " ele retorna uma estrutura `Pin`, cujo genérico determina as funções\n" " utilizáveis nesse modo, que não estão no próprio `Pin`. [^4]\n" "\n" "- A biblioteca de cliente `hiper` HTTP usa isso para expor APIs ricas para " "diferentes\n" " solicitações conectáveis. Clientes com conectores diferentes têm métodos " "diferentes\n" " sobre eles, bem como implementações de características diferentes, " "enquanto um conjunto básico de\n" " Os métodos se aplicam a qualquer conector. [^5]\n" "\n" "- O padrão \"tipo de estado\" -- onde um objeto ganha e perde API com base " "em um\n" " estado interno ou invariante -- é implementado em Rust usando o mesmo\n" " conceito e uma técnica ligeiramente diferente. [^6]" #: src\functional/generics-type-classes.md:263 #, fuzzy msgid "" "See: [impl From\\ for " "Vec\\](https://doc.rust-lang.org/1.59.0/src/std/ffi/c_str.rs.html#803-811)" msgstr "" "Veja: [impl From\\ for " "Vec\\](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\\ From\\\\> for " "BinaryHeap\\](https://doc.rust-lang.org/stable/src/alloc/collections/binary_heap.rs.html#1345-1354)" msgstr "" "Veja: [impl\\ From\\\\> for " "BinaryHeap\\](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 "" "Veja: [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 "" "Exemplo:\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 "" "Ver:\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 "" "Ver:\n" "[O caso para o padrão de estado de " "tipo](https://web.archive.org/web/20210325065112/https://www.novatec-gmbh.de/en/blog/the-case-for-the-typestate- " "padrão-o-tipo-estado-padrão-em-si/)\n" "e\n" "[Série Rusty Typestate (uma tese " "extensa)](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 "# Lentes e Prismas" #: 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 "" "Este é um conceito funcional puro que não é usado com frequência no Rust.\n" "No entanto, explorar o conceito pode ser útil para entender outras\n" "padrões em Rust APIs, como [visitors](../patterns/behavioural/visitor.md).\n" "Eles também têm casos de uso de nicho." #: src\functional/lenses.md:8 #, fuzzy msgid "## Lenses: Uniform Access Across Types" msgstr "## Lentes: Acesso uniforme entre os tipos" #: 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 "" "Uma lente é um conceito de linguagens de programação funcional que permite\n" "acessando partes de um tipo de dados de forma abstrata e unificada.[^1]\n" "No conceito básico, é semelhante à maneira como as características do Rust " "funcionam com o apagamento de tipo,\n" "mas tem um pouco mais de potência e flexibilidade." #: 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 "" "Por exemplo, suponha que um banco contenha vários formatos JSON para " "clientes\n" "dados.\n" "Isso ocorre porque eles vêm de diferentes bancos de dados ou sistemas " "legados.\n" "Um banco de dados contém os dados necessários para realizar verificações de " "crédito:" #: 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 "Outro contém as informações da conta:" #: 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 "" "Observe que ambos os tipos têm um número de identificação do cliente que " "corresponde a uma pessoa.\n" "Como uma única função lidaria com ambos os registros de tipos diferentes?" #: 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 "" "Em Rust, uma `struct` poderia representar cada um desses tipos, e um trait " "teria\n" "uma função `get_customer_id` que eles implementariam:" #: 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,\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(records: &[R]) -> HashSet {\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(iterator: I) -> HashSet\n" " where I: Iterator>\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 "" "As lentes, no entanto, permitem que o código que suporta a ID do cliente " "seja movido do\n" "_type_ para a função _accessor_.\n" "Em vez de implementar uma característica em cada tipo, todas as estruturas " "correspondentes podem\n" "simplesmente ser acessado da mesma maneira." #: 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 "" "Embora a própria linguagem Rust não suporte isso (o apagamento de tipo é o\n" "solução preferida para este problema), o [lens-rs " "crate](https://github.com/TOETOE55/lens-rs/blob/master/guide.md) permite o " "código\n" "que se sente assim para ser escrito com macros:" #: 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,\n" "}\n" "\n" "fn unique_ids_lens(iter: impl Iterator) -> HashSet\n" "where\n" " T: LensRef, // 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 "" "A versão de `unique_ids_lens` mostrada aqui permite que qualquer tipo esteja " "no iterador,\n" "desde que tenha um atributo chamado `customer_id` que pode ser acessado por\n" "a função.\n" "É assim que a maioria das linguagens de programação funcionais operam nas " "lentes." #: 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 "" "Em vez de macros, eles conseguem isso com uma técnica conhecida como " "\"currying\".\n" "Ou seja, eles \"constroem parcialmente\" a função, deixando o tipo do\n" "parâmetro final (o valor que está sendo operado) não preenchido até que a " "função seja\n" "chamado.\n" "Assim, pode ser chamado com diferentes tipos dinamicamente, mesmo de um " "lugar em\n" "o código.\n" "Isso é o que `optics!` e `view_ref` no exemplo acima simulam." #: 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 "" "A abordagem funcional não precisa ser restrita aos membros de acesso.\n" "Podem ser criadas lentes mais poderosas que _configuram_ e _obtêm_ dados em " "um\n" "estrutura.\n" "Mas o conceito realmente se torna interessante quando usado como bloco de " "construção para\n" "composição.\n" "É aí que o conceito aparece com mais clareza em Rust." #: src\functional/lenses.md:169 #, fuzzy msgid "## Prisms: A Higher-Order form of \"Optics\"" msgstr "## Prismas: Uma forma de ordem superior de \"Óptica\"" #: 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 "" "Uma função simples como `unique_ids_lens` acima opera em uma única lente.\n" "Um _prisma_ é uma função que opera em uma _família_ de lentes.\n" "É um nível conceitual superior, usando lentes como bloco de construção e\n" "continuando a metáfora, faz parte de uma família de \"ópticas\".\n" "É o principal que é útil para entender as APIs do Rust, assim será o\n" "foco aqui." #: 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 "" "Da mesma forma que as características permitem um design \"semelhante a uma " "lente\" com polimorfismo estático e\n" "despacho dinâmico, designs semelhantes a prismas aparecem em APIs Rust que " "dividem problemas\n" "em vários tipos associados a serem compostos.\n" "Um bom exemplo disso são as características na caixa de análise _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 "" "Tentar entender como o _Serde_ funciona apenas lendo a API é uma\n" "desafio, especialmente na primeira vez.\n" "Considere o trait `Deserializer`, implementado por algum tipo em qualquer " "biblioteca\n" "que analisa um novo formato:" #: src\functional/lenses.md:188 msgid "" "```rust,ignore\n" "pub trait Deserializer<'de>: Sized {\n" " type Error: Error;\n" "\n" " fn deserialize_any(self, visitor: V) -> Result\n" " where\n" " V: Visitor<'de>;\n" "\n" " fn deserialize_bool(self, visitor: V) -> Result\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 "" "Para uma característica que deve apenas analisar dados de um formato e " "retornar um\n" "valor, isso parece estranho." #: src\functional/lenses.md:207 #, fuzzy msgid "Why are all the return types type erased?" msgstr "Por que todos os tipos de retorno são apagados?" #: 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 "" "Para entender isso, precisamos manter o conceito de lente em mente e olhar " "para\n" "a definição do tipo `Visitor` que é passado genericamente:" #: src\functional/lenses.md:212 msgid "" "```rust,ignore\n" "pub trait Visitor<'de>: Sized {\n" " type Value;\n" "\n" " fn visit_bool(self, v: bool) -> Result\n" " where\n" " E: Error;\n" "\n" " fn visit_u64(self, v: u64) -> Result\n" " where\n" " E: Error;\n" "\n" " fn visit_str(self, v: &str) -> Result\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 "" "O trabalho do tipo `Visitor` é construir valores no modelo de dados " "_Serde_,\n" "que são representados por seu tipo `Value` associado." #: 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 "" "Esses valores representam partes do valor Rust sendo desserializado.\n" "Se falhar, ele retornará um tipo `Error` - um tipo de erro determinado pelo\n" "`Deserializer` quando seus métodos foram chamados." #: 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 "" "Isso destaca que `Deserializer` é semelhante a `CustomerId` de antes,\n" "permitindo que qualquer analisador de formato que o implemente crie " "`Valores`s com base no que\n" "ele analisou.\n" "O traço `Valor` está agindo como uma lente em linguagens de programação " "funcional." #: 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 "" "Mas ao contrário do trait `CustomerId`, os tipos de retorno dos métodos " "`Visitor` são\n" "_genérico_, e o tipo `Valor` concreto é _determinado pelo próprio Visitante_." #: 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 "" "Em vez de atuar como uma lente, ela efetivamente atua como uma família de\n" "lentes, uma para cada tipo concreto de 'Visitante'." #: 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 "" "A API `Deserializer` é baseada em ter um conjunto genérico de \"lentes\" " "trabalhando\n" "um conjunto de outros tipos genéricos para \"observação\".\n" "É um _prisma_." #: src\functional/lenses.md:254 #, fuzzy msgid "For example, consider the identity record from earlier but simplified:" msgstr "" "Por exemplo, considere o registro de identidade anterior, mas simplificado:" #: 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 "" "Como a biblioteca _Serde_ desserializaria este JSON em `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. O usuário chamaria uma função de biblioteca para desserializar os dados. " "Isso seria\n" " crie um `Deserializer` baseado no formato JSON.\n" "1. Com base nos campos da estrutura, um `Visitor` seria criado (mais sobre\n" " isso daqui a pouco) que sabe como criar cada tipo em um data genérico\n" " modelo necessário para representá-lo: `u64` e `String`.\n" "1. O desserializador faria chamadas para o `Visitor` enquanto analisava os " "itens.\n" "1. O 'Visitante' indicaria se os itens encontrados eram esperados e, se " "não,\n" " gera um erro para indicar que a desserialização falhou." #: src\functional/lenses.md:273 #, fuzzy msgid "For our very simple structure above, the expected pattern would be:" msgstr "Para nossa estrutura muito simples acima, o padrão esperado seria:" #: 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. Visite um mapa (equivalente de _Serde_ a `HashMap` ou dicionário de " "JSON).\n" "1. Visite uma chave de string chamada \"nome\".\n" "1. Visite um valor de string, que irá para o campo `name`.\n" "1. Visite uma chave de string chamada \"customer_id\".\n" "1. Visite um valor de string, que irá para o campo `customer_id`.\n" "1. Visite o final do mapa." #: src\functional/lenses.md:282 #, fuzzy msgid "But what determines which \"observation\" pattern is expected?" msgstr "Mas o que determina qual padrão de \"observação\" é esperado?" #: 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 "" "Uma linguagem de programação funcional seria capaz de usar currying para " "criar\n" "reflexão de cada tipo com base no próprio tipo.\n" "Rust não suporta isso, então cada tipo precisaria ter seu próprio\n" "código escrito com base em seus campos e suas propriedades." #: src\functional/lenses.md:289 #, fuzzy msgid "_Serde_ solves this usability challenge with a derive macro:" msgstr "_Serde_ resolve esse desafio de usabilidade com uma macro de derivação:" #: 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 "" "Essa macro simplesmente gera um bloco impl fazendo com que o struct " "implemente um\n" "traço chamado `Deserialize`." #: src\functional/lenses.md:304 #, fuzzy msgid "It is defined this way:" msgstr "É definido desta forma:" #: src\functional/lenses.md:306 msgid "" "```rust,ignore\n" "pub trait Deserialize<'de>: Sized {\n" " fn deserialize(deserializer: D) -> Result\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 "" "Esta é a função que determina como criar a própria estrutura.\n" "O código é gerado com base nos campos da estrutura.\n" "Quando a biblioteca de análise é chamada - em nosso exemplo, uma biblioteca " "de análise JSON -\n" "ele cria um `Deserializer` e chama `Type::deserialize` com ele como um\n" "parâmetro." #: 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 "" "O código `deserialize` criará então um `Visitor` que terá suas chamadas\n" "\"refratado\" pelo `Deserializer`.\n" "Se tudo correr bem, eventualmente esse `Visitor` construirá um valor\n" "correspondente ao tipo que está sendo analisado e retorná-lo." #: src\functional/lenses.md:325 #, fuzzy msgid "" "For a complete example, see the [_Serde_ " "documentation](https://serde.rs/deserialize-struct.html)." msgstr "" "Para obter um exemplo completo, consulte a [documentação do " "_Serde_](https://serde.rs/deserialize-struct.html)." #: src\functional/lenses.md:327 #, fuzzy msgid "To wrap up, this is the power of _Serde_:" msgstr "Para finalizar, este é o poder do _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. A estrutura que está sendo analisada é representada por um bloco `impl` " "para `Deserialize`\n" "1. O formato de dados de entrada (por exemplo, JSON) é representado por um " "`Deserializer` chamado\n" " por `Deserialize`\n" "1. O `Deserializer` age como um prisma que \"refrata\" o `Visitor` " "semelhante a uma lente\n" " chamadas que realmente constroem o valor dos dados" #: 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 "" "O resultado é que os tipos a serem desserializados implementam apenas a " "\"camada superior\" de\n" "a API e os formatos de arquivo só precisam implementar a \"camada " "inferior\".\n" "Cada peça pode então \"simplesmente funcionar\" com o resto do ecossistema, " "desde\n" "os tipos os unirão." #: 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 "" "Para enfatizar, a única razão pela qual este modelo funciona em qualquer " "formato e qualquer tipo é\n" "porque o tipo de saída do trait `Deserializer` ** é especificado pelo\n" "implementador de `Visitor` é passado**, em vez de ser vinculado a um " "específico\n" "tipo.\n" "Isso não era verdade no exemplo de conta anterior." #: 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 "" "O sistema de tipo de inspiração genérica de Rust pode aproximá-lo desses " "conceitos e\n" "use seu poder, conforme mostrado neste design de API.\n" "Mas também pode precisar de macros processuais para criar pontes para seus " "genéricos." #: src\functional/lenses.md:350 #, fuzzy msgid "## See Also" msgstr "## Veja também" #: 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) para lentes " "pré-construídas\n" " implementação, com uma interface mais limpa do que esses exemplos\n" "- [serde](https://serde.rs) em si, o que torna esses conceitos intuitivos " "para\n" " usuários finais (isto é, definindo as estruturas) sem precisar entender o\n" " detalhes\n" "- [luminância](https://github.com/phaazon/luminance-rs) é uma caixa para " "desenho\n" " computação gráfica que usa design de API de lentes, incluindo macros " "processuais para\n" " criar prismas completos para buffers de diferentes tipos de pixel que " "permanecem genéricos\n" "- [Um artigo sobre lentes em " "Scala](https://web.archive.org/web/20221128185849/https://medium.com/zyseme-technology/functional-references-lens-and-other-optics-in- " "scala-e5f7e2fdafe)\n" " que é muito legível mesmo sem experiência em Scala.\n" "- [Papel: Profunctor Optics: Modular Data\n" " " "Acessadores](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 "" "[Escola de Haskell: um pequeno tutorial para iniciantes em " "lentes](https://web.archive.org/web/20221128190041/https://www.schoolofhaskell.com/school/to-infinity-and-beyond/pick-of- " "the-week/a-little-lens-starter-tutorial)" #: src\additional_resources/index.md:1 #, fuzzy msgid "# Additional resources" msgstr "# Recursos adicionais" #: src\additional_resources/index.md:3 #, fuzzy msgid "A collection of complementary helpful content" msgstr "Uma coleção de conteúdo útil complementar" #: src\additional_resources/index.md:5 #, fuzzy msgid "## Talks" msgstr "## Palestras" #: 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 "" "- [Padrões de design em " "ferrugem](https://www.youtube.com/watch?v=Pm_oO0N5B9k) por\n" " Nicholas Cameron no PDRust (2016)\n" "- [Escrevendo bibliotecas idiomáticas em " "ferrugem](https://www.youtube.com/watch?v=0zOg8_B71gE)\n" " por Pascal Hertleif no RustFest (2017)\n" "- [Técnicas de Programação " "Rust](https://www.youtube.com/watch?v=vqavdUGKeb4) por\n" " Nicholas Cameron na LinuxConfAu (2018)" #: src\additional_resources/index.md:14 #, fuzzy msgid "## Books (Online)" msgstr "## Livros (On-line)" #: src\additional_resources/index.md:16 #, fuzzy msgid "- [The Rust API Guidelines](https://rust-lang.github.io/api-guidelines)" msgstr "- [Diretrizes da Rust API](https://rust-lang.github.io/api-guidelines)" #: src\additional_resources/design-principles.md:1 #, fuzzy msgid "# Design principles" msgstr "# Princípios de design" #: src\additional_resources/design-principles.md:3 #, fuzzy msgid "## A brief overview over common design principles" msgstr "## Uma breve visão geral sobre os princípios de design comuns" #: src\additional_resources/design-principles.md:7 #, fuzzy msgid "## [SOLID](https://en.wikipedia.org/wiki/SOLID)" msgstr "## [SOLID](https://en.wikipedia.org/wiki/SOLID)" #: 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 "" "- [Princípio de Responsabilidade Única " "(SRP)](https://en.wikipedia.org/wiki/Single-responsibility_principle):\n" " Uma classe deve ter apenas uma única responsabilidade, ou seja, apenas " "alterações\n" " uma parte da especificação do software deve ser capaz de afetar o\n" " especificação da classe.\n" "- [Princípio Aberto/Fechado " "(OCP)](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle):\n" " \"Entidades de software ... devem estar abertas para extensão, mas " "fechadas para\n" " modificação.\"\n" "- [Princípio de Substituição de Liskov " "(LSP)](https://en.wikipedia.org/wiki/Liskov_substitution_principle):\n" " \"Objetos em um programa devem ser substituíveis por instâncias de seus " "subtipos\n" " sem alterar a correção desse programa.\"\n" "- [Princípio de Segregação de Interface " "(ISP)](https://en.wikipedia.org/wiki/Interface_segregation_principle):\n" " \"Muitas interfaces específicas do cliente são melhores do que uma de uso " "geral\n" " interface.\"\n" "- [Princípio de Inversão de Dependência " "(DIP)](https://en.wikipedia.org/wiki/Dependency_inversion_principle):\n" " Deve-se \"depender de abstrações, [não] concreções\"." #: 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 (Don't Repeat " "Yourself)](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 "" "“Cada pedaço de conhecimento deve ter um único, inequívoco, autoritário\n" "representação dentro de um sistema\"" #: src\additional_resources/design-principles.md:30 #, fuzzy msgid "## [KISS principle](https://en.wikipedia.org/wiki/KISS_principle)" msgstr "## [princípio 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 "## [Lei de Demeter (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 "" "um determinado objeto deve assumir o mínimo possível sobre a estrutura ou\n" "propriedades de qualquer outra coisa (incluindo seus subcomponentes), de " "acordo com\n" "o princípio de \"ocultação de informações\"" #: src\additional_resources/design-principles.md:42 #, fuzzy msgid "" "## [Design by contract " "(DbC)](https://en.wikipedia.org/wiki/Design_by_contract)" msgstr "" "## [Design por contrato " "(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 "" "designers de software devem definir interface formal, precisa e verificável\n" "especificações para componentes de software, que estendem a definição comum " "de\n" "tipos de dados abstratos com pré-condições, pós-condições e invariantes" #: src\additional_resources/design-principles.md:48 #, fuzzy msgid "" "## " "[Encapsulation](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming))" msgstr "" "## " "[Encapsulation](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 "" "agrupamento de dados com os métodos que operam nesses dados, ou a restrição\n" "de acesso direto a alguns dos componentes de um objeto. O encapsulamento é " "usado para\n" "ocultar os valores ou estado de um objeto de dados estruturados dentro de " "uma classe, evitando\n" "acesso direto de partes não autorizadas a eles." #: 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 "" "“As funções não devem produzir efeitos colaterais abstratos... apenas " "comandos\n" "(procedimentos) serão permitidos para produzir efeitos colaterais.” " "-Bertrand Meyer:\n" "Construção de Software Orientado a Objetos" #: src\additional_resources/design-principles.md:61 #, fuzzy msgid "" "## [Principle of least astonishment " "(POLA)](https://en.wikipedia.org/wiki/Principle_of_least_astonishment)" msgstr "" "## [Princípio do menor espanto " "(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 "" "um componente de um sistema deve se comportar de uma maneira que a maioria " "dos usuários espera\n" "comportar-se. O comportamento não deve surpreender ou surpreender os usuários" #: src\additional_resources/design-principles.md:66 #, fuzzy msgid "## Linguistic-Modular-Units" msgstr "## Linguistic-Modular-Units" #: 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 "" "“Os módulos devem corresponder às unidades sintáticas da linguagem " "utilizada.” -Bertrand\n" "Meyer: Construção de Software Orientado a Objetos" #: src\additional_resources/design-principles.md:71 #, fuzzy msgid "## Self-Documentation" msgstr "## Autodocumentação" #: 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 "" "“O projetista de um módulo deve se esforçar para tornar todas as informações " "sobre o\n" "parte do módulo do próprio módulo.” - Bertrand Meyer: Software Orientado a " "Objetos\n" "Construção" #: src\additional_resources/design-principles.md:77 #, fuzzy msgid "## Uniform-Access" msgstr "## Uniform-Access" #: 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 "" "“Todos os serviços oferecidos por um módulo devem estar disponíveis por meio " "de um\n" "notação, que não revela se eles são implementados por meio de armazenamento " "ou\n" "através da computação”. - Bertrand Meyer: Construção de Software Orientado a " "Objetos" #: src\additional_resources/design-principles.md:83 #, fuzzy msgid "## Single-Choice" msgstr "## Escolha única" #: 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 "" "“Sempre que um sistema de software deve suportar um conjunto de " "alternativas, uma e somente\n" "um módulo no sistema deve conhecer sua lista exaustiva.” -Bertrand Meyer:\n" "Construção de Software Orientado a Objetos" #: src\additional_resources/design-principles.md:89 #, fuzzy msgid "## Persistence-Closure" msgstr "## Persistência-Fechamento" #: 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 "" "“Sempre que um mecanismo de armazenamento armazena um objeto, ele deve " "armazenar com ele o\n" "dependentes desse objeto. Sempre que um mecanismo de recuperação recupera " "um\n" "objeto armazenado anteriormente, ele também deve recuperar qualquer " "dependente desse objeto\n" "que ainda não foi recuperado.” - Bertrand Meyer: Software Orientado a " "Objetos\n" "Construção" msgid "" msgstr "" msgid "" msgstr "" msgid "" msgstr "" msgid "" msgstr "" msgid "" msgstr "" msgid "" msgstr "" msgid "" msgstr "" msgid "" msgstr "" msgid "" msgstr "" msgid "" msgstr "" ================================================ FILE: src/SUMMARY.md ================================================ # Summary - [Introduction](./intro.md) - [Translations](./translations.md) - [Idioms](./idioms/index.md) - [Use borrowed types for arguments](./idioms/coercion-arguments.md) - [Concatenating Strings with format!](./idioms/concat-format.md) - [Constructor](./idioms/ctor.md) - [The Default Trait](./idioms/default.md) - [Collections Are Smart Pointers](./idioms/deref.md) - [Finalisation in Destructors](./idioms/dtor-finally.md) - [`mem::{take(_), replace(_)}`](./idioms/mem-replace.md) - [On-Stack Dynamic Dispatch](./idioms/on-stack-dyn-dispatch.md) - [Foreign function interface (FFI)](./idioms/ffi/intro.md) - [Idiomatic Errors](./idioms/ffi/errors.md) - [Accepting Strings](./idioms/ffi/accepting-strings.md) - [Passing Strings](./idioms/ffi/passing-strings.md) - [Iterating over an Option](./idioms/option-iter.md) - [Pass Variables to Closure](./idioms/pass-var-to-closure.md) - [Privacy For Extensibility](./idioms/priv-extend.md) - [Easy doc initialization](./idioms/rustdoc-init.md) - [Temporary mutability](./idioms/temporary-mutability.md) - [Return consumed arg on error](./idioms/return-consumed-arg-on-error.md) - [Design Patterns](./patterns/index.md) - [Behavioural](./patterns/behavioural/intro.md) - [Command](./patterns/behavioural/command.md) - [Interpreter](./patterns/behavioural/interpreter.md) - [Newtype](./patterns/behavioural/newtype.md) - [RAII Guards](./patterns/behavioural/RAII.md) - [Strategy](./patterns/behavioural/strategy.md) - [Visitor](./patterns/behavioural/visitor.md) - [Creational](./patterns/creational/intro.md) - [Builder](./patterns/creational/builder.md) - [Fold](./patterns/creational/fold.md) - [Structural](./patterns/structural/intro.md) - [Compose Structs](./patterns/structural/compose-structs.md) - [Prefer Small Crates](./patterns/structural/small-crates.md) - [Contain unsafety in small modules](./patterns/structural/unsafe-mods.md) - [Avoid complex type bounds with custom traits](./patterns/structural/trait-for-bounds.md) - [Foreign function interface (FFI)](./patterns/ffi/intro.md) - [Object-Based APIs](./patterns/ffi/export.md) - [Type Consolidation into Wrappers](./patterns/ffi/wrappers.md) - [Anti-patterns](./anti_patterns/index.md) - [Clone to satisfy the borrow checker](./anti_patterns/borrow_clone.md) - [`#[deny(warnings)]`](./anti_patterns/deny-warnings.md) - [Deref Polymorphism](./anti_patterns/deref.md) - [Functional Programming](./functional/index.md) - [Programming paradigms](./functional/paradigms.md) - [Generics as Type Classes](./functional/generics-type-classes.md) - [Functional Optics](./functional/optics.md) - [Additional Resources](./additional_resources/index.md) - [Design principles](./additional_resources/design-principles.md) ================================================ FILE: src/additional_resources/design-principles.md ================================================ # Design principles ## A brief overview over common design principles --- ## [SOLID](https://en.wikipedia.org/wiki/SOLID) - [Single Responsibility Principle (SRP)](https://en.wikipedia.org/wiki/Single-responsibility_principle): A class should only have a single responsibility, that is, only changes to one part of the software's specification should be able to affect the specification of the class. - [Open/Closed Principle (OCP)](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle): "Software entities ... should be open for extension, but closed for modification." - [Liskov Substitution Principle (LSP)](https://en.wikipedia.org/wiki/Liskov_substitution_principle): "Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program." - [Interface Segregation Principle (ISP)](https://en.wikipedia.org/wiki/Interface_segregation_principle): "Many client-specific interfaces are better than one general-purpose interface." - [Dependency Inversion Principle (DIP)](https://en.wikipedia.org/wiki/Dependency_inversion_principle): One should "depend upon abstractions, [not] concretions." ## [CRP (Composite Reuse Principle) or Composition over inheritance](https://en.wikipedia.org/wiki/Composition_over_inheritance) “a the principle that classes should favor polymorphic behavior and code reuse by their composition (by containing instances of other classes that implement the desired functionality) over inheritance from a base or parent class” - Knoernschild, Kirk (2002). Java Design - Objects, UML, and Process ## [DRY (Don’t Repeat Yourself)](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) "Every piece of knowledge must have a single, unambiguous, authoritative representation within a system" ## [KISS principle](https://en.wikipedia.org/wiki/KISS_principle) most systems work best if they are kept simple rather than made complicated; therefore, simplicity should be a key goal in design, and unnecessary complexity should be avoided ## [Law of Demeter (LoD)](https://en.wikipedia.org/wiki/Law_of_Demeter) a given object should assume as little as possible about the structure or properties of anything else (including its subcomponents), in accordance with the principle of "information hiding" ## [Design by contract (DbC)](https://en.wikipedia.org/wiki/Design_by_contract) software designers should define formal, precise and verifiable interface specifications for software components, which extend the ordinary definition of abstract data types with preconditions, postconditions and invariants ## [Encapsulation](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)) bundling of data with the methods that operate on that data, or the restricting of direct access to some of an object's components. Encapsulation is used to hide the values or state of a structured data object inside a class, preventing unauthorized parties' direct access to them. ## [Command-Query-Separation (CQS)](https://en.wikipedia.org/wiki/Command%E2%80%93query_separation) “Functions should not produce abstract side effects...only commands (procedures) will be permitted to produce side effects.” - Bertrand Meyer: Object-Oriented Software Construction ## [Principle of least astonishment (POLA)](https://en.wikipedia.org/wiki/Principle_of_least_astonishment) a component of a system should behave in a way that most users will expect it to behave. The behavior should not astonish or surprise users ## Linguistic-Modular-Units “Modules must correspond to syntactic units in the language used.” - Bertrand Meyer: Object-Oriented Software Construction ## Self-Documentation “The designer of a module should strive to make all information about the module part of the module itself.” - Bertrand Meyer: Object-Oriented Software Construction ## Uniform-Access “All services offered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation.” - Bertrand Meyer: Object-Oriented Software Construction ## Single-Choice “Whenever a software system must support a set of alternatives, one and only one module in the system should know their exhaustive list.” - Bertrand Meyer: Object-Oriented Software Construction ## Persistence-Closure “Whenever a storage mechanism stores an object, it must store with it the dependents of that object. Whenever a retrieval mechanism retrieves a previously stored object, it must also retrieve any dependent of that object that has not yet been retrieved.” - Bertrand Meyer: Object-Oriented Software Construction ================================================ FILE: src/additional_resources/index.md ================================================ # Additional resources A collection of complementary helpful content ## Talks - [Design Patterns in Rust](https://www.youtube.com/watch?v=Pm_oO0N5B9k) by Nicholas Cameron at the PDRust (2016) - [Writing Idiomatic Libraries in Rust](https://www.youtube.com/watch?v=0zOg8_B71gE) by Pascal Hertleif at RustFest (2017) - [Rust Programming Techniques](https://www.youtube.com/watch?v=vqavdUGKeb4) by Nicholas Cameron at LinuxConfAu (2018) ## Books (Online) - [The Rust API Guidelines](https://rust-lang.github.io/api-guidelines) ================================================ FILE: src/anti_patterns/borrow_clone.md ================================================ # Clone to satisfy the borrow checker ## Description The borrow checker prevents Rust users from developing otherwise unsafe code by ensuring that either: only one mutable reference exists, or potentially many but all immutable references exist. If the code written does not hold true to these conditions, this anti-pattern arises when the developer resolves the compiler error by cloning the variable. ## Example ```rust // define any variable let mut x = 5; // Borrow `x` -- but clone it first let y = &mut (x.clone()); // without the x.clone() two lines prior, this line would fail on compile as // x has been borrowed // thanks to x.clone(), x was never borrowed, and this line will run. println!("{x}"); // perform some action on the borrow to prevent rust from optimizing this //out of existence *y += 1; ``` ## Motivation It is tempting, particularly for beginners, to use this pattern to resolve confusing issues with the borrow checker. However, there are serious consequences. Using `.clone()` causes a copy of the data to be made. Any changes between the two are not synchronized -- as if two completely separate variables exist. There are special cases -- `Rc` is designed to handle clones intelligently. It internally manages exactly one copy of the data. Invoking `.clone()` on `Rc` produces a new `Rc` instance, which points to the same data as the source `Rc`, while increasing a reference count. The same applies to `Arc`, the thread-safe counterpart of `Rc`. In general, clones should be deliberate, with full understanding of the consequences. If a clone is used to make a borrow checker error disappear, that's a good indication this anti-pattern may be in use. Even though `.clone()` is an indication of a bad pattern, sometimes **it is fine to write inefficient code**, in cases such as when: - the developer is still new to ownership - the code doesn't have great speed or memory constraints (like hackathon projects or prototypes) - satisfying the borrow checker is really complicated, and you prefer to optimize readability over performance If an unnecessary clone is suspected, The [Rust Book's chapter on Ownership](https://doc.rust-lang.org/book/ownership.html) should be understood fully before assessing whether the clone is required or not. Also be sure to always run `cargo clippy` in your project, which will detect some cases in which `.clone()` is not necessary. ## See also - [`mem::{take(_), replace(_)}` to keep owned values in changed enums](../idioms/mem-replace.md) - [`Rc` documentation, which handles .clone() intelligently](http://doc.rust-lang.org/std/rc/) - [`Arc` documentation, a thread-safe reference-counting pointer](https://doc.rust-lang.org/std/sync/struct.Arc.html) - [Tricks with ownership in Rust](https://web.archive.org/web/20210120233744/https://xion.io/post/code/rust-borrowchk-tricks.html) ================================================ FILE: src/anti_patterns/deny-warnings.md ================================================ # `#![deny(warnings)]` ## Description A well-intentioned crate author wants to ensure their code builds without warnings. So they annotate their crate root with the following: ## Example ```rust #![deny(warnings)] // All is well. ``` ## Advantages It is short and will stop the build if anything is amiss. ## Drawbacks By disallowing the compiler to build with warnings, a crate author opts out of Rust's famed stability. Sometimes new features or old misfeatures need a change in how things are done, thus lints are written that `warn` for a certain grace period before being turned to `deny`. For example, it was discovered that a type could have two `impl`s with the same method. This was deemed a bad idea, but in order to make the transition smooth, the `overlapping-inherent-impls` lint was introduced to give a warning to those stumbling on this fact, before it becomes a hard error in a future release. Also sometimes APIs get deprecated, so their use will emit a warning where before there was none. All this conspires to potentially break the build whenever something changes. Furthermore, crates that supply additional lints (e.g. [rust-clippy]) can no longer be used unless the annotation is removed. This is mitigated with [--cap-lints]. The `--cap-lints=warn` command line argument, turns all `deny` lint errors into warnings. ## Alternatives There are two ways of tackling this problem: First, we can decouple the build setting from the code, and second, we can name the lints we want to deny explicitly. The following command line will build with all warnings set to `deny`: `RUSTFLAGS="-D warnings" cargo build` This can be done by any individual developer (or be set in a CI tool like Travis, but remember that this may break the build when something changes) without requiring a change to the code. Alternatively, we can specify the lints that we want to `deny` in the code. Here is a list of warning lints that is (hopefully) safe to deny (as of rustc 1.48.0): ```rust,ignore #![deny( bad_style, const_err, dead_code, improper_ctypes, non_shorthand_field_patterns, no_mangle_generic_items, overflowing_literals, path_statements, patterns_in_fns_without_body, private_in_public, unconditional_recursion, unused, unused_allocation, unused_comparisons, unused_parens, while_true )] ``` In addition, the following `allow`ed lints may be a good idea to `deny`: ```rust,ignore #![deny( missing_debug_implementations, missing_docs, trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_import_braces, unused_qualifications, unused_results )] ``` Some may also want to add `missing-copy-implementations` to their list. Note that we explicitly did not add the `deprecated` lint, as it is fairly certain that there will be more deprecated APIs in the future. ## See also - [A collection of all clippy lints](https://rust-lang.github.io/rust-clippy/master) - [deprecate attribute] documentation - Type `rustc -W help` for a list of lints on your system. Also type `rustc --help` for a general list of options - [rust-clippy] is a collection of lints for better Rust code [rust-clippy]: https://github.com/rust-lang/rust-clippy [deprecate attribute]: https://doc.rust-lang.org/reference/attributes.html#deprecation [--cap-lints]: https://doc.rust-lang.org/rustc/lints/levels.html#capping-lints ================================================ FILE: src/anti_patterns/deref.md ================================================ # `Deref` polymorphism ## Description Misuse the `Deref` trait to emulate inheritance between structs, and thus reuse methods. ## Example Sometimes we want to emulate the following common pattern from OO languages such as Java: ```java class Foo { void m() { ... } } class Bar extends Foo {} public static void main(String[] args) { Bar b = new Bar(); b.m(); } ``` We can use the deref polymorphism anti-pattern to do so: ```rust use std::ops::Deref; struct Foo {} impl Foo { fn m(&self) { //.. } } struct Bar { f: Foo, } impl Deref for Bar { type Target = Foo; fn deref(&self) -> &Foo { &self.f } } fn main() { let b = Bar { f: Foo {} }; b.m(); } ``` There is no struct inheritance in Rust. Instead we use composition and include an instance of `Foo` in `Bar` (since the field is a value, it is stored inline, so if there were fields, they would have the same layout in memory as the Java version (probably, you should use `#[repr(C)]` if you want to be sure)). In order to make the method call work we implement `Deref` for `Bar` with `Foo` as the target (returning the embedded `Foo` field). That means that when we dereference a `Bar` (for example, using `*`) then we will get a `Foo`. That is pretty weird. Dereferencing usually gives a `T` from a reference to `T`, here we have two unrelated types. However, since the dot operator does implicit dereferencing, it means that the method call will search for methods on `Foo` as well as `Bar`. ## Advantages You save a little boilerplate, e.g., ```rust,ignore impl Bar { fn m(&self) { self.f.m() } } ``` ## Disadvantages Most importantly this is a surprising idiom - future programmers reading this in code will not expect this to happen. That's because we are misusing the `Deref` trait rather than using it as intended (and documented, etc.). It's also because the mechanism here is completely implicit. This pattern does not introduce subtyping between `Foo` and `Bar` like inheritance in Java or C++ does. Furthermore, traits implemented by `Foo` are not automatically implemented for `Bar`, so this pattern interacts badly with bounds checking and thus generic programming. Using this pattern gives subtly different semantics from most OO languages with regards to `self`. Usually it remains a reference to the sub-class, with this pattern it will be the 'class' where the method is defined. Finally, this pattern only supports single inheritance, and has no notion of interfaces, class-based privacy, or other inheritance-related features. So, it gives an experience that will be subtly surprising to programmers used to Java inheritance, etc. ## Discussion There is no one good alternative. Depending on the exact circumstances it might be better to re-implement using traits or to write out the facade methods to dispatch to `Foo` manually. We do intend to add a mechanism for inheritance similar to this to Rust, but it is likely to be some time before it reaches stable Rust. See these [blog](http://aturon.github.io/blog/2015/09/18/reuse/) [posts](http://smallcultfollowing.com/babysteps/blog/2015/10/08/virtual-structs-part-4-extended-enums-and-thin-traits/) and this [RFC issue](https://github.com/rust-lang/rfcs/issues/349) for more details. The `Deref` trait is designed for the implementation of custom pointer types. The intention is that it will take a pointer-to-`T` to a `T`, not convert between different types. It is a shame that this isn't (probably cannot be) enforced by the trait definition. Rust tries to strike a careful balance between explicit and implicit mechanisms, favouring explicit conversions between types. Automatic dereferencing in the dot operator is a case where the ergonomics strongly favour an implicit mechanism, but the intention is that this is limited to degrees of indirection, not conversion between arbitrary types. ## See also - [Collections are smart pointers idiom](../idioms/deref.md). - Delegation crates for less boilerplate like [delegate](https://crates.io/crates/delegate) or [ambassador](https://crates.io/crates/ambassador) - [Documentation for `Deref` trait](https://doc.rust-lang.org/std/ops/trait.Deref.html). ================================================ FILE: src/anti_patterns/index.md ================================================ # Anti-patterns An [anti-pattern](https://en.wikipedia.org/wiki/Anti-pattern) is a solution to a "recurring problem that is usually ineffective and risks being highly counterproductive". Just as valuable as knowing how to solve a problem, is knowing how *not* to solve it. Anti-patterns give us great counter-examples to consider relative to design patterns. Anti-patterns are not confined to code. For example, a process can be an anti-pattern, too. ================================================ FILE: src/functional/generics-type-classes.md ================================================ # Generics as Type Classes ## Description Rust's type system is designed more like functional languages (like Haskell) rather than imperative languages (like Java and C++). As a result, Rust can turn many kinds of programming problems into "static typing" problems. This is one of the biggest wins of choosing a functional language, and is critical to many of Rust's compile time guarantees. A key part of this idea is the way generic types work. In C++ and Java, for example, generic types are a meta-programming construct for the compiler. `vector` and `vector` in C++ are just two different copies of the same boilerplate code for a `vector` type (known as a `template`) with two different types filled in. In Rust, a generic type parameter creates what is known in functional languages as a "type class constraint", and each different parameter filled in by an end user *actually changes the type*. In other words, `Vec` and `Vec` *are two different types*, which are recognized as distinct by all parts of the type system. This is called **monomorphization**, where different types are created from **polymorphic** code. This special behavior requires `impl` blocks to specify generic parameters. Different values for the generic type cause different types, and different types can have different `impl` blocks. In object-oriented languages, classes can inherit behavior from their parents. However, this allows the attachment of not only additional behavior to particular members of a type class, but extra behavior as well. The nearest equivalent is the runtime polymorphism in Javascript and Python, where new members can be added to objects willy-nilly by any constructor. However, unlike those languages, all of Rust's additional methods can be type checked when they are used, because their generics are statically defined. That makes them more usable while remaining safe. ## Example Suppose you are designing a storage server for a series of lab machines. Because of the software involved, there are two different protocols you need to support: BOOTP (for PXE network boot), and NFS (for remote mount storage). Your goal is to have one program, written in Rust, which can handle both of them. It will have protocol handlers and listen for both kinds of requests. The main application logic will then allow a lab administrator to configure storage and security controls for the actual files. The requests from machines in the lab for files contain the same basic information, no matter what protocol they came from: an authentication method, and a file name to retrieve. A straightforward implementation would look something like this: ```rust,ignore enum AuthInfo { Nfs(crate::nfs::AuthInfo), Bootp(crate::bootp::AuthInfo), } struct FileDownloadRequest { file_name: PathBuf, authentication: AuthInfo, } ``` This design might work well enough. But now suppose you needed to support adding metadata that was *protocol specific*. For example, with NFS, you wanted to determine what their mount point was in order to enforce additional security rules. The way the current struct is designed leaves the protocol decision until runtime. That means any method that applies to one protocol and not the other requires the programmer to do a runtime check. Here is how getting an NFS mount point would look: ```rust,ignore struct FileDownloadRequest { file_name: PathBuf, authentication: AuthInfo, mount_point: Option, } impl FileDownloadRequest { // ... other methods ... /// Gets an NFS mount point if this is an NFS request. Otherwise, /// return None. pub fn mount_point(&self) -> Option<&Path> { self.mount_point.as_ref() } } ``` Every caller of `mount_point()` must check for `None` and write code to handle it. This is true even if they know only NFS requests are ever used in a given code path! It would be far more optimal to cause a compile-time error if the different request types were confused. After all, the entire path of the user's code, including what functions from the library they use, will know whether a request is an NFS request or a BOOTP request. In Rust, this is actually possible! The solution is to *add a generic type* in order to split the API. Here is what that looks like: ```rust use std::path::{Path, PathBuf}; mod nfs { #[derive(Clone)] pub(crate) struct AuthInfo(String); // NFS session management omitted } mod bootp { pub(crate) struct AuthInfo(); // no authentication in bootp } // Keep the module private to prevent outside users from inventing their own protocols. mod proto_trait { use super::{bootp, nfs}; use std::path::{Path, PathBuf}; pub(crate) trait ProtoKind { type AuthInfo; fn auth_info(&self) -> Self::AuthInfo; } pub struct Nfs { auth: nfs::AuthInfo, mount_point: PathBuf, } impl Nfs { pub(crate) fn mount_point(&self) -> &Path { &self.mount_point } } impl ProtoKind for Nfs { type AuthInfo = nfs::AuthInfo; fn auth_info(&self) -> Self::AuthInfo { self.auth.clone() } } pub struct Bootp(); // no additional metadata impl ProtoKind for Bootp { type AuthInfo = bootp::AuthInfo; fn auth_info(&self) -> Self::AuthInfo { bootp::AuthInfo() } } } use proto_trait::ProtoKind; // keep internal to prevent impls pub use proto_trait::{Bootp, Nfs}; // re-export so callers can see them struct FileDownloadRequest { file_name: PathBuf, protocol: P, } // all common API parts go into a generic impl block impl FileDownloadRequest

{ fn file_path(&self) -> &Path { &self.file_name } fn auth_info(&self) -> P::AuthInfo { self.protocol.auth_info() } } // all protocol-specific impls go into their own block impl FileDownloadRequest { fn mount_point(&self) -> &Path { self.protocol.mount_point() } } fn main() { // your code here } ``` With this approach, if the user were to make a mistake and use the wrong type; ```rust,ignore fn main() { let mut socket = crate::bootp::listen()?; while let Some(request) = socket.next_request()? { match request.mount_point().as_ref() { "/secure" => socket.send("Access denied"), _ => {} // continue on... } // Rest of the code here } } ``` They would get a syntax error. The type `FileDownloadRequest` does not implement `mount_point()`, only the type `FileDownloadRequest` does. And that is created by the NFS module, not the BOOTP module of course! ## Advantages First, it allows fields that are common to multiple states to be de-duplicated. By making the non-shared fields generic, they are implemented once. Second, it makes the `impl` blocks easier to read, because they are broken down by state. Methods common to all states are typed once in one block, and methods unique to one state are in a separate block. Both of these mean there are fewer lines of code, and they are better organized. ## Disadvantages This currently increases the size of the binary, due to the way monomorphization is implemented in the compiler. Hopefully the implementation will be able to improve in the future. ## Alternatives - If a type seems to need a "split API" due to construction or partial initialization, consider the [Builder Pattern](../patterns/creational/builder.md) instead. - If the API between types does not change -- only the behavior does -- then the [Strategy Pattern](../patterns/behavioural/strategy.md) is better used instead. ## See also This pattern is used throughout the standard library: - `Vec` can be cast from a String, unlike every other type of `Vec`.[^1] - Iterators can be cast into a binary heap, but only if they contain a type that implements the `Ord` trait.[^2] - The `to_string` method was specialized for `Cow` only of type `str`.[^3] It is also used by several popular crates to allow API flexibility: - The `embedded-hal` ecosystem used for embedded devices makes extensive use of this pattern. For example, it allows statically verifying the configuration of device registers used to control embedded pins. When a pin is put into a mode, it returns a `Pin` struct, whose generic determines the functions usable in that mode, which are not on the `Pin` itself. [^4] - The `hyper` HTTP client library uses this to expose rich APIs for different pluggable requests. Clients with different connectors have different methods on them as well as different trait implementations, while a core set of methods apply to any connector. [^5] - The "type state" pattern -- where an object gains and loses API based on an internal state or invariant -- is implemented in Rust using the same basic concept, and a slightly different technique. [^6] [^1]: See: [impl From\ for Vec\](https://doc.rust-lang.org/1.59.0/src/std/ffi/c_str.rs.html#803-811) [^2]: See: [impl\ FromIterator\ for BinaryHeap\](https://web.archive.org/web/20201030132806/https://doc.rust-lang.org/stable/src/alloc/collections/binary_heap.rs.html#1330-1335) [^3]: See: [impl\<'\_\> ToString for Cow\<'\_, str>](https://doc.rust-lang.org/stable/src/alloc/string.rs.html#2235-2240) [^4]: Example: [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) [^5]: See: [https://docs.rs/hyper/0.14.5/hyper/client/struct.Client.html](https://docs.rs/hyper/0.14.5/hyper/client/struct.Client.html) [^6]: See: [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/) and [Rusty Typestate Series (an extensive thesis)](https://web.archive.org/web/20210328164854/https://rustype.github.io/notes/notes/rust-typestate-series/rust-typestate-index) ================================================ FILE: src/functional/index.md ================================================ # Functional Usage of Rust Rust is an imperative language, but it follows many [functional programming](https://en.wikipedia.org/wiki/Functional_programming) paradigms. > In computer science, *functional programming* is a programming paradigm where > programs are constructed by applying and composing functions. It is a > declarative programming paradigm in which function definitions are trees of > expressions that each return a value, rather than a sequence of imperative > statements which change the state of the program. ================================================ FILE: src/functional/optics.md ================================================ # Functional Language Optics Optics is a type of API design that is common to functional languages. This is a pure functional concept that is not frequently used in Rust. Nevertheless, exploring the concept may be helpful to understand other patterns in Rust APIs, such as [visitors](../patterns/behavioural/visitor.md). They also have niche use cases. This is quite a large topic, and would require actual books on language design to fully get into its abilities. However their applicability in Rust is much simpler. To explain the relevant parts of the concept, the `Serde`-API will be used as an example, as it is one that is difficult for many to understand from simply the API documentation. In the process, different specific patterns, called Optics, will be covered. These are *The Iso*, *The Poly Iso*, and *The Prism*. ## An API Example: Serde Trying to understand the way *Serde* works by only reading the API is a challenge, especially the first time. Consider the `Deserializer` trait, implemented by any library which parses a new data format: ```rust,ignore pub trait Deserializer<'de>: Sized { type Error: Error; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>; fn deserialize_bool(self, visitor: V) -> Result where V: Visitor<'de>; // remainder omitted } ``` And here's the definition of the `Visitor` trait passed in generically: ```rust,ignore pub trait Visitor<'de>: Sized { type Value; fn visit_bool(self, v: bool) -> Result where E: Error; fn visit_u64(self, v: u64) -> Result where E: Error; fn visit_str(self, v: &str) -> Result where E: Error; // remainder omitted } ``` There is a lot of type erasure going on here, with multiple levels of associated types being passed back and forth. But what is the big picture? Why not just have the `Visitor` return the pieces the caller needs in a streaming API, and call it a day? Why all the extra pieces? One way to understand it is to look at a functional languages concept called *optics*. This is a way to do composition of behavior and proprieties that is designed to facilitate patterns common to Rust: failure, type transformation, etc.[^1] The Rust language does not have very good support for these directly. However, they appear in the design of the language itself, and their concepts can help to understand some of Rust's APIs. As a result, this attempts to explain the concepts with the way Rust does it. This will perhaps shed light on what those APIs are achieving: specific properties of composability. ## Basic Optics ### The Iso The Iso is a value transformer between two types. It is extremely simple, but a conceptually important building block. As an example, suppose that we have a custom Hash table structure used as a concordance for a document.[^2] It uses strings for keys (words) and a list of indexes for values (file offsets, for instance). A key feature is the ability to serialize this format to disk. A "quick and dirty" approach would be to implement a conversion to and from a string in JSON format. (Errors are ignored for the time being, they will be handled later.) To write it in a normal form expected by functional language users: ```text case class ConcordanceSerDe { serialize: Concordance -> String deserialize: String -> Concordance } ``` The Iso is thus a pair of functions which convert values of different types: `serialize` and `deserialize`. A straightforward implementation: ```rust use std::collections::HashMap; struct Concordance { keys: HashMap, value_table: Vec<(usize, usize)>, } struct ConcordanceSerde {} impl ConcordanceSerde { fn serialize(value: Concordance) -> String { todo!() } // invalid concordances are empty fn deserialize(value: String) -> Concordance { todo!() } } ``` This may seem rather silly. In Rust, this type of behavior is typically done with traits. After all, the standard library has `FromStr` and `ToString` in it. But that is where our next subject comes in: Poly Isos. ### Poly Isos The previous example was simply converting between values of two fixed types. This next block builds upon it with generics, and is more interesting. Poly Isos allow an operation to be generic over any type while returning a single type. This brings us closer to parsing. Consider what a basic parser would do ignoring error cases. Again, this is its normal form: ```text case class Serde[T] { deserialize(String) -> T serialize(T) -> String } ``` Here we have our first generic, the type `T` being converted. In Rust, this could be implemented with a pair of traits in the standard library: `FromStr` and `ToString`. The Rust version even handles errors: ```rust,ignore pub trait FromStr: Sized { type Err; fn from_str(s: &str) -> Result; } pub trait ToString { fn to_string(&self) -> String; } ``` Unlike the Iso, the Poly Iso allows application of multiple types, and returns them generically. This is what you would want for a basic string parser. At first glance, this seems like a good option for writing a parser. Let's see it in action: ```rust,ignore use anyhow; use std::str::FromStr; struct TestStruct { a: usize, b: String, } impl FromStr for TestStruct { type Err = anyhow::Error; fn from_str(s: &str) -> Result { todo!() } } impl ToString for TestStruct { fn to_string(&self) -> String { todo!() } } fn main() { let a = TestStruct { a: 5, b: "hello".to_string(), }; println!("Our Test Struct as JSON: {}", a.to_string()); } ``` That seems quite logical. However, there are two problems with this. First, `to_string` does not indicate to API users, "this is JSON." Every type would need to agree on a JSON representation, and many of the types in the Rust standard library already don't. Using this is a poor fit. This can easily be resolved with our own trait. But there is a second, subtler problem: scaling. When every type writes `to_string` by hand, this works. But if every single person who wants their type to be serializable has to write a bunch of code -- and possibly different JSON libraries -- to do it themselves, it will turn into a mess very quickly! The answer is one of Serde's two key innovations: an independent data model to represent Rust data in structures common to data serialization languages. The result is that it can use Rust's code generation abilities to create an intermediary conversion type it calls a `Visitor`. This means, in normal form (again, skipping error handling for simplicity): ```text case class Serde[T] { deserialize: Visitor[T] -> T serialize: T -> Visitor[T] } case class Visitor[T] { toJson: Visitor[T] -> String fromJson: String -> Visitor[T] } ``` The result is one Poly Iso and one Iso (respectively). Both of these can be implemented with traits: ```rust trait Serde { type V; fn deserialize(visitor: Self::V) -> Self; fn serialize(self) -> Self::V; } trait Visitor { fn to_json(self) -> String; fn from_json(json: String) -> Self; } ``` Because there is a uniform set of rules to transform Rust structures to the independent form, it is even possible to have code generation creating the `Visitor` associated with type `T`: ```rust,ignore #[derive(Default, Serde)] // the "Serde" derive creates the trait impl block struct TestStruct { a: usize, b: String, } // user writes this macro to generate an associated visitor type generate_visitor!(TestStruct); ``` But let's actually try that approach. ```rust,ignore fn main() { let a = TestStruct { a: 5, b: "hello".to_string() }; let a_data = a.serialize().to_json(); println!("Our Test Struct as JSON: {a_data}"); let b = TestStruct::deserialize( generated_visitor_for!(TestStruct)::from_json(a_data)); } ``` It turns out that the conversion isn't symmetric after all! On paper it is, but with the auto-generated code the name of the actual type necessary to convert all the way from `String` is hidden. We'd need some kind of `generated_visitor_for!` macro to obtain the type name. It's wonky, but it works... until we get to the elephant in the room. The only format currently supported is JSON. How would we support more formats? The current design requires completely re-writing all of the code generation and creating a new Serde trait. That is quite terrible and not extensible at all! In order to solve that, we need something more powerful. ## Prism To take format into account, we need something in normal form like this: ```text case class Serde[T, F] { serialize: T, F -> String deserialize: String, F -> Result[T, Error] } ``` This construct is called a Prism. It is "one level higher" in generics than Poly Isos (in this case, the "intersecting" type F is the key). Unfortunately because `Visitor` is a trait (since each incarnation requires its own custom code), this would require a kind of generic type boundary that Rust does not support. Fortunately, we still have that `Visitor` type from before. What is the `Visitor` doing? It is attempting to allow each data structure to define the way it is itself parsed. Well what if we could add one more interface for the generic format? Then the `Visitor` is just an implementation detail, and it would "bridge" the two APIs. In normal form: ```text case class Serde[T] { serialize: F -> String deserialize F, String -> Result[T, Error] } case class VisitorForT { build: F, String -> Result[T, Error] decompose: F, T -> String } case class SerdeFormat[T, V] { toString: T, V -> String fromString: V, String -> Result[T, Error] } ``` And what do you know, a pair of Poly Isos at the bottom which can be implemented as traits! Thus we have the Serde API: 1. Each type to be serialized implements `Deserialize` or `Serialize`, equivalent to the `Serde` class 1. They get a type (well two, one for each direction) implementing the `Visitor` trait, which is usually (but not always) done through code generated by a derive macro. This contains the logic to construct or destruct between the data type and the format of the Serde data model. 1. The type implementing the `Deserializer` trait handles all details specific to the format, being "driven by" the `Visitor`. This splitting and Rust type erasure is really to achieve a Prism through indirection. You can see it on the `Deserializer` trait ```rust,ignore pub trait Deserializer<'de>: Sized { type Error: Error; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>; fn deserialize_bool(self, visitor: V) -> Result where V: Visitor<'de>; // remainder omitted } ``` And the visitor: ```rust,ignore pub trait Visitor<'de>: Sized { type Value; fn visit_bool(self, v: bool) -> Result where E: Error; fn visit_u64(self, v: u64) -> Result where E: Error; fn visit_str(self, v: &str) -> Result where E: Error; // remainder omitted } ``` And the trait `Deserialize` implemented by the macros: ```rust,ignore pub trait Deserialize<'de>: Sized { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>; } ``` This has been abstract, so let's look at a concrete example. How does actual Serde deserialize a bit of JSON into `struct Concordance` from earlier? 1. The user would call a library function to deserialize the data. This would create a `Deserializer` based on the JSON format. 1. Based on the fields in the struct, a `Visitor` would be created (more on that in a moment) which knows how to create each type in a generic data model that was needed to represent it: `Vec` (list), `u64` and `String`. 1. The deserializer would make calls to the `Visitor` as it parsed items. 1. The `Visitor` would indicate if the items found were expected, and if not, raise an error to indicate deserialization has failed. For our very simple structure above, the expected pattern would be: 1. Begin visiting a map (*Serde*'s equivalent to `HashMap` or JSON's dictionary). 1. Visit a string key called "keys". 1. Begin visiting a map value. 1. For each item, visit a string key then an integer value. 1. Visit the end of the map. 1. Store the map into the `keys` field of the data structure. 1. Visit a string key called "value_table". 1. Begin visiting a list value. 1. For each item, visit an integer. 1. Visit the end of the list 1. Store the list into the `value_table` field. 1. Visit the end of the map. But what determines which "observation" pattern is expected? A functional programming language would be able to use currying to create reflection of each type based on the type itself. Rust does not support that, so every single type would need to have its own code written based on its fields and their properties. *Serde* solves this usability challenge with a derive macro: ```rust,ignore use serde::Deserialize; #[derive(Deserialize)] struct IdRecord { name: String, customer_id: String, } ``` That macro simply generates an impl block causing the struct to implement a trait called `Deserialize`. This is the function that determines how to create the struct itself. Code is generated based on the struct's fields. When the parsing library is called - in our example, a JSON parsing library - it creates a `Deserializer` and calls `Type::deserialize` with it as a parameter. The `deserialize` code will then create a `Visitor` which will have its calls "refracted" by the `Deserializer`. If everything goes well, eventually that `Visitor` will construct a value corresponding to the type being parsed and return it. For a complete example, see the [*Serde* documentation](https://serde.rs/deserialize-struct.html). The result is that types to be deserialized only implement the "top layer" of the API, and file formats only need to implement the "bottom layer". Each piece can then "just work" with the rest of the ecosystem, since generic types will bridge them. In conclusion, Rust's generic-inspired type system can bring it close to these concepts and use their power, as shown in this API design. But it may also need procedural macros to create bridges for its generics. If you are interested in learning more about this topic, please check the following section. ## See Also - [lens-rs crate](https://crates.io/crates/lens-rs) for a pre-built lenses implementation, with a cleaner interface than these examples - [Serde](https://serde.rs) itself, which makes these concepts intuitive for end users (i.e. defining the structs) without needing to understand the details - [luminance](https://github.com/phaazon/luminance-rs) is a crate for drawing computer graphics that uses similar API design, including procedural macros to create full prisms for buffers of different pixel types that remain generic - [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) that is very readable even without Scala expertise. - [Paper: Profunctor Optics: Modular Data Accessors](https://web.archive.org/web/20220701102832/https://arxiv.org/ftp/arxiv/papers/1703/1703.10857.pdf) - [Musli](https://github.com/udoprog/musli) is a library which attempts to use a similar structure with a different approach, e.g. doing away with the visitor [^1]: [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) [^2]: [Concordance on Wikipedia](https://en.wikipedia.org/wiki/Concordance_(publishing)) ================================================ FILE: src/functional/paradigms.md ================================================ # Programming paradigms One of the biggest hurdles to understanding functional programs when coming from an imperative background is the shift in thinking. Imperative programs describe **how** to do something, whereas declarative programs describe **what** to do. Let's sum the numbers from 1 to 10 to show this. ## Imperative ```rust let mut sum = 0; for i in 1..11 { sum += i; } println!("{sum}"); ``` With imperative programs, we have to play compiler to see what is happening. Here, we start with a `sum` of `0`. Next, we iterate through the range from 1 to 10. Each time through the loop, we add the corresponding value in the range. Then we print it out. | `i` | `sum` | | :-: | :---: | | 1 | 1 | | 2 | 3 | | 3 | 6 | | 4 | 10 | | 5 | 15 | | 6 | 21 | | 7 | 28 | | 8 | 36 | | 9 | 45 | | 10 | 55 | This is how most of us start out programming. We learn that a program is a set of steps. ## Declarative ```rust println!("{}", (1..11).fold(0, |a, b| a + b)); ``` Whoa! This is really different! What's going on here? Remember that with declarative programs we are describing **what** to do, rather than **how** to do it. `fold` is a function that [composes](https://en.wikipedia.org/wiki/Function_composition) functions. The name is a convention from Haskell. Here, we are composing functions of addition (this closure: `|a, b| a + b`) with a range from 1 to 10. The `0` is the starting point, so `a` is `0` at first. `b` is the first element of the range, `1`. `0 + 1 = 1` is the result. So now we `fold` again, with `a = 1`, `b = 2` and so `1 + 2 = 3` is the next result. This process continues until we get to the last element in the range, `10`. | `a` | `b` | result | | :-: | :-: | :----: | | 0 | 1 | 1 | | 1 | 2 | 3 | | 3 | 3 | 6 | | 6 | 4 | 10 | | 10 | 5 | 15 | | 15 | 6 | 21 | | 21 | 7 | 28 | | 28 | 8 | 36 | | 36 | 9 | 45 | | 45 | 10 | 55 | ================================================ FILE: src/idioms/coercion-arguments.md ================================================ # Use borrowed types for arguments ## Description Using a target of a deref coercion can increase the flexibility of your code when you are deciding which argument type to use for a function argument. In this way, the function will accept more input types. This is not limited to slice-able or fat pointer types. In fact, you should always prefer using the **borrowed type** over **borrowing the owned type**. Such as `&str` over `&String`, `&[T]` over `&Vec`, or `&T` over `&Box`. Using borrowed types you can avoid layers of indirection for those instances where the owned type already provides a layer of indirection. For instance, a `String` has a layer of indirection, so a `&String` will have two layers of indirection. We can avoid this by using `&str` instead, and letting `&String` coerce to a `&str` whenever the function is invoked. ## Example For this example, we will illustrate some differences for using `&String` as a function argument versus using a `&str`, but the ideas apply as well to using `&Vec` versus using a `&[T]` or using a `&Box` versus a `&T`. Consider an example where we wish to determine if a word contains three consecutive vowels. We don't need to own the string to determine this, so we will take a reference. The code might look something like this: ```rust fn three_vowels(word: &String) -> bool { let mut vowel_count = 0; for c in word.chars() { match c { 'a' | 'e' | 'i' | 'o' | 'u' => { vowel_count += 1; if vowel_count >= 3 { return true; } } _ => vowel_count = 0, } } false } fn main() { let ferris = "Ferris".to_string(); let curious = "Curious".to_string(); println!("{}: {}", ferris, three_vowels(&ferris)); println!("{}: {}", curious, three_vowels(&curious)); // This works fine, but the following two lines would fail: // println!("Ferris: {}", three_vowels("Ferris")); // println!("Curious: {}", three_vowels("Curious")); } ``` This works fine because we are passing a `&String` type as a parameter. If we remove the comments on the last two lines, the example will fail. This is because a `&str` type will not coerce to a `&String` type. We can fix this by simply modifying the type for our argument. For instance, if we change our function declaration to: ```rust, ignore fn three_vowels(word: &str) -> bool { ``` then both versions will compile and print the same output. ```bash Ferris: false Curious: true ``` But wait, that's not all! There is more to this story. It's likely that you may say to yourself: that doesn't matter, I will never be using a `&'static str` as an input anyways (as we did when we used `"Ferris"`). Even ignoring this special example, you may still find that using `&str` will give you more flexibility than using a `&String`. Let's now take an example where someone gives us a sentence, and we want to determine if any of the words in the sentence contain three consecutive vowels. We probably should make use of the function we have already defined and simply feed in each word from the sentence. An example of this could look like this: ```rust fn three_vowels(word: &str) -> bool { let mut vowel_count = 0; for c in word.chars() { match c { 'a' | 'e' | 'i' | 'o' | 'u' => { vowel_count += 1; if vowel_count >= 3 { return true; } } _ => vowel_count = 0, } } false } fn main() { let sentence_string = "Once upon a time, there was a friendly curious crab named Ferris".to_string(); for word in sentence_string.split(' ') { if three_vowels(word) { println!("{word} has three consecutive vowels!"); } } } ``` Running this example using our function declared with an argument type `&str` will yield ```bash curious has three consecutive vowels! ``` However, this example will not run when our function is declared with an argument type `&String`. This is because string slices are a `&str` and not a `&String` which would require an allocation to be converted to `&String` which is not implicit, whereas converting from `String` to `&str` is cheap and implicit. ## See also - [Rust Language Reference on Type Coercions](https://doc.rust-lang.org/reference/type-coercions.html) - For more discussion on how to handle `String` and `&str` see [this blog series (2015)](https://web.archive.org/web/20201112023149/https://hermanradtke.com/2015/05/03/string-vs-str-in-rust-functions.html) by Herman J. Radtke III - [Steve Klabnik's Blogpost on 'When should I use String vs &str?'](https://archive.ph/LBpD0) ================================================ FILE: src/idioms/concat-format.md ================================================ # Concatenating strings with `format!` ## Description It is possible to build up strings using the `push` and `push_str` methods on a mutable `String`, or using its `+` operator. However, it is often more convenient to use `format!`, especially where there is a mix of literal and non-literal strings. ## Example ```rust fn say_hello(name: &str) -> String { // We could construct the result string manually. // let mut result = "Hello ".to_owned(); // result.push_str(name); // result.push('!'); // result // But using format! is better. format!("Hello {name}!") } ``` ## Advantages Using `format!` is usually the most succinct and readable way to combine strings. ## Disadvantages It is usually not the most efficient way to combine strings - a series of `push` operations on a mutable string is usually the most efficient (especially if the string has been pre-allocated to the expected size). ================================================ FILE: src/idioms/ctor.md ================================================ # Constructors ## Description Rust does not have constructors as a language construct. Instead, the convention is to use an [associated function][associated function] `new` to create an object: ````rust /// Time in seconds. /// /// # Example /// /// ``` /// let s = Second::new(42); /// assert_eq!(42, s.value()); /// ``` pub struct Second { value: u64, } impl Second { // Constructs a new instance of [`Second`]. // Note this is an associated function - no self. pub fn new(value: u64) -> Self { Self { value } } /// Returns the value in seconds. pub fn value(&self) -> u64 { self.value } } ```` ## Default Constructors Rust supports default constructors with the [`Default`][std-default] trait: ````rust /// Time in seconds. /// /// # Example /// /// ``` /// let s = Second::default(); /// assert_eq!(0, s.value()); /// ``` pub struct Second { value: u64, } impl Second { /// Returns the value in seconds. pub fn value(&self) -> u64 { self.value } } impl Default for Second { fn default() -> Self { Self { value: 0 } } } ```` `Default` can also be derived if all types of all fields implement `Default`, like they do with `Second`: ````rust /// Time in seconds. /// /// # Example /// /// ``` /// let s = Second::default(); /// assert_eq!(0, s.value()); /// ``` #[derive(Default)] pub struct Second { value: u64, } impl Second { /// Returns the value in seconds. pub fn value(&self) -> u64 { self.value } } ```` **Note:** It is common and expected for types to implement both `Default` and an empty `new` constructor. `new` is the constructor convention in Rust, and users expect it to exist, so if it is reasonable for the basic constructor to take no arguments, then it should, even if it is functionally identical to default. **Hint:** The advantage of implementing or deriving `Default` is that your type can now be used where a `Default` implementation is required, most prominently, any of the [`*or_default` functions in the standard library][std-or-default]. ## See also - The [default idiom](default.md) for a more in-depth description of the `Default` trait. - The [builder pattern](../patterns/creational/builder.md) for constructing objects where there are multiple configurations. - [API Guidelines/C-COMMON-TRAITS][API Guidelines/C-COMMON-TRAITS] for implementing both, `Default` and `new`. [associated function]: https://doc.rust-lang.org/stable/book/ch05-03-method-syntax.html#associated-functions [std-default]: https://doc.rust-lang.org/stable/std/default/trait.Default.html [std-or-default]: https://doc.rust-lang.org/stable/std/?search=or_default [API Guidelines/C-COMMON-TRAITS]: https://rust-lang.github.io/api-guidelines/interoperability.html#types-eagerly-implement-common-traits-c-common-traits ================================================ FILE: src/idioms/default.md ================================================ # The `Default` Trait ## Description Many types in Rust have a [constructor]. However, this is *specific* to the type; Rust cannot abstract over "everything that has a `new()` method". To allow this, the [`Default`] trait was conceived, which can be used with containers and other generic types (e.g. see [`Option::unwrap_or_default()`]). Notably, some containers already implement it where applicable. Not only do one-element containers like `Cow`, `Box` or `Arc` implement `Default` for contained `Default` types, one can automatically `#[derive(Default)]` for structs whose fields all implement it, so the more types implement `Default`, the more useful it becomes. On the other hand, constructors can take multiple arguments, while the `default()` method does not. There can even be multiple constructors with different names, but there can only be one `Default` implementation per type. ## Example ```rust use std::{path::PathBuf, time::Duration}; // note that we can simply auto-derive Default here. #[derive(Default, Debug, PartialEq)] struct MyConfiguration { // Option defaults to None output: Option, // Vecs default to empty vector search_path: Vec, // Duration defaults to zero time timeout: Duration, // bool defaults to false check: bool, } impl MyConfiguration { // add setters here } fn main() { // construct a new instance with default values let mut conf = MyConfiguration::default(); // do something with conf here conf.check = true; println!("conf = {conf:#?}"); // partial initialization with default values, creates the same instance let conf1 = MyConfiguration { check: true, ..Default::default() }; assert_eq!(conf, conf1); } ``` ## See also - The [constructor] idiom is another way to generate instances that may or may not be "default" - The [`Default`] documentation (scroll down for the list of implementors) - [`Option::unwrap_or_default()`] - [`derive(new)`] [constructor]: ctor.md [`Default`]: https://doc.rust-lang.org/stable/std/default/trait.Default.html [`Option::unwrap_or_default()`]: https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.unwrap_or_default [`derive(new)`]: https://crates.io/crates/derive-new/ ================================================ FILE: src/idioms/deref.md ================================================ # Collections are smart pointers ## Description Use the [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) trait to treat collections like smart pointers, offering owning and borrowed views of data. ## Example ```rust,ignore use std::ops::Deref; struct Vec { data: RawVec, //.. } impl Deref for Vec { type Target = [T]; fn deref(&self) -> &[T] { //.. } } ``` A `Vec` is an owning collection of `T`s, while a slice (`&[T]`) is a borrowed collection of `T`s. Implementing `Deref` for `Vec` allows implicit dereferencing from `&Vec` to `&[T]` and includes the relationship in auto-dereferencing searches. Most methods you might expect to be implemented for `Vec`s are instead implemented for slices. Also `String` and `&str` have a similar relation. ## Motivation Ownership and borrowing are key aspects of the Rust language. Data structures must account for these semantics properly to give a good user experience. When implementing a data structure that owns its data, offering a borrowed view of that data allows for more flexible APIs. ## Advantages Most methods can be implemented only for the borrowed view, they are then implicitly available for the owning view. Gives clients a choice between borrowing or taking ownership of data. ## Disadvantages Methods and traits only available via dereferencing are not taken into account when bounds checking, so generic programming with data structures using this pattern can get complex (see the `Borrow` and `AsRef` traits, etc.). ## Discussion Smart pointers and collections are analogous: a smart pointer points to a single object, whereas a collection points to many objects. From the point of view of the type system, there is little difference between the two. A collection owns its data if the only way to access each datum is via the collection and the collection is responsible for deleting the data (even in cases of shared ownership, some kind of borrowed view may be appropriate). If a collection owns its data, it is usually useful to provide a view of the data as borrowed so that it can be referenced multiple times. Most smart pointers (e.g., `Foo`) implement `Deref`. However, collections will usually dereference to a custom type. `[T]` and `str` have some language support, but in the general case, this is not necessary. `Foo` can implement `Deref>` where `Bar` is a dynamically sized type and `&Bar` is a borrowed view of the data in `Foo`. Commonly, ordered collections will implement `Index` for `Range`s to provide slicing syntax. The target will be the borrowed view. ## See also - [Deref polymorphism anti-pattern](../anti_patterns/deref.md). - [Documentation for `Deref` trait](https://doc.rust-lang.org/std/ops/trait.Deref.html). ================================================ FILE: src/idioms/dtor-finally.md ================================================ # Finalisation in destructors ## Description Rust does not provide the equivalent to `finally` blocks - code that will be executed no matter how a function is exited. Instead, an object's destructor can be used to run code that must be run before exit. ## Example ```rust,ignore fn baz() -> Result<(), ()> { // some code } fn bar() -> Result<(), ()> { // These don't need to be defined inside the function. struct Foo; // Implement a destructor for Foo. impl Drop for Foo { fn drop(&mut self) { println!("exit"); } } // The destructor of _exit will run however the function `bar` is exited. let _exit = Foo; // Implicit return with `?` operator. baz()?; // Normal return. Ok(()) } ``` ## Motivation If a function has multiple return points, then executing code on exit becomes difficult and repetitive (and thus bug-prone). This is especially the case where return is implicit due to a macro. A common case is the `?` operator which returns if the result is an `Err`, but continues if it is `Ok`. `?` is used as an exception handling mechanism, but unlike Java (which has `finally`), there is no way to schedule code to run in both the normal and exceptional cases. Panicking will also exit a function early. ## Advantages Code in destructors will (nearly) always be run - copes with panics, early returns, etc. ## Disadvantages It is not guaranteed that destructors will run. For example, if there is an infinite loop in a function or if running a function crashes before exit. Destructors are also not run in the case of a panic in an already panicking thread. Therefore, destructors cannot be relied on as finalizers where it is absolutely essential that finalisation happens. This pattern introduces some hard to notice, implicit code. Reading a function gives no clear indication of destructors to be run on exit. This can make debugging tricky. Requiring an object and `Drop` impl just for finalisation is heavy on boilerplate. ## Discussion There is some subtlety about how exactly to store the object used as a finalizer. It must be kept alive until the end of the function and must then be destroyed. The object must always be a value or uniquely owned pointer (e.g., `Box`). If a shared pointer (such as `Rc`) is used, then the finalizer can be kept alive beyond the lifetime of the function. For similar reasons, the finalizer should not be moved or returned. The finalizer must be assigned into a variable, otherwise it will be destroyed immediately, rather than when it goes out of scope. The variable name must start with `_` if the variable is only used as a finalizer, otherwise the compiler will warn that the finalizer is never used. However, do not call the variable `_` with no suffix - in that case it will be destroyed immediately. In Rust, destructors are run when an object goes out of scope. This happens whether we reach the end of block, there is an early return, or the program panics. When panicking, Rust unwinds the stack running destructors for each object in each stack frame. So, destructors get called even if the panic happens in a function being called. If a destructor panics while unwinding, there is no good action to take, so Rust aborts the thread immediately, without running further destructors. This means that destructors are not absolutely guaranteed to run. It also means that you must take extra care in your destructors not to panic, since it could leave resources in an unexpected state. ## See also [RAII guards](../patterns/behavioural/RAII.md). ================================================ FILE: src/idioms/ffi/accepting-strings.md ================================================ # Accepting Strings ## Description When accepting strings via FFI through pointers, there are two principles that should be followed: 1. Keep foreign strings "borrowed", rather than copying them directly. 2. Minimize the amount of complexity and `unsafe` code involved in converting from a C-style string to native Rust strings. ## Motivation The strings used in C have different behaviours to those used in Rust, namely: - C strings are null-terminated while Rust strings store their length - C strings can contain any arbitrary non-zero byte while Rust strings must be UTF-8 - C strings are accessed and manipulated using `unsafe` pointer operations while interactions with Rust strings go through safe methods The Rust standard library comes with C equivalents of Rust's `String` and `&str` called `CString` and `&CStr`, that allow us to avoid a lot of the complexity and `unsafe` code involved in converting between C strings and Rust strings. The `&CStr` type also allows us to work with borrowed data, meaning passing strings between Rust and C is a zero-cost operation. ## Code Example ```rust,ignore pub mod unsafe_module { // other module content /// Log a message at the specified level. /// /// # Safety /// /// It is the caller's guarantee to ensure `msg`: /// /// - is not a null pointer /// - points to valid, initialized data /// - points to memory ending in a null byte /// - won't be mutated for the duration of this function call #[no_mangle] pub unsafe extern "C" fn mylib_log(msg: *const libc::c_char, level: libc::c_int) { let level: crate::LogLevel = match level { /* ... */ }; // SAFETY: The caller has already guaranteed this is okay (see the // `# Safety` section of the doc-comment). let msg_str: &str = match std::ffi::CStr::from_ptr(msg).to_str() { Ok(s) => s, Err(e) => { crate::log_error("FFI string conversion failed"); return; } }; crate::log(msg_str, level); } } ``` ## Advantages The example is written to ensure that: 1. The `unsafe` block is as small as possible. 2. The pointer with an "untracked" lifetime becomes a "tracked" shared reference Consider an alternative, where the string is actually copied: ```rust,ignore pub mod unsafe_module { // other module content pub extern "C" fn mylib_log(msg: *const libc::c_char, level: libc::c_int) { // DO NOT USE THIS CODE. // IT IS UGLY, VERBOSE, AND CONTAINS A SUBTLE BUG. let level: crate::LogLevel = match level { /* ... */ }; let msg_len = unsafe { /* SAFETY: strlen is what it is, I guess? */ libc::strlen(msg) }; let mut msg_data = Vec::with_capacity(msg_len + 1); let msg_cstr: std::ffi::CString = unsafe { // SAFETY: copying from a foreign pointer expected to live // for the entire stack frame into owned memory std::ptr::copy_nonoverlapping(msg, msg_data.as_mut(), msg_len); msg_data.set_len(msg_len + 1); std::ffi::CString::from_vec_with_nul(msg_data).unwrap() } let msg_str: String = unsafe { match msg_cstr.into_string() { Ok(s) => s, Err(e) => { crate::log_error("FFI string conversion failed"); return; } } }; crate::log(&msg_str, level); } } ``` This code is inferior to the original in two respects: 1. There is much more `unsafe` code, and more importantly, more invariants it must uphold. 2. Due to the extensive arithmetic required, there is a bug in this version that causes Rust `undefined behaviour`. The bug here is a simple mistake in pointer arithmetic: the string was copied, all `msg_len` bytes of it. However, the `NUL` terminator at the end was not. The Vector then had its size *set* to the length of the *zero padded string* -- rather than *resized* to it, which could have added a zero at the end. As a result, the last byte in the Vector is uninitialized memory. When the `CString` is created at the bottom of the block, its read of the Vector will cause `undefined behaviour`! Like many such issues, this would be difficult issue to track down. Sometimes it would panic because the string was not `UTF-8`, sometimes it would put a weird character at the end of the string, sometimes it would just completely crash. ## Disadvantages None? ================================================ FILE: src/idioms/ffi/errors.md ================================================ # Error Handling in FFI ## Description In foreign languages like C, errors are represented by return codes. However, Rust's type system allows much more rich error information to be captured and propagated through a full type. This best practice shows different kinds of error codes, and how to expose them in a usable way: 1. Flat Enums should be converted to integers and returned as codes. 2. Structured Enums should be converted to an integer code with a string error message for detail. 3. Custom Error Types should become "transparent", with a C representation. ## Code Example ### Flat Enums ```rust,ignore enum DatabaseError { IsReadOnly = 1, // user attempted a write operation IOError = 2, // user should read the C errno() for what it was FileCorrupted = 3, // user should run a repair tool to recover it } impl From for libc::c_int { fn from(e: DatabaseError) -> libc::c_int { (e as i8).into() } } ``` ### Structured Enums ```rust,ignore pub mod errors { enum DatabaseError { IsReadOnly, IOError(std::io::Error), FileCorrupted(String), // message describing the issue } impl From for libc::c_int { fn from(e: DatabaseError) -> libc::c_int { match e { DatabaseError::IsReadOnly => 1, DatabaseError::IOError(_) => 2, DatabaseError::FileCorrupted(_) => 3, } } } } pub mod c_api { use super::errors::DatabaseError; use core::ptr; #[no_mangle] pub extern "C" fn db_error_description( e: Option>, ) -> Option> { // SAFETY: we assume that the lifetime of `e` is greater than // the current stack frame. let error = unsafe { e?.as_ref() }; let error_str: String = match error { DatabaseError::IsReadOnly => { format!("cannot write to read-only database") } DatabaseError::IOError(e) => { format!("I/O Error: {e}") } DatabaseError::FileCorrupted(s) => { format!("File corrupted, run repair: {}", &s) } }; let error_bytes = error_str.as_bytes(); let c_error = unsafe { // SAFETY: copying error_bytes to an allocated buffer with a '\0' // byte at the end. let buffer = ptr::NonNull::::new(libc::malloc(error_bytes.len() + 1).cast())?; buffer .as_ptr() .copy_from_nonoverlapping(error_bytes.as_ptr(), error_bytes.len()); buffer.as_ptr().add(error_bytes.len()).write(0_u8); buffer }; Some(c_error.cast()) } } ``` ### Custom Error Types ```rust,ignore struct ParseError { expected: char, line: u32, ch: u16, } impl ParseError { /* ... */ } /* Create a second version which is exposed as a C structure */ #[repr(C)] pub struct parse_error { pub expected: libc::c_char, pub line: u32, pub ch: u16, } impl From for parse_error { fn from(e: ParseError) -> parse_error { let ParseError { expected, line, ch } = e; parse_error { expected, line, ch } } } ``` ## Advantages This ensures that the foreign language has clear access to error information while not compromising the Rust code's API at all. ## Disadvantages It's a lot of typing, and some types may not be able to be converted easily to C. ================================================ FILE: src/idioms/ffi/intro.md ================================================ # FFI Idioms Writing FFI code is an entire course in itself. However, there are several idioms here that can act as pointers, and avoid traps for inexperienced users of `unsafe` Rust. This section contains idioms that may be useful when doing FFI. 1. [Idiomatic Errors](./errors.md) - Error handling with integer codes and sentinel return values (such as `NULL` pointers) 2. [Accepting Strings](./accepting-strings.md) with minimal unsafe code 3. [Passing Strings](./passing-strings.md) to FFI functions ================================================ FILE: src/idioms/ffi/passing-strings.md ================================================ # Passing Strings ## Description When passing strings to FFI functions, there are four principles that should be followed: 1. Make the lifetime of owned strings as long as possible. 2. Minimize `unsafe` code during the conversion. 3. If the C code can modify the string data, use `Vec` instead of `CString`. 4. Unless the Foreign Function API requires it, the ownership of the string should not transfer to the callee. ## Motivation Rust has built-in support for C-style strings with its `CString` and `CStr` types. However, there are different approaches one can take with strings that are being sent to a foreign function call from a Rust function. The best practice is simple: use `CString` in such a way as to minimize `unsafe` code. However, a secondary caveat is that *the object must live long enough*, meaning the lifetime should be maximized. In addition, the documentation explains that "round-tripping" a `CString` after modification is UB, so additional work is necessary in that case. ## Code Example ```rust,ignore pub mod unsafe_module { // other module content extern "C" { fn seterr(message: *const libc::c_char); fn geterr(buffer: *mut libc::c_char, size: libc::c_int) -> libc::c_int; } fn report_error_to_ffi>(err: S) -> Result<(), std::ffi::NulError> { let c_err = std::ffi::CString::new(err.into())?; unsafe { // SAFETY: calling an FFI whose documentation says the pointer is // const, so no modification should occur seterr(c_err.as_ptr()); } Ok(()) // The lifetime of c_err continues until here } fn get_error_from_ffi() -> Result { let mut buffer = vec![0u8; 1024]; unsafe { // SAFETY: calling an FFI whose documentation implies // that the input need only live as long as the call let written: usize = geterr(buffer.as_mut_ptr(), 1023).into(); buffer.truncate(written + 1); } std::ffi::CString::new(buffer).unwrap().into_string() } } ``` ## Advantages The example is written in a way to ensure that: 1. The `unsafe` block is as small as possible. 2. The `CString` lives long enough. 3. Errors with typecasts are always propagated when possible. A common mistake (so common it's in the documentation) is to not use the variable in the first block: ```rust,ignore pub mod unsafe_module { // other module content fn report_error>(err: S) -> Result<(), std::ffi::NulError> { unsafe { // SAFETY: whoops, this contains a dangling pointer! seterr(std::ffi::CString::new(err.into())?.as_ptr()); } Ok(()) } } ``` This code will result in a dangling pointer, because the lifetime of the `CString` is not extended by the pointer creation, unlike if a reference were created. Another issue frequently raised is that the initialization of a 1k vector of zeroes is "slow". However, recent versions of Rust actually optimize that particular macro to a call to `zmalloc`, meaning it is as fast as the operating system's ability to return zeroed memory (which is quite fast). ## Disadvantages None? ================================================ FILE: src/idioms/index.md ================================================ # Idioms [Idioms](https://en.wikipedia.org/wiki/Programming_idiom) are commonly used styles, guidelines and patterns largely agreed upon by a community. Writing idiomatic code allows other developers to understand better what is happening. After all, the computer only cares about the machine code that is generated by the compiler. Instead, the source code is mainly beneficial to the developer. So, since we have this abstraction layer, why not make it more readable? Remember the [KISS principle](https://en.wikipedia.org/wiki/KISS_principle): "Keep It Simple, Stupid". It claims that "most systems work best if they are kept simple rather than made complicated; therefore, simplicity should be a key goal in design, and unnecessary complexity should be avoided". > Code is there for humans, not computers, to understand. ================================================ FILE: src/idioms/mem-replace.md ================================================ # `mem::{take(_), replace(_)}` to keep owned values in changed enums ## Description Say we have a `&mut MyEnum` which has (at least) two variants, `A { name: String, x: u8 }` and `B { name: String }`. Now we want to change `MyEnum::A` to a `B` if `x` is zero, while keeping `MyEnum::B` intact. We can do this without cloning the `name`. ## Example ```rust use std::mem; enum MyEnum { A { name: String, x: u8 }, B { name: String }, } fn a_to_b(e: &mut MyEnum) { if let MyEnum::A { name, x: 0 } = e { // This takes out our `name` and puts in an empty String instead // (note that empty strings don't allocate). // Then, construct the new enum variant (which will // be assigned to `*e`). *e = MyEnum::B { name: mem::take(name), } } } ``` This also works with more variants: ```rust use std::mem; enum MultiVariateEnum { A { name: String }, B { name: String }, C, D, } fn swizzle(e: &mut MultiVariateEnum) { use MultiVariateEnum::*; *e = match e { // Ownership rules do not allow taking `name` by value, but we cannot // take the value out of a mutable reference, unless we replace it: A { name } => B { name: mem::take(name), }, B { name } => A { name: mem::take(name), }, C => D, D => C, } } ``` ## Motivation When working with enums, we may want to change an enum value in place, perhaps to another variant. This is usually done in two phases to keep the borrow checker happy. In the first phase, we observe the existing value and look at its parts to decide what to do next. In the second phase we may conditionally change the value (as in the example above). The borrow checker won't allow us to take out `name` of the enum (because *something* must be there.) We could of course `.clone()` name and put the clone 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 can avoid the extra allocation by changing `e` with only a mutable borrow. `mem::take` lets us swap out the value, replacing it with its default value, and returning the previous value. For `String`, the default value is an empty `String`, which does not need to allocate. As a result, we get the original `name` *as an owned value*. We can then wrap this in another enum. **NOTE:** `mem::replace` is very similar, but allows us to specify what to replace the value with. An equivalent to our `mem::take` line would be `mem::replace(name, String::new())`. Note, however, that if we are using an `Option` and want to replace its value with a `None`, `Option`’s `take()` method provides a shorter and more idiomatic alternative. ## Advantages Look ma, no allocation! Also you may feel like Indiana Jones while doing it. ## Disadvantages This gets a bit wordy. Getting it wrong repeatedly will make you hate the borrow checker. The compiler may fail to optimize away the double store, resulting in reduced performance as opposed to what you'd do in unsafe languages. Furthermore, the type you are taking needs to implement the [`Default` trait](./default.md). However, if the type you're working with doesn't implement this, you can instead use `mem::replace`. ## Discussion This pattern is only of interest in Rust. In GC'd languages, you'd take the reference to the value by default (and the GC would keep track of refs), and in other low-level languages like C you'd simply alias the pointer and fix things later. However, in Rust, we have to do a little more work to do this. An owned value may only have one owner, so to take it out, we need to put something back in – like Indiana Jones, replacing the artifact with a bag of sand. ## See also This gets rid of the [Clone to satisfy the borrow checker](../anti_patterns/borrow_clone.md) anti-pattern in a specific case. ================================================ FILE: src/idioms/on-stack-dyn-dispatch.md ================================================ # On-Stack Dynamic Dispatch ## Description We can dynamically dispatch over multiple values, however, to do so, we need to declare multiple variables to bind differently-typed objects. To extend the lifetime as necessary, we can use deferred conditional initialization, as seen below: ## Example ```rust use std::io; use std::fs; # fn main() -> Result<(), Box> { # let arg = "-"; // We need to describe the type to get dynamic dispatch. let readable: &mut dyn io::Read = if arg == "-" { &mut io::stdin() } else { &mut fs::File::open(arg)? }; // Read from `readable` here. # Ok(()) # } ``` ## Motivation Rust monomorphises code by default. This means a copy of the code will be generated for each type it is used with and optimized independently. While this allows for very fast code on the hot path, it also bloats the code in places where performance is not of the essence, thus costing compile time and cache usage. Luckily, Rust allows us to use dynamic dispatch, but we have to explicitly ask for it. ## Advantages We do not need to allocate anything on the heap. Neither do we need to initialize something we won't use later, nor do we need to monomorphize the whole code that follows to work with both `File` or `Stdin`. ## Disadvantages Before Rust 1.79.0, the code needed two `let` bindings with deferred initialization, which made up more moving parts than the `Box`-based version: ```rust,ignore // We still need to ascribe the type for dynamic dispatch. let readable: Box = if arg == "-" { Box::new(io::stdin()) } else { Box::new(fs::File::open(arg)?) }; // Read from `readable` here. ``` Luckily, this disadvantage is now gone. Yay! ## Discussion Since Rust 1.79.0, the compiler will automatically extend the lifetimes of temporary values within `&` or `&mut` as long as possible within the scope of the function. This means we can simply use a `&mut` value here without worrying about placing the contents into some `let` binding (which would have been needed for deferred initialization, which was the solution used before that change). We still have a place for each value (even if that place is temporary), the compiler knows the size of each value and each borrowed value outlives all references borrowed from it. ## See also - [Finalisation in destructors](dtor-finally.md) and [RAII guards](../patterns/behavioural/RAII.md) can benefit from tight control over lifetimes. - For conditionally filled `Option<&T>`s of (mutable) references, one can initialize an `Option` directly and use its [`.as_ref()`] method to get an optional reference. [`.as_ref()`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.as_ref ================================================ FILE: src/idioms/option-iter.md ================================================ # Iterating over an `Option` ## Description `Option` can be viewed as a container that contains either zero or one element. In particular, it implements the `IntoIterator` trait, and as such can be used with generic code that needs such a type. ## Examples Since `Option` implements `IntoIterator`, it can be used as an argument to [`.extend()`](https://doc.rust-lang.org/std/iter/trait.Extend.html#tymethod.extend): ```rust let turing = Some("Turing"); let mut logicians = vec!["Curry", "Kleene", "Markov"]; logicians.extend(turing); // equivalent to if let Some(turing_inner) = turing { logicians.push(turing_inner); } ``` If you need to tack an `Option` to the end of an existing iterator, you can pass it to [`.chain()`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.chain): ```rust let turing = Some("Turing"); let logicians = vec!["Curry", "Kleene", "Markov"]; for logician in logicians.iter().chain(turing.iter()) { println!("{logician} is a logician"); } ``` Note that if the `Option` is always `Some`, then it is more idiomatic to use [`std::iter::once`](https://doc.rust-lang.org/std/iter/fn.once.html) on the element instead. Also, since `Option` implements `IntoIterator`, it's possible to iterate over it using a `for` loop. This is equivalent to matching it with `if let Some(..)`, and in most cases you should prefer the latter. ## See also - [`std::iter::once`](https://doc.rust-lang.org/std/iter/fn.once.html) is an iterator which yields exactly one element. It's a more readable alternative to `Some(foo).into_iter()`. - [`Iterator::filter_map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter_map) is a version of [`Iterator::map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map), specialized to mapping functions which return `Option`. - The [`ref_slice`](https://crates.io/crates/ref_slice) crate provides functions for converting an `Option` to a zero- or one-element slice. - [Documentation for `Option`](https://doc.rust-lang.org/std/option/enum.Option.html) ================================================ FILE: src/idioms/pass-var-to-closure.md ================================================ # Pass variables to closure ## Description By default, closures capture their environment by borrowing. Or you can use a `move`-closure to move the whole environment. However, often you want to move just some variables to the closure, give it a copy of some data, pass by reference, or perform some other transformation. Use variable rebinding in a separate scope for that. ## Example Use ```rust use std::rc::Rc; let num1 = Rc::new(1); let num2 = Rc::new(2); let num3 = Rc::new(3); let closure = { // `num1` is moved let num2 = num2.clone(); // `num2` is cloned let num3 = num3.as_ref(); // `num3` is borrowed move || { *num1 + *num2 + *num3; } }; ``` instead of ```rust use std::rc::Rc; let num1 = Rc::new(1); let num2 = Rc::new(2); let num3 = Rc::new(3); let num2_cloned = num2.clone(); let num3_borrowed = num3.as_ref(); let closure = move || { *num1 + *num2_cloned + *num3_borrowed; }; ``` ## Advantages Copied data are grouped together with the closure definition, so their purpose is more clear, and they will be dropped immediately even if they are not consumed by the closure. The closure uses the same variable names as the surrounding code, whether data are copied or moved. ## Disadvantages Additional indentation of the closure body. ================================================ FILE: src/idioms/priv-extend.md ================================================ # `#[non_exhaustive]` and private fields for extensibility ## Description A small set of scenarios exist where a library author may want to add public fields to a public struct or new variants to an enum without breaking backwards compatibility. Rust offers two solutions to this problem: - Use `#[non_exhaustive]` on `struct`s, `enum`s, and `enum` variants. For extensive documentation on all the places where `#[non_exhaustive]` can be used, see [the docs](https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute). - You may add a private field to a struct to prevent it from being directly instantiated or matched against (see Alternative) ## Example ```rust mod a { // Public struct. #[non_exhaustive] pub struct S { pub foo: i32, } #[non_exhaustive] pub enum AdmitMoreVariants { VariantA, VariantB, #[non_exhaustive] VariantC { a: String, }, } } fn print_matched_variants(s: a::S) { // Because S is `#[non_exhaustive]`, it cannot be named here and // we must use `..` in the pattern. let a::S { foo: _, .. } = s; let some_enum = a::AdmitMoreVariants::VariantA; match some_enum { a::AdmitMoreVariants::VariantA => println!("it's an A"), a::AdmitMoreVariants::VariantB => println!("it's a b"), // .. required because this variant is non-exhaustive as well a::AdmitMoreVariants::VariantC { a, .. } => println!("it's a c"), // The wildcard match is required because more variants may be // added in the future _ => println!("it's a new variant"), } } ``` ## Alternative: `Private fields` for structs `#[non_exhaustive]` only works across crate boundaries. Within a crate, the private field method may be used. Adding a field to a struct is a mostly backwards compatible change. However, if a client uses a pattern to deconstruct a struct instance, they might name all the fields in the struct and adding a new one would break that pattern. The client could name some fields and use `..` in the pattern, in which case adding another field is backwards compatible. Making at least one of the struct's fields private forces clients to use the latter form of patterns, ensuring that the struct is future-proof. The downside of this approach is that you might need to add an otherwise unneeded field to the struct. You can use the `()` type so that there is no runtime overhead and prepend `_` to the field name to avoid the unused field warning. ```rust pub struct S { pub a: i32, // Because `b` is private, you cannot match on `S` without using `..` and `S` // cannot be directly instantiated or matched against _b: (), } ``` ## Discussion On `struct`s, `#[non_exhaustive]` allows adding additional fields in a backwards compatible way. It will also prevent clients from using the struct constructor, even if all the fields are public. This may be helpful, but it's worth considering if you *want* an additional field to be found by clients as a compiler error rather than something that may be silently undiscovered. `#[non_exhaustive]` can be applied to enum variants as well. A `#[non_exhaustive]` variant behaves in the same way as a `#[non_exhaustive]` struct. Use this deliberately and with caution: incrementing the major version when adding fields or variants is often a better option. `#[non_exhaustive]` may be appropriate in scenarios where you're modeling an external resource that may change out-of-sync with your library, but is not a general purpose tool. ### Disadvantages `#[non_exhaustive]` can make your code much less ergonomic to use, especially when forced to handle unknown enum variants. It should only be used when these sorts of evolutions are required **without** incrementing the major version. When `#[non_exhaustive]` is applied to `enum`s, it forces clients to handle a wildcard variant. If there is no sensible action to take in this case, this may lead to awkward code and code paths that are only executed in extremely rare circumstances. If a client decides to `panic!()` in this scenario, it may have been better to expose this error at compile time. In fact, `#[non_exhaustive]` forces clients to handle the "Something else" case; there is rarely a sensible action to take in this scenario. ## See also - [RFC introducing #[non_exhaustive] attribute for enums and structs](https://github.com/rust-lang/rfcs/blob/master/text/2008-non-exhaustive.md) ================================================ FILE: src/idioms/return-consumed-arg-on-error.md ================================================ # Return consumed argument on error ## Description If a fallible function consumes (moves) an argument, return that argument back inside an error. ## Example ```rust pub fn send(value: String) -> Result<(), SendError> { println!("using {value} in a meaningful way"); // Simulate non-deterministic fallible action. use std::time::SystemTime; let period = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .unwrap(); if period.subsec_nanos() % 2 == 1 { Ok(()) } else { Err(SendError(value)) } } pub struct SendError(String); fn main() { let mut value = "imagine this is very long string".to_string(); let success = 's: { // Try to send value two times. for _ in 0..2 { value = match send(value) { Ok(()) => break 's true, Err(SendError(value)) => value, } } false }; println!("success: {success}"); } ``` ## Motivation In case of error you may want to try some alternative way or to retry action in case of non-deterministic function. But if the argument is always consumed, you are forced to clone it on every call, which is not very efficient. The standard library uses this approach in e.g. `String::from_utf8` method. When given a vector that doesn't contain valid UTF-8, a `FromUtf8Error` is returned. You can get original vector back using `FromUtf8Error::into_bytes` method. ## Advantages Better performance because of moving arguments whenever possible. ## Disadvantages Slightly more complex error types. ================================================ FILE: src/idioms/rustdoc-init.md ================================================ # Easy doc initialization ## Description If a struct takes significant effort to initialize when writing docs, it can be quicker to wrap your example with a helper function which takes the struct as an argument. ## Motivation Sometimes there is a struct with multiple or complicated parameters and several methods. Each of these methods should have examples. For example: ````rust,ignore struct Connection { name: String, stream: TcpStream, } impl Connection { /// Sends a request over the connection. /// /// # Example /// ```no_run /// # // Boilerplate are required to get an example working. /// # let stream = TcpStream::connect("127.0.0.1:34254"); /// # let connection = Connection { name: "foo".to_owned(), stream }; /// # let request = Request::new("RequestId", RequestType::Get, "payload"); /// let response = connection.send_request(request); /// assert!(response.is_ok()); /// ``` fn send_request(&self, request: Request) -> Result { // ... } /// Oh no, all that boilerplate needs to be repeated here! fn check_status(&self) -> Status { // ... } } ```` ## Example Instead of typing all of this boilerplate to create a `Connection` and `Request`, it is easier to just create a wrapping helper function which takes them as arguments: ````rust,ignore struct Connection { name: String, stream: TcpStream, } impl Connection { /// Sends a request over the connection. /// /// # Example /// ``` /// # fn call_send(connection: Connection, request: Request) { /// let response = connection.send_request(request); /// assert!(response.is_ok()); /// # } /// ``` fn send_request(&self, request: Request) -> Result { // ... } } ```` **Note** in the above example the line `assert!(response.is_ok());` will not actually run while testing because it is inside a function which is never invoked. ## Advantages This is much more concise and avoids repetitive code in examples. ## Disadvantages As example is in a function, the code will not be tested. Though it will still be checked to make sure it compiles when running a `cargo test`. So this pattern is most useful when you need `no_run`. With this, you do not need to add `no_run`. ## Discussion If assertions are not required this pattern works well. If they are, an alternative can be to create a public method to create a helper instance which is annotated with `#[doc(hidden)]` (so that users won't see it). Then this method can be called inside of rustdoc because it is part of the crate's public API. ================================================ FILE: src/idioms/temporary-mutability.md ================================================ # Temporary mutability ## Description Often it is necessary to prepare and process some data, but after that data are only inspected and never modified. The intention can be made explicit by redefining the mutable variable as immutable. It can be done either by processing data within a nested block or by redefining the variable. ## Example Say, vector must be sorted before usage. Using nested block: ```rust,ignore let data = { let mut data = get_vec(); data.sort(); data }; // Here `data` is immutable. ``` Using variable rebinding: ```rust,ignore let mut data = get_vec(); data.sort(); let data = data; // Here `data` is immutable. ``` ## Advantages Compiler ensures that you don't accidentally mutate data after some point. ## Disadvantages Nested block requires additional indentation of block body. One more line to return data from block or redefine variable. ================================================ FILE: src/intro.md ================================================ # Introduction ## Participation If you are interested in contributing to this book, check out the [contribution guidelines](https://github.com/rust-unofficial/patterns/blob/master/CONTRIBUTING.md). ## News - **2025-12-14**: New pattern added: [Use custom traits to avoid complex type bounds](./patterns/structural/trait-for-bounds.md) - **2024-03-17**: You can now download the [book in PDF format](https://rust-unofficial.github.io/patterns/rust-design-patterns.pdf). ## Design patterns In software development, we often come across problems that share similarities regardless of the environment they appear in. Although the implementation details are crucial to solve the task at hand, we may abstract from these particularities to find the common practices that are generically applicable. Design patterns are a collection of reusable and tested solutions to recurring problems in engineering. They make our software more modular, maintainable, and extensible. Moreover, these patterns provide a common language for developers, making them an excellent tool for effective communication when problem-solving in teams. Keep in mind: Each pattern comes with its own set of trade-offs. It's crucial to focus on why you choose a particular pattern rather than just on how to implement it.[^1] ## Design patterns in Rust Rust is not object-oriented, and the combination of all its characteristics, such as functional elements, a strong type system, and the borrow checker, makes it unique. Because of this, Rust design patterns vary with respect to other traditional object-oriented programming languages. That's why we decided to write this book. We hope you enjoy reading it! The book is divided in three main chapters: - [Idioms](./idioms/index.md): guidelines to follow when coding. They are the social norms of the community. You should break them only if you have a good reason for it. - [Design patterns](./patterns/index.md): methods to solve common problems when coding. - [Anti-patterns](./anti_patterns/index.md): methods to solve common problems when coding. However, while design patterns give us benefits, anti-patterns create more problems. [^1]: ([Archive](https://web.archive.org/web/20240124025806/https://www.infoq.com/podcasts/software-architecture-hard-parts/)) ================================================ FILE: src/patterns/behavioural/RAII.md ================================================ # RAII with guards ## Description [RAII][wikipedia] stands for "Resource Acquisition is Initialisation" which is a terrible name. The essence of the pattern is that resource initialisation is done in the constructor of an object and finalisation in the destructor. This pattern is extended in Rust by using a RAII object as a guard of some resource and relying on the type system to ensure that access is always mediated by the guard object. ## Example Mutex guards are the classic example of this pattern from the std library (this is a simplified version of the real implementation): ```rust,ignore use std::ops::Deref; struct Foo {} struct Mutex { // We keep a reference to our data: T here. //.. } struct MutexGuard<'a, T: 'a> { data: &'a T, //.. } // Locking the mutex is explicit. impl Mutex { fn lock(&self) -> MutexGuard { // Lock the underlying OS mutex. //.. // MutexGuard keeps a reference to self MutexGuard { data: self, //.. } } } // Destructor for unlocking the mutex. impl<'a, T> Drop for MutexGuard<'a, T> { fn drop(&mut self) { // Unlock the underlying OS mutex. //.. } } // Implementing Deref means we can treat MutexGuard like a pointer to T. impl<'a, T> Deref for MutexGuard<'a, T> { type Target = T; fn deref(&self) -> &T { self.data } } fn baz(x: Mutex) { let xx = x.lock(); xx.foo(); // foo is a method on Foo. // The borrow checker ensures we can't store a reference to the underlying // Foo which will outlive the guard xx. // x is unlocked when we exit this function and xx's destructor is executed. } ``` ## Motivation Where a resource must be finalised after use, RAII can be used to do this finalisation. If it is an error to access that resource after finalisation, then this pattern can be used to prevent such errors. ## Advantages Prevents errors where a resource is not finalised and where a resource is used after finalisation. ## Discussion RAII is a useful pattern for ensuring resources are properly deallocated or finalised. We can make use of the borrow checker in Rust to statically prevent errors stemming from using resources after finalisation takes place. The core aim of the borrow checker is to ensure that references to data do not outlive that data. The RAII guard pattern works because the guard object contains a reference to the underlying resource and only exposes such references. Rust ensures that the guard cannot outlive the underlying resource and that references to the resource mediated by the guard cannot outlive the guard. To see how this works it is helpful to examine the signature of `deref` without lifetime elision: ```rust,ignore fn deref<'a>(&'a self) -> &'a T { //.. } ``` The returned reference to the resource has the same lifetime as `self` (`'a`). The borrow checker therefore ensures that the lifetime of the reference to `T` is shorter than the lifetime of `self`. Note that implementing `Deref` is not a core part of this pattern, it only makes using the guard object more ergonomic. Implementing a `get` method on the guard works just as well. ## See also [Finalisation in destructors idiom](../../idioms/dtor-finally.md) RAII is a common pattern in C++: [cppreference.com](http://en.cppreference.com/w/cpp/language/raii), [wikipedia][wikipedia]. [wikipedia]: https://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization [Style guide entry](https://doc.rust-lang.org/1.0.0/style/ownership/raii.html) (currently just a placeholder). ================================================ FILE: src/patterns/behavioural/command.md ================================================ # Command ## Description The basic idea of the Command pattern is to separate out actions into its own objects and pass them as parameters. ## Motivation Suppose we have a sequence of actions or transactions encapsulated as objects. We want these actions or commands to be executed or invoked in some order later at different time. These commands may also be triggered as a result of some event. For example, when a user pushes a button, or on arrival of a data packet. In addition, these commands might be undoable. This may come in useful for operations of an editor. We might want to store logs of executed commands so that we could reapply the changes later if the system crashes. ## Example Define two database operations `create table` and `add field`. Each of these operations is a command which knows how to undo the command, e.g., `drop table` and `remove field`. When a user invokes a database migration operation then each command is executed in the defined order, and when the user invokes the rollback operation then the whole set of commands is invoked in reverse order. ## Approach: Using trait objects We define a common trait which encapsulates our command with two operations `execute` and `rollback`. All command `structs` must implement this trait. ```rust pub trait Migration { fn execute(&self) -> &str; fn rollback(&self) -> &str; } pub struct CreateTable; impl Migration for CreateTable { fn execute(&self) -> &str { "create table" } fn rollback(&self) -> &str { "drop table" } } pub struct AddField; impl Migration for AddField { fn execute(&self) -> &str { "add field" } fn rollback(&self) -> &str { "remove field" } } struct Schema { commands: Vec>, } impl Schema { fn new() -> Self { Self { commands: vec![] } } fn add_migration(&mut self, cmd: Box) { self.commands.push(cmd); } fn execute(&self) -> Vec<&str> { self.commands.iter().map(|cmd| cmd.execute()).collect() } fn rollback(&self) -> Vec<&str> { self.commands .iter() .rev() // reverse iterator's direction .map(|cmd| cmd.rollback()) .collect() } } fn main() { let mut schema = Schema::new(); let cmd = Box::new(CreateTable); schema.add_migration(cmd); let cmd = Box::new(AddField); schema.add_migration(cmd); assert_eq!(vec!["create table", "add field"], schema.execute()); assert_eq!(vec!["remove field", "drop table"], schema.rollback()); } ``` ## Approach: Using function pointers We could follow another approach by creating each individual command as a different function and store function pointers to invoke these functions later at a different time. Since function pointers implement all three traits `Fn`, `FnMut`, and `FnOnce` we could as well pass and store closures instead of function pointers. ```rust type FnPtr = fn() -> String; struct Command { execute: FnPtr, rollback: FnPtr, } struct Schema { commands: Vec, } impl Schema { fn new() -> Self { Self { commands: vec![] } } fn add_migration(&mut self, execute: FnPtr, rollback: FnPtr) { self.commands.push(Command { execute, rollback }); } fn execute(&self) -> Vec { self.commands.iter().map(|cmd| (cmd.execute)()).collect() } fn rollback(&self) -> Vec { self.commands .iter() .rev() .map(|cmd| (cmd.rollback)()) .collect() } } fn add_field() -> String { "add field".to_string() } fn remove_field() -> String { "remove field".to_string() } fn main() { let mut schema = Schema::new(); schema.add_migration(|| "create table".to_string(), || "drop table".to_string()); schema.add_migration(add_field, remove_field); assert_eq!(vec!["create table", "add field"], schema.execute()); assert_eq!(vec!["remove field", "drop table"], schema.rollback()); } ``` ## Approach: Using `Fn` trait objects Finally, instead of defining a common command trait we could store each command implementing the `Fn` trait separately in vectors. ```rust type Migration<'a> = Box &'a str>; struct Schema<'a> { executes: Vec>, rollbacks: Vec>, } impl<'a> Schema<'a> { fn new() -> Self { Self { executes: vec![], rollbacks: vec![], } } fn add_migration(&mut self, execute: E, rollback: R) where E: Fn() -> &'a str + 'static, R: Fn() -> &'a str + 'static, { self.executes.push(Box::new(execute)); self.rollbacks.push(Box::new(rollback)); } fn execute(&self) -> Vec<&str> { self.executes.iter().map(|cmd| cmd()).collect() } fn rollback(&self) -> Vec<&str> { self.rollbacks.iter().rev().map(|cmd| cmd()).collect() } } fn add_field() -> &'static str { "add field" } fn remove_field() -> &'static str { "remove field" } fn main() { let mut schema = Schema::new(); schema.add_migration(|| "create table", || "drop table"); schema.add_migration(add_field, remove_field); assert_eq!(vec!["create table", "add field"], schema.execute()); assert_eq!(vec!["remove field", "drop table"], schema.rollback()); } ``` ## Discussion If our commands are small and may be defined as functions or passed as a closure then using function pointers might be preferable since it does not exploit dynamic dispatch. But if our command is a whole struct with a bunch of functions and variables defined as separated module then using trait objects would be more suitable. A case of application can be found in [`actix`](https://actix.rs/), which uses trait objects when it registers a handler function for routes. In case of using `Fn` trait objects we can create and use commands in the same way as we used in case of function pointers. As performance, there is always a trade-off between performance and code simplicity and organisation. Static dispatch gives faster performance, while dynamic dispatch provides flexibility when we structure our application. ## See also - [Command pattern](https://en.wikipedia.org/wiki/Command_pattern) - [Another example for the `command` pattern](https://web.archive.org/web/20210223131236/https://chercher.tech/rust/command-design-pattern-rust) ================================================ FILE: src/patterns/behavioural/interpreter.md ================================================ # Interpreter ## Description If a problem occurs very often and requires long and repetitive steps to solve it, then the problem instances might be expressed in a simple language and an interpreter object could solve it by interpreting the sentences written in this simple language. Basically, for any kind of problems we define: - A [domain specific language](https://en.wikipedia.org/wiki/Domain-specific_language), - A grammar for this language, - An interpreter that solves the problem instances. ## Motivation Our goal is to translate simple mathematical expressions into postfix expressions (or [Reverse Polish notation](https://en.wikipedia.org/wiki/Reverse_Polish_notation)) For simplicity, our expressions consist of ten digits `0`, ..., `9` and two operations `+`, `-`. For example, the expression `2 + 4` is translated into `2 4 +`. ## Context Free Grammar for our problem Our task is translating infix expressions into postfix ones. Let's define a context free grammar for a set of infix expressions over `0`, ..., `9`, `+`, and `-`, where: - Terminal symbols: `0`, `...`, `9`, `+`, `-` - Non-terminal symbols: `exp`, `term` - Start symbol is `exp` - And the following are production rules ```ignore exp -> exp + term exp -> exp - term exp -> term term -> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ``` **NOTE:** This grammar should be further transformed depending on what we are going to do with it. For example, we might need to remove left recursion. For more details please see [Compilers: Principles,Techniques, and Tools](https://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools) (aka Dragon Book). ## Solution We simply implement a recursive descent parser. For simplicity's sake, the code panics when an expression is syntactically wrong (for example `2-34` or `2+5-` are wrong according to the grammar definition). ```rust pub struct Interpreter<'a> { it: std::str::Chars<'a>, } impl<'a> Interpreter<'a> { pub fn new(infix: &'a str) -> Self { Self { it: infix.chars() } } fn next_char(&mut self) -> Option { self.it.next() } pub fn interpret(&mut self, out: &mut String) { self.term(out); while let Some(op) = self.next_char() { if op == '+' || op == '-' { self.term(out); out.push(op); } else { panic!("Unexpected symbol '{op}'"); } } } fn term(&mut self, out: &mut String) { match self.next_char() { Some(ch) if ch.is_digit(10) => out.push(ch), Some(ch) => panic!("Unexpected symbol '{ch}'"), None => panic!("Unexpected end of string"), } } } pub fn main() { let mut intr = Interpreter::new("2+3"); let mut postfix = String::new(); intr.interpret(&mut postfix); assert_eq!(postfix, "23+"); intr = Interpreter::new("1-2+3-4"); postfix.clear(); intr.interpret(&mut postfix); assert_eq!(postfix, "12-3+4-"); } ``` ## Discussion There may be a wrong perception that the Interpreter design pattern is about design grammars for formal languages and implementation of parsers for these grammars. In fact, this pattern is about expressing problem instances in a more specific way and implementing functions/classes/structs that solve these problem instances. Rust language has `macro_rules!` that allow us to define special syntax and rules on how to expand this syntax into source code. In the following example we create a simple `macro_rules!` that computes [Euclidean length](https://en.wikipedia.org/wiki/Euclidean_distance) of `n` dimensional vectors. Writing `norm!(x,1,2)` might be easier to express and more efficient than packing `x,1,2` into a `Vec` and calling a function computing the length. ```rust macro_rules! norm { ($($element:expr),*) => { { let mut n = 0.0; $( n += ($element as f64)*($element as f64); )* n.sqrt() } }; } fn main() { let x = -3f64; let y = 4f64; assert_eq!(3f64, norm!(x)); assert_eq!(5f64, norm!(x, y)); assert_eq!(0f64, norm!(0, 0, 0)); assert_eq!(1f64, norm!(0.5, -0.5, 0.5, -0.5)); } ``` ## See also - [Interpreter pattern](https://en.wikipedia.org/wiki/Interpreter_pattern) - [Context free grammar](https://en.wikipedia.org/wiki/Context-free_grammar) - [macro_rules!](https://doc.rust-lang.org/rust-by-example/macros.html) ================================================ FILE: src/patterns/behavioural/intro.md ================================================ # Behavioural Patterns From [Wikipedia](https://en.wikipedia.org/wiki/Behavioral_pattern): > Design patterns that identify common communication patterns among objects. By > doing so, these patterns increase flexibility in carrying out communication. ================================================ FILE: src/patterns/behavioural/newtype.md ================================================ # Newtype What if in some cases we want a type to behave similar to another type or enforce some behaviour at compile time when using only type aliases would not be enough? For example, if we want to create a custom `Display` implementation for `String` due to security considerations (e.g. passwords). For such cases we could use the `Newtype` pattern to provide **type safety** and **encapsulation**. ## Description Use a tuple struct with a single field to make an opaque wrapper for a type. This creates a new type, rather than an alias to a type (`type` items). ## Example ```rust use std::fmt::Display; // Create Newtype Password to override the Display trait for String struct Password(String); impl Display for Password { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "****************") } } fn main() { let unsecured_password: String = "ThisIsMyPassword".to_string(); let secured_password: Password = Password(unsecured_password.clone()); println!("unsecured_password: {unsecured_password}"); println!("secured_password: {secured_password}"); } ``` ```shell unsecured_password: ThisIsMyPassword secured_password: **************** ``` ## Motivation The primary motivation for newtypes is abstraction. It allows you to share implementation details between types while precisely controlling the interface. By using a newtype rather than exposing the implementation type as part of an API, it allows you to change implementation backwards compatibly. Newtypes can be used for distinguishing units, e.g., wrapping `f64` to give distinguishable `Miles` and `Kilometres`. ## Advantages The wrapped and wrapper types are not type compatible (as opposed to using `type`), so users of the newtype will never 'confuse' the wrapped and wrapper types. Newtypes are a zero-cost abstraction - there is no runtime overhead. The privacy system ensures that users cannot access the wrapped type (if the field is private, which it is by default). ## Disadvantages The downside of newtypes (especially compared with type aliases), is that there is no special language support. This means there can be *a lot* of boilerplate. You need a 'pass through' method for every method you want to expose on the wrapped type, and an impl for every trait you want to also be implemented for the wrapper type. ## Discussion Newtypes are very common in Rust code. Abstraction or representing units are the most common uses, but they can be used for other reasons: - restricting functionality (reduce the functions exposed or traits implemented), - making a type with copy semantics have move semantics, - abstraction by providing a more concrete type and thus hiding internal types, e.g., ```rust,ignore pub struct Foo(Bar); ``` Here, `Bar` might be some public, generic type and `T1` and `T2` are some internal types. Users of our module shouldn't know that we implement `Foo` by using a `Bar`, but what we're really hiding here is the types `T1` and `T2`, and how they are used with `Bar`. ## See also - [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) - [Newtypes in Haskell](https://wiki.haskell.org/Newtype) - [Type aliases](https://doc.rust-lang.org/stable/book/ch19-04-advanced-types.html#creating-type-synonyms-with-type-aliases) - [derive_more](https://crates.io/crates/derive_more), a crate for deriving many builtin traits on newtypes. - [The Newtype Pattern In Rust](https://web.archive.org/web/20230519162111/https://www.worthe-it.co.za/blog/2020-10-31-newtype-pattern-in-rust.html) ================================================ FILE: src/patterns/behavioural/strategy.md ================================================ # Strategy (aka Policy) ## Description The [Strategy design pattern](https://en.wikipedia.org/wiki/Strategy_pattern) is a technique that enables separation of concerns. It also allows to decouple software modules through [Dependency Inversion](https://en.wikipedia.org/wiki/Dependency_inversion_principle). The basic idea behind the Strategy pattern is that, given an algorithm solving a particular problem, we define only the skeleton of the algorithm at an abstract level, and we separate the specific algorithm’s implementation into different parts. In this way, a client using the algorithm may choose a specific implementation, while the general algorithm workflow remains the same. In other words, the abstract specification of the class does not depend on the specific implementation of the derived class, but specific implementation must adhere to the abstract specification. This is why we call it "Dependency Inversion". ## Motivation Imagine we are working on a project that generates reports every month. We need the reports to be generated in different formats (strategies), e.g., in `JSON` or `Plain Text` formats. But things vary over time, and we don't know what kind of requirement we may get in the future. For example, we may need to generate our report in a completely new format, or just modify one of the existing formats. ## Example In this example our invariants (or abstractions) are `Formatter` and `Report`, while `Text` and `Json` are our strategy structs. These strategies have to implement the `Formatter` trait. ```rust use std::collections::HashMap; type Data = HashMap; trait Formatter { fn format(&self, data: &Data, buf: &mut String); } struct Report; impl Report { // Write should be used but we kept it as String to ignore error handling fn generate(g: T, s: &mut String) { // backend operations... let mut data = HashMap::new(); data.insert("one".to_string(), 1); data.insert("two".to_string(), 2); // generate report g.format(&data, s); } } struct Text; impl Formatter for Text { fn format(&self, data: &Data, buf: &mut String) { for (k, v) in data { let entry = format!("{k} {v}\n"); buf.push_str(&entry); } } } struct Json; impl Formatter for Json { fn format(&self, data: &Data, buf: &mut String) { buf.push('['); for (k, v) in data.into_iter() { let entry = format!(r#"{{"{}":"{}"}}"#, k, v); buf.push_str(&entry); buf.push(','); } if !data.is_empty() { buf.pop(); // remove extra , at the end } buf.push(']'); } } fn main() { let mut s = String::from(""); Report::generate(Text, &mut s); assert!(s.contains("one 1")); assert!(s.contains("two 2")); s.clear(); // reuse the same buffer Report::generate(Json, &mut s); assert!(s.contains(r#"{"one":"1"}"#)); assert!(s.contains(r#"{"two":"2"}"#)); } ``` ## Advantages The main advantage is separation of concerns. For example, in this case `Report` does not know anything about specific implementations of `Json` and `Text`, whereas the output implementations does not care about how data is preprocessed, stored, and fetched. The only thing they have to know is a specific trait to implement and its method defining the concrete algorithm implementation processing the result, i.e., `Formatter` and `format(...)`. ## Disadvantages For each strategy there must be implemented at least one module, so number of modules increases with number of strategies. If there are many strategies to choose from then users have to know how strategies differ from one another. ## Discussion In the previous example all strategies are implemented in a single file. Ways of providing different strategies includes: - All in one file (as shown in this example, similar to being separated as modules) - Separated as modules, E.g. `formatter::json` module, `formatter::text` module - Use compiler feature flags, E.g. `json` feature, `text` feature - Separated as crates, E.g. `json` crate, `text` crate Serde crate is a good example of the `Strategy` pattern in action. Serde allows [full customization](https://serde.rs/custom-serialization.html) of the serialization behavior by manually implementing `Serialize` and `Deserialize` traits for our type. For example, we could easily swap `serde_json` with `serde_cbor` since they expose similar methods. Having this makes the helper crate `serde_transcode` much more useful and ergonomic. However, we don't need to use traits in order to design this pattern in Rust. The following toy example demonstrates the idea of the Strategy pattern using Rust `closures`: ```rust struct Adder; impl Adder { pub fn add(x: u8, y: u8, f: F) -> u8 where F: Fn(u8, u8) -> u8, { f(x, y) } } fn main() { let arith_adder = |x, y| x + y; let bool_adder = |x, y| { if x == 1 || y == 1 { 1 } else { 0 } }; let custom_adder = |x, y| 2 * x + y; assert_eq!(9, Adder::add(4, 5, arith_adder)); assert_eq!(0, Adder::add(0, 0, bool_adder)); assert_eq!(5, Adder::add(1, 3, custom_adder)); } ``` In fact, Rust already uses this idea for `Options`'s `map` method: ```rust fn main() { let val = Some("Rust"); let len_strategy = |s: &str| s.len(); assert_eq!(4, val.map(len_strategy).unwrap()); let first_byte_strategy = |s: &str| s.bytes().next().unwrap(); assert_eq!(82, val.map(first_byte_strategy).unwrap()); } ``` ## See also - [Strategy Pattern](https://en.wikipedia.org/wiki/Strategy_pattern) - [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) - [Policy Based Design](https://en.wikipedia.org/wiki/Modern_C++_Design#Policy-based_design) - [Implementing a TCP server for Space Applications in Rust using the Strategy Pattern](https://web.archive.org/web/20231003171500/https://robamu.github.io/posts/rust-strategy-pattern/) ================================================ FILE: src/patterns/behavioural/visitor.md ================================================ # Visitor ## Description A visitor encapsulates an algorithm that operates over a heterogeneous collection of objects. It allows multiple different algorithms to be written over the same data without having to modify the data (or their primary behaviour). Furthermore, the visitor pattern allows separating the traversal of a collection of objects from the operations performed on each object. ## Example ```rust,ignore // The data we will visit mod ast { pub enum Stmt { Expr(Expr), Let(Name, Expr), } pub struct Name { value: String, } pub enum Expr { IntLit(i64), Add(Box, Box), Sub(Box, Box), } } // The abstract visitor mod visit { use ast::*; pub trait Visitor { fn visit_name(&mut self, n: &Name) -> T; fn visit_stmt(&mut self, s: &Stmt) -> T; fn visit_expr(&mut self, e: &Expr) -> T; } } use ast::*; use visit::*; // An example concrete implementation - walks the AST interpreting it as code. struct Interpreter; impl Visitor for Interpreter { fn visit_name(&mut self, n: &Name) -> i64 { panic!() } fn visit_stmt(&mut self, s: &Stmt) -> i64 { match *s { Stmt::Expr(ref e) => self.visit_expr(e), Stmt::Let(..) => unimplemented!(), } } fn visit_expr(&mut self, e: &Expr) -> i64 { match *e { Expr::IntLit(n) => n, Expr::Add(ref lhs, ref rhs) => self.visit_expr(lhs) + self.visit_expr(rhs), Expr::Sub(ref lhs, ref rhs) => self.visit_expr(lhs) - self.visit_expr(rhs), } } } ``` One could implement further visitors, for example a type checker, without having to modify the AST data. ## Motivation The visitor pattern is useful anywhere that you want to apply an algorithm to heterogeneous data. If data is homogeneous, you can use an iterator-like pattern. Using a visitor object (rather than a functional approach) allows the visitor to be stateful and thus communicate information between nodes. ## Discussion It is common for the `visit_*` methods to return void (as opposed to in the example). In that case it is possible to factor out the traversal code and share it between algorithms (and also to provide noop default methods). In Rust, the common way to do this is to provide `walk_*` functions for each datum. For example, ```rust,ignore pub fn walk_expr(visitor: &mut Visitor, e: &Expr) { match *e { Expr::IntLit(_) => {} Expr::Add(ref lhs, ref rhs) => { visitor.visit_expr(lhs); visitor.visit_expr(rhs); } Expr::Sub(ref lhs, ref rhs) => { visitor.visit_expr(lhs); visitor.visit_expr(rhs); } } } ``` In other languages (e.g., Java) it is common for data to have an `accept` method which performs the same duty. ## See also The visitor pattern is a common pattern in most OO languages. [Wikipedia article](https://en.wikipedia.org/wiki/Visitor_pattern) The [fold](../creational/fold.md) pattern is similar to visitor but produces a new version of the visited data structure. ================================================ FILE: src/patterns/creational/builder.md ================================================ # Builder ## Description Construct an object with calls to a builder helper. ## Example ```rust #[derive(Debug, PartialEq)] pub struct Foo { // Lots of complicated fields. bar: String, } impl Foo { // This method will help users to discover the builder pub fn builder() -> FooBuilder { FooBuilder::default() } } #[derive(Default)] pub struct FooBuilder { // Probably lots of optional fields. bar: String, } impl FooBuilder { pub fn new(/* ... */) -> FooBuilder { // Set the minimally required fields of Foo. FooBuilder { bar: String::from("X"), } } pub fn name(mut self, bar: String) -> FooBuilder { // Set the name on the builder itself, and return the builder by value. self.bar = bar; self } // If we can get away with not consuming the Builder here, that is an // advantage. It means we can use the FooBuilder as a template for constructing // many Foos. pub fn build(self) -> Foo { // Create a Foo from the FooBuilder, applying all settings in FooBuilder // to Foo. Foo { bar: self.bar } } } #[test] fn builder_test() { let foo = Foo { bar: String::from("Y"), }; let foo_from_builder: Foo = FooBuilder::new().name(String::from("Y")).build(); assert_eq!(foo, foo_from_builder); } ``` ## Motivation Useful when you would otherwise require many constructors or where construction has side effects. ## Advantages Separates methods for building from other methods. Prevents proliferation of constructors. Can be used for one-liner initialisation as well as more complex construction. When you add new fields to the target struct, you can update the builder to leave client code backwards compatible. ## Disadvantages More complex than creating a struct object directly, or a simple constructor function. ## Discussion This pattern is seen more frequently in Rust (and for simpler objects) than in many other languages because Rust lacks overloading and default values for function parameters. Since you can only have a single method with a given name, having multiple constructors is less nice in Rust than in C++, Java, or others. This pattern is often used where the builder object is useful in its own right, rather than being just a builder. For example, see [`std::process::Command`](https://doc.rust-lang.org/std/process/struct.Command.html) is a builder for [`Child`](https://doc.rust-lang.org/std/process/struct.Child.html) (a process). In these cases, the `T` and `TBuilder` naming pattern is not used. The example takes and returns the builder by value. It is often more ergonomic (and more efficient) to take and return the builder as a mutable reference. The borrow checker makes this work naturally. This approach has the advantage that one can write code like ```rust,ignore let mut fb = FooBuilder::new(); fb.a(); fb.b(); let f = fb.build(); ``` as well as the `FooBuilder::new().a().b().build()` style. ## See also - [Description in the style guide](https://web.archive.org/web/20210104103100/https://doc.rust-lang.org/1.12.0/style/ownership/builders.html) - [derive_builder](https://crates.io/crates/derive_builder), a crate for automatically implementing this pattern while avoiding the boilerplate. - [Constructor pattern](../../idioms/ctor.md) for when construction is simpler. - [Builder pattern (wikipedia)](https://en.wikipedia.org/wiki/Builder_pattern) - [Construction of complex values](https://web.archive.org/web/20210104103000/https://rust-lang.github.io/api-guidelines/type-safety.html#c-builder) ================================================ FILE: src/patterns/creational/fold.md ================================================ # Fold ## Description Run an algorithm over each item in a collection of data to create a new item, thus creating a whole new collection. The etymology here is unclear to me. The terms 'fold' and 'folder' are used in the Rust compiler, although it appears to me to be more like a map than a fold in the usual sense. See the discussion below for more details. ## Example ```rust,ignore // The data we will fold, a simple AST. mod ast { pub enum Stmt { Expr(Box), Let(Box, Box), } pub struct Name { value: String, } pub enum Expr { IntLit(i64), Add(Box, Box), Sub(Box, Box), } } // The abstract folder mod fold { use ast::*; pub trait Folder { // A leaf node just returns the node itself. In some cases, we can do this // to inner nodes too. fn fold_name(&mut self, n: Box) -> Box { n } // Create a new inner node by folding its children. fn fold_stmt(&mut self, s: Box) -> Box { match *s { Stmt::Expr(e) => Box::new(Stmt::Expr(self.fold_expr(e))), Stmt::Let(n, e) => Box::new(Stmt::Let(self.fold_name(n), self.fold_expr(e))), } } fn fold_expr(&mut self, e: Box) -> Box { ... } } } use fold::*; use ast::*; // An example concrete implementation - renames every name to 'foo'. struct Renamer; impl Folder for Renamer { fn fold_name(&mut self, n: Box) -> Box { Box::new(Name { value: "foo".to_owned() }) } // Use the default methods for the other nodes. } ``` The result of running the `Renamer` on an AST is a new AST identical to the old one, but with every name changed to `foo`. A real life folder might have some state preserved between nodes in the struct itself. A folder can also be defined to map one data structure to a different (but usually similar) data structure. For example, we could fold an AST into a HIR tree (HIR stands for high-level intermediate representation). ## Motivation It is common to want to map a data structure by performing some operation on each node in the structure. For simple operations on simple data structures, this can be done using `Iterator::map`. For more complex operations, perhaps where earlier nodes can affect the operation on later nodes, or where iteration over the data structure is non-trivial, using the fold pattern is more appropriate. Like the visitor pattern, the fold pattern allows us to separate traversal of a data structure from the operations performed to each node. ## Discussion Mapping data structures in this fashion is common in functional languages. In OO languages, it would be more common to mutate the data structure in place. The 'functional' approach is common in Rust, mostly due to the preference for immutability. Using fresh data structures, rather than mutating old ones, makes reasoning about the code easier in most circumstances. The trade-off between efficiency and reusability can be tweaked by changing how nodes are accepted by the `fold_*` methods. In the above example we operate on `Box` pointers. Since these own their data exclusively, the original copy of the data structure cannot be re-used. On the other hand if a node is not changed, reusing it is very efficient. If we were to operate on borrowed references, the original data structure can be reused; however, a node must be cloned even if unchanged, which can be expensive. Using a reference counted pointer gives the best of both worlds - we can reuse the original data structure, and we don't need to clone unchanged nodes. However, they are less ergonomic to use and mean that the data structures cannot be mutable. ## See also Iterators have a `fold` method, however this folds a data structure into a value, rather than into a new data structure. An iterator's `map` is more like this fold pattern. In other languages, fold is usually used in the sense of Rust's iterators, rather than this pattern. Some functional languages have powerful constructs for performing flexible maps over data structures. The [visitor](../behavioural/visitor.md) pattern is closely related to fold. They share the concept of walking a data structure performing an operation on each node. However, the visitor does not create a new data structure nor consume the old one. ================================================ FILE: src/patterns/creational/intro.md ================================================ # Creational Patterns From [Wikipedia](https://en.wikipedia.org/wiki/Creational_pattern): > Design patterns that deal with object creation mechanisms, trying to create > objects in a manner suitable to the situation. The basic form of object > creation could result in design problems or in added complexity to the design. > Creational design patterns solve this problem by somehow controlling this > object creation. ================================================ FILE: src/patterns/ffi/export.md ================================================ # Object-Based APIs ## Description When designing APIs in Rust which are exposed to other languages, there are some important design principles which are contrary to normal Rust API design: 1. All Encapsulated types should be *owned* by Rust, *managed* by the user, and *opaque*. 2. All Transactional data types should be *owned* by the user, and *transparent*. 3. All library behavior should be functions acting upon Encapsulated types. 4. All library behavior should be encapsulated into types not based on structure, but *provenance/lifetime*. ## Motivation Rust has built-in FFI support to other languages. It does this by providing a way for crate authors to provide C-compatible APIs through different ABIs (though that is unimportant to this practice). Well-designed Rust FFI follows C API design principles, while compromising the design in Rust as little as possible. There are three goals with any foreign API: 1. Make it easy to use in the target language. 2. Avoid the API dictating internal unsafety on the Rust side as much as possible. 3. Keep the potential for memory unsafety and Rust `undefined behaviour` as small as possible. Rust code must trust the memory safety of the foreign language beyond a certain point. However, every bit of `unsafe` code on the Rust side is an opportunity for bugs, or to exacerbate `undefined behaviour`. For example, if a pointer provenance is wrong, that may be a segfault due to invalid memory access. But if it is manipulated by unsafe code, it could become full-blown heap corruption. The Object-Based API design allows for writing shims that have good memory safety characteristics, and a clean boundary of what is safe and what is `unsafe`. ## Code Example 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). It is an excellent example of an "object-based" API. Here is the definition in C, which hopefully should be easy to read for those involved in FFI. The commentary below should help explain it for those who miss the subtleties. ```C struct DBM; typedef struct { void *dptr, size_t dsize } datum; int dbm_clearerr(DBM *); void dbm_close(DBM *); int dbm_delete(DBM *, datum); int dbm_error(DBM *); datum dbm_fetch(DBM *, datum); datum dbm_firstkey(DBM *); datum dbm_nextkey(DBM *); DBM *dbm_open(const char *, int, mode_t); int dbm_store(DBM *, datum, datum, int); ``` This API defines two types: `DBM` and `datum`. The `DBM` type was called an "encapsulated" type above. It is designed to contain internal state, and acts as an entry point for the library's behavior. It is completely opaque to the user, who cannot create a `DBM` themselves since they don't know its size or layout. Instead, they must call `dbm_open`, and that only gives them *a pointer to one*. This means all `DBM`s are "owned" by the library in a Rust sense. The internal state of unknown size is kept in memory controlled by the library, not the user. The user can only manage its life cycle with `open` and `close`, and perform operations on it with the other functions. The `datum` type was called a "transactional" type above. It is designed to facilitate the exchange of information between the library and its user. The database is designed to store "unstructured data", with no pre-defined length or meaning. As a result, the `datum` is the C equivalent of a Rust slice: a bunch of bytes, and a count of how many there are. The main difference is that there is no type information, which is what `void` indicates. Keep in mind that this header is written from the library's point of view. The user likely has some type they are using, which has a known size. But the library does not care, and by the rules of C casting, any type behind a pointer can be cast to `void`. As noted earlier, this type is *transparent* to the user. But also, this type is *owned* by the user. This has subtle ramifications, due to that pointer inside it. The question is, who owns the memory that pointer points to? The answer for best memory safety is, "the user". But in cases such as retrieving a value, the user does not know how to allocate it correctly (since they don't know how long the value is). In this case, the library code is expected to use the heap that the user has access to -- such as the C library `malloc` and `free` -- and then *transfer ownership* in the Rust sense. This may all seem speculative, but this is what a pointer means in C. It means the same thing as Rust: "user defined lifetime." The user of the library needs to read the documentation in order to use it correctly. That said, there are some decisions that have fewer or greater consequences if users do it wrong. Minimizing those are what this best practice is about, and the key is to *transfer ownership of everything that is transparent*. ## Advantages This minimizes the number of memory safety guarantees the user must uphold to a relatively small number: 1. Do not call any function with a pointer not returned by `dbm_open` (invalid access or corruption). 2. Do not call any function on a pointer after close (use after free). 3. The `dptr` on any `datum` must be `NULL`, or point to a valid slice of memory at the advertised length. In addition, it avoids a lot of pointer provenance issues. To understand why, let us consider an alternative in some depth: key iteration. Rust is well known for its iterators. When implementing one, the programmer makes a separate type with a bounded lifetime to its owner, and implements the `Iterator` trait. Here is how iteration would be done in Rust for `DBM`: ```rust,ignore struct Dbm { ... } impl Dbm { /* ... */ pub fn keys<'it>(&'it self) -> DbmKeysIter<'it> { ... } /* ... */ } struct DbmKeysIter<'it> { owner: &'it Dbm, } impl<'it> Iterator for DbmKeysIter<'it> { ... } ``` This is clean, idiomatic, and safe. thanks to Rust's guarantees. However, consider what a straightforward API translation would look like: ```rust,ignore #[no_mangle] pub extern "C" fn dbm_iter_new(owner: *const Dbm) -> *mut DbmKeysIter { // THIS API IS A BAD IDEA! For real applications, use object-based design instead. } #[no_mangle] pub extern "C" fn dbm_iter_next( iter: *mut DbmKeysIter, key_out: *const datum ) -> libc::c_int { // THIS API IS A BAD IDEA! For real applications, use object-based design instead. } #[no_mangle] pub extern "C" fn dbm_iter_del(*mut DbmKeysIter) { // THIS API IS A BAD IDEA! For real applications, use object-based design instead. } ``` This API loses a key piece of information: the lifetime of the iterator must not exceed the lifetime of the `Dbm` object that owns it. A user of the library could use it in a way which causes the iterator to outlive the data it is iterating on, resulting in reading uninitialized memory. This example written in C contains a bug that will be explained afterwards: ```C int count_key_sizes(DBM *db) { // DO NOT USE THIS FUNCTION. IT HAS A SUBTLE BUT SERIOUS BUG! datum key; int len = 0; if (!dbm_iter_new(db)) { dbm_close(db); return -1; } int l; while ((l = dbm_iter_next(owner, &key)) >= 0) { // an error is indicated by -1 free(key.dptr); len += key.dsize; if (l == 0) { // end of the iterator dbm_close(owner); } } if l >= 0 { return -1; } else { return len; } } ``` This bug is a classic. Here's what happens when the iterator returns the end-of-iteration marker: 1. The loop condition sets `l` to zero, and enters the loop because `0 >= 0`. 2. The length is incremented, in this case by zero. 3. The if statement is true, so the database is closed. There should be a break statement here. 4. The loop condition executes again, causing a `next` call on the closed object. The worst part about this bug? If the Rust implementation was careful, this code will work most of the time! If the memory for the `Dbm` object is not immediately reused, an internal check will almost certainly fail, resulting in the iterator returning a `-1` indicating an error. But occasionally, it will cause a segmentation fault, or even worse, nonsensical memory corruption! None of this can be avoided by Rust. From its perspective, it put those objects on its heap, returned pointers to them, and gave up control of their lifetimes. The C code simply must "play nice". The programmer must read and understand the API documentation. While some consider that par for the course in C, a good API design can mitigate this risk. The POSIX API for `DBM` did this by *consolidating the ownership* of the iterator with its parent: ```C datum dbm_firstkey(DBM *); datum dbm_nextkey(DBM *); ``` Thus, all the lifetimes were bound together, and such unsafety was prevented. ## Disadvantages However, this design choice also has a number of drawbacks, which should be considered as well. First, the API itself becomes less expressive. With POSIX DBM, there is only one iterator per object, and every call changes its state. This is much more restrictive than iterators in almost any language, even though it is safe. Perhaps with other related objects, whose lifetimes are less hierarchical, this limitation is more of a cost than the safety. Second, depending on the relationships of the API's parts, significant design effort may be involved. Many of the easier design points have other patterns associated with them: - [Wrapper Type Consolidation](./wrappers.md) groups multiple Rust types together into an opaque "object" - [FFI Error Passing](../../idioms/ffi/errors.md) explains error handling with integer codes and sentinel return values (such as `NULL` pointers) - [Accepting Foreign Strings](../../idioms/ffi/accepting-strings.md) allows accepting strings with minimal unsafe code, and is easier to get right than [Passing Strings to FFI](../../idioms/ffi/passing-strings.md) However, not every API can be done this way. It is up to the best judgement of the programmer as to who their audience is. ================================================ FILE: src/patterns/ffi/intro.md ================================================ # FFI Patterns Writing FFI code is an entire course in itself. However, there are several idioms here that can act as pointers, and avoid traps for inexperienced users of unsafe Rust. This section contains design patterns that may be useful when doing FFI. 1. [Object-Based API](./export.md) design that has good memory safety characteristics, and a clean boundary of what is safe and what is unsafe 2. [Type Consolidation into Wrappers](./wrappers.md) - group multiple Rust types together into an opaque "object" ================================================ FILE: src/patterns/ffi/wrappers.md ================================================ # Type Consolidation into Wrappers ## Description This pattern is designed to allow gracefully handling multiple related types, while minimizing the surface area for memory unsafety. One of the cornerstones of Rust's aliasing rules is lifetimes. This ensures that many patterns of access between types can be memory safe, data race safety included. However, when Rust types are exported to other languages, they are usually transformed into pointers. In Rust, a pointer means "the user manages the lifetime of the pointee." It is their responsibility to avoid memory unsafety. Some level of trust in the user code is thus required, notably around use-after-free which Rust can do nothing about. However, some API designs place higher burdens than others on the code written in the other language. The lowest risk API is the "consolidated wrapper", where all possible interactions with an object are folded into a "wrapper type", while keeping the Rust API clean. ## Code Example To understand this, let us look at a classic example of an API to export: iteration through a collection. That API looks like this: 1. The iterator is initialized with `first_key`. 2. Each call to `next_key` will advance the iterator. 3. Calls to `next_key` if the iterator is at the end will do nothing. 4. As noted above, the iterator is "wrapped into" the collection (unlike the native Rust API). If the iterator implements `nth()` efficiently, then it is possible to make it ephemeral to each function call: ```rust,ignore struct MySetWrapper { myset: MySet, iter_next: usize, } impl MySetWrapper { pub fn first_key(&mut self) -> Option<&Key> { self.iter_next = 0; self.next_key() } pub fn next_key(&mut self) -> Option<&Key> { if let Some(next) = self.myset.keys().nth(self.iter_next) { self.iter_next += 1; Some(next) } else { None } } } ``` As a result, the wrapper is simple and contains no `unsafe` code. ## Advantages This makes APIs safer to use, avoiding issues with lifetimes between types. See [Object-Based APIs](./export.md) for more on the advantages and pitfalls this avoids. ## Disadvantages Often, wrapping types is quite difficult, and sometimes a Rust API compromise would make things easier. As an example, consider an iterator which does not efficiently implement `nth()`. It would definitely be worth putting in special logic to make the object handle iteration internally, or to support a different access pattern efficiently that only the Foreign Function API will use. ### Trying to Wrap Iterators (and Failing) To wrap any type of iterator into the API correctly, the wrapper would need to do what a C version of the code would do: erase the lifetime of the iterator, and manage it manually. Suffice it to say, this is *incredibly* difficult. Here is an illustration of just *one* pitfall. A first version of `MySetWrapper` would look like this: ```rust,ignore struct MySetWrapper { myset: MySet, iter_next: usize, // created from a transmuted Box iterator: Option>>, } ``` With `transmute` being used to extend a lifetime, and a pointer to hide it, it's ugly already. But it gets even worse: *any other operation can cause Rust `undefined behaviour`*. Consider that the `MySet` in the wrapper could be manipulated by other functions during iteration, such as storing a new value to the key it was iterating over. The API doesn't discourage this, and in fact some similar C libraries expect it. A simple implementation of `myset_store` would be: ```rust,ignore pub mod unsafe_module { // other module content pub fn myset_store(myset: *mut MySetWrapper, key: datum, value: datum) -> libc::c_int { // DO NOT USE THIS CODE. IT IS UNSAFE TO DEMONSTRATE A PROBLEM. let myset: &mut MySet = unsafe { // SAFETY: whoops, UB occurs in here! &mut (*myset).myset }; /* ...check and cast key and value data... */ match myset.store(casted_key, casted_value) { Ok(_) => 0, Err(e) => e.into(), } } } ``` If the iterator exists when this function is called, we have violated one of Rust's aliasing rules. According to Rust, the mutable reference in this block must have *exclusive* access to the object. If the iterator simply exists, it's not exclusive, so we have `undefined behaviour`! [^1] To avoid this, we must have a way of ensuring that mutable reference really is exclusive. That basically means clearing out the iterator's shared reference while it exists, and then reconstructing it. In most cases, that will still be less efficient than the C version. Some may ask: how can C do this more efficiently? The answer is, it cheats. Rust's aliasing rules are the problem, and C simply ignores them for its pointers. In exchange, it is common to see code that is declared in the manual as "not thread safe" under some or all circumstances. In fact, the [GNU C library](https://manpages.debian.org/buster/manpages/attributes.7.en.html) has an entire lexicon dedicated to concurrent behavior! Rust would rather make everything memory safe all the time, for both safety and optimizations that C code cannot attain. Being denied access to certain shortcuts is the price Rust programmers need to pay. [^1]: For the C programmers out there scratching their heads, the iterator need not be read *during* this code to cause the UB. The exclusivity rule also enables compiler optimizations which may cause inconsistent observations by the iterator's shared reference (e.g. stack spills or reordering instructions for efficiency). These observations may happen *any time after* the mutable reference is created. ================================================ FILE: src/patterns/index.md ================================================ # Design Patterns [Design patterns](https://en.wikipedia.org/wiki/Software_design_pattern) are "general reusable solutions to a commonly occurring problem within a given context in software design". Design patterns are a great way to describe the culture of a programming language. Design patterns are very language-specific - what is a pattern in one language may be unnecessary in another due to a language feature, or impossible to express due to a missing feature. If overused, design patterns can add unnecessary complexity to programs. However, they are a great way to share intermediate and advanced level knowledge about a programming language. ## Design patterns in Rust Rust has many unique features. These features give us great benefit by removing whole classes of problems. Some of them are also patterns that are *unique* to Rust. ## YAGNI YAGNI is an acronym that stands for `You Aren't Going to Need It`. It's a vital software design principle to apply as you write code. > The best code I ever wrote was code I never wrote. If we apply YAGNI to design patterns, we see that the features of Rust allow us to throw out many patterns. For instance, there is no need for the [strategy pattern](https://en.wikipedia.org/wiki/Strategy_pattern) in Rust because we can just use [traits](https://doc.rust-lang.org/book/traits.html). ================================================ FILE: src/patterns/structural/compose-structs.md ================================================ # Struct decomposition for independent borrowing ## Description Sometimes a large struct will cause issues with the borrow checker - although fields can be borrowed independently, sometimes the whole struct ends up being used at once, preventing other uses. A solution might be to decompose the struct into several smaller structs. Then compose these together into the original struct. Then each struct can be borrowed separately and have more flexible behaviour. This will often lead to a better design in other ways: applying this design pattern often reveals smaller units of functionality. ## Example Here is a contrived example of where the borrow checker foils us in our plan to use a struct: ```rust,ignore struct Database { connection_string: String, timeout: u32, pool_size: u32, } fn print_database(database: &Database) { println!("Connection string: {}", database.connection_string); println!("Timeout: {}", database.timeout); println!("Pool size: {}", database.pool_size); } fn main() { let mut db = Database { connection_string: "initial string".to_string(), timeout: 30, pool_size: 100, }; let connection_string = &mut db.connection_string; print_database(&db); *connection_string = "new string".to_string(); } ``` The compiler throws following errors: ```ignore let connection_string = &mut db.connection_string; ------------------------- mutable borrow occurs here print_database(&db); ^^^ immutable borrow occurs here *connection_string = "new string".to_string(); ------------------ mutable borrow later used here ``` We can apply this design pattern and refactor `Database` into three smaller structs, thus solving the borrow checking issue: ```rust // Database is now composed of three structs - ConnectionString, Timeout and PoolSize. // Let's decompose it into smaller structs #[derive(Debug, Clone)] struct ConnectionString(String); #[derive(Debug, Clone, Copy)] struct Timeout(u32); #[derive(Debug, Clone, Copy)] struct PoolSize(u32); // We then compose these smaller structs back into `Database` struct Database { connection_string: ConnectionString, timeout: Timeout, pool_size: PoolSize, } // print_database can then take ConnectionString, Timeout and Poolsize struct instead fn print_database(connection_str: ConnectionString, timeout: Timeout, pool_size: PoolSize) { println!("Connection string: {connection_str:?}"); println!("Timeout: {timeout:?}"); println!("Pool size: {pool_size:?}"); } fn main() { // Initialize the Database with the three structs let mut db = Database { connection_string: ConnectionString("localhost".to_string()), timeout: Timeout(30), pool_size: PoolSize(100), }; let connection_string = &mut db.connection_string; print_database(connection_string.clone(), db.timeout, db.pool_size); *connection_string = ConnectionString("new string".to_string()); } ``` ## Motivation This pattern is most useful, when you have a struct that ended up with a lot of fields that you want to borrow independently. Thus having a more flexible behaviour in the end. ## Advantages Decomposition of structs lets you work around limitations in the borrow checker. And it often produces a better design. ## Disadvantages It can lead to more verbose code. And sometimes, the smaller structs are not good abstractions, and so we end up with a worse design. That is probably a 'code smell', indicating that the program should be refactored in some way. ## Discussion This pattern is not required in languages that don't have a borrow checker, so in that sense is unique to Rust. However, making smaller units of functionality often leads to cleaner code: a widely acknowledged principle of software engineering, independent of the language. This pattern relies on Rust's borrow checker to be able to borrow fields independently of each other. In the example, the borrow checker knows that `a.b` and `a.c` are distinct and can be borrowed independently, it does not try to borrow all of `a`, which would make this pattern useless. ================================================ FILE: src/patterns/structural/intro.md ================================================ # Structural Patterns From [Wikipedia](https://en.wikipedia.org/wiki/Structural_pattern): > Design patterns that ease the design by identifying a simple way to realize > relationships among entities. ================================================ FILE: src/patterns/structural/small-crates.md ================================================ # Prefer small crates ## Description Prefer small crates that do one thing well. Cargo and crates.io make it easy to add third-party libraries, much more so than in say C or C++. Moreover, since packages on crates.io cannot be edited or removed after publication, any build that works now should continue to work in the future. We should take advantage of this tooling, and use smaller, more fine-grained dependencies. ## Advantages - Small crates are easier to understand, and encourage more modular code. - Crates allow for re-using code between projects. For example, the `url` crate was developed as part of the Servo browser engine, but has since found wide use outside the project. - Since the compilation unit of Rust is the crate, splitting a project into multiple crates can allow more of the code to be built in parallel. ## Disadvantages - This can lead to "dependency hell", when a project depends on multiple conflicting versions of a crate at the same time. For example, the `url` crate has both versions 1.0 and 0.5. Since the `Url` from `url:1.0` and the `Url` from `url:0.5` are different types, an HTTP client that uses `url:0.5` would not accept `Url` values from a web scraper that uses `url:1.0`. - Packages on crates.io are not curated. A crate may be poorly written, have unhelpful documentation, or be outright malicious. - Two small crates may be less optimized than one large one, since the compiler does not perform link-time optimization (LTO) by default. ## Examples The [`url`](https://crates.io/crates/url) crate provides tools for working with URLs. The [`num_cpus`](https://crates.io/crates/num_cpus) crate provides a function to query the number of CPUs on a machine. The [`ref_slice`](https://crates.io/crates/ref_slice) crate provides functions for converting `&T` to `&[T]`. (Historical example) ## See also - [crates.io: The Rust community crate host](https://crates.io/) ================================================ FILE: src/patterns/structural/trait-for-bounds.md ================================================ # Use custom traits to avoid complex type bounds ## Description Trait bounds can become somewhat unwieldy, especially if one of the `Fn` traits[^fn-traits] is involved and there are specific requirements on the output type. In such cases the introduction of a new trait may help reduce verbosity, eliminate some type parameters and thus increase expressiveness. Such a trait can be accompanied with a generic `impl` for all types satisfying the original bound. ## Example Let's imagine some sort of monitoring or information gathering system. The system retrieves values of various types from diverse sources. It may derive from them some sort of status indicating issues. For example, the total amount of free memory should be above a certain theshold, and the user with the id `0` should always be named "root". For management reasons, we probably want type erasure on the top level. However, we also need to provide specific (user configurable) assesments for specific types of data sources (e.g. thresholds and ranges for numerical types). And since sources for these values are diverse, we may choose to supply data sources as closures that return a value when called. Because we are probably getting those values from the operating system, we are likely confronted with operations that may fail. We thus may have settled on the following types and traits for handling specific values: ```rust use std::fmt::Display; struct Value Result, S: Fn(&T) -> Status, T: Display> { value: Option, getter: G, status: S, } impl Result, S: Fn(&T) -> Status, T: Display> Value { pub fn update(&mut self) -> Result<(), Error> { (self.getter)().map(|v| self.value = Some(v)) } pub fn value(&self) -> Option<&T> { self.value.as_ref() } pub fn status(&self) -> Option { self.value().map(&self.status) } } // ... enum Status { // ... } struct Error { // ... } ``` With these types, we will need to repeat the trait bounds for `G` in at least a few places. Readability suffers, partially due the the fact that the getter returns a `Result`. Introducing a bound for "getters" allows a more expressive bound and eliminate one of the type parameters: ```rust # use std::fmt::Display; trait Getter { type Output: Display; fn get_value(&mut self) -> Result; } impl Result, T: Display> Getter for F { type Output = T; fn get_value(&mut self) -> Result { self() } } struct Value Status> { value: Option, getter: G, status: S, } // ... # enum Status {} # struct Error; ``` ## Advantages Introducing a new trait can help simplify type bounds, particularly via the elimination of type parameters. A good name for the new trait will also make the bound more expressive. The new trait, an abstraction, also offers opportunities in itself, including: - additional, specialized types implementing the new trait (e.g. representing an idendity of some sort) as well as other useful traits such as `Default` and - additional methods, as long as they can be implemented for all relevant types. ## Disadvantages Introducing new items such as the trait means we need to find an appropriate name and place for it. It also means one more item users of the original functionality need to investigate[^read-docs]. Depending on presentation, it may not be obvious right away that a simple closure may be used as a `Getter` in the example above. [^fn-traits]: i.e. `Fn`, `FnOnce` and `FnMut` [^read-docs]: meaning they may need to read more documentation ================================================ FILE: src/patterns/structural/unsafe-mods.md ================================================ # Contain unsafety in small modules ## Description If you have `unsafe` code, create the smallest possible module that can uphold the needed invariants to build a minimal safe interface upon the unsafety. Embed this into a larger module that contains only safe code and presents an ergonomic interface. Note that the outer module can contain unsafe functions and methods that call directly into the unsafe code. Users may use this to gain speed benefits. ## Advantages - This restricts the unsafe code that must be audited - Writing the outer module is much easier, since you can count on the guarantees of the inner module ## Disadvantages - Sometimes, it may be hard to find a suitable interface. - The abstraction may introduce inefficiencies. ## Examples - The [`toolshed`](https://docs.rs/toolshed) crate contains its unsafe operations in submodules, presenting a safe interface to users. - `std`'s `String` class is a wrapper over `Vec` with the added invariant that the contents must be valid UTF-8. The operations on `String` ensure this behavior. However, users have the option of using an `unsafe` method to create a `String`, in which case the onus is on them to guarantee the validity of the contents. ## See also - [Ralf Jung's Blog about invariants in unsafe code](https://www.ralfj.de/blog/2018/08/22/two-kinds-of-invariants.html) ================================================ FILE: src/refactoring/index.md ================================================ # Refactoring Refactoring is very important in relation to these topics. Just as important as the other topics covered here, is how to take good code and turn it into great code. We can use [design patterns](../patterns/index.md) to [DRY] up code and generalize abstractions. We must avoid [anti-patterns](../anti_patterns/index.md) while we do this. While they may be tempting to employ, their costs outweigh their benefits. > Shortcuts make for long days. We can also use [idioms](../idioms/index.md) to structure our code in a way that is understandable. ## Tests Tests are of vital importance during refactoring. ## Small changes [DRY]: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself ================================================ FILE: src/translations.md ================================================ # Translations We are utilizing [mdbook-i18n-helper](https://github.com/google/mdbook-i18n-helpers). Please read up on how to *add* and *update* translations in [their repository](https://github.com/google/mdbook-i18n-helpers#creating-and-updating-translations) ## External translations - [简体中文](https://fomalhauthmj.github.io/patterns/) If you want to add a translation, please open an issue in the [main repository](https://github.com/rust-unofficial/patterns). ================================================ FILE: styles/last-changed.css ================================================ footer { font-size: 0.8em; text-align: center; border-top: 1px solid grey; padding: 1.25em 0; margin-top: 1.25em; } ================================================ FILE: template.md ================================================ # A succinct name for the pattern ## Description A short, prose description of the pattern. ## Example ```rust // An example of the pattern in action, should be mostly code, commented // liberally. ``` When writing examples, please try to make them compile. This allows us to test them. If you fail to write an example that is both complete and readable, please at least mark your example code with `ignore` as in here: ```rust,ignore // A non-runnable example of the pattern in action, should be mostly code, commented // liberally. ``` ## Motivation Why and where you should use the pattern ## Advantages Good things about this pattern. ## Disadvantages Bad things about this pattern. Possible contraindications. ## Discussion A deeper discussion about this pattern. You might want to cover how this is done in other languages, alternative approaches, why this is particularly nice in Rust, etc. ## See also Related patterns (link to the pattern file). Versions of this pattern in other languages. ================================================ FILE: theme/css/language-picker.css ================================================ #language-list { left: auto; right: 10px; } [dir="rtl"] #language-list { left: 10px; right: auto; } #language-list a { color: inherit; } ================================================ FILE: theme/head.hbs ================================================ {{! Move to template code after fixing this issue: https://github.com/google/mdbook-i18n-helpers/issues/70 }} ================================================ FILE: theme/index.hbs ================================================ {{ title }} {{#if is_print }} {{/if}} {{#if base_url}} {{/if}} {{> head}} {{#if favicon_svg}} {{/if}} {{#if favicon_png}} {{/if}} {{#if print_enable}} {{/if}} {{#each additional_css}} {{/each}} {{#if mathjax_support}} {{/if}}

Keyboard shortcuts

Press or to navigate between chapters

{{#if search_enabled}}

Press S or / to search in the book

{{/if}}

Press ? to show this help

Press Esc to hide this help

{{> header}}
{{#if search_enabled}} {{/if}}
{{#if live_reload_endpoint}} {{/if}} {{#if playground_line_numbers}} {{/if}} {{#if playground_copyable}} {{/if}} {{#if playground_js}} {{/if}} {{#if search_js}} {{/if}} {{#each additional_js}} {{/each}} {{#if is_print}} {{#if mathjax_support}} {{else}} {{/if}} {{/if}} {{#if fragment_map}} {{/if}}
================================================ FILE: third_party/mdbook/LICENSE ================================================ Mozilla Public License, version 2.0 1. Definitions 1.1. "Contributor" means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. 1.2. "Contributor Version" means the combination of the Contributions of others (if any) used by a Contributor and that particular Contributor's Contribution. 1.3. "Contribution" means Covered Software of a particular Contributor. 1.4. "Covered Software" means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. 1.5. "Incompatible With Secondary Licenses" means a. that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or b. that the Covered Software was made available under the terms of version 1.1 or earlier of the License, but not also under the terms of a Secondary License. 1.6. "Executable Form" means any form of the work other than Source Code Form. 1.7. "Larger Work" means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software. 1.8. "License" means this document. 1.9. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently, any and all of the rights conveyed by this License. 1.10. "Modifications" means any of the following: a. any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software; or b. any new file in Source Code Form that contains any Covered Software. 1.11. "Patent Claims" of a Contributor means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of either its Contributions or its Contributor Version. 1.12. "Secondary License" means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. 1.13. "Source Code Form" means the form of the work preferred for making modifications. 1.14. "You" (or "Your") means an individual or a legal entity exercising rights under this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. License Grants and Conditions 2.1. Grants Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: a. under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and b. under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and otherwise transfer either its Contributions or its Contributor Version. 2.2. Effective Date The licenses granted in Section 2.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first distributes such Contribution. 2.3. Limitations on Grant Scope The licenses granted in this Section 2 are the only rights granted under this License. No additional rights or licenses will be implied from the distribution or licensing of Covered Software under this License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor: a. for any code that a Contributor has removed from Covered Software; or b. for infringements caused by: (i) Your and any other third party's modifications of Covered Software, or (ii) the combination of its Contributions with other software (except as part of its Contributor Version); or c. under Patent Claims infringed by Covered Software in the absence of its Contributions. This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the notice requirements in Section 3.4). 2.4. Subsequent Licenses No Contributor makes additional grants as a result of Your choice to distribute the Covered Software under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary License (if permitted under the terms of Section 3.3). 2.5. Representation Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. 2.6. Fair Use This License is not intended to limit any rights You have under applicable copyright doctrines of fair use, fair dealing, or other equivalents. 2.7. Conditions Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1. 3. Responsibilities 3.1. Distribution of Source Form All distribution of Covered Software in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License. You must inform recipients that the Source Code Form of the Covered Software is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter or restrict the recipients' rights in the Source Code Form. 3.2. Distribution of Executable Form If You distribute Covered Software in Executable Form then: a. such Covered Software must also be made available in Source Code Form, as described in Section 3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and b. You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients' rights in the Source Code Form under this License. 3.3. Distribution of a Larger Work You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s). 3.4. Notices You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Covered Software, except that You may alter any license notices to the extent required to remedy known factual inaccuracies. 3.5. Application of Additional Terms You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, You may do so only on Your own behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any jurisdiction. 4. Inability to Comply Due to Statute or Regulation If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Software due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be placed in a text file included with all distributions of the Covered Software under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5. Termination 5.1. The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30 days after Your receipt of the notice. 5.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or Your distributors under this License prior to termination shall survive termination. 6. Disclaimer of Warranty Covered Software is provided under this License on an "as is" basis, without warranty of any kind, either expressed, implied, or statutory, including, without limitation, warranties that the Covered Software is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire risk as to the quality and performance of the Covered Software is with You. Should any Covered Software prove defective in any respect, You (not any Contributor) assume the cost of any necessary servicing, repair, or correction. This disclaimer of warranty constitutes an essential part of this License. No use of any Covered Software is authorized under this License except under this disclaimer. 7. Limitation of Liability Under no circumstances and under no legal theory, whether tort (including negligence), contract, or otherwise, shall any Contributor, or anyone who distributes Covered Software as permitted above, be liable to You for any direct, indirect, special, incidental, or consequential damages of any character including, without limitation, damages for lost profits, loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses, even if such party shall have been informed of the possibility of such damages. This limitation of liability shall not apply to liability for death or personal injury resulting from such party's negligence to the extent applicable law prohibits such limitation. Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so this exclusion and limitation may not apply to You. 8. Litigation Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party's ability to bring cross-claims or counter-claims. 9. Miscellaneous This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor. 10. Versions of the License 10.1. New Versions Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number. 10.2. Effect of New Versions You may distribute the Covered Software under the terms of the version of the License under which You originally received the Covered Software, or under the terms of any subsequent version published by the license steward. 10.3. Modified Versions If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the license steward (except to note that such modified license differs from this License). 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the notice described in Exhibit B of this License must be attached. Exhibit A - Source Code Form License Notice This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice. You may add additional accurate notices of copyright ownership. Exhibit B - "Incompatible With Secondary Licenses" Notice This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. ================================================ FILE: third_party/mdbook/README.md ================================================ # mdBook This directory contains files copied from mdBook. Please see for the full project. ## License mdBook is licensed under the Mozilla Public License v2.0 ([LICENSE](LICENSE)). ================================================ FILE: third_party/mdbook/book.js ================================================ "use strict"; /* global default_theme, default_dark_theme, default_light_theme, hljs, ClipboardJS */ // Fix back button cache problem window.onunload = function() {}; // Global variable, shared between modules function playground_text(playground, hidden = true) { const code_block = playground.querySelector("code"); if (window.ace && code_block.classList.contains("editable")) { const editor = window.ace.edit(code_block); return editor.getValue(); } else if (hidden) { return code_block.textContent; } else { return code_block.innerText; } } (function codeSnippets() { function fetch_with_timeout(url, options, timeout = 6000) { return Promise.race([ fetch(url, options), new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), timeout) ), ]); } const playgrounds = Array.from(document.querySelectorAll(".playground")); if (playgrounds.length > 0) { fetch_with_timeout("https://play.rust-lang.org/meta/crates", { headers: { "Content-Type": "application/json", }, method: "POST", mode: "cors", }) .then(response => response.json()) .then(response => { // get list of crates available in the rust playground const playground_crates = response.crates.map(item => item["id"]); playgrounds.forEach(block => handle_crate_list_update(block, playground_crates) ); }); } function handle_crate_list_update(playground_block, playground_crates) { // update the play buttons after receiving the response update_play_button(playground_block, playground_crates); // and install on change listener to dynamically update ACE editors if (window.ace) { const code_block = playground_block.querySelector("code"); if (code_block.classList.contains("editable")) { const editor = window.ace.edit(code_block); editor.addEventListener("change", () => { update_play_button(playground_block, playground_crates); }); // add Ctrl-Enter command to execute rust code editor.commands.addCommand({ name: "run", bindKey: { win: "Ctrl-Enter", mac: "Ctrl-Enter", }, exec: _editor => run_rust_code(playground_block), }); } } } // updates the visibility of play button based on `no_run` class and // used crates vs ones available on https://play.rust-lang.org function update_play_button(pre_block, playground_crates) { const play_button = pre_block.querySelector(".play-button"); // skip if code is `no_run` if (pre_block.querySelector("code").classList.contains("no_run")) { play_button.classList.add("hidden"); return; } // get list of `extern crate`'s from snippet const txt = playground_text(pre_block); const re = /extern\s+crate\s+([a-zA-Z_0-9]+)\s*;/g; const snippet_crates = []; let item; while (item = re.exec(txt)) { snippet_crates.push(item[1]); } // check if all used crates are available on play.rust-lang.org const all_available = snippet_crates.every(function(elem) { return playground_crates.indexOf(elem) > -1; }); if (all_available) { play_button.classList.remove("hidden"); play_button.hidden = false; } else { play_button.classList.add("hidden"); } } function run_rust_code(code_block) { let result_block = code_block.querySelector(".result"); if (!result_block) { result_block = document.createElement("code"); result_block.className = "result hljs language-bash"; code_block.append(result_block); } const text = playground_text(code_block); const classes = code_block.querySelector("code").classList; let edition = "2015"; classes.forEach(className => { if (className.startsWith("edition")) { edition = className.slice(7); } }); const params = { version: "stable", optimize: "0", code: text, edition: edition, }; if (text.indexOf("#![feature") !== -1) { params.version = "nightly"; } result_block.innerText = "Running..."; fetch_with_timeout("https://play.rust-lang.org/evaluate.json", { headers: { "Content-Type": "application/json", }, method: "POST", mode: "cors", body: JSON.stringify(params), }) .then(response => response.json()) .then(response => { if (response.result.trim() === "") { result_block.innerText = "No output"; result_block.classList.add("result-no-output"); } else { result_block.innerText = response.result; result_block.classList.remove("result-no-output"); } }) .catch(error => result_block.innerText = "Playground Communication: " + error.message ); } // Syntax highlighting Configuration hljs.configure({ tabReplace: " ", // 4 spaces languages: [], // Languages used for auto-detection }); const code_nodes = Array .from(document.querySelectorAll("code")) // Don't highlight `inline code` blocks in headers. .filter(function(node) { return !node.parentElement.classList.contains("header"); }); if (window.ace) { // language-rust class needs to be removed for editable // blocks or highlightjs will capture events code_nodes .filter(function(node) { return node.classList.contains("editable"); }) .forEach(function(block) { block.classList.remove("language-rust"); }); code_nodes .filter(function(node) { return !node.classList.contains("editable"); }) .forEach(function(block) { hljs.highlightBlock(block); }); } else { code_nodes.forEach(function(block) { hljs.highlightBlock(block); }); } // Adding the hljs class gives code blocks the color css // even if highlighting doesn't apply code_nodes.forEach(function(block) { block.classList.add("hljs"); }); Array.from(document.querySelectorAll("code.hljs")).forEach(function(block) { const lines = Array.from(block.querySelectorAll(".boring")); // If no lines were hidden, return if (!lines.length) { return; } block.classList.add("hide-boring"); const buttons = document.createElement("div"); buttons.className = "buttons"; buttons.innerHTML = ""; buttons.firstChild.innerHTML = document.getElementById("fa-eye").innerHTML; // add expand button const pre_block = block.parentNode; pre_block.insertBefore(buttons, pre_block.firstChild); buttons.firstChild.addEventListener("click", function(e) { if (this.title === "Show hidden lines") { this.innerHTML = document.getElementById("fa-eye-slash").innerHTML; this.title = "Hide lines"; this.setAttribute("aria-label", e.target.title); block.classList.remove("hide-boring"); } else if (this.title === "Hide lines") { this.innerHTML = document.getElementById("fa-eye").innerHTML; this.title = "Show hidden lines"; this.setAttribute("aria-label", e.target.title); block.classList.add("hide-boring"); } }); }); if (window.playground_copyable) { Array.from(document.querySelectorAll("pre code")).forEach(function(block) { const pre_block = block.parentNode; if (!pre_block.classList.contains("playground")) { let buttons = pre_block.querySelector(".buttons"); if (!buttons) { buttons = document.createElement("div"); buttons.className = "buttons"; pre_block.insertBefore(buttons, pre_block.firstChild); } const clipButton = document.createElement("button"); clipButton.className = "clip-button"; clipButton.title = "Copy to clipboard"; clipButton.setAttribute("aria-label", clipButton.title); clipButton.innerHTML = ""; buttons.insertBefore(clipButton, buttons.firstChild); } }); } // Process playground code blocks Array.from(document.querySelectorAll(".playground")).forEach( function(pre_block) { // Add play button let buttons = pre_block.querySelector(".buttons"); if (!buttons) { buttons = document.createElement("div"); buttons.className = "buttons"; pre_block.insertBefore(buttons, pre_block.firstChild); } const runCodeButton = document.createElement("button"); runCodeButton.className = "play-button"; runCodeButton.hidden = true; runCodeButton.title = "Run this code"; runCodeButton.setAttribute("aria-label", runCodeButton.title); runCodeButton.innerHTML = document.getElementById("fa-play").innerHTML; buttons.insertBefore(runCodeButton, buttons.firstChild); runCodeButton.addEventListener("click", () => { run_rust_code(pre_block); }); if (window.playground_copyable) { const copyCodeClipboardButton = document.createElement("button"); copyCodeClipboardButton.className = "clip-button"; copyCodeClipboardButton.innerHTML = ""; copyCodeClipboardButton.title = "Copy to clipboard"; copyCodeClipboardButton.setAttribute( "aria-label", copyCodeClipboardButton.title, ); buttons.insertBefore(copyCodeClipboardButton, buttons.firstChild); } const code_block = pre_block.querySelector("code"); if (window.ace && code_block.classList.contains("editable")) { const undoChangesButton = document.createElement("button"); undoChangesButton.className = "reset-button"; undoChangesButton.title = "Undo changes"; undoChangesButton.setAttribute("aria-label", undoChangesButton.title); undoChangesButton.innerHTML += document.getElementById("fa-clock-rotate-left").innerHTML; buttons.insertBefore(undoChangesButton, buttons.firstChild); undoChangesButton.addEventListener("click", function() { const editor = window.ace.edit(code_block); editor.setValue(editor.originalCode); editor.clearSelection(); }); } }, ); })(); (function themes() { const html = document.querySelector("html"); const themeToggleButton = document.getElementById("mdbook-theme-toggle"); const themePopup = document.getElementById("mdbook-theme-list"); const themeColorMetaTag = document.querySelector( "meta[name=\"theme-color\"]", ); const themeIds = []; themePopup.querySelectorAll("button.theme").forEach(function(el) { themeIds.push(el.id); }); const stylesheets = { ayuHighlight: document.querySelector("#mdbook-ayu-highlight-css"), tomorrowNight: document.querySelector("#mdbook-tomorrow-night-css"), highlight: document.querySelector("#mdbook-highlight-css"), }; function showThemes() { themePopup.style.display = "block"; themeToggleButton.setAttribute("aria-expanded", true); themePopup.querySelector("button#mdbook-theme-" + get_theme()).focus(); } function updateThemeSelected() { themePopup.querySelectorAll(".theme-selected").forEach(function(el) { el.classList.remove("theme-selected"); }); const selected = get_saved_theme() ?? "default_theme"; let element = themePopup.querySelector("button#mdbook-theme-" + selected); if (element === null) { // Fall back in case there is no "Default" item. element = themePopup.querySelector("button#mdbook-theme-" + get_theme()); } element.classList.add("theme-selected"); } function hideThemes() { themePopup.style.display = "none"; themeToggleButton.setAttribute("aria-expanded", false); themeToggleButton.focus(); } function get_saved_theme() { let theme = null; try { theme = localStorage.getItem("mdbook-theme"); } catch { // ignore error. } return theme; } function delete_saved_theme() { localStorage.removeItem("mdbook-theme"); } function get_theme() { const theme = get_saved_theme(); if ( theme === null || theme === undefined || !themeIds.includes("mdbook-theme-" + theme) ) { if (typeof default_dark_theme === "undefined") { // A customized index.hbs might not define this, so fall back to // old behavior of determining the default on page load. return default_theme; } return window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme; } else { return theme; } } let previousTheme = default_theme; function set_theme(theme, store = true) { let ace_theme; if (theme === "coal" || theme === "navy") { stylesheets.ayuHighlight.disabled = true; stylesheets.tomorrowNight.disabled = false; stylesheets.highlight.disabled = true; ace_theme = "ace/theme/tomorrow_night"; } else if (theme === "ayu") { stylesheets.ayuHighlight.disabled = false; stylesheets.tomorrowNight.disabled = true; stylesheets.highlight.disabled = true; ace_theme = "ace/theme/tomorrow_night"; } else { stylesheets.ayuHighlight.disabled = true; stylesheets.tomorrowNight.disabled = true; stylesheets.highlight.disabled = false; ace_theme = "ace/theme/dawn"; } setTimeout(function() { themeColorMetaTag.content = getComputedStyle(document.documentElement).backgroundColor; }, 1); if (window.ace && window.editors) { window.editors.forEach(function(editor) { editor.setTheme(ace_theme); }); } if (store) { try { localStorage.setItem("mdbook-theme", theme); } catch { // ignore error. } } html.classList.remove(previousTheme); html.classList.add(theme); previousTheme = theme; updateThemeSelected(); } const query = window.matchMedia("(prefers-color-scheme: dark)"); query.onchange = function() { set_theme(get_theme(), false); }; // Set theme. set_theme(get_theme(), false); themeToggleButton.addEventListener("click", function() { if (themePopup.style.display === "block") { hideThemes(); } else { showThemes(); } }); themePopup.addEventListener("click", function(e) { let theme; if (e.target.className === "theme") { theme = e.target.id; } else if (e.target.parentElement.className === "theme") { theme = e.target.parentElement.id; } else { return; } theme = theme.replace(/^mdbook-theme-/, ""); if (theme === "default_theme" || theme === null) { delete_saved_theme(); set_theme(get_theme(), false); } else { set_theme(theme); } }); themePopup.addEventListener("focusout", function(e) { // e.relatedTarget is null in Safari and Firefox on macOS (see workaround below) if ( !!e.relatedTarget && !themeToggleButton.contains(e.relatedTarget) && !themePopup.contains(e.relatedTarget) ) { hideThemes(); } }); // Should not be needed, but it works around an issue on macOS & iOS: // https://github.com/rust-lang/mdBook/issues/628 document.addEventListener("click", function(e) { if ( themePopup.style.display === "block" && !themeToggleButton.contains(e.target) && !themePopup.contains(e.target) ) { hideThemes(); } }); document.addEventListener("keydown", function(e) { if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; } if (!themePopup.contains(e.target)) { return; } let li; switch (e.key) { case "Escape": e.preventDefault(); hideThemes(); break; case "ArrowUp": e.preventDefault(); li = document.activeElement.parentElement; if (li && li.previousElementSibling) { li.previousElementSibling.querySelector("button").focus(); } break; case "ArrowDown": e.preventDefault(); li = document.activeElement.parentElement; if (li && li.nextElementSibling) { li.nextElementSibling.querySelector("button").focus(); } break; case "Home": e.preventDefault(); themePopup.querySelector("li:first-child button").focus(); break; case "End": e.preventDefault(); themePopup.querySelector("li:last-child button").focus(); break; } }); })(); (function sidebar() { const sidebar = document.getElementById("mdbook-sidebar"); const sidebarLinks = document.querySelectorAll("#mdbook-sidebar a"); const sidebarToggleButton = document.getElementById("mdbook-sidebar-toggle"); const sidebarResizeHandle = document.getElementById( "mdbook-sidebar-resize-handle", ); const sidebarCheckbox = document.getElementById( "mdbook-sidebar-toggle-anchor", ); let firstContact = null; /* Because we cannot change the `display` using only CSS after/before the transition, we need JS to do it. We change the display to prevent the browsers search to find text inside the collapsed sidebar. */ if (!document.documentElement.classList.contains("sidebar-visible")) { sidebar.style.display = "none"; } sidebar.addEventListener("transitionend", () => { /* We only change the display to "none" if we're collapsing the sidebar. */ if (!sidebarCheckbox.checked) { sidebar.style.display = "none"; } }); sidebarToggleButton.addEventListener("click", () => { /* To allow the sidebar expansion animation, we first need to put back the display. */ if (!sidebarCheckbox.checked) { sidebar.style.display = ""; // Workaround for Safari skipping the animation when changing // `display` and a transform in the same event loop. This forces a // reflow after updating the display. sidebar.offsetHeight; } }); function showSidebar() { document.documentElement.classList.add("sidebar-visible"); Array.from(sidebarLinks).forEach(function(link) { link.setAttribute("tabIndex", 0); }); sidebarToggleButton.setAttribute("aria-expanded", true); sidebar.setAttribute("aria-hidden", false); try { localStorage.setItem("mdbook-sidebar", "visible"); } catch { // Ignore error. } } function hideSidebar() { document.documentElement.classList.remove("sidebar-visible"); Array.from(sidebarLinks).forEach(function(link) { link.setAttribute("tabIndex", -1); }); sidebarToggleButton.setAttribute("aria-expanded", false); sidebar.setAttribute("aria-hidden", true); try { localStorage.setItem("mdbook-sidebar", "hidden"); } catch { // Ignore error. } } // Toggle sidebar sidebarCheckbox.addEventListener("change", function sidebarToggle() { if (sidebarCheckbox.checked) { const current_width = parseInt( document.documentElement.style.getPropertyValue( "--sidebar-target-width", ), 10, ); if (current_width < 150) { document.documentElement.style.setProperty( "--sidebar-target-width", "150px", ); } showSidebar(); } else { hideSidebar(); } }); sidebarResizeHandle.addEventListener("mousedown", initResize, false); function initResize() { window.addEventListener("mousemove", resize, false); window.addEventListener("mouseup", stopResize, false); document.documentElement.classList.add("sidebar-resizing"); } function resize(e) { let pos = e.clientX - sidebar.offsetLeft; if (pos < 20) { hideSidebar(); } else { if (!document.documentElement.classList.contains("sidebar-visible")) { showSidebar(); } pos = Math.min(pos, window.innerWidth - 100); document.documentElement.style.setProperty( "--sidebar-target-width", pos + "px", ); } } // on mouseup remove windows functions mousemove & mouseup function stopResize() { document.documentElement.classList.remove("sidebar-resizing"); window.removeEventListener("mousemove", resize, false); window.removeEventListener("mouseup", stopResize, false); } document.addEventListener("touchstart", function(e) { firstContact = { x: e.touches[0].clientX, time: Date.now(), }; }, { passive: true }); document.addEventListener("touchmove", function(e) { if (!firstContact) { return; } const curX = e.touches[0].clientX; const xDiff = curX - firstContact.x, tDiff = Date.now() - firstContact.time; if (tDiff < 250 && Math.abs(xDiff) >= 150) { if ( xDiff >= 0 && firstContact.x < Math.min(document.body.clientWidth * 0.25, 300) ) { showSidebar(); } else if (xDiff < 0 && curX < 300) { hideSidebar(); } firstContact = null; } }, { passive: true }); })(); (function chapterNavigation() { document.addEventListener("keydown", function(e) { if (e.altKey || e.ctrlKey || e.metaKey) { return; } if (window.search && window.search.hasFocus()) { return; } const html = document.querySelector("html"); function next() { const nextButton = document.querySelector(".nav-chapters.next"); if (nextButton) { window.location.href = nextButton.href; } } function prev() { const previousButton = document.querySelector(".nav-chapters.previous"); if (previousButton) { window.location.href = previousButton.href; } } function showHelp() { const container = document.getElementById("mdbook-help-container"); const overlay = document.getElementById("mdbook-help-popup"); container.style.display = "flex"; // Clicking outside the popup will dismiss it. const mouseHandler = event => { if (overlay.contains(event.target)) { return; } if (event.button !== 0) { return; } event.preventDefault(); event.stopPropagation(); document.removeEventListener("mousedown", mouseHandler); hideHelp(); }; // Pressing esc will dismiss the popup. const escapeKeyHandler = event => { if (event.key === "Escape") { event.preventDefault(); event.stopPropagation(); document.removeEventListener("keydown", escapeKeyHandler, true); hideHelp(); } }; document.addEventListener("keydown", escapeKeyHandler, true); document.getElementById("mdbook-help-container") .addEventListener("mousedown", mouseHandler); } function hideHelp() { document.getElementById("mdbook-help-container").style.display = "none"; } // Usually needs the Shift key to be pressed switch (e.key) { case "?": e.preventDefault(); showHelp(); break; } // Rest of the keys are only active when the Shift key is not pressed if (e.shiftKey) { return; } switch (e.key) { case "ArrowRight": e.preventDefault(); if (html.dir === "rtl") { prev(); } else { next(); } break; case "ArrowLeft": e.preventDefault(); if (html.dir === "rtl") { next(); } else { prev(); } break; } }); })(); (function clipboard() { const clipButtons = document.querySelectorAll(".clip-button"); function hideTooltip(elem) { elem.firstChild.innerText = ""; elem.className = "clip-button"; } function showTooltip(elem, msg) { elem.firstChild.innerText = msg; elem.className = "clip-button tooltipped"; } const clipboardSnippets = new ClipboardJS(".clip-button", { text: function(trigger) { hideTooltip(trigger); const playground = trigger.closest("pre"); return playground_text(playground, false); }, }); Array.from(clipButtons).forEach(function(clipButton) { clipButton.addEventListener("mouseout", function(e) { hideTooltip(e.currentTarget); }); }); clipboardSnippets.on("success", function(e) { e.clearSelection(); showTooltip(e.trigger, "Copied!"); }); clipboardSnippets.on("error", function(e) { showTooltip(e.trigger, "Clipboard error!"); }); })(); (function scrollToTop() { const menuTitle = document.querySelector(".menu-title"); menuTitle.addEventListener("click", function() { document.scrollingElement.scrollTo({ top: 0, behavior: "smooth" }); }); })(); (function controllMenu() { const menu = document.getElementById("mdbook-menu-bar"); (function controllPosition() { let scrollTop = document.scrollingElement.scrollTop; let prevScrollTop = scrollTop; const minMenuY = -menu.clientHeight - 50; // When the script loads, the page can be at any scroll (e.g. if you refresh it). menu.style.top = scrollTop + "px"; // Same as parseInt(menu.style.top.slice(0, -2), but faster let topCache = menu.style.top.slice(0, -2); menu.classList.remove("sticky"); let stickyCache = false; // Same as menu.classList.contains('sticky'), but faster document.addEventListener("scroll", function() { scrollTop = Math.max(document.scrollingElement.scrollTop, 0); // `null` means that it doesn't need to be updated let nextSticky = null; let nextTop = null; const scrollDown = scrollTop > prevScrollTop; const menuPosAbsoluteY = topCache - scrollTop; if (scrollDown) { nextSticky = false; if (menuPosAbsoluteY > 0) { nextTop = prevScrollTop; } } else { if (menuPosAbsoluteY > 0) { nextSticky = true; } else if (menuPosAbsoluteY < minMenuY) { nextTop = prevScrollTop + minMenuY; } } if (nextSticky === true && stickyCache === false) { menu.classList.add("sticky"); stickyCache = true; } else if (nextSticky === false && stickyCache === true) { menu.classList.remove("sticky"); stickyCache = false; } if (nextTop !== null) { menu.style.top = nextTop + "px"; topCache = nextTop; } prevScrollTop = scrollTop; }, { passive: true }); })(); (function controllBorder() { function updateBorder() { if (menu.offsetTop === 0) { menu.classList.remove("bordered"); } else { menu.classList.add("bordered"); } } updateBorder(); document.addEventListener("scroll", updateBorder, { passive: true }); })(); })();