From d3a9f31404d197b2d774683cd31bfc73aa6af22f Mon Sep 17 00:00:00 2001 From: cryptonerdcn Date: Tue, 30 May 2023 14:20:04 +0900 Subject: [PATCH 01/14] =?UTF-8?q?Update:=20Add=20zh-cn=20translation.=20?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=EF=BC=9A=20=E6=B7=BB=E5=8A=A0=E7=AE=80?= =?UTF-8?q?=E4=BD=93=E4=B8=AD=E6=96=87=E7=BF=BB=E8=AF=91=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- po/zh-cn.po | 16830 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 16830 insertions(+) create mode 100644 po/zh-cn.po diff --git a/po/zh-cn.po b/po/zh-cn.po new file mode 100644 index 000000000..a5f393a8c --- /dev/null +++ b/po/zh-cn.po @@ -0,0 +1,16830 @@ +msgid "" +msgstr "" +"Project-Id-Version: The Cairo Programming Language\n" +"POT-Creation-Date: \n" +"PO-Revision-Date: 2023-05-30 09:32+0900\n" +"Last-Translator: cryptonerdcn \n" +"Language-Team: Language zh-cn\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Poedit 3.3.1\n" + +#: src/SUMMARY.md:1 +msgid "The Cairo Programming Language" +msgstr "Cairo编程语言" + +#: src/SUMMARY.md:4 +msgid "Foreword" +msgstr "前言" + +#: src/SUMMARY.md:5 +msgid "Introduction" +msgstr "介绍" + +#: src/SUMMARY.md:7 +msgid "Getting Started" +msgstr "入门" + +#: src/SUMMARY.md:11 +msgid "Installation" +msgstr "安装" + +#: src/SUMMARY.md:12 +msgid "Hello, World!" +msgstr "Hello,world!" + +#: src/SUMMARY.md:13 +msgid "Hello, Scarb!" +msgstr "Hello,Scarb!" + +#: src/SUMMARY.md:15 +msgid "Common Programming Concepts" +msgstr "常见的编程概念" + +#: src/SUMMARY.md:18 +msgid "Variables and Mutability" +msgstr "变量与可变性" + +#: src/SUMMARY.md:19 +msgid "Data Types" +msgstr "数据类型" + +#: src/SUMMARY.md:20 +msgid "Functions" +msgstr "函数" + +#: src/SUMMARY.md:21 +msgid "Comments" +msgstr "注释" + +#: src/SUMMARY.md:22 +msgid "Control Flow" +msgstr "控制流" + +#: src/SUMMARY.md:23 +msgid "Common Collections" +msgstr "常见集合" + +#: src/SUMMARY.md:25 +msgid "Understanding Ownership" +msgstr "认识所有权" + +#: src/SUMMARY.md:28 +msgid "What is Ownership?" +msgstr "什么是所有权?" + +#: src/SUMMARY.md:29 +msgid "References and Snapshots" +msgstr "参考资料和快照" + +#: src/SUMMARY.md:31 +msgid "Using Structs to Structure Related Data" +msgstr "使用结构体组织相关联的数据" + +#: src/SUMMARY.md:34 +msgid "Defining and Instantiating Structs" +msgstr "结构体的定义和实例化" + +#: src/SUMMARY.md:35 +msgid "An Example Program Using Structs" +msgstr "结构体实例程序" + +#: src/SUMMARY.md:36 +msgid "Method Syntax" +msgstr "方法语法" + +#: src/SUMMARY.md:38 +msgid "Enums and Pattern Matching" +msgstr "枚举和模式匹配" + +#: src/SUMMARY.md:38 +msgid "Enums" +msgstr "枚举的定义" + +#: src/SUMMARY.md:42 +msgid "The Match Control Flow Construct" +msgstr "匹配控制流结构" + +#: src/SUMMARY.md:44 +msgid "Managing Cairo Projects with Packages, Crates and Modules" +msgstr "使用包、Crate 和模块管理Cairo项目" + +#: src/SUMMARY.md:48 +msgid "Packages and Crates" +msgstr "包和 Crate" + +#: src/SUMMARY.md:50 +msgid "Defining Modules to Control Scope" +msgstr "定义模块以控制作用域" + +#: src/SUMMARY.md:51 +msgid "Paths for Referring to an Item in the Module Tree" +msgstr "引用模块项目的路径" + +#: src/SUMMARY.md:52 +msgid "Bringing Paths into Scope with the 'use' Keyword" +msgstr "使用 ‘use’ 关键字将路径引入作用域" + +#: src/SUMMARY.md:53 +msgid "Separating Modules into Different Files" +msgstr "将模块拆分成多个文件" + +#: src/SUMMARY.md:57 +msgid "Generic Types" +msgstr "泛型" + +#: src/SUMMARY.md:59 +msgid "Generic Functions" +msgstr "在函数定义中使用泛型" + +#: src/SUMMARY.md:60 +msgid "Traits in Cairo" +msgstr "Cairo中的Trait" + +#: src/SUMMARY.md:62 +msgid "Testing Cairo Programs" +msgstr "测试Cairo 程序" + +#: src/SUMMARY.md:66 +msgid "How To Write Tests" +msgstr "如何编写测试" + +#: src/SUMMARY.md:67 +msgid "Testing Organization" +msgstr "测试的组织结构" + +#: src/SUMMARY.md:69 +msgid "Error Handling" +msgstr "错误处理" + +#: src/SUMMARY.md:72 +msgid "Unrecoverable Errors with panic" +msgstr "用panic处理不可恢复的错误" + +#: src/SUMMARY.md:73 +msgid "Recoverable Errors with Result" +msgstr "用Result处理可恢复的错误" + +#: src/SUMMARY.md:77 +msgid "Starknet Smart Contracts" +msgstr "Starknet智能合约" + +#: src/SUMMARY.md:79 +msgid "Introduction to smart-contracts" +msgstr "智能合约简介" + +#: src/SUMMARY.md:80 +msgid "Writing Starknet Contracts" +msgstr "编写Starknet智能合约" + +#: src/SUMMARY.md:81 +msgid "ABIs and Cross-contract Interactions" +msgstr "ABI和跨合约交互" + +#: src/SUMMARY.md:82 +msgid "ABIs and Interfaces" +msgstr "ABI和接口" + +#: src/SUMMARY.md:83 +msgid "Contract Dispatchers, Library Dispachers and system calls" +msgstr "合约调度器、库调度器和系统调用" + +#: src/SUMMARY.md:85 +msgid "Appendix" +msgstr "附录" + +#: src/SUMMARY.md:86 +msgid "B - Operators and Symbols" +msgstr "B - 运算符和符号" + +#: src/SUMMARY.md:87 +msgid "C - Derivable Traits" +msgstr "C - 可派生的 Trait" + +#: src/SUMMARY.md:88 +msgid "D - Useful Development Tools" +msgstr "D - 实用开发工具" + +#: src/title-page.md:1 +msgid "# The Cairo Programming Language" +msgstr "# Cairo编程语言" + +#: src/title-page.md:3 +msgid "" +"by the Cairo Community and its [contributors](https://github.com/cairo-book/" +"cairo-book.github.io). Special thanks to [Starkware](https://starkware.co/) " +"through [OnlyDust](https://www.onlydust.xyz/), and [Voyager](https://voyager." +"online/) for supporting the creation of this book." +msgstr "" +"由Cairo社区和它的[贡献者](https://github.com/cairo-book/cairo-book.github." +"io)。特别感谢[Starkware](https://starkware.co/)通过[OnlyDust](https://www." +"onlydust.xyz/)和[Voyager](https://voyager.online/)支持这本书的创作。" + +#: src/title-page.md:5 +msgid "" +"This version of the text assumes you’re using Cairo v1.0.0 (released " +"2023-05-15). See the “Installation” section of Chapter 1 to install or " +"update Cairo." +msgstr "" +"这个版本的文本假设你使用的是Cairo v1.0.0(2023-05-15发布)。请参阅第1章的 " +"\"安装 \"部分来安装或更新Cairo。" + +#: src/ch00-01-foreword.md:1 +msgid "# Foreword" +msgstr "# 前言" + +#: src/ch00-01-foreword.md:3 +msgid "" +"In 2020, StarkWare released Cairo 0, a Turing-complete programming language " +"supporting verifiable computation. Cairo started as an assembly language and " +"gradually became more expressive. The learning curve was initially steep, as " +"Cairo 0.x was a low-level language that did not entirely abstract the " +"underlying cryptographic primitives required to build a proof for the " +"execution of a program." +msgstr "" +"2020年,StarkWare发布了Cairo 0,这是一种支持可验证计算的图灵完全编程语言。" +"Cairo最初是一种汇编语言,后来逐渐变得更具表现力。最初的学习曲线很陡峭,因为" +"Cairo 0.x是一种低级语言,没有完全抽象出为程序的执行建立证明所需的底层加密原" +"语。" + +#: src/ch00-01-foreword.md:5 +msgid "" +"With the release of Cairo 1, the developer experience has considerably " +"improved, abstracting away the underlying immutable memory model of the " +"Cairo architecture where possible. Strongly inspired by Rust, Cairo 1 has " +"been built to help you create provable programs without specific knowledge " +"of its underlying architecture so that you can focus on the program itself, " +"increasing the overall security of Cairo programs. Powered by a Rust VM, the " +"execution of Cairo programs is now _blazingly_ fast, allowing you to build " +"an extensive test suite without compromising on performance." +msgstr "" +"随着Cairo 1的发布,开发者的体验有了很大的改善,尽可能地抽象出Cairo架构的底层" +"不可变的内存模型。受到Rust的强烈启发,Cairo 1的建立是为了帮助你创建可证明的程" +"序,而不需要具体了解其底层架构,这样你就可以专注于程序本身,提高Cairo程序的整" +"体安全性。在Rust虚拟机的支持下,Cairo程序的执行速度现在快得惊人,允许你在不影" +"响性能的情况下建立一个广泛的测试套件。" + +#: src/ch00-01-foreword.md:7 +msgid "" +"Blockchain developers that want to deploy contracts on Starknet will use the " +"Cairo programming language to code their smart contracts. This allows the " +"Starknet OS to generate execution traces for transactions to be proved by a " +"prover, which is then verified on Ethereum L1 prior to updating the state " +"root of Starknet." +msgstr "" +"想在Starknet上部署合约的区块链开发者将使用Cairo编程语言来编写他们的智能合约。" +"这允许Starknet操作系统生成交易的执行跟踪,以供证明者生成证明,然后在更新" +"Starknet的状态根之前在Ethereum L1上由验证者验证该证明。" + +#: src/ch00-01-foreword.md:9 +msgid "" +"However, Cairo is not only for blockchain developers. As a general purpose " +"programming language, it can be used for any computation that would benefit " +"from being proved on one computer and verified on other machines with lower " +"hardware requirements." +msgstr "" +"然而,Cairo不仅适用于区块链开发者。作为一种通用的编程语言,它可以用于任何需要" +"在一台计算机上生成证明并在其他硬件要求较低的机器上验证的计算场景。" + +#: src/ch00-01-foreword.md:11 +msgid "" +"This book is designed for developers with a basic understanding of " +"programming concepts. It is a friendly and approachable text intended to " +"help you level up your knowledge of Cairo, but also help you develop your " +"programming skills in general. So, dive in and get ready to learn all there " +"is to know about Cairo!" +msgstr "" +"本书是为对编程概念有基本了解的开发人员设计的。它是一本友好而平易近人的文本," +"旨在帮助你提高你的Cairo知识水平,同时也帮助你发展你的一般编程技能。因此,请潜" +"心学习,并准备好学习所有关于Cairo的知识!" + +#: src/ch00-01-foreword.md:13 +msgid "— The Cairo community" +msgstr "- Cairo社区" + +#: src/ch00-00-introduction.md:1 +msgid "# Introduction" +msgstr "# #介绍" + +#: src/ch00-00-introduction.md:3 +msgid "## What is Cairo?" +msgstr "## 什么是Cairo?" + +#: src/ch00-00-introduction.md:5 +msgid "" +"Cairo is a programming language designed for a virtual CPU of the same name. " +"The unique aspect of this processor is that it was not created for the " +"physical constraints of our world but for cryptographic ones, making it " +"capable of efficiently proving the execution of any program running on it. " +"This means that you can perform time consuming operations on a machine you " +"don't trust, and check the result very quickly on a cheaper machine.\n" +"While Cairo 0 used to be directly compiled to CASM, the Cairo CPU assembly, " +"Cairo 1 is a more high level language. It first compiles to Sierra, an " +"intermediate representation of Cairo which will compile later down to a safe " +"subset of CASM. The point of Sierra is to ensure your CASM will always be " +"provable, even when the computation fails." +msgstr "" +"Cairo是一种为同名的虚拟CPU设计的编程语言。这种处理器的独特之处在于,它不是为" +"我们世界的物理限制而创造的,而是为加密限制而创造的,这使得它能够有效地证明在" +"其上运行的任何程序的执行。这意味着你可以在一台你不信任的机器上进行耗时的操" +"作,而在一台更便宜的机器上非常迅速地检查结果。\n" +"虽然Cairo 0曾经直接编译成CASM,即Cairo CPU汇编,但Cairo 1是一种更高水平的语" +"言。它首先编译到Sierra,这是Cairo的一个中间表示,以后会编译成CASM的一个安全子" +"集。Sierra的意义在于确保你的CASM总是可以证明的,即使计算失败。" + +#: src/ch00-00-introduction.md:8 +msgid "## What can you do with it?" +msgstr "∮∮你能用它做什么?" + +#: src/ch00-00-introduction.md:10 +msgid "" +"Cairo allows you to compute trustworthy values on untrusted machines. One " +"major usecase is Starknet, a solution to Ethereum scaling. Ethereum is a " +"decentralized blockchain platform that enables the creation of decentralized " +"applications where every single interaction between a user and a d-app is " +"verified by all the participants. Starknet is a Layer 2 built on top of " +"Ethereum. Instead of having all the participants of the network to verify " +"all user interactions, only one node, called the prover, execute the " +"programs and generate proofs that the computations were done correctly.These " +"proofs are then verified by an Ethereum smart contract, requiring " +"significantly less computational power compared to executing the " +"interactions themselves. This approach allows for increased throughput and " +"reduced transaction costs but preserving Ethereum security." +msgstr "" +"Cairo允许你在不被信任的机器上计算值得信任的值。一个主要的用例是Starknet,这是" +"一个针对Ethereum扩展的解决方案。以太坊是一个去中心化的区块链平台,它可以创建" +"去中心化的应用程序,用户和d-app之间的每一次互动都会被所有参与者验证。Starknet" +"是一个建立在以太坊之上的第二层。与其让网络的所有参与者来验证所有的用户互动," +"不如只让一个被称为验证者的节点来执行程序,并生成计算正确的证明。这些证明再由" +"以太坊智能合约来验证,与执行互动本身相比,需要的计算能力要少得多。这种方法允" +"许增加吞吐量和降低交易成本,但保留了Ethereum的安全性。" + +#: src/ch00-00-introduction.md:12 +msgid "## What are the differences with other programming languages?" +msgstr "##与其他编程语言有什么区别?" + +#: src/ch00-00-introduction.md:14 +msgid "" +"Cairo is quite different from traditional programming languages, especially " +"when it comes to overhead costs and its primary advantages. Your program can " +"be executed in two different ways:" +msgstr "" +"Cairo与传统的编程语言有很大不同,特别是在开销成本和主要优势方面。你的程序可以" +"通过两种不同的方式执行:" + +#: src/ch00-00-introduction.md:16 +msgid "" +"- When executed by the prover, it is similar to any other language. Because " +"Cairo is virtualized, and because the operations were not specifically " +"designed for maximum efficiency, this can lead to some performance overhead " +"but it is not the most relevant part to optimize.\n" +"\n" +"- When the generated proof is verified by a verifier, it is a bit different. " +"This has to be as cheap as possible since it could potentially be verified " +"on many very small machines. Fortunately verifying is faster than computing " +"and Cairo has some unique advantages to improve it even more. A notable one " +"is non-determinism. This is a topic you will cover in more detail later in " +"this book, but the idea is that you can theoretically use a different " +"algorithm for verifying than for computing. Currently, writing custom non-" +"deterministic code is not supported for the developers, but the standard " +"library leverages non-determinism for improved performance. For example " +"sorting an array in Cairo costs the same price than copying it. Because the " +"verifier doesn't sort the array, it just checks that it is sorted, which is " +"cheaper." +msgstr "" +"- 当被验证者执行时,它与任何其他语言相似。因为Cairo是虚拟化的,而且操作并不是" +"专门为最大效率而设计的,这可能会导致一些性能开销,但这并不是最需要优化的相关" +"部分。\n" +"\n" +"- 当生成的证明被验证者验证时,情况就有点不同了。这必须是尽可能便宜的,因为它" +"有可能在许多非常小的机器上进行验证。幸运的是,验证比计算更快,而且开罗有一些" +"独特的优势,可以进一步改善它。一个值得注意的是非确定性。这是一个你将在本书后" +"面详细介绍的话题,但其想法是,理论上你可以使用不同的算法来验证,而不是计算。" +"目前,开发人员不支持编写自定义的非确定性代码,但标准库利用非确定性来提高性" +"能。例如,在开罗对一个数组进行排序的成本与复制它的成本相同。因为验证器不对数" +"组进行排序,它只是检查它是否被排序,这就更便宜了。" + +#: src/ch00-00-introduction.md:20 +msgid "" +"Another aspect that sets the language apart is its memory model. In Cairo, " +"memory access is immutable, meaning that once a value is written to memory, " +"it cannot be changed. Cairo 1 provides abstractions that help developers " +"work with these constraints, but it does not fully simulate mutability. " +"Therefore, developers must think carefully about how they manage memory and " +"data structures in their programs to optimize performance." +msgstr "" +"使该语言与众不同的另一个方面是其内存模型。在Cairo中,内存访问是不可改变的,这" +"意味着一旦一个值被写入内存,它就不能被改变。Cairo 1提供了帮助开发者处理这些约" +"束的抽象,但它并没有完全模拟可变性。因此,开发人员必须仔细考虑如何在他们的程" +"序中管理内存和数据结构以优化性能。" + +#: src/ch00-00-introduction.md:22 +msgid "## References" +msgstr "## 参考文献" + +#: src/ch00-00-introduction.md:24 +msgid "" +"- Cairo CPU Architecture: \n" +"- Cairo, Sierra and Casm: \n" +"- State of non determinism: " +msgstr "" +"- CairoCPU架构:\n" +"- Cairo, Sierra and Casm:\n" +"- 非确定性的状态:" + +#: src/ch01-01-installation.md:1 +msgid "# Installation" +msgstr "# 安装" + +#: src/ch01-01-installation.md:3 +msgid "" +"The first step is to install Cairo. We will download Cairo manually, using " +"cairo repository or with an installation script. You’ll need an internet " +"connection for the download." +msgstr "" +"第一步是安装Cairo。我们可以手动下载Cairo(使用Cairo仓库)或使用安装脚本。下载" +"过程需要互联网连接。" + +#: src/ch01-01-installation.md:5 +msgid "### Prerequisites" +msgstr "###先决条件" + +#: src/ch01-01-installation.md:7 +msgid "First you will need to have Rust and Git installed." +msgstr "首先,你需要安装Rust和Git。" + +#: src/ch01-01-installation.md:9 +msgid "" +"```bash\n" +"# Install stable Rust\n" +"rustup override set stable && rustup update\n" +"```" +msgstr "" +"```bash\n" +"# 安装稳定的Rust\n" +"rustup override set stable && rustup update\n" +"```" + +#: src/ch01-01-installation.md:14 +msgid "Install [Git](https://git-scm.com/)." +msgstr "安装[Git](https://git-scm.com/)。" + +#: src/ch01-01-installation.md:16 +msgid "" +"## Installing Cairo with a Script ([Installer](https://github.com/franalgaba/" +"cairo-installer) by [Fran](https://github.com/franalgaba))" +msgstr "" +"##用脚本安装Cairo([Installer](https://github.com/franalgaba/cairo-" +"installer) by [Fran](https://github.com/franalgaba))" + +#: src/ch01-01-installation.md:18 +msgid "### Install" +msgstr "###安装" + +#: src/ch01-01-installation.md:20 +msgid "" +"If you wish to install a specific release of Cairo rather than the latest " +"head, set the `CAIRO_GIT_TAG` environment variable (e.g. `export " +"CAIRO_GIT_TAG=v1.0.0`)." +msgstr "" +"如果你想安装一个特定的Cairo版本,而不是最新版本,可以设置`CAIRO_GIT_TAG`环境" +"变量(例如`export CAIRO_GIT_TAG=v1.0.0`)。" + +#: src/ch01-01-installation.md:22 +msgid "" +"```bash\n" +"curl -L https://github.com/franalgaba/cairo-installer/raw/main/bin/cairo-" +"installer | bash\n" +"```" +msgstr "" +"```bash\n" +"curl -L https://github.com/franalgaba/cairo-installer/raw/main/bin/cairo-" +"installer | bash\n" +"```" + +#: src/ch01-01-installation.md:26 +msgid "" +"After installing, follow [these instructions](#set-up-your-shell-environment-" +"for-cairo) to set up your shell environment." +msgstr "" +"安装完毕后,按照[说明](#set-up-your-shell-environment-for-cairo)来设置你的" +"shell环境。" + +#: src/ch01-01-installation.md:28 +msgid "### Update" +msgstr "###更新" + +#: src/ch01-01-installation.md:30 +msgid "" +"```\n" +"rm -fr ~/.cairo\n" +"curl -L https://github.com/franalgaba/cairo-installer/raw/main/bin/cairo-" +"installer | bash\n" +"```" +msgstr "" +"```\n" +"rm -fr ~/.cairo\n" +"curl -L https://github.com/franalgaba/cairo-installer/raw/main/bin/cairo-" +"installer | bash\n" +"```" + +#: src/ch01-01-installation.md:35 +msgid "### Uninstall" +msgstr "###卸载" + +#: src/ch01-01-installation.md:37 +msgid "" +"Cairo is installed within `$CAIRO_ROOT` (default: ~/.cairo). To uninstall, " +"just remove it:" +msgstr "Cairo被安装在`$CAIRO_ROOT`(默认:~/.cairo)。要卸载它,只需删除它:" + +#: src/ch01-01-installation.md:39 +msgid "" +"```bash\n" +"rm -fr ~/.cairo\n" +"```" +msgstr "" +"```bash\n" +"rm -fr ~/.cairo\n" +"```" + +#: src/ch01-01-installation.md:43 +msgid "then remove these three lines from .bashrc:" +msgstr "然后从.bashrc中删除这三行:" + +#: src/ch01-01-installation.md:45 +msgid "" +"```bash\n" +"export PATH=\"$HOME/.cairo/target/release:$PATH\"\n" +"```" +msgstr "" +"```bash\n" +"export PATH=\"$HOME/.cairo/target/release:$PATH\"\n" +"```" + +#: src/ch01-01-installation.md:49 +msgid "and finally, restart your shell:" +msgstr "最后,重新启动你的shell:" + +#: src/ch01-01-installation.md:51 +msgid "" +"```bash\n" +"exec $SHELL\n" +"```" +msgstr "" +"``bash\n" +"exec $SHELL\n" +"```" + +#: src/ch01-01-installation.md:55 +msgid "### Set up your shell environment for Cairo" +msgstr "###为Cairo设置你的shell环境" + +#: src/ch01-01-installation.md:57 +msgid "" +"- Define environment variable `CAIRO_ROOT` to point to the path where\n" +" Cairo will store its data. `$HOME/.cairo` is the default.\n" +" If you installed Cairo via Git checkout, we recommend\n" +" to set it to the same location as where you cloned it.\n" +"- Add the `cairo-*` executables to your `PATH` if it's not already there" +msgstr "" +"- 定义环境变量`CAIRO_ROOT`,以指向Cairo存储数据的路径。\n" +" Cairo将存储其数据的路径。`$HOME/.cairo`是默认的。\n" +" 如果你通过Git checkout安装Cairo,我们建议\n" +" 把它设置到与你克隆它的位置相同的位置。\n" +"- 将`cairo-*`可执行文件添加到你的`PATH`中,如果它还不在那里的话" + +#: src/ch01-01-installation.md:63 +msgid "" +"The below setup should work for the vast majority of users for common use " +"cases." +msgstr "下面的设置应该适用于绝大多数用户的一般使用情况。" + +#: src/ch01-01-installation.md:65 +msgid "" +"- For **bash**:\n" +"\n" +" Stock Bash startup files vary widely between distributions in which of " +"them source\n" +" which, under what circumstances, in what order and what additional " +"configuration they perform.\n" +" As such, the most reliable way to get Cairo in all environments is to " +"append Cairo\n" +" configuration commands to both `.bashrc` (for interactive shells)\n" +" and the profile file that Bash would use (for login shells).\n" +"\n" +" First, add the commands to `~/.bashrc` by running the following in your " +"terminal:\n" +"\n" +" ```bash\n" +" echo 'export CAIRO_ROOT=\"$HOME/.cairo\"' >> ~/.bashrc\n" +" echo 'command -v cairo-compile >/dev/null || export PATH=\"$CAIRO_ROOT/" +"target/release:$PATH\"' >> ~/.bashrc\n" +" ```\n" +"\n" +" Then, if you have `~/.profile`, `~/.bash_profile` or `~/.bash_login`, add " +"the commands there as well.\n" +" If you have none of these, add them to `~/.profile`.\n" +"\n" +" - to add to `~/.profile`:\n" +"\n" +" ```bash\n" +" echo 'export CAIRO_ROOT=\"$HOME/.cairo\"' >> ~/.profile\n" +" echo 'command -v cairo-compile >/dev/null || export PATH=\"$CAIRO_ROOT/" +"target/release:$PATH\"' >> ~/.profile\n" +" ```\n" +"\n" +" - to add to `~/.bash_profile`:\n" +" ```bash\n" +" echo 'export CAIRO_ROOT=\"$HOME/.cairo\"' >> ~/.bash_profile\n" +" echo 'command -v cairo-compile >/dev/null || export PATH=\"$CAIRO_ROOT/" +"target/release:$PATH\"' >> ~/.bash_profile\n" +" ```\n" +"\n" +"- For **Zsh**:\n" +"\n" +" ```zsh\n" +" echo 'export CAIRO_ROOT=\"$HOME/.cairo\"' >> ~/.zshrc\n" +" echo 'command -v cairo-compile >/dev/null || export PATH=\"$CAIRO_ROOT/" +"target/release:$PATH\"' >> ~/.zshrc\n" +" ```\n" +"\n" +" If you wish to get Cairo in non-interactive login shells as well, also add " +"the commands to `~/.zprofile` or `~/.zlogin`.\n" +"\n" +"- For **Fish shell**:\n" +"\n" +" If you have Fish 3.2.0 or newer, execute this interactively:\n" +"\n" +" ```fish\n" +" set -Ux CAIRO_ROOT $HOME/.cairo\n" +" fish_add_path $CAIRO_ROOT/target/release\n" +" ```\n" +"\n" +" Otherwise, execute the snippet below:\n" +"\n" +" ```fish\n" +" set -Ux CAIRO_ROOT $HOME/.cairo\n" +" set -U fish_user_paths $CAIRO_ROOT/target/release $fish_user_paths\n" +" ```" +msgstr "" +"- 对于 **bash** 来说:\n" +"\n" +" 各个发行版间的 Stock Bash 的启动文件在什么情况下调用什么样的文件,以什么顺" +"序执行,并进行哪些额外的配置都存在很大的差异\n" +" 因此,在所有环境中获得 Cairo 的最可靠方法是将 Cairo 配置命令附加到`.bashrc`" +"(用于交互式shell)和Bash将使用的配置文件中。(用于登录shell)。\n" +"\n" +" 首先,通过在终端运行以下命令,将这些命令添加到`~/.bashrc`中:\n" +"\n" +" ``bash\n" +" echo 'export CAIRO_ROOT=\"$HOME/.cairo\"' >> ~/.bashrc\n" +" echo 'command -v cairo-compile >/dev/null || export PATH=\"$CAIRO_ROOT/" +"target/release:$PATH\">> ~/.bashrc\n" +" ```\n" +"\n" +" 然后,如果你有 `~/.profile`、`~/.bash_profile`或`~/.bash_login`,也将这些命" +"令添加到它们所对应的文件中。如果没有这些文件,则添加到 `~/.profile`中。\n" +"\n" +" - 来添加到 `~/.profile` 中:\n" +"\n" +" ``bash\n" +" echo 'export CAIRO_ROOT=\"$HOME/.cairo\"' >> ~/.profile\n" +" echo 'command -v cairo-compile >/dev/null || export PATH=\"$CAIRO_ROOT/" +"target/release:$PATH\"'>> ~/.profile\n" +" ```\n" +"\n" +" - 来添加到`~/.bash_profile`:\n" +" ``bash\n" +" echo 'export CAIRO_ROOT=\"$HOME/.cairo\"' >> ~/.bash_profile\n" +" echo 'command -v cairo-compile >/dev/null || export PATH=\"$CAIRO_ROOT/" +"target/release:$PATH\">> ~/.bash_profile\n" +" ```\n" +"\n" +"- 对于**Zsh**:\n" +"\n" +" ``zsh\n" +" echo 'export CAIRO_ROOT=\"$HOME/.cairo\"' >> ~/.zshrc\n" +" echo 'command -v cairo-compile >/dev/null || export PATH=\"$CAIRO_ROOT/" +"target/release:$PATH\"' 。>> ~/.zshrc\n" +" ```\n" +"\n" +" 如果你希望在非交互式登录shell中也能得到Cairo,也可以将这些命令添加到`~/." +"zprofile`或`~/.zlogin`。\n" +"\n" +"- 对于**Fish shell**:\n" +"\n" +" 如果你有Fish 3.2.0或更新版本,请以交互方式执行:\n" +"\n" +" ```fish\n" +" set -Ux CAIRO_ROOT $HOME/.cairo\n" +" fish_add_path $CAIRO_ROOT/target/release\n" +" ```\n" +"\n" +" 否则,执行下面的片段:\n" +"\n" +" ``fish\n" +" set -Ux CAIRO_ROOT $HOME/.cairo\n" +" set -U fish_user_paths $CAIRO_ROOT/target/release $fish_user_paths\n" +" ```" + +#: src/ch01-01-installation.md:121 +msgid "" +"In MacOS, you might also want to install [Fig](https://fig.io/) which\n" +"provides alternative shell completions for many command line tools with an\n" +"IDE-like popup interface in the terminal window.\n" +"(Note that their completions are independent from Cairo's codebase\n" +"so they might be slightly out of sync for bleeding-edge interface changes.)" +msgstr "" +"在 MacOS 中,你可能还想安装[Fig](https://fig.io/)。它为许多命令行工具提供了" +"替\n" +"代性的 shell 补全功能,并在终端窗口有一个类似于 IDE 的弹出式界面。(注意,他" +"们\n" +"的完成方式与Cairo的代码库无关,所以他们可能在最新界面更改方面略微不同步)。" + +#: src/ch01-01-installation.md:127 +msgid "### Restart your shell" +msgstr "### 重新启动你的shell" + +#: src/ch01-01-installation.md:129 +msgid "for the `PATH` changes to take effect." +msgstr "以使 \"PATH \"的改变生效。" + +#: src/ch01-01-installation.md:131 +msgid "" +"```sh\n" +"exec \"$SHELL\"\n" +"```" +msgstr "" +"```sh\n" +"exec \"$SHELL\"\n" +"```" + +#: src/ch01-01-installation.md:135 +msgid "" +"## Installing Cairo Manually ([Guide](https://github.com/auditless/cairo-" +"template) by [Abdel](https://github.com/abdelhamidbakhta))" +msgstr "" +"##手动安装Cairo([指南](https://github.com/auditless/cairo-template)由[Abdel]" +"(https://github.com/abdelhamidbakhta)提供)" + +#: src/ch01-01-installation.md:137 +msgid "### Step 1: Install Cairo 1.0" +msgstr "###第1步:安装Cairo 1.0" + +#: src/ch01-01-installation.md:139 +msgid "" +"If you are using an x86 Linux system and can use the release binary, " +"download Cairo here: ." +msgstr "" +"如果你使用的是 x86 Linux 系统,并且可以使用发布的二进制文件,请在这里下载" +"Cairo:。" + +#: src/ch01-01-installation.md:141 +msgid "For everyone else, we recommend compiling Cairo from source as follows:" +msgstr "对于其他人,我们建议从源码编译 Cairo,如下所示:" + +#: src/ch01-01-installation.md:143 +msgid "" +"```bash\n" +"# Start by defining environment variable CAIRO_ROOT\n" +"export CAIRO_ROOT=\"${HOME}/.cairo\"\n" +"\n" +"# Create .cairo folder if it doesn't exist yet\n" +"mkdir $CAIRO_ROOT\n" +"\n" +"# Clone the Cairo compiler in $CAIRO_ROOT (default root)\n" +"cd $CAIRO_ROOT && git clone git@github.com:starkware-libs/cairo.git .\n" +"\n" +"# OPTIONAL/RECOMMENDED: If you want to install a specific version of the " +"compiler\n" +"# Fetch all tags (versions)\n" +"git fetch --all --tags\n" +"# View tags (you can also do this in the cairo compiler repository)\n" +"git describe --tags `git rev-list --tags`\n" +"# Checkout the version you want\n" +"git checkout tags/v1.0.0\n" +"\n" +"# Generate release binaries\n" +"cargo build --all --release\n" +"```" +msgstr "" +"```bash\n" +"# 开始定义环境变量CAIRO_ROOT\n" +"export CAIRO_ROOT=\"${HOME}/.cairo\"\n" +"\n" +"# 创建.cairo文件夹,如果它还不存在的话\n" +"mkdir $CAIRO_ROOT\n" +"\n" +"# 在$CAIRO_ROOT中克隆Cairo编译器(默认根目录)\n" +"cd $CAIRO_ROOT && git clone git@github.com:starkware-libs/cairo.git .\n" +"\n" +"# OPTIONAL/RECOMMENDED: 如果你想安装一个特定版本的编译器\n" +"# 获取所有标签(版本)\n" +"git fetch --all --tags\n" +"# 查看标签(你也可以在 cairo 编译器仓库中这样做)\n" +"git describe --tags `git rev-list --tags`。\n" +"# 检查你想要的版本\n" +"git checkout tags/v1.0.0\n" +"\n" +"# 生成发布版二进制文件\n" +"cargo build --all --release\n" +"```" + +#: src/ch01-01-installation.md:165 +msgid "." +msgstr "." + +#: src/ch01-01-installation.md:167 +msgid "**NOTE: Keeping Cairo up to date**" +msgstr "**注意:保持Cairo已更新到最新版本**" + +#: src/ch01-01-installation.md:169 +msgid "" +"Now that your Cairo compiler is in a cloned repository, all you will need to " +"do\n" +"is pull the latest changes and rebuild as follows:" +msgstr "" +"现在你的Cairo编译器已经在一个克隆的仓库里了,你所需要做的是拉取最新的修改,\n" +"并按如下方式重建:" + +#: src/ch01-01-installation.md:172 +msgid "" +"```bash\n" +"cd $CAIRO_ROOT && git fetch && git pull && cargo build --all --release\n" +"```" +msgstr "" +"``bash\n" +"cd $CAIRO_ROOT && git fetch && git pull && cargo build --all --release\n" +"```" + +#: src/ch01-01-installation.md:176 +msgid "### Step 2: Add Cairo 1.0 executables to your path" +msgstr "###第二步:将Cairo 1.0的可执行文件添加到你的路径中" + +#: src/ch01-01-installation.md:178 +msgid "" +"```bash\n" +"export PATH=\"$CAIRO_ROOT/target/release:$PATH\"\n" +"```" +msgstr "" +"``bash\n" +"export PATH=\"$CAIRO_ROOT/target/release:$PATH\"\n" +"```" + +#: src/ch01-01-installation.md:182 +msgid "" +"**NOTE: If installing from a Linux binary, adapt the destination path " +"accordingly.**" +msgstr "**注意:如果从Linux二进制文件安装,请相应调整目标路径**" + +#: src/ch01-01-installation.md:184 +msgid "### Step 3: Setup Language Server" +msgstr "### 第三步:设置语言服务器" + +#: src/ch01-01-installation.md:186 +msgid "#### VS Code Extension" +msgstr "#### VS代码扩展" + +#: src/ch01-01-installation.md:188 +msgid "" +"- Disable previous Cairo 0.x extension\n" +"- Install the Cairo 1 extension for proper syntax highlighting and code " +"navigation.\n" +" Just follow the steps indicated [here](https://github.com/starkware-libs/" +"cairo/blob/main/vscode-cairo/README.md)." +msgstr "" +"- 禁用以前的 Cairo 0.x 扩展\n" +"- 安装Cairo 1扩展以获得正确的语法高亮和代码导航。\n" +"只要按照[这里](https://github.com/starkware-libs/cairo/blob/main/vscode-" +"cairo/README.md)所示的步骤就可以了。" + +#: src/ch01-01-installation.md:192 +msgid "#### Cairo Language Server" +msgstr "#### Cairo语言服务器" + +#: src/ch01-01-installation.md:194 +msgid "" +"From [Step 1](#step-1-install-cairo-10-guide-by-abdel), the `cairo-language-" +"server` binary should be built and executing this command will copy its path " +"into your clipboard." +msgstr "" +"从[Step 1](#step-1-install-cairo-10-guide-by-abdel),`cairo-language-" +"server'二进制文件应该已经建立,执行这个命令将复制其路径到你的剪贴板。" + +#: src/ch01-01-installation.md:196 +msgid "" +"```bash\n" +"which cairo-language-server | pbcopy\n" +"```" +msgstr "" +"```bash\n" +"which cairo-language-server | pbcopy\n" +"```" + +#: src/ch01-01-installation.md:200 +msgid "" +"Update the `languageServerPath` of the Cairo 1.0 extension by pasting the " +"path." +msgstr "通过粘贴路径更新Cairo 1.0扩展的`languageServerPath`。" + +#: src/ch01-02-hello-world.md:1 +msgid "## Hello, World" +msgstr "## Hello, World" + +#: src/ch01-02-hello-world.md:3 +msgid "" +"Now that you’ve installed Cairo, it’s time to write your first Cairo " +"program.\n" +"It’s traditional when learning a new language to write a little program " +"that\n" +"prints the text `Hello, world!` to the screen, so we’ll do the same here!" +msgstr "" +"现在你已经安装了Cairo,是时候编写你的第一个Cairo程序了。\n" +"在学习一门新语言时,传统的做法是写一个小程序\n" +"将文字`Hello, world!`打印到屏幕上,所以我们在这里也要这样做!" + +#: src/ch01-02-hello-world.md:7 +msgid "" +"> Note: This book assumes basic familiarity with the command line. Cairo " +"makes\n" +"> no specific demands about your editing or tooling or where your code " +"lives, so\n" +"> if you prefer to use an integrated development environment (IDE) instead " +"of\n" +"> the command line, feel free to use your favorite IDE. The Cairo team has " +"developed\n" +"> a VSCode extension for the Cairo language that you can use to get the " +"features from\n" +"> the language server and code highlighting. See [Appendix A][devtools]\n" +"> for more details." +msgstr "" +"> 注意:本书假定对命令行有基本的熟悉。Cairo对\n" +"> 对你的编辑或工具或你的代码所处的位置没有特别要求,所以\n" +"> 如果你喜欢使用集成开发环境(IDE)而不是\n" +"> 命令行,请随意使用你喜欢的IDE。Cairo团队已经开发了\n" +"> Cairo语言的VSCode扩展,你可以用它来获得来自\n" +"> 语言服务器和代码高亮。参见[附录A][devtools]。\n" +"> 了解更多细节。" + +#: src/ch01-02-hello-world.md:15 +msgid "### Creating a Project Directory" +msgstr "### 创建一个项目目录" + +#: src/ch01-02-hello-world.md:17 +msgid "" +"You’ll start by making a directory to store your Cairo code. It doesn’t " +"matter\n" +"to Cairo where your code lives, but for the exercises and projects in this " +"book,\n" +"we suggest making a _cairo_projects_ directory in your home directory and " +"keeping all\n" +"your projects there." +msgstr "" +"你首先要做一个目录来存储你的Cairo代码。对于Cairo来说,你的代码放在哪里并不重" +"要。\n" +"但对于本书中的练习和项目来说,我们建议在你的主目录下建立一个_cairo_projects_" +"目录,并保存所有的代码、\n" +"我们建议在你的主目录下建立一个_cairo_projects_目录,并将所有的\n" +"你的项目都放在那里。" + +#: src/ch01-02-hello-world.md:22 +msgid "" +"Open a terminal and enter the following commands to make a _cairo_projects_ " +"directory\n" +"and a directory for the “Hello, world!” project within the _cairo_projects_ " +"directory." +msgstr "" +"打开一个终端,输入以下命令,建立一个_cairo_projects_目录\n" +"并在_cairo_projects_目录下为 \"Hello, world!\"项目建立一个目录。" + +#: src/ch01-02-hello-world.md:25 +msgid "For Linux, macOS, and PowerShell on Windows, enter this:" +msgstr "对于Linux、macOS和Windows上的PowerShell,输入这个:" + +#: src/ch01-02-hello-world.md:27 +msgid "" +"```console\n" +"mkdir ~/cairo_projects\n" +"cd ~/cairo_projects\n" +"mkdir hello_world\n" +"cd hello_world\n" +"```" +msgstr "" +"```console\n" +"mkdir ~/cairo_projects\n" +"cd ~/cairo_projects\n" +"mkdir hello_world\n" +"cd hello_world\n" +"```" + +#: src/ch01-02-hello-world.md:34 +msgid "For Windows CMD, enter this:" +msgstr "对于Windows CMD,请输入以下内容:" + +#: src/ch01-02-hello-world.md:36 +msgid "" +"```cmd\n" +"> mkdir \"%USERPROFILE%\\projects\"\n" +"> cd /d \"%USERPROFILE%\\projects\"\n" +"> mkdir hello_world\n" +"> cd hello_world\n" +"```" +msgstr "" +"```cmd\n" +"> mkdir \"%USERPROFILE%\\projects\"\n" +"> cd /d \"%USERPROFILE%/projects\"\n" +"> mkdir hello_world\n" +"> cd hello_world\n" +"```" + +#: src/ch01-02-hello-world.md:43 +msgid "### Writing and Running a Cairo Program" +msgstr "### 编写和运行Cairo程序" + +#: src/ch01-02-hello-world.md:45 +msgid "" +"Next, make a new source file and call it _main.cairo_. Cairo files always " +"end with\n" +"the _.cairo_ extension. If you’re using more than one word in your filename, " +"the\n" +"convention is to use an underscore to separate them. For example, use\n" +"_hello_world.cairo_ rather than _helloworld.cairo_." +msgstr "" +"接下来,制作一个新的源代码文件,并将其称为_main.cairo_。Cairo文件总是以\n" +"扩展名为_.cairo_。如果你在文件名中使用一个以上的词,惯例是用下划线来分隔它" +"们。\n" +"惯例是用下划线来分隔它们。例如,使用\n" +"_hello_world.cairo_而不是_helloworld.cairo_。" + +#: src/ch01-02-hello-world.md:50 +msgid "" +"Now open the _main.cairo_ file you just created and enter the code in " +"Listing 1-1." +msgstr "现在打开你刚刚创建的_main.cairo_文件,输入清单1-1中的代码。" + +#: src/ch01-02-hello-world.md:52 src/ch02-05-control-flow.md:9 +#: src/ch02-05-control-flow.md:58 src/ch02-05-control-flow.md:90 +msgid "Filename: main.cairo" +msgstr "文件名:main.cairo" + +#: src/ch01-02-hello-world.md:54 +msgid "" +"```rust,file=hello_world.cairo\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" 'Hello, world!'.print();\n" +"}\n" +"```" +msgstr "" +"``rust,file=hello_world.cairo\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" 'Hello, world!'.print();\n" +"}\n" +"```" + +#: src/ch01-02-hello-world.md:61 +msgid "" +"Listing 1-1: A program that prints `Hello, world!`" +msgstr "" +"清单1-1:一个打印 \"Hello,world\"的程序。" + +#: src/ch01-02-hello-world.md:63 +msgid "" +"Save the file and go back to your terminal window in the\n" +"_~/cairo_projects/hello_world_ directory. Enter the following\n" +"commands to compile and run the file:" +msgstr "" +"保存该文件,并回到你的终端窗口,在\n" +"_~/cairo_projects/hello_world_目录。输入以下\n" +"命令来编译和运行该文件:" + +#: src/ch01-02-hello-world.md:67 +msgid "" +"```console\n" +"$ cairo-run main.cairo\n" +"Hello, world!\n" +"```" +msgstr "" +"```console\n" +"$ cairo-run main.cairo\n" +"Hello, world!\n" +"```" + +#: src/ch01-02-hello-world.md:72 +msgid "" +"Regardless of your operating system, the string `Hello, world!` should print " +"to\n" +"the terminal." +msgstr "无论你的操作系统如何,字符串`Hello, world!`应该打印到终端。" + +#: src/ch01-02-hello-world.md:75 +msgid "" +"If `Hello, world!` did print, congratulations! You’ve officially written a " +"Cairo\n" +"program. That makes you a Cairo programmer—welcome!" +msgstr "" +"如果 \"Hello,world!\"确实打印出来了,那么恭喜你!你已经正式写出了Cairo!\n" +"你已经正式写了一个Cairo程序。这使你成为一名Cairo程序员--欢迎!" + +#: src/ch01-02-hello-world.md:78 +msgid "### Anatomy of a Cairo Program" +msgstr "### 解析Cairo程序" + +#: src/ch01-02-hello-world.md:80 +msgid "" +"Let’s review this “Hello, world!” program in detail. Here’s the first piece " +"of\n" +"the puzzle:" +msgstr "" +"让我们详细回顾一下这个 \"Hello,world!\"程序。这里有第一块\n" +"拼图的第一部分:" + +#: src/ch01-02-hello-world.md:83 +msgid "" +"```rust\n" +"fn main() {\n" +"\n" +"}\n" +"```" +msgstr "" +"``rust\n" +"fn main() {\n" +"\n" +"}\n" +"```" + +#: src/ch01-02-hello-world.md:89 +msgid "" +"These lines define a function named `main`. The `main` function is special: " +"it\n" +"is always the first code that runs in every executable Cairo program. Here, " +"the\n" +"first line declares a function named `main` that has no parameters and " +"returns\n" +"nothing. If there were parameters, they would go inside the parentheses `()`." +msgstr "" +"这些行定义了一个名为 \"main \"的函数。`main'函数很特别:它总是每个可执行的" +"Cairo程序中运行的第一个代码。\n" +"始终是每个可执行的Cairo程序中运行的第一段代码。这里,第一行\n" +"第一行声明了一个名为 \"main \"的函数,没有参数,也不返回\n" +"什么都没有。如果有参数,它们会被放在括号`()`里。" + +#: src/ch01-02-hello-world.md:94 +msgid "" +"The function body is wrapped in `{}`. Cairo requires curly brackets around " +"all\n" +"function bodies. It’s good style to place the opening curly bracket on the " +"same\n" +"line as the function declaration, adding one space in between." +msgstr "" +"函数主体被包裹在\"{}\"中。Cairo要求在所有的函数体周围加上大括号\n" +"将开头的左大括号与函数声明放在同一行是很好的编码风格。\n" +"别忘了在它们中间加一个空格。" + +#: src/ch01-02-hello-world.md:98 +msgid "" +"> Note: If you want to stick to a standard style across Cairo projects, you " +"can\n" +"> use the automatic formatter tool called `cairo-format` to format your code " +"in a\n" +"> particular style (more on `cairo-format` in\n" +"> [Appendix A][devtools]). The Cairo team has included this tool\n" +"> with the standard Cairo distribution, as `cairo-run` is, so it should " +"already be\n" +"> installed on your computer!" +msgstr "" +"> 注意:如果你想在Cairo项目中坚持一个标准的风格,你可以\n" +"> 使用自动格式化工具`cairo-format`来将你的代码格式化为\n" +"> 特定的风格(更多关于`cairo-format'的信息见\n" +"> [附录A][devtools])。Cairo团队已经将这个工具\n" +"> 包含在标准的Cairo发行版中,就像`cairo-run`一样,所以它应该已经被\n" +"> 已经安装在你的计算机上了!" + +#: src/ch01-02-hello-world.md:105 +msgid "" +"Prior to the main function declaration, The line `use debug::PrintTrait;` is " +"responsible for importing an item defined in another module. In this case, " +"we are importing the `PrintTrait` item from the Cairo core library. By doing " +"so, we gain the ability to use the `print()` method on data types that are " +"compatible with printing." +msgstr "" +"在主函数声明之前,`use debug::PrintTrait;`一行负责导入另一个模块中定义的项" +"目。在这个例子中,我们从Cairo核心库中导入了`PrintTrait`项目。通过这样做,我们" +"获得了在兼容打印的数据类型上使用`print()`方法的能力。" + +#: src/ch01-02-hello-world.md:107 +msgid "The body of the `main` function holds the following code:" +msgstr "`main`函数的主体包含以下代码:" + +#: src/ch01-02-hello-world.md:109 +msgid "" +"```rust\n" +" 'Hello, world!'.print();\n" +"```" +msgstr "" +"``rust\n" +" 'Hello, world!'.print();\n" +"```" + +#: src/ch01-02-hello-world.md:113 +msgid "" +"This line does all the work in this little program: it prints text to the\n" +"screen. There are four important details to notice here." +msgstr "" +"这一行完成了这个小程序的所有工作:它将文本打印到\n" +"屏幕上。这里有四个重要的细节需要注意。" + +#: src/ch01-02-hello-world.md:116 +msgid "First, Cairo style is to indent with four spaces, not a tab." +msgstr "首先,Cairo的风格是用四个空格缩进,而不是用制表符。" + +#: src/ch01-02-hello-world.md:118 +msgid "" +"Second, the `print()` function called is a method from the trait " +"`PrintTrait`. This trait is imported from the Cairo core library, and it " +"defines how to print values to the screen for different data types. In our " +"case, our text is defined as a \"short string\", which is an ASCII string " +"that can fit in Cairo's basic data type, which is the `felt252` type. By " +"calling `Hello, world!'.print()`, we're calling the `print()` method of the " +"`felt252` implementation of the `PrintTrait` trait." +msgstr "" +"第二,调用的`print()`函数是来自trait`PrintTrait`的一个方法。这个trait是从" +"Cairo核心库中导入的,它定义了如何将不同数据类型的值打印到屏幕上。在我们的例子" +"中,我们的文本被定义为 \"short string\",这是一个ASCII字符串,可以适合Cairo的" +"基本数据类型,即`felt252`类型。通过调用`Hello, world!'.print()`,我们正在调用" +"`PrintTrait`特质的`felt252`实现的`print()`方法。" + +#: src/ch01-02-hello-world.md:120 +msgid "" +"Third, you see the `'Hello, world!'` short string. We pass this short string " +"as an argument\n" +"to `print()`, and the short string is printed to the screen." +msgstr "" +"第三,你看到了\"'Hello, world!'\"短字符串。我们把这个短字符串作为一个参数传" +"给\n" +"作为参数传递给`print()',短字符串被打印到屏幕上。" + +#: src/ch01-02-hello-world.md:123 +msgid "" +"Fourth, we end the line with a semicolon (`;`), which indicates that this\n" +"expression is over and the next one is ready to begin. Most lines of Cairo " +"code\n" +"end with a semicolon." +msgstr "" +"第四,我们用分号(`;`)来结束这一行,这表示这个表达式已经结束,下一个表达式准" +"备开始。\n" +"表达式已经结束,下一个表达式可以开始了。大多数Cairo的代码行\n" +"以分号结束。" + +#: src/ch01-02-hello-world.md:127 +msgid "" +"Just running with `cairo-run` is fine for simple programs, but as your " +"project\n" +"grows, you’ll want to manage all the options and make it easy to share your\n" +"code. Next, we’ll introduce you to the Scarb tool, which will help you " +"write\n" +"real-world Cairo programs." +msgstr "" +"只用`cairo-run`运行简单的程序是可以的,但随着你的项目\n" +"增长,你会希望管理所有的选项,并使之易于分享你的\n" +"代码。接下来,我们将向你介绍Scarb工具,它将帮助你编写\n" +"真实世界的Cairo程序。" + +#: src/ch01-03-hello-scarb.md:1 +msgid "# Hello, Scarb" +msgstr "# 你好,Scarb" + +#: src/ch01-03-hello-scarb.md:3 +msgid "" +"Scarb is the Cairo package manager and heavily inspired by [Cargo](https://" +"doc.rust-lang.org/cargo/), Rust’s build system and package manager." +msgstr "" +"Scarb是Cairo的软件包管理器,在很大程度上受到[Cargo](https://doc.rust-lang." +"org/cargo/)的启发,Rust的构建系统和软件包管理器。" + +#: src/ch01-03-hello-scarb.md:5 +msgid "" +"Scarb handles a lot of tasks for you, such as building your code (either " +"pure Cairo or Starknet contracts), downloading the libraries your code " +"depends on, and building those libraries." +msgstr "" +"Scarb为你处理很多任务,比如构建你的代码(纯Cairo或Starknet合约),下载你的代" +"码所依赖的库,并构建这些库。" + +#: src/ch01-03-hello-scarb.md:7 +msgid "" +"If we were to build the 'Hello, world!' project using Scarb, only the part " +"of Scarb that handles building the code would be utilized, since the program " +"doesn't require any external dependencies. As you write more complex Cairo " +"programs, you’ll add dependencies, and if you start a project using Scarb, " +"adding dependencies will be much easier to do." +msgstr "" +"如果我们用Scarb来构建'Hello, world!'项目,只有Scarb处理构建代码的部分会被利" +"用,因为该程序不需要任何外部依赖。当你编写更复杂的Cairo程序时,你会增加依赖" +"性,如果你使用Scarb开始一个项目,增加依赖性将更容易做到。" + +#: src/ch01-03-hello-scarb.md:9 +msgid "Let's start by installing Scarb." +msgstr "让我们从安装Scarb开始。" + +#: src/ch01-03-hello-scarb.md:11 +msgid "## Installing Scarb" +msgstr "## 安装Scarb" + +#: src/ch01-03-hello-scarb.md:13 +msgid "### Requirements" +msgstr "###要求" + +#: src/ch01-03-hello-scarb.md:15 +msgid "" +"Scarb requires a Git executable to be available in the `PATH` environment " +"variable." +msgstr "Scarb需要在`PATH`环境变量里有一个Git可执行文件。" + +#: src/ch01-03-hello-scarb.md:17 +msgid "### Installation" +msgstr "###安装" + +#: src/ch01-03-hello-scarb.md:19 +msgid "As for now, Scarb needs manual installation with the following steps:" +msgstr "就目前而言,Scarb需要手动安装,步骤如下:" + +#: src/ch01-03-hello-scarb.md:21 +msgid "" +"- Download the release archive matching your operating system and CPU " +"architecture, from [Scarb releases on GitHub](https://github.com/software-" +"mansion/scarb/releases)\n" +"- Extract it to a location where you would like to have Scarb installed, e." +"g. `~/scarb`\n" +"- Add path to the `scarb/bin` directory to your `PATH` environment " +"variable.\n" +"\n" +" This depend on what shell you are using. Let’s take the example of [zsh]" +"(https://ohmyz.sh/) and you have extracted Scarb to `~/scarb`:\n" +"\n" +" - Open `~/.zshrc` file in your favorite editor\n" +" - Add the following line to the end of the file: `export PATH=\"$PATH:~/" +"scarb/bin\"`\n" +"\n" +"- Verify installation by running the following command in new terminal " +"session, it should print both Scarb and Cairo language versions, e.g:\n" +"\n" +" ```bash\n" +" $ scarb --version\n" +" scarb 0.1.0 (289137c24 2023-03-28)\n" +" cairo: 1.0.0-alpha.6\n" +" ```" +msgstr "" +"- 从[GitHub上的Scarb发布](https://github.com/software-mansion/scarb/releases)" +"下载与你的操作系统和CPU架构相匹配的发布档案。\n" +"- 将其解压到你想安装Scarb的位置,例如`~/scarb`。\n" +"- 将`scarb/bin`目录的路径添加到你的`PATH`环境变量中。\n" +"\n" +" 这取决于你使用的是什么shell。让我们以[zsh](https://ohmyz.sh/)为例,你已经将" +"Scarb提取到`~/scarb`:\n" +"\n" +" - 用你喜欢的编辑器打开`~/.zshrc`文件\n" +" - 在文件的末尾添加以下一行:`export PATH=\"$PATH:~/scarb/bin\"`。\n" +"\n" +"- 在新的终端会话中运行以下命令来验证安装,它应该同时打印Scarb和Cairo语言版" +"本,例如\n" +"\n" +" ``bash\n" +" $ scarb --版本\n" +" scarb 0.1.0 (289137c24 2023-03-28)\n" +" cairo: 1.0.0-alpha.6\n" +" ```" + +#: src/ch01-03-hello-scarb.md:38 +msgid "### Creating a Project with Scarb" +msgstr "###用Scarb创建一个项目" + +#: src/ch01-03-hello-scarb.md:40 +msgid "" +"Let’s create a new project using Scarb and look at how it differs from our " +"original “Hello, world!” project." +msgstr "" +"让我们用Scarb创建一个新的项目,看看它与我们原来的 \"Hello, world!\"项目有什么" +"不同。" + +#: src/ch01-03-hello-scarb.md:42 +msgid "" +"Navigate back to your projects directory (or wherever you decided to store " +"your code). Then run the following:" +msgstr "导航到你的项目目录(或你决定存储代码的地方)。然后运行以下程序:" + +#: src/ch01-03-hello-scarb.md:44 +msgid "" +"```bash\n" +"$ scarb new hello_scarb\n" +"```" +msgstr "" +"```bash\n" +"$ scarb new hello_scarb\n" +"```" + +#: src/ch01-03-hello-scarb.md:48 +msgid "" +"It creates a new directory and project called hello_scarb. We’ve named our " +"project hello_scarb, and Scarb creates its files in a directory of the same " +"name." +msgstr "" +"它创建了一个新的目录和项目,名为hello_scarb。我们把我们的项目命名为" +"hello_scarb,Scarb在同名的目录下创建它的文件。" + +#: src/ch01-03-hello-scarb.md:50 +msgid "" +"Go into the hello_scarb directory with the command `cd hello_scarb`. You’ll " +"see that Scarb has generated two files and one directory for us: a `Scarb." +"toml` file and a src directory with a `lib.cairo` file inside." +msgstr "" +"用`cd hello_scarb`命令进入hello_scarb目录。你会看到Scarb已经为我们生成了两个" +"文件和一个目录:一个`Scarb.toml`文件和一个src目录,里面有一个`lib.cairo`文" +"件。" + +#: src/ch01-03-hello-scarb.md:52 +msgid "" +"It has also initialized a new Git repository along with a `.gitignore` file" +msgstr "它还初始化了一个新的Git仓库和一个`.gitignore`文件" + +#: src/ch01-03-hello-scarb.md:54 +msgid "" +"> Note: Git is a common version control system. You can stop using version " +"control system by using the `--vcs` flag.\n" +"> Run `scarb new -help` to see the available options." +msgstr "" +"> 注意:Git是一个常见的版本控制系统。你可以通过使用`--vcs`标志停止使用版本控" +"制系统。\n" +"> 运行`scarb new -help`以查看可用选项。" + +#: src/ch01-03-hello-scarb.md:57 +msgid "" +"Open _Scarb.toml_ in your text editor of choice. It should look similar to " +"the code in Listing 1-2." +msgstr "" +"在你选择的文本编辑器中打开_Scarb.toml_。它看起来应该与清单1-2中的代码相似。" + +#: src/ch01-03-hello-scarb.md:59 +msgid "Filename: Scarb.toml" +msgstr "文件名:Scarb.toml" + +#: src/ch01-03-hello-scarb.md:61 +msgid "" +"```toml\n" +"[package]\n" +"name = \"hello_scarb\"\n" +"version = \"0.1.0\"\n" +"\n" +"# See more keys and their definitions at https://docs.swmansion.com/scarb/" +"docs/reference/manifest\n" +"\n" +"[dependencies]\n" +"# foo = { path = \"vendor/foo\" }\n" +"```" +msgstr "" +"```toml\n" +"[package]\n" +"name = \"hello_scarb\"\n" +"version = \"0.1.0\"\n" +"\n" +"# 看到更多的键和它们的定义,https://docs.swmansion.com/scarb/docs/reference/" +"manifest\n" +"\n" +"[dependencies]\n" +"# foo = { path = \"vendor/foo\" }\n" +"```" + +#: src/ch01-03-hello-scarb.md:72 +msgid "" +"Listing 1-2: Contents of Scarb.toml generated by " +"`scarb new`" +msgstr "" +"清单1-2:由`scarb new`生成的Scarb.toml的内容" + +#: src/ch01-03-hello-scarb.md:74 +msgid "" +"This file is in the [TOML](https://toml.io/) (Tom’s Obvious, Minimal " +"Language) format, which is Scarb’s configuration format." +msgstr "" +"这个文件是[TOML](https://toml.io/)(Tom's Obvious, Minimal Language)的格式," +"这是Scarb的配置格式。" + +#: src/ch01-03-hello-scarb.md:76 +msgid "" +"The first line, `[package]`, is a section heading that indicates that the " +"following statements are configuring a package. As we add more information " +"to this file, we’ll add other sections." +msgstr "" +"第一行,`[package]`,是一个章节标题,表示下面的语句是在配置一个包。随着我们向" +"这个文件添加更多的信息,我们将添加其他部分。" + +#: src/ch01-03-hello-scarb.md:78 +msgid "" +"The next two lines set the configuration information Scarb needs to compile " +"your program: the name and the version of Scarb to use." +msgstr "" +"接下来的两行设置了Scarb在编译你的程序时需要的配置信息:名称和要使用的Scarb版" +"本。" + +#: src/ch01-03-hello-scarb.md:80 +msgid "" +"The last line, `[dependencies]`, is the start of a section for you to list " +"any of your project’s dependencies. In Cairo, packages of code are referred " +"to as crates. We won’t need any other crates for this project." +msgstr "" +"最后一行,`[dependencies]`,是一个部分的开始,供你列出你的项目的任何依赖性。" +"在Cairo中,代码包被称为crate。在这个项目中,我们不需要任何其他的crates。" + +#: src/ch01-03-hello-scarb.md:82 +msgid "" +"The other file created by Scarb is `src/lib.cairo`, let's delete all the " +"content and put in the following content, we will explain the reason later." +msgstr "" +"Scarb创建的另一个文件是`src/lib.cairo`,让我们删除所有的内容,放入以下内容," +"我们将在后面解释原因。" + +#: src/ch01-03-hello-scarb.md:84 +msgid "" +"```rust\n" +"mod hello_scarb;\n" +"```" +msgstr "" +"``rust\n" +"mod hello_scarb;\n" +"```" + +#: src/ch01-03-hello-scarb.md:88 +msgid "" +"Then create a new file called `src/hello_scarb.cairo` and put the following " +"code in it:" +msgstr "" +"然后创建一个名为`src/hello_scarb.cairo`的新文件,并将以下代码放入其中:" + +#: src/ch01-03-hello-scarb.md:90 +msgid "Filename: src/hello_scarb.cairo" +msgstr "文件名: src/hello_scarb.cairo" + +#: src/ch01-03-hello-scarb.md:92 +msgid "" +"```rust,file=hello_scarb.cairo\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" 'Hello, Scarb!'.print();\n" +"}\n" +"```" +msgstr "" +"``rust,file=hello_scarb.cairo\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" 'Hello,Scarb!'.print();\n" +"}\n" +"```" + +#: src/ch01-03-hello-scarb.md:99 +msgid "" +"We have just created a file called `lib.cairo`, which contains a module " +"declaration referencing another module named \"hello_scarb\", as well as the " +"file `hello_scarb.cairo`,containing the implementation details of the " +"\"hello_scarb\" module." +msgstr "" +"我们刚刚创建了一个名为`lib.cairo`的文件,其中包含一个模块声明,引用了另一个名" +"为 \"hello_scarb \"的模块,以及文件`hello_scarb.cairo`,包含 \"hello_scarb " +"\"模块的实现细节。" + +#: src/ch01-03-hello-scarb.md:101 +msgid "" +"Scarb requires your source files to be located within the src directory." +msgstr "Scarb要求你的源文件位于src目录中。" + +#: src/ch01-03-hello-scarb.md:103 +msgid "" +"The top-level project directory is reserved for README files, license " +"information, configuration files, and any other non-code-related content.\n" +"Scarb ensures a designated location for all project components, maintaining " +"a structured organization." +msgstr "" +"顶层项目目录是为README文件、许可证信息、配置文件和任何其他与代码无关的内容保" +"留的。\n" +"Scarb确保所有项目组件都有一个指定的位置,维持一个结构化的组织。" + +#: src/ch01-03-hello-scarb.md:106 +msgid "" +"If you started a project that doesn’t use Scarb, as we did with the “Hello, " +"world!” project, you can convert it to a project that does use Scarb. Move " +"the project code into the src directory and create an appropriate `Scarb." +"toml` file." +msgstr "" +"如果你启动了一个不使用Scarb的项目,就像我们在 \"Hello, world!\"项目中所做的那" +"样,你可以把它转换成一个使用Scarb的项目。将项目代码移到src目录下,并创建一个" +"适当的`Scarb.toml`文件。" + +#: src/ch01-03-hello-scarb.md:108 +msgid "### Building a Scarb Project" +msgstr "###建立一个Scarb项目" + +#: src/ch01-03-hello-scarb.md:110 +msgid "" +"From your hello_scarb directory, build your project by entering the " +"following command:" +msgstr "从你的hello_scarb目录,通过输入以下命令建立你的项目:" + +#: src/ch01-03-hello-scarb.md:112 +msgid "" +"```bash\n" +"$ scarb build\n" +" Compiling hello_scarb v0.1.0 (file:///projects/Scarb.toml)\n" +" Finished release target(s) in 0 seconds\n" +"```" +msgstr "" +"```bash\n" +"$ scarb build\n" +" Compiling hello_scarb v0.1.0 (file:///projects/Scarb.toml)\n" +" Finished release target(s) in 0 seconds\n" +"```" + +#: src/ch01-03-hello-scarb.md:118 +msgid "" +"This command creates a `sierra` file in `target/release`, let's ignore the " +"`sierra` file for now." +msgstr "" +"这个命令在`target/release`中创建了一个`sierra`文件,现在我们先忽略`sierra`文" +"件。" + +#: src/ch01-03-hello-scarb.md:120 +msgid "" +"If you have installed Cairo correctly, you should be able to run and see the " +"following output:" +msgstr "如果你正确安装了Cairo,你应该能够运行并看到以下输出:" + +#: src/ch01-03-hello-scarb.md:122 +msgid "" +"```bash\n" +"$ cairo-run src/lib.cairo\n" +"[DEBUG] Hello, Scarb! (raw: " +"5735816763073854913753904210465)\n" +"\n" +"Run completed successfully, returning []\n" +"```" +msgstr "" +"```bash\n" +"$ cairo-run src/lib.cairo\n" +"[DEBUG] Hello, Scarb! (raw: " +"5735816763073854913753904210465)\n" +"\n" +"Run completed successfully, returning []\n" +"```" + +#: src/ch01-03-hello-scarb.md:129 +msgid "" +"> Note: You will notice here that we didn't use a Scarb command, but rather " +"a command from the Cairo binaries directly.\n" +"> As Scarb doesn't have a command to execute Cairo code yet, we have to use " +"the `cairo-run` command directly.\n" +"> We will use this command in the rest of the tutorial, but we will also use " +"Scarb commands to initialize projects." +msgstr "" +"> 注意:你会注意到这里我们没有使用Scarb的命令,而是直接使用了Cairo二进制文件" +"的命令。\n" +"> 由于Scarb还没有执行Cairo代码的命令,我们必须直接使用`cairo-run`命令。\n" +"> 在接下来的教程中我们将使用这个命令,但我们也将使用Scarb命令来初始化项目。" + +#: src/ch01-03-hello-scarb.md:133 +msgid "### Defining Custom Scripts" +msgstr "###定义自定义脚本" + +#: src/ch01-03-hello-scarb.md:135 +msgid "" +"We can define Scarb scripts in `Scarb.toml` file, which can be used to " +"execute custom shell scripts.\n" +"Add the following line to your `Scarb.toml` file:" +msgstr "" +"我们可以在`Scarb.toml`文件中定义Scarb脚本,它可以用来执行自定义的shell脚" +"本。\n" +"在你的`Scarb.toml`文件中添加以下一行:" + +#: src/ch01-03-hello-scarb.md:138 +msgid "" +"```toml\n" +"[scripts]\n" +"run-lib = \"cairo-run src/lib.cairo\"\n" +"```" +msgstr "" +"```toml\n" +"[scripts]\n" +"run-lib = \"cairo-run src/lib.cairo\"\n" +"```" + +#: src/ch01-03-hello-scarb.md:143 +msgid "Now you can run the following command to run the project:" +msgstr "现在你可以运行以下命令来运行该项目:" + +#: src/ch01-03-hello-scarb.md:145 +msgid "" +"```bash\n" +"$ scarb run run-lib\n" +"[DEBUG] Hello, Scarb! (raw: " +"5735816763073854913753904210465)\n" +"\n" +"Run completed successfully, returning []\n" +"```" +msgstr "" +"```bash\n" +"$ scarb run run-lib\n" +"[DEBUG] Hello, Scarb! (raw: " +"5735816763073854913753904210465)\n" +"\n" +"Run completed successfully, returning []\n" +"```" + +#: src/ch01-03-hello-scarb.md:152 +msgid "" +"Using `scarb run` is a convenient way to run custom shell scripts that can " +"be useful to run files and test your project." +msgstr "" +"使用 \"scarb run \"是运行自定义shell脚本的一种方便的方法,可以用来运行文件和" +"测试你的项目。" + +#: src/ch01-03-hello-scarb.md:154 +msgid "Let’s recap what we’ve learned so far about Scarb:" +msgstr "让我们回顾一下到目前为止我们所了解到的关于Scarb的情况:" + +#: src/ch01-03-hello-scarb.md:156 +msgid "" +"- We can create a project using `scarb new`.\n" +"- We can build a project using `scarb build` to generate the compiled Sierra " +"code.\n" +"- We can define custom scripts in `Scarb.toml` and call them with the `scarb " +"run` command." +msgstr "" +"- 我们可以使用`scarb new`创建一个项目。\n" +"- 我们可以使用`scarb build`建立一个项目,以生成编译后的Sierra代码。\n" +"- 我们可以在`Scarb.toml`中定义自定义脚本,并使用`scarb run`命令调用它们。" + +#: src/ch01-03-hello-scarb.md:160 +msgid "" +"An additional advantage of using Scarb is that the commands are the same no " +"matter which operating system you’re working on. So, at this point, we’ll no " +"longer provide specific instructions for Linux and macOS versus Windows." +msgstr "" +"使用Scarb的另一个好处是,无论你在哪个操作系统上工作,命令都是一样的。所以,在" +"这一点上,我们将不再提供Linux和macOS与Windows的具体说明。" + +#: src/ch01-03-hello-scarb.md:162 +msgid "# Summary" +msgstr "# 摘要" + +#: src/ch01-03-hello-scarb.md:164 +msgid "" +"You’re already off to a great start on your Cairo journey! In this chapter, " +"you’ve learned how to:" +msgstr "你的Cairo之旅已经有了一个良好的开端!在本章中,你已经学会了如何:" + +#: src/ch01-03-hello-scarb.md:166 +msgid "" +"- Install the latest stable version of Cairo\n" +"- Write and run a “Hello, world!” program using `cairo-run` directly\n" +"- Create and run a new project using the conventions of Scarb" +msgstr "" +"- 安装最新的稳定版本的Cairo\n" +"- 直接使用`cairo-run`编写并运行一个 \"Hello, world!\"程序\n" +"- 使用Scarb的惯例创建并运行一个新项目" + +#: src/ch01-03-hello-scarb.md:170 +msgid "" +"This is a great time to build a more substantial program to get used to " +"reading and writing Cairo code." +msgstr "这是一个建立更多实用程序的好时机,以习惯于阅读和编写Cairo代码。" + +#: src/ch02-00-common-programming-concepts.md:1 +msgid "# Common Programming Concepts" +msgstr "# 常见的编程概念" + +#: src/ch02-00-common-programming-concepts.md:3 +msgid "" +"This chapter covers concepts that appear in almost every programming " +"language and how they work in Cairo. Many programming languages have much in " +"common at their core. None of the concepts presented in this chapter are " +"unique to Cairo, but we’ll discuss them in the context of Cairo and explain " +"the conventions around using these concepts." +msgstr "" +"本章涵盖了几乎所有编程语言中出现的概念,以及它们在Cairo的工作原理。许多编程语" +"言的核心都有很多共同点。本章介绍的概念没有一个是Cairo独有的,但我们会在Cairo" +"的背景下讨论它们,并解释使用这些概念的惯例。" + +#: src/ch02-00-common-programming-concepts.md:5 +msgid "" +"Specifically, you’ll learn about variables, basic types, functions, " +"comments, and control flow. These foundations will be in every Cairo " +"program, and learning them early will give you a strong core to start from." +msgstr "" +"具体来说,你将学习到变量、基本类型、函数、注释和控制流。这些基础将出现在每个" +"Cairo程序中,尽早学习它们将给你一个强大的核心开始。" + +#: src/ch02-01-variables-and-mutability.md:1 +msgid "## Variables and Mutability" +msgstr "## 变量和可变性" + +#: src/ch02-01-variables-and-mutability.md:3 +msgid "" +"Cairo uses an immutable memory model, meaning that once a memory cell is " +"written to,\n" +"it can't be overwritten but only read from. To reflect this immutable memory " +"model,\n" +"variables in Cairo are immutable by default.\n" +"However, the language abstracts this model and gives you the option to make " +"your\n" +"variables mutable. Let’s explore how and why Cairo enforces immutability, " +"and how\n" +"you can make your variables mutable." +msgstr "" +"Cairo使用一个不可改变的内存模型,这意味着一旦一个内存单元被写入就不能被覆\n" +"盖,只能被读出。为了反映这种不可变的内存模型,变量在Cairo中默认是不可变的。\n" +"然而,该语言对这种模式进行了抽象,让你可以选择让你的变量是可变的。让我们来\n" +"探讨一下Cairo是如何以及为什么要执行不可变性的变量,以及你如何使你的变量成为可" +"变的。" + +#: src/ch02-01-variables-and-mutability.md:10 +msgid "" +"When a variable is immutable, once a value is bound to a name, you can’t " +"change\n" +"that value. To illustrate this, generate a new project called _variables_ " +"in\n" +"your _cairo_projects_ directory by using `scarb new variables`." +msgstr "" +"当一个变量是不可变的,一旦一个值被绑定到一个名字上,你就不能改变\n" +"该值。为了说明这一点,在你的_cairo_projects_目录下生成一个名为_variables_的新" +"项目。\n" +"你的_cairo_projects_目录下,使用`scarb new variables`生成一个名为_variables的" +"新项目。" + +#: src/ch02-01-variables-and-mutability.md:14 +msgid "" +"Then, in your new _variables_ directory, open _src/lib.cairo_ and replace " +"its\n" +"code with the following code, which won’t compile just yet:" +msgstr "" +"然后,在你新的_变量_目录下,打开_src/lib.cairo_并将其替换为\n" +"替换为下面的代码,这段代码还不会被编译:" + +#: src/ch02-01-variables-and-mutability.md:17 +#: src/ch02-01-variables-and-mutability.md:76 +#: src/ch02-01-variables-and-mutability.md:154 src/ch02-05-control-flow.md:130 +#: src/ch03-02-references-and-snapshots.md:23 +#: src/ch03-02-references-and-snapshots.md:111 +#: src/ch04-02-an-example-program-using-structs.md:7 +#: src/ch04-02-an-example-program-using-structs.md:48 +#: src/ch04-02-an-example-program-using-structs.md:74 +#: src/ch04-02-an-example-program-using-structs.md:106 +#: src/ch04-02-an-example-program-using-structs.md:142 +#: src/ch04-03-method-syntax.md:18 src/ch04-03-method-syntax.md:93 +#: src/ch04-03-method-syntax.md:135 src/ch04-03-method-syntax.md:192 +#: src/ch04-03-method-syntax.md:231 +#: src/ch06-02-defining-modules-to-control-scope.md:90 +#: src/ch06-02-defining-modules-to-control-scope.md:144 +#: src/ch06-03-paths-for-referring-to-an-item-in-the-module-tree.md:15 +#: src/ch06-03-paths-for-referring-to-an-item-in-the-module-tree.md:62 +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:10 +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:35 +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:74 +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:131 +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:156 +#: src/ch06-05-separating-modules-into-different-files.md:18 +#: src/ch08-01-how-to-write-tests.md:426 src/ch08-01-how-to-write-tests.md:464 +msgid "Filename: src/lib.cairo" +msgstr "文件名: src/lib.cairo" + +#: src/ch02-01-variables-and-mutability.md:19 +msgid "" +"```rust,does_not_compile\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let x = 5;\n" +" x.print();\n" +" x = 6;\n" +" x.print();\n" +"}\n" +"```" +msgstr "" +"```rust,does_not_compile\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let x = 5;\n" +" x.print();\n" +" x = 6;\n" +" x.print();\n" +"}\n" +"```" + +#: src/ch02-01-variables-and-mutability.md:29 +msgid "" +"Save and run the program using `cairo-run src/lib.cairo`. You should receive " +"an error message\n" +"regarding an immutability error, as shown in this output:" +msgstr "" +"保存并使用`cairo-run src/lib.cairo`运行该程序。你应该收到一条错误信息\n" +"关于不可变性的错误,如图所示:" + +#: src/ch02-01-variables-and-mutability.md:32 +msgid "" +"```console\n" +"error: Cannot assign to an immutable variable.\n" +" --> lib.cairo:5:5\n" +" x = 6;\n" +" ^***^\n" +"\n" +"Error: failed to compile: src/lib.cairo\n" +"```" +msgstr "" +"```console\n" +"error: Cannot assign to an immutable variable.\n" +" --> lib.cairo:5:5\n" +" x = 6;\n" +" ^***^\n" +"\n" +"Error: failed to compile: src/lib.cairo\n" +"```" + +#: src/ch02-01-variables-and-mutability.md:41 +msgid "" +"This example shows how the compiler helps you find errors in your programs.\n" +"Compiler errors can be frustrating, but really they only mean your program\n" +"isn’t safely doing what you want it to do yet; they do _not_ mean that " +"you’re\n" +"not a good programmer! Experienced Caironautes still get compiler errors." +msgstr "" +"这个例子显示了编译器如何帮助你发现程序中的错误。\n" +"编译器错误可能令人沮丧,但实际上它们只意味着你的程序\n" +"还没有安全地完成你想做的事情;它们并不意味着你不是一个好的程序员。\n" +"不是一个好的程序员!有经验的Caironautes仍然会出现编译器错误。" + +#: src/ch02-01-variables-and-mutability.md:46 +msgid "" +"You received the error message `Cannot assign to an immutable variable.`\n" +"because you tried to assign a second value to the immutable `x` variable." +msgstr "" +"你收到的错误信息是 `Cannot assign to an immutable variable.`。\n" +"因为你试图给不可变的`x`变量分配第二个值。" + +#: src/ch02-01-variables-and-mutability.md:49 +msgid "" +"It’s important that we get compile-time errors when we attempt to change a\n" +"value that’s designated as immutable because this specific situation can " +"lead to\n" +"bugs. If one part of our code operates on the assumption that a value will\n" +"never change and another part of our code changes that value, it’s possible\n" +"that the first part of the code won’t do what it was designed to do. The " +"cause\n" +"of this kind of bug can be difficult to track down after the fact, " +"especially\n" +"when the second piece of code changes the value only _sometimes_. The Cairo\n" +"compiler guarantees that when you state that a value won’t change, it " +"really\n" +"won’t change, so you don’t have to keep track of it yourself. Your code is " +"thus\n" +"easier to reason through." +msgstr "" +"在尝试改变预设为不可变的值时,产生编译时错误是很重要的,因为这种情况可能导\n" +"致 bug。如果一部分代码假设一个值永远也不会改变,而另一部分代码改变了这个\n" +"值,第一部分代码就有可能以不可预料的方式运行。不得不承认这种 bug 的起因难以\n" +"跟踪,尤其是第二部分代码只是 有时 会改变值。\n" +"Cairo 编译器保证,如果声明一个值不会变,它就真的不会变,所以你不必自己跟\n" +"踪它。这意味着你的代码更易于推导。" + +#: src/ch02-01-variables-and-mutability.md:60 +msgid "" +"But mutability can be very useful, and can make code more convenient to " +"write.\n" +"Although variables are immutable by default, you can make them mutable by\n" +"adding `mut` in front of the variable name. Adding `mut` also conveys\n" +"intent to future readers of the code by indicating that other parts of the " +"code\n" +"will be changing this variable’s value." +msgstr "" +"不过可变性也是非常有用的,可以用来更方便地编写代码。尽管变量默认是不可变的," +"你仍然可以在变量名前添加 `mut` 来使其可变。`mut` 也向读者表明了其他代码将会改" +"变这个变量值的意图。" + +#: src/ch02-01-variables-and-mutability.md:66 +msgid "" +"However, you might be wondering at this point what exactly happens when a " +"variable\n" +"is declared as `mut`, as we previously mentioned that Cairo's memory is " +"immutable.\n" +"The answer is that Cairo's memory is immutable, but the memory address the " +"variable points\n" +"to can be changed. Upon examining the low-level Cairo Assembly code, it " +"becomes clear that\n" +"variable mutation is implemented as syntactic sugar, which translates " +"mutation operations\n" +"into a series of steps equivalent to variable shadowing. The only difference " +"is that at the Cairo\n" +"level, the variable is not redeclared so its type cannot change." +msgstr "" +"然而,你可能想知道,当一个变量被声明为 `mut` 时,究竟会发生什么?\n" +"被声明为 `mut` 时会发生什么,因为我们之前提到Cairo的内存是不可改变的。\n" +"答案是,Cairo的内存是不可改变的,但变量指向的内存地址可以被改变。在检查了低\n" +"级别的Cairo汇编代码后,我们可以清楚地发现变量变化是以语法糖的形式实现的,它\n" +"将变异操作转化为一系列相当于变量变化的步骤。将变化操作转化为一系列的步\n" +"骤,等同于变量的隐藏。唯一的区别是,在Cairo,变量没有被重新声明,所以它\n" +"的类型不能改变。" + +#: src/ch02-01-variables-and-mutability.md:74 +msgid "For example, let’s change _src/lib.cairo_ to the following:" +msgstr "例如,让我们把_src/lib.cairo_改为以下内容:" + +#: src/ch02-01-variables-and-mutability.md:78 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let mut x = 5;\n" +" x.print();\n" +" x = 6;\n" +" x.print();\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let mut x = 5;\n" +" x.print();\n" +" x = 6;\n" +" x.print();\n" +"}\n" +"```" + +#: src/ch02-01-variables-and-mutability.md:88 +msgid "When we run the program now, we get this:" +msgstr "当我们现在运行该程序时,我们得到了这个结果:" + +#: src/ch02-01-variables-and-mutability.md:90 +msgid "" +"```console\n" +"❯ cairo-run src/lib.cairo\n" +"[DEBUG]\t \t(raw: 5)\n" +"\n" +"[DEBUG]\t \t(raw: 6)\n" +"\n" +"Run completed successfully, returning []\n" +"```" +msgstr "" +"```console\n" +"❯ cairo-run src/lib.cairo\n" +"[DEBUG]\t \t(raw: 5)\n" +"\n" +"[DEBUG]\t \t(raw: 6)\n" +"\n" +"Run completed successfully, returning []\n" +"```" + +#: src/ch02-01-variables-and-mutability.md:99 +msgid "" +"We’re allowed to change the value bound to `x` from `5` to `6` when `mut` " +"is\n" +"used. Ultimately, deciding whether to use mutability or not is up to you " +"and\n" +"depends on what you think is clearest in that particular situation." +msgstr "" +"当使用 `mut` 时,我们将在`x`绑定的值从`5`改为 `6` 。\n" +"最终,决定是否使用可变性取决于你自己,并取决于你认为在特定情况下什么是最清楚" +"的。" + +#: src/ch02-01-variables-and-mutability.md:103 +msgid "### Constants" +msgstr "### 常量" + +#: src/ch02-01-variables-and-mutability.md:105 +msgid "" +"Like immutable variables, _constants_ are values that are bound to a name " +"and\n" +"are not allowed to change, but there are a few differences between " +"constants\n" +"and variables." +msgstr "" +"类似于不可变变量,常量 (constants) 是绑定到一个名称的不允许改变的值,不过常\n" +"量与变量还是有一些区别。" + +#: src/ch02-01-variables-and-mutability.md:109 +msgid "" +"First, you aren’t allowed to use `mut` with constants. Constants aren’t " +"just\n" +"immutable by default—they’re always immutable. You declare constants using " +"the\n" +"`const` keyword instead of the `let` keyword, and the type of the value " +"_must_\n" +"be annotated. We’ll cover types and type annotations in the next section,\n" +"[“Data Types”][data-types], so don’t worry about the details\n" +"right now. Just know that you must always annotate the type." +msgstr "" +"首先,不允许对常量使用 `mut`。常量不光默认不可变,它总是不可变。声明常量使用 " +"`const` 关键字而不是 `let`,并且_必须_注明值的类型。在下一部分,[“数据类型”]" +"[data-types]中会介绍类型和类型注解,现在无需关心这些细节,记住总是标注类型即" +"可。" + +#: src/ch02-01-variables-and-mutability.md:116 +msgid "" +"Constants can only be declared in the global scope, which makes\n" +"them useful for values that many parts of code need to know about." +msgstr "" +"常量可以在任何作用域中声明,包括全局作用域,这在一个值需要被很多部分的代码\n" +"用到时很有用。" + +#: src/ch02-01-variables-and-mutability.md:119 +msgid "" +"The last difference is that constants may be set only to a constant " +"expression,\n" +"not the result of a value that could only be computed at runtime. Only " +"literal constants\n" +"are currently supported." +msgstr "" +"最后一个区别是,常量只能被设置为常量表达式,而不可以是其他任何只能在运行时\n" +"计算出的值。目前只支持字面常量。" + +#: src/ch02-01-variables-and-mutability.md:123 +msgid "Here’s an example of a constant declaration:" +msgstr "下面是一个声明常量的例子:" + +#: src/ch02-01-variables-and-mutability.md:125 +msgid "" +"```rust\n" +"const ONE_HOUR_IN_SECONDS: u32 = 3600_u32;\n" +"```" +msgstr "" +"``rust\n" +"const ONE_HOUR_IN_SECONDS: u32 = 3600_u32;\n" +"```" + +#: src/ch02-01-variables-and-mutability.md:129 +msgid "" +"Cairo's naming convention for constants is to use all uppercase with\n" +"underscores between words." +msgstr "Cairo的常量命名规则是使用所有大写字母,单词之间使用下划线。" + +#: src/ch02-01-variables-and-mutability.md:132 +msgid "" +"Constants are valid for the entire time a program runs, within the scope in\n" +"which they were declared. This property makes constants useful for values " +"in\n" +"your application domain that multiple parts of the program might need to " +"know\n" +"about, such as the maximum number of points any player of a game is allowed " +"to\n" +"earn, or the speed of light." +msgstr "" +"在声明它的作用域之中,常量在整个程序生命周期中都有效,此属性使得常量可以作\n" +"为多处代码使用的全局范围的值,例如一个游戏中所有玩家可以获取的最高分或者光\n" +"速。" + +#: src/ch02-01-variables-and-mutability.md:138 +msgid "" +"Naming hardcoded values used throughout your program as constants is useful " +"in\n" +"conveying the meaning of that value to future maintainers of the code. It " +"also\n" +"helps to have only one place in your code you would need to change if the\n" +"hardcoded value needed to be updated in the future." +msgstr "" +"将遍布于应用程序中的硬编码值声明为常量,能帮助后来的代码维护人员了解值的意\n" +"图。如果将来需要修改硬编码值,也只需修改汇聚于一处的硬编码值。" + +#: src/ch02-01-variables-and-mutability.md:143 +msgid "### Shadowing" +msgstr "### 隐藏" + +#: src/ch02-01-variables-and-mutability.md:145 +msgid "" +"Variable shadowing refers to the declaration of a\n" +"new variable with the same name as a previous variable. Caironautes say that " +"the\n" +"first variable is _shadowed_ by the second, which means that the second\n" +"variable is what the compiler will see when you use the name of the " +"variable.\n" +"In effect, the second variable overshadows the first, taking any uses of " +"the\n" +"variable name to itself until either it itself is shadowed or the scope " +"ends.\n" +"We can shadow a variable by using the same variable’s name and repeating " +"the\n" +"use of the `let` keyword as follows:" +msgstr "" +"变量隐藏指的是声明一个与之前变量同名的新的变量。\n" +"Caironautes 说第一个变量被第二个变量所_隐藏_了,这意味着当您使用变量的名称" +"时,编译器将看到第二个变量\n" +"实际上,第二个变量“遮蔽”了第一个变量,此时任何使用该变量名的行为中都会视为\n" +"是在使用第二个变量,直到第二个变量自己也被隐藏或第二个变量的作用域结束。可\n" +"以用相同变量名称来隐藏一个变量,以及重复使用 `let` 关键字来多次隐藏,如下\n" +"所示:" + +#: src/ch02-01-variables-and-mutability.md:156 +msgid "" +"```swift\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let x = 5;\n" +" let x = x + 1;\n" +" {\n" +" let x = x * 2;\n" +" 'Inner scope x value is:'.print();\n" +" x.print()\n" +" }\n" +" 'Outer scope x value is:'.print();\n" +" x.print();\n" +"}\n" +"```" +msgstr "" +"```swift\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let x = 5;\n" +" let x = x + 1;\n" +" {\n" +" let x = x * 2;\n" +" 'Inner scope x value is:'.print();\n" +" x.print()\n" +" }\n" +" 'Outer scope x value is:'.print();\n" +" x.print();\n" +"}\n" +"```" + +#: src/ch02-01-variables-and-mutability.md:171 +msgid "" +"This program first binds `x` to a value of `5`. Then it creates a new " +"variable\n" +"`x` by repeating `let x =`, taking the original value and adding `1` so the\n" +"value of `x` is then `6`. Then, within an inner scope created with the " +"curly\n" +"brackets, the third `let` statement also shadows `x` and creates a new\n" +"variable, multiplying the previous value by `2` to give `x` a value of " +"`12`.\n" +"When that scope is over, the inner shadowing ends and `x` returns to being " +"`6`.\n" +"When we run this program, it will output the following:" +msgstr "" +"这个程序首先将 `x` 绑定到值 `5` 上。接着通过 `let x =` 创建了一个新变量 " +"`x` ,获取初始值并加 `1` ,这样 `x` 的值就变成 `6` 了。然后,在使用花括号创建" +"的内部作用域内,第三个 `let` 语句也隐藏了 `x` 并创建了一个新的变量,将之前的" +"值乘以 `2` , `x` 得到的值是 `12`。当该作用域结束时,内部 shadowing 的作用域" +"也结束了, `x` 又返回到 `6`。运行这个程序,它会有如下输出:" + +#: src/ch02-01-variables-and-mutability.md:179 +msgid "" +"```console\n" +"cairo-run src/lib.cairo\n" +"[DEBUG]\tInner scope x value is: \t(raw: " +"7033328135641142205392067879065573688897582790068499258)\n" +"\n" +"[DEBUG]\n" +" \t(raw: 12)\n" +"\n" +"[DEBUG]\tOuter scope x value is: \t(raw: " +"7610641743409771490723378239576163509623951327599620922)\n" +"\n" +"[DEBUG]\t \t(raw: 6)\n" +"\n" +"Run completed successfully, returning []\n" +"```" +msgstr "" +"```console\n" +"cairo-run src/lib.cairo\n" +"[DEBUG]\tInner scope x value is: \t(raw: " +"7033328135641142205392067879065573688897582790068499258)\n" +"\n" +"[DEBUG]\n" +" \t(raw: 12)\n" +"\n" +"[DEBUG]\tOuter scope x value is: \t(raw: " +"7610641743409771490723378239576163509623951327599620922)\n" +"\n" +"[DEBUG]\t \t(raw: 6)\n" +"\n" +"Run completed successfully, returning []\n" +"```" + +#: src/ch02-01-variables-and-mutability.md:193 +msgid "" +"Shadowing is different from marking a variable as `mut` because we’ll get a\n" +"compile-time error if we accidentally try to reassign to this variable " +"without\n" +"using the `let` keyword. By using `let`, we can perform a few " +"transformations\n" +"on a value but have the variable be immutable after those transformations " +"have\n" +"been completed." +msgstr "" +"隐藏与将变量标记为 `mut` 是有区别的。\n" +"当不小心尝试对变量重新赋值时,如果没有使用 `let` 关键字,就会导致编译时错" +"误。\n" +"通过使用 `let`,我们可以用这个值进行一些计算,不过计算完之后变量仍然是不可变" +"的。" + +#: src/ch02-01-variables-and-mutability.md:199 +msgid "" +"Another distinction between `mut` and shadowing is that when we use the " +"`let` keyword again,\n" +"we are effectively creating a new variable, which allows us to change the " +"type of the\n" +"value while reusing the same name. As mentioned before, variable shadowing " +"and mutable variables\n" +"are equivalent at the lower level.\n" +"The only difference is that by shadowing a variable, the compiler will not " +"complain \n" +"if you change its type. For example, say our program performs a type " +"conversion between the\n" +"`u64` and `felt252` types." +msgstr "" +"`mut` 与隐藏的另一个区别是,当再次使用 `let` 时,实际上创建了一个新变量,我们" +"可以改变值的类型,并且复用这个名字。\n" +"如前所述,变量隐藏和可变量在较低层次上是等同的。\n" +"唯一的区别是,通过隐藏变量,编译器将不会检测到错误\n" +"如果你改变它的类型。例如,假设我们的程序在 `u64` 和 `u64` 之间进行了类型转" +"换。\n" +"`u64` 和 `felt252` 类型之间进行转换。" + +#: src/ch02-01-variables-and-mutability.md:207 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"use traits::Into;\n" +"fn main() {\n" +" let x = 2_u64;\n" +" x.print();\n" +" let x: felt252 = x.into(); // converts x to a felt, type annotation is " +"required.\n" +" x.print()\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"use traits::Into;\n" +"fn main() {\n" +" let x = 2_u64;\n" +" x.print();\n" +" let x: felt252 = x.into(); // converts x to a felt, type annotation is " +"required.\n" +" x.print()\n" +"}\n" +"```" + +#: src/ch02-01-variables-and-mutability.md:218 +msgid "" +"The first `x` variable has a `u64` type while the second `x` variable has a " +"`felt252` type.\n" +"Shadowing thus spares us from having to come up with different names, such " +"as `x_u64`\n" +"and `x_felt252`; instead, we can reuse the simpler `x` name. However, if we " +"try to use\n" +"`mut` for this, as shown here, we’ll get a compile-time error:" +msgstr "" +"第一个 `x` 变量的类型是 `u64`,而第二个 `x` 变量的类型是 `felt252`。\n" +"因此,隐藏使我们不必想出不同的名字,例如 `x_u64` 和 `x_felt252`;\n" +"相反,我们可以重新使用更简单的 `x` 名称。然而,如果我们试图使用\n" +"`mut` 来实现,我们会得到一个编译时错误,如下所示:" + +#: src/ch02-01-variables-and-mutability.md:223 +msgid "" +"```rust,does_not_compile\n" +"use debug::PrintTrait;\n" +"use traits::Into;\n" +"fn main() {\n" +" let mut x = 2_u64;\n" +" x.print();\n" +" x = x.into();\n" +" x.print()\n" +"}\n" +"```" +msgstr "" +"```rust,does_not_compile\n" +"use debug::PrintTrait;\n" +"use traits::Into;\n" +"fn main() {\n" +" let mut x = 2_u64;\n" +" x.print();\n" +" x = x.into();\n" +" x.print()\n" +"}\n" +"```" + +#: src/ch02-01-variables-and-mutability.md:234 +msgid "" +"The error says we’re were expecting a `u64` (the original type) but we got a " +"different type:" +msgstr "" +"这个错误表示我们预期得到一个 `u64` 类型(原始类型),但实际得到了不同的类型:" + +#: src/ch02-01-variables-and-mutability.md:236 +msgid "" +"```console\n" +"❯ cairo-run src/lib.cairo\n" +"error: Unexpected argument type. Expected: \"core::integer::u64\", found: " +"\"core::felt252\".\n" +" --> lib.cairo:6:9\n" +" x = x.into();\n" +" ^******^\n" +"\n" +"Error: failed to compile: src/lib.cairo\n" +"```" +msgstr "" +"```console\n" +"❯ cairo-run src/lib.cairo\n" +"error: Unexpected argument type. Expected: \"core::integer::u64\", found: " +"\"core::felt252\".\n" +" --> lib.cairo:6:9\n" +" x = x.into();\n" +" ^******^\n" +"\n" +"Error: failed to compile: src/lib.cairo\n" +"```" + +#: src/ch02-01-variables-and-mutability.md:246 +msgid "" +"Now that we’ve explored how variables work, let’s look at more data types " +"they\n" +"can have." +msgstr "现在我们已经了解了变量如何工作,让我们看看变量可以拥有的更多数据类型。" + +#: src/ch02-02-data-types.md:1 +msgid "## Data Types" +msgstr "## 数据类型" + +#: src/ch02-02-data-types.md:3 +msgid "" +"Every value in Cairo is of a certain _data type_, which tells Cairo what " +"kind of\n" +"data is being specified so it knows how to work with that data. This section " +"covers two subsets of data types: scalars and compounds." +msgstr "" +"在 Cairo 中,每一个值都属于某一个数据类型(data type),\n" +"这告诉 Cairo 它被指定为何种数据,以便明确数据处理方式。我们将看到两类数据类型" +"子集:标量(scalar)和复合(compound)。" + +#: src/ch02-02-data-types.md:6 +msgid "" +"Keep in mind that Cairo is a _statically typed_ language, which means that " +"it\n" +"must know the types of all variables at compile time. The compiler can " +"usually infer the desired type based on the value and its usage. In cases\n" +"when many types are possible, we can use a cast method where we specify the " +"desired output type." +msgstr "" +"记住,Cairo 是静态类型(statically typed)语言,也就是说在编译时就必须知道所" +"有变量的类型。根据值及其使用方式,编译器通常可以推断出我们想要用的类型。\n" +"\n" +"在可能存在多种类型的情况下,我们可以使用一种称为“转换方法”的方法,在其中指定" +"所需的输出类型。" + +#: src/ch02-02-data-types.md:10 +msgid "" +"```Rust\n" +"use traits::TryInto;\n" +"use option::OptionTrait;\n" +"fn main(){\n" +" let x: felt252 = 3;\n" +" let y:u32 = x.try_into().unwrap();\n" +"}\n" +"```" +msgstr "" +"```Rust\n" +"use traits::TryInto;\n" +"use option::OptionTrait;\n" +"fn main(){\n" +" let x: felt252 = 3;\n" +" let y:u32 = x.try_into().unwrap();\n" +"}\n" +"```" + +#: src/ch02-02-data-types.md:19 +msgid "You’ll see different type annotations for other data types." +msgstr "你会看到其它数据类型的各种类型注解。" + +#: src/ch02-02-data-types.md:21 +msgid "### Scalar Types" +msgstr "### 标量类型" + +#: src/ch02-02-data-types.md:23 +msgid "" +"A _scalar_ type represents a single value. Cairo has three primary scalar " +"types:\n" +"felts, integers, and booleans. You may recognize\n" +"these from other programming languages. Let’s jump into how they work in " +"Cairo." +msgstr "" +"一个_标量_(scalar)类型表示一个单一的值。Cairo 有三种主要的标量类型:\n" +"felts、整数(integers)和布尔值(booleans)。你可能在其他语言中见过它们。\n" +"让我们深入了解它们在 Cairo 中是如何工作的。" + +#: src/ch02-02-data-types.md:27 +msgid "#### Felt Type" +msgstr "#### Felt 类型" + +#: src/ch02-02-data-types.md:29 +msgid "" +"In Cairo, if you don't specify the type of a variable or argument, its type " +"defaults to a field element, represented by the keyword `felt252`. In the " +"context of Cairo, when we say “a field element” we mean an integer in the " +"range `0 <= x < P`,\n" +"where `P` is a very large prime number currently equal to `P = 2^{251} + 17 " +"* 2^{192}+1`. When adding, subtracting, or multiplying, if the result falls " +"outside the specified range of the prime number, an overflow occurs, and an " +"appropriate multiple of P is added or subtracted to bring the result back " +"within the range (i.e., the result is computed modulo P)." +msgstr "" +"在 Cairo 中,如果你没有指定一个变量或参数的类型,它的类型默认为一个字段元素," +"由关键字 `felt252` 表示。在 Cairo 中,当我们说 \"一个字段元素 \"时,我们指的" +"是范围为 `0 <= x < P` 的整数、\n" +"其中 `P` 是一个非常大的素数,目前等于 `P = 2^{251} + 17 * 2^{192}+1`。当加减" +"或乘法时,如果结果超出了质数的指定范围,就会发生溢出,然后再加上或减去 P 的适" +"当倍数,使结果回到范围内(也就是说,结果是以 P 为模数计算的)。" + +#: src/ch02-02-data-types.md:32 +msgid "" +"The most important difference between integers and field elements is " +"division: Division of field elements (and therefore division in Cairo) is " +"unlike regular CPUs division, where\n" +"integer division `x / y` is defined as `[x/y]` where the integer part of the " +"quotient is returned (so you get `7 / 3 = 2`) and it may or may not satisfy " +"the equation `(x / y) * y == x`,\n" +"depending on the divisibility of `x` by `y`." +msgstr "" +"整数和字段元素之间最重要的区别是除法:字段元素的除法(以及 Cairo 的除法)与普" +"通 CPU 的除法不同,其中整数除法 `x / y` 被定义为`[x/y]`,\n" +"其中商的整数部分被返回(所以你得到`7 / 3 = 2`),它可能满足或不满足方程式 " +"`(x / y) * y == x`,这取决于 `x` 是否能被 `y` 除以。" + +#: src/ch02-02-data-types.md:36 +msgid "" +"In Cairo, the result of `x/y` is defined to always satisfy the equation " +"`(x / y) * y == x`. If y divides x as integers, you will get the expected " +"result in Cairo (for example `6 / 2`\n" +"will indeed result in `3`).\n" +"But when y does not divide x, you may get a surprising result: For example, " +"since `2 * ((P+1)/2) = P+1 ≡ 1 mod[P]`, the value of `1 / 2` in Cairo is " +"`(P+1)/2` (and not 0 or 0.5), as it satisfies the above equation." +msgstr "" +"在 Cairo,`x/y` 的结果被定义为总是满足方程式 `(x / y) * y == x`。如果y除以x为" +"整数,你将得到 Cairo 的预期结果(例如,`6 / 2` 确实会得到`3`)。\n" +"但是当 y 不除以 x 时,你可能会得到一个令人惊讶的结果:\n" +"例如,由于 `2 * ((P+1)/2) = P+1 ≡ 1 mod[P]`,在 Cairo 中 `1 / 2` 的值是 " +"`(P+1)/2`(而不是0或0.5),因为它满足上述公式。" + +#: src/ch02-02-data-types.md:40 +msgid "#### Integer Types" +msgstr "#### 整数类型" + +#: src/ch02-02-data-types.md:42 +msgid "" +"The felt252 type is a fundamental type that serves as the basis for creating " +"all types in the core library.\n" +"However, it is highly recommended for programmers to use the integer types " +"instead of the `felt252` type whenever possible, as the `integer` types come " +"with added security features that provide extra protection against potential " +"vulnerabilities in the code, such as overflow checks. By using these integer " +"types, programmers can ensure that their programs are more secure and less " +"susceptible to attacks or other security threats.\n" +"An _integer_ is a number without a fractional component. This type " +"declaration indicates the number of bits the programmer can use to store the " +"integer.\n" +"Table 3-1 shows\n" +"the built-in integer types in Cairo. We can use any of these variants to " +"declare\n" +"the type of an integer value." +msgstr "" +"felt252 类型是一个基本类型,是创建核心库中所有类型的基础。\n" +"然而,强烈建议程序员尽可能使用整数类型而不是 `felt252` 类型,因为 " +"`integer` \n" +"类型带有额外的安全功能,对代码中的潜在漏洞提供额外保护,如溢出检查。通过使用" +"这些整数类型,程序员可以确保他们的程序更加安全,不容易受到攻击或其他安全威" +"胁。一个_integer_是一个没有小数部分的数字。这个类型声明指出了程序员可以用来存" +"储整数的比特数。\n" +"表3-1显示了Cairo中内建的整数类型。我们可以使用这些变体中的任何一种来声明一个" +"整数值的类型。" + +#: src/ch02-02-data-types.md:49 +msgid "Table 3-1: Integer Types in Cairo" +msgstr "表格3-1: Cairo 的整数类型" + +#: src/ch02-02-data-types.md:51 +msgid "" +"| Length | Unsigned |\n" +"| ------- | -------- |\n" +"| 8-bit | `u8` |\n" +"| 16-bit | `u16` |\n" +"| 32-bit | `u32` |\n" +"| 64-bit | `u64` |\n" +"| 128-bit | `u128` |\n" +"| 256-bit | `u256` |\n" +"| 32-bit | `usize` |" +msgstr "" +"| 长度 | 无符号 |\n" +"| ------- | -------- |\n" +"| 8-bit | `u8` |\n" +"| 16-bit | `u16` |\n" +"| 32-bit | `u32` |\n" +"| 64-bit | `u64` |\n" +"| 128-bit | `u128` |\n" +"| 256-bit | `u256` |\n" +"| 32-bit | `usize` |" + +#: src/ch02-02-data-types.md:61 +msgid "" +"Each variant has an explicit size. Note that for now, the `usize` type is " +"just an alias for `u32`; however, it might be useful when in the future " +"Cairo can be compiled to MLIR.\n" +"As variables are unsigned, they can't contain a negative number. This code " +"will cause the program to panic:" +msgstr "" +"每个变量都有一个明确的大小。注意,现在,`usize `类型只是 `u32` 的别名;然而," +"当将来 Cairo 可以被编译为 MLIR 时,它可能会很有用。\n" +"由于变量是无符号的,它们不能包含一个负数。这段代码会引起程序出现错误:" + +#: src/ch02-02-data-types.md:64 +msgid "" +"```rust\n" +"fn sub_u8s(x: u8, y: u8) -> u8 {\n" +" x - y\n" +"}\n" +"\n" +"fn main() {\n" +" sub_u8s(1, 3);\n" +"}\n" +"```" +msgstr "" +"``rust\n" +"fn sub_u8s(x: u8, y: u8) -> u8 {\n" +" x - y\n" +"}\n" +"\n" +"fn main() {\n" +" sub_u8s(1, 3);\n" +"}\n" +"```" + +#: src/ch02-02-data-types.md:74 +msgid "" +"You can write integer literals in any of the forms shown in Table 3-2. Note\n" +"that number literals that can be multiple numeric types allow a type " +"suffix,\n" +"such as `57_u8`, to designate the type." +msgstr "" +"你可以用表 3-2 中的任何一种形式编写数字字面值。\n" +"请注意可以是多种数字类型的数字字面值允许使用类型后缀,\n" +"例如 `57_u8` 来指定类型。" + +#: src/ch02-02-data-types.md:78 +msgid "Table 3-2: Integer Literals in Cairo" +msgstr "表3-2:Cairo 的整数类型字面值" + +#: src/ch02-02-data-types.md:80 +msgid "" +"| Numeric literals | Example |\n" +"| ---------------- | --------- |\n" +"| Decimal | `98222` |\n" +"| Hex | `0xff` |\n" +"| Octal | `0o04321` |\n" +"| Binary | `0b01` |" +msgstr "" +"| 数字字面值 | 例子 |\n" +"| ---------------- | --------- |\n" +"| Decimal(十进制) | `98222` |\n" +"| Hex (十六进制) | `0xff` |\n" +"| Octal (八进制) | `0o04321` |\n" +"| Binary (二进制) | `0b01` |" + +#: src/ch02-02-data-types.md:87 +msgid "" +"So how do you know which type of integer to use? Try to estimate the max " +"value your int can have and choose the good size.\n" +"The primary situation in which you’d use `usize` is when indexing some sort " +"of collection." +msgstr "" +"那么,你如何知道要使用哪种类型的整数?试着估计你的 int 可以有的最大值,然后选" +"择合适的大小。\n" +"你使用 `usize` 的主要情况是在为某种集合做索引时。" + +#: src/ch02-02-data-types.md:90 +msgid "#### Numeric Operations" +msgstr "#### 数值运算" + +#: src/ch02-02-data-types.md:92 +msgid "" +"Cairo supports the basic mathematical operations you’d expect for all the " +"integer\n" +"types: addition, subtraction, multiplication, division, and remainder. " +"Integer\n" +"division truncates toward zero to the nearest integer. The following code " +"shows\n" +"how you’d use each numeric operation in a `let` statement:" +msgstr "" +"Cairo 支持所有整数类型的基本数学运算:\n" +"加法、减法、乘法、除法和取余。\n" +"整数除法将向最接近的整数截断。以下代码展示了如何在 `let` 语句中使用它们:" + +#: src/ch02-02-data-types.md:97 +msgid "" +"```rust\n" +"fn main() {\n" +" // addition\n" +" let sum = 5_u128 + 10_u128;\n" +"\n" +" // subtraction\n" +" let difference = 95_u128 - 4_u128;\n" +"\n" +" // multiplication\n" +" let product = 4_u128 * 30_u128;\n" +"\n" +" // division\n" +" let quotient = 56_u128 / 32_u128; //result is 1\n" +" let quotient = 64_u128 / 32_u128; //result is 2\n" +"\n" +" // remainder\n" +" let remainder = 43_u128 % 5_u128; // result is 3\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"fn main() {\n" +" // addition\n" +" let sum = 5_u128 + 10_u128;\n" +"\n" +" // subtraction\n" +" let difference = 95_u128 - 4_u128;\n" +"\n" +" // multiplication\n" +" let product = 4_u128 * 30_u128;\n" +"\n" +" // division\n" +" let quotient = 56_u128 / 32_u128; //result is 1\n" +" let quotient = 64_u128 / 32_u128; //result is 2\n" +"\n" +" // remainder\n" +" let remainder = 43_u128 % 5_u128; // result is 3\n" +"}\n" +"```" + +#: src/ch02-02-data-types.md:117 +msgid "" +"Each expression in these statements uses a mathematical operator and " +"evaluates\n" +"to a single value, which is then bound to a variable." +msgstr "" +"这些语句中的每个表达式使用了一个数学运算符并计算出了一个值,\n" +"然后绑定给一个变量。" + +#: src/ch02-02-data-types.md:120 +msgid "" +"\n" +"" +msgstr "" +"<!-- TODO: 附录运算符 -->\n" +"<!-- [附录B][appendix_b] 忽略包含 Cairo 提供的所有操作符的列表。 -->" + +#: src/ch02-02-data-types.md:123 +msgid "#### The Boolean Type" +msgstr "#### 布尔类型" + +#: src/ch02-02-data-types.md:125 +msgid "" +"As in most other programming languages, a Boolean type in Cairo has two " +"possible\n" +"values: `true` and `false`. Booleans are one felt252 in size. The Boolean " +"type in\n" +"Cairo is specified using `bool`. For example:" +msgstr "" +"正如其他大部分编程语言一样,Cairo 中的布尔类型有两个可能的值:`true` 和 " +"`false`。布尔型的大小为一个 felt252。\n" +"布尔类型在 Cairo 中是用 `bool` 来指定的。例如:" + +#: src/ch02-02-data-types.md:129 +msgid "" +"```rust\n" +"fn main() {\n" +" let t = true;\n" +"\n" +" let f: bool = false; // with explicit type annotation\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"fn main() {\n" +" let t = true;\n" +"\n" +" let f: bool = false; // with explicit type annotation\n" +"}\n" +"```" + +#: src/ch02-02-data-types.md:139 +msgid "" +"The main way to use Boolean values is through conditionals, such as an `if`\n" +"expression. We’ll cover how `if` expressions work in Cairo in the [“Control\n" +"Flow”][control-flow] section." +msgstr "" +"使用布尔值的主要方式是通过条件语句,如 `if` 表达式。\n" +"我们将在[\"控制流\"][控制流]部分介绍 `if` 表达式在 Cairo 中的工作原理。" + +#: src/ch02-02-data-types.md:143 +msgid "#### The Short String Type" +msgstr "#### 短字符串类型" + +#: src/ch02-02-data-types.md:145 +msgid "" +"Cairo doesn't have a native type for strings, but you can store characters " +"forming what we call a \"short string\" inside `felt252`s. A short string " +"has a max length of 31 chars. This is to ensure that it can fit in a single " +"felt (a felt is 252 bits, one ASCII char is 8 bits).\n" +"Here are some examples of declaring values by putting them between single " +"quotes:" +msgstr "" +"Cairo 没有字符串(String)的原生类型,但你可以在 `felt252' 中存储短字符,形成" +"我们所说的 \"短字符串\"。一个短字符串的最大长度为 31 个字符。这是为了确保它能" +"装入一个 felt (一个 felt 是252位,一个 ASCII 字符是 8 位)。\n" +"下面是一些通过把值放在单引号之间来声明的例子:" + +#: src/ch02-02-data-types.md:148 +msgid "" +"```rust\n" +"let my_first_char = 'C';\n" +"let my_first_string = 'Hello world';\n" +"```" +msgstr "" +"``rust\n" +"let my_first_char = 'C';\n" +"let my_first_string = 'Hello world';\n" +"```" + +#: src/ch02-02-data-types.md:153 +msgid "### Type casting" +msgstr "### 类型转换" + +#: src/ch02-02-data-types.md:155 +msgid "" +"In Cairo, you can convert values between common scalar types and `felt252` " +"using the `try_into` and `into` methods provided by the `TryInto` and `Into` " +"traits, respectively." +msgstr "" +"在 Cairo 中,你可以使用 `TryInto' 和 `Into' 特性提供的 `try_into` 和 `into` " +"方法在普通标量类型和 `felt252` 之间转换数值。" + +#: src/ch02-02-data-types.md:157 +msgid "" +"The `try_into` method allows for safe type casting when the target type " +"might not fit the source value. Keep in mind that `try_into` returns an " +"`Option` type, which you'll need to unwrap to access the new value." +msgstr "" +"`try_into` 方法允许在目标类型可能不适合源值时进行安全的类型转换。请记住," +"`try_into` 返回一个 `Option` 类型,你需要解开这个类型来访问新的值。" + +#: src/ch02-02-data-types.md:159 +msgid "" +"On the other hand, the `into` method can be used for type casting when " +"success is guaranteed, such as when the source type is smaller than the " +"destination type." +msgstr "" +"另一方面,当成功得到保证时,如源类型小于目的类型时,`into` 方法可用于类型转" +"换。" + +#: src/ch02-02-data-types.md:161 +msgid "" +"To perform the conversion, call `var.into()` or `var.try_into()` on the " +"source value to cast it to another type. The new variable's type must be " +"explicitly defined, as demonstrated in the example below." +msgstr "" +"为了进行转换,在源值上调用 `var.into()` 或 `var.try_into()` 来将其转换为另一" +"种类型。新变量的类型必须被明确定义,如下面的例子所示。" + +#: src/ch02-02-data-types.md:163 +msgid "" +"```rust\n" +"use traits::TryInto;\n" +"use traits::Into;\n" +"use option::OptionTrait;\n" +"\n" +"fn main(){\n" +" let my_felt = 10;\n" +" let my_u8: u8 = my_felt.try_into().unwrap(); // Since a felt252 might " +"not fit in a u8, we need to unwrap the Option type\n" +" let my_u16: u16 = my_felt.try_into().unwrap();\n" +" let my_u32: u32 = my_felt.try_into().unwrap();\n" +" let my_u64: u64 = my_felt.try_into().unwrap();\n" +" let my_u128: u128 = my_felt.try_into().unwrap();\n" +" let my_u256: u256 = my_felt.into(); // As a felt252 is smaller than a " +"u256, we can use the into() method\n" +" let my_usize: usize = my_felt.try_into().unwrap();\n" +" let my_felt2: felt252 = my_u8.into();\n" +" let my_felt3: felt252 = my_u16.into();\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use traits::TryInto;\n" +"use traits::Into;\n" +"use option::OptionTrait;\n" +"\n" +"fn main(){\n" +" let my_felt = 10;\n" +" let my_u8: u8 = my_felt.try_into().unwrap(); // Since a felt252 might " +"not fit in a u8, we need to unwrap the Option type\n" +" let my_u16: u16 = my_felt.try_into().unwrap();\n" +" let my_u32: u32 = my_felt.try_into().unwrap();\n" +" let my_u64: u64 = my_felt.try_into().unwrap();\n" +" let my_u128: u128 = my_felt.try_into().unwrap();\n" +" let my_u256: u256 = my_felt.into(); // As a felt252 is smaller than a " +"u256, we can use the into() method\n" +" let my_usize: usize = my_felt.try_into().unwrap();\n" +" let my_felt2: felt252 = my_u8.into();\n" +" let my_felt3: felt252 = my_u16.into();\n" +"}\n" +"```" + +#: src/ch02-02-data-types.md:182 +msgid "### The Tuple Type" +msgstr "### 元组类型" + +#: src/ch02-02-data-types.md:184 +msgid "" +"A _tuple_ is a general way of grouping together a number of values with a\n" +"variety of types into one compound type. Tuples have a fixed length: once\n" +"declared, they cannot grow or shrink in size." +msgstr "" +"_元组_是一个将多个其他类型的值组合进一个复合类型的主要方式。\n" +"元组长度固定:一旦声明,其长度不会增大或缩小。" + +#: src/ch02-02-data-types.md:188 +msgid "" +"We create a tuple by writing a comma-separated list of values inside\n" +"parentheses. Each position in the tuple has a type, and the types of the\n" +"different values in the tuple don’t have to be the same. We’ve added " +"optional\n" +"type annotations in this example:" +msgstr "" +"我们使用包含在圆括号中的逗号分隔的值列表来创建一个元组。\n" +"元组中的每一个位置都有一个类型,而且这些不同值的类型也不必是相同的。\n" +"这个例子中使用了可选的类型注解:" + +#: src/ch02-02-data-types.md:193 +msgid "" +"```rust\n" +"fn main() {\n" +" let tup: (u32,u64,bool) = (10,20,true);\n" +"}\n" +"```" +msgstr "" +"``rust\n" +"fn main() {\n" +" let tup: (u32,u64,bool) = (10,20,true);\n" +"}\n" +"```" + +#: src/ch02-02-data-types.md:199 +msgid "" +"The variable `tup` binds to the entire tuple because a tuple is considered " +"a\n" +"single compound element. To get the individual values out of a tuple, we " +"can\n" +"use pattern matching to destructure a tuple value, like this:" +msgstr "" +"`tup` 变量绑定到整个元组上,因为元组是一个单独的复合元素。\n" +"为了从元组中获取单个值,可以使用模式匹配(pattern matching)\n" +"来解构(destructure)元组值,像这样:" + +#: src/ch02-02-data-types.md:203 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let tup = (500, 6, true);\n" +"\n" +" let (x, y, z) = tup;\n" +"\n" +" if y == 6 {\n" +" 'y is six!'.print();\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let tup = (500, 6, true);\n" +"\n" +" let (x, y, z) = tup;\n" +"\n" +" if y == 6 {\n" +" 'y is six!'.print();\n" +" }\n" +"}\n" +"```" + +#: src/ch02-02-data-types.md:216 +msgid "" +"This program first creates a tuple and binds it to the variable `tup`. It " +"then\n" +"uses a pattern with `let` to take `tup` and turn it into three separate\n" +"variables, `x`, `y`, and `z`. This is called _destructuring_ because it " +"breaks\n" +"the single tuple into three parts. Finally, the program prints `y is six` as " +"the value of\n" +"`y` is `6`." +msgstr "" +"程序首先创建了一个元组并绑定到 `tup` 变量上。\n" +"接着使用了 `let` 和一个模式将 `tup` 分成了三个不同的变量,\n" +" `x`、`y` 和 `z`。这叫做解构(destructuring),\n" +"因为它将一个元组拆成了三个部分。最后,程序打印出了 `y` 的值,\n" +"也就是 `6`。" + +#: src/ch02-02-data-types.md:222 +msgid "" +"We can also declare the tuple with value and name at the same time.\n" +"For example:" +msgstr "" +"我们也可以同时用 value 和 name 来声明元组。\n" +"比如说:" + +#: src/ch02-02-data-types.md:225 +msgid "" +"```rust\n" +"fn main() {\n" +" let (x, y): (felt252, felt252) = (2, 3);\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"fn main() {\n" +" let (x, y): (felt252, felt252) = (2, 3);\n" +"}\n" +"```" + +#: src/ch02-02-data-types.md:231 +msgid "### The unit type ()" +msgstr "###unit类型()" + +#: src/ch02-02-data-types.md:233 +msgid "" +"A _unit type_ is a type which has only one value `()`.\n" +"It is represented by a tuple with no elements.\n" +"Its size is always zero, and it is guaranteed to not exist in the compiled " +"code." +msgstr "" +"一个_unit 类型_是一个只有一个值 `()` 的类型。\n" +"它由一个没有元素的元组来表示。\n" +"它的大小总是为零,并且保证它在编译后的代码中不存在。" + +#: src/ch02-03-functions.md:1 src/ch99-01-02-writing-starknet-contracts.md:134 +msgid "## Functions" +msgstr "## 函数" + +#: src/ch02-03-functions.md:3 +msgid "" +"Functions are prevalent in Cairo code. You’ve already seen one of the most\n" +"important functions in the language: the `main` function, which is the " +"entry\n" +"point of many programs. You’ve also seen the `fn` keyword, which allows you " +"to\n" +"declare new functions." +msgstr "" +"函数在 Cairo 代码中非常普遍。你已经见过语言中最重要的函数之一:\n" +" `main` 函数,它是很多程序的入口点。\n" +"你也见过 `fn` 关键字,它用来声明新函数。" + +#: src/ch02-03-functions.md:8 +msgid "" +"Cairo code uses *snake case* as the conventional style for function and " +"variable\n" +"names, in which all letters are lowercase and underscores separate words.\n" +"Here’s a program that contains an example function definition:" +msgstr "" +"Cairo代码使用*蛇形大小写*作为函数和变量名称的常规样式。\n" +"所有的字母都是小写的,并以下划线分隔单词。\n" +"这里有一个程序,包含一个函数定义的例子:" + +#: src/ch02-03-functions.md:13 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"fn another_function() {\n" +" 'Another function.'.print();\n" +"}\n" +"\n" +"fn main() {\n" +" 'Hello, world!'.print();\n" +" another_function();\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"fn another_function() {\n" +" 'Another function.'.print();\n" +"}\n" +"\n" +"fn main() {\n" +" 'Hello, world!'.print();\n" +" another_function();\n" +"}\n" +"```" + +#: src/ch02-03-functions.md:26 +msgid "" +"We define a function in Cairo by entering `fn` followed by a function name " +"and a\n" +"set of parentheses. The curly brackets tell the compiler where the function\n" +"body begins and ends." +msgstr "" +"在 Cairo 中,我们通过输入 `fn` 和函数名称以及一组括号来定义一个函数。大括号告" +"诉编译器函数体的开始和结束位置。" + +#: src/ch02-03-functions.md:30 +msgid "" +"We can call any function we’ve defined by entering its name followed by a " +"set\n" +"of parentheses. Because `another_function` is defined in the program, it can " +"be\n" +"called from inside the `main` function. Note that we defined " +"`another_function`\n" +"*before* the `main` function in the source code; we could have defined it " +"after\n" +"as well. Cairo doesn’t care where you define your functions, only that " +"they’re\n" +"defined somewhere in a scope that can be seen by the caller." +msgstr "" +"可以使用函数名后跟圆括号来调用我们定义过的任意函数。\n" +"因为程序中已定义 `another_function` 函数,所以可以在 `main` 函数中调用它。\n" +"注意,源码中 `another_function` 定义在 `main` 函数*之后*;也可以定义在之" +"前。\n" +"Cairo 不关心函数定义所在的位置,只要函数被调用时出现在调用之处可见的作用域内" +"就行。" + +#: src/ch02-03-functions.md:37 +msgid "" +"Let’s start a new project with Scarb named *functions* to explore functions\n" +"further. Place the `another_function` example in *src/lib.cairo* and run it. " +"You\n" +"should see the following output:" +msgstr "" +"让我们用 Scarb 启动一个名为 *functions* 的新项目来进一步探索函数。\n" +"更进一步。把 `another_function` 的例子写入 *src/lib.cairo* 中并运行它。你\n" +"你应该看到以下输出:" + +#: src/ch02-03-functions.md:41 +msgid "" +"```console\n" +"$ cairo-run src/lib.cairo\n" +"[DEBUG] Hello, world! (raw: 5735816763073854953388147237921)\n" +"[DEBUG] Another function. (raw: " +"22265147635379277118623944509513687592494)\n" +"```" +msgstr "" +"```console\n" +"$ cairo-run src/lib.cairo\n" +"[DEBUG] Hello, world! (raw: 5735816763073854953388147237921)\n" +"[DEBUG] Another function. (raw: " +"22265147635379277118623944509513687592494)\n" +"```" + +#: src/ch02-03-functions.md:47 +msgid "" +"The lines execute in the order in which they appear in the `main` function.\n" +"First the “Hello, world!” message prints, and then `another_function` is " +"called\n" +"and its message is printed." +msgstr "" +"这几行是按照它们在 `main` 函数中出现的顺序执行的。\n" +"首先打印 \"Hello, world!\" 信息,然后调用 `another_function`,并打印其信息。" + +#: src/ch02-03-functions.md:51 +msgid "### Parameters" +msgstr "###参数" + +#: src/ch02-03-functions.md:53 +msgid "" +"We can define functions to have *parameters*, which are special variables " +"that\n" +"are part of a function’s signature. When a function has parameters, you can\n" +"provide it with concrete values for those parameters. Technically, the " +"concrete\n" +"values are called *arguments*, but in casual conversation, people tend to " +"use\n" +"the words *parameter* and *argument* interchangeably for either the " +"variables\n" +"in a function’s definition or the concrete values passed in when you call a\n" +"function." +msgstr "" +"我们可以定义为拥有 *参数(parameters)* 的函数,参数是特殊变量,是函数签名的" +"一部分。当函数拥有参数(形参)时,可以为这些参数提供具体的值(实参)。技术上" +"讲,这些具体值被称为 *参数*(arguments),但是在日常交流中,人们倾向于不区分" +"使用 *parameter* 和 *argument* 来表示函数定义中的变量或调用函数时传入的具体" +"值。" + +#: src/ch02-03-functions.md:61 +msgid "In this version of `another_function` we add a parameter:" +msgstr "在这个版本的 `another_function` 中,我们添加了一个参数:" + +#: src/ch02-03-functions.md:63 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" another_function(5);\n" +"}\n" +"\n" +"fn another_function(x: felt252) {\n" +" x.print();\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" another_function(5);\n" +"}\n" +"\n" +"fn another_function(x: felt252) {\n" +" x.print();\n" +"}\n" +"```" + +#: src/ch02-03-functions.md:75 +msgid "Try running this program; you should get the following output:" +msgstr "尝试运行这个程序;你应该得到以下输出:" + +#: src/ch02-03-functions.md:77 src/ch02-03-functions.md:250 +msgid "" +"```console\n" +"$ cairo-run src/lib.cairo\n" +"[DEBUG] (raw: 5)\n" +"```" +msgstr "" +"```console\n" +"$ cairo-run src/lib.cairo\n" +"[DEBUG] (raw: 5)\n" +"```" + +#: src/ch02-03-functions.md:82 +msgid "" +"The declaration of `another_function` has one parameter named `x`. The type " +"of\n" +"`x` is specified as `felt252`. When we pass `5` in to `another_function`, " +"the\n" +"`.print()` function outputs `5` in the console." +msgstr "" +"`another_function` 的声明有一个名为 `x` 的参数。\n" +"`x` 的类型被指定为 `felt252`。当我们把 `5` 传给 `another_function` 时,`." +"print()`函数在控制台中会输出 `5`。" + +#: src/ch02-03-functions.md:86 +msgid "" +"In function signatures, you *must* declare the type of each parameter. This " +"is\n" +"a deliberate decision in Cairo’s design: requiring type annotations in " +"function\n" +"definitions means the compiler almost never needs you to use them elsewhere " +"in\n" +"the code to figure out what type you mean. The compiler is also able to " +"give\n" +"more helpful error messages if it knows what types the function expects." +msgstr "" +"在函数签名中,必须 声明每个参数的类型。\n" +"这是 Cairo 设计中一个经过慎重考虑的决定:\n" +"要求在函数定义中提供类型注解,意味着编译器再也不需要你在代码的\n" +"其他地方注明类型来指出你的意图。而且,在知道函数需要什么类型后,\n" +"编译器就能够给出更有用的错误消息。" + +#: src/ch02-03-functions.md:92 +msgid "" +"When defining multiple parameters, separate the parameter declarations with\n" +"commas, like this:" +msgstr "" +"当定义多个参数时,用逗号分隔。\n" +"像这样:" + +#: src/ch02-03-functions.md:95 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" another_function(5,6);\n" +"}\n" +"\n" +"fn another_function(x: felt252, y:felt252) {\n" +" x.print();\n" +" y.print();\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" another_function(5,6);\n" +"}\n" +"\n" +"fn another_function(x: felt252, y:felt252) {\n" +" x.print();\n" +" y.print();\n" +"}\n" +"```" + +#: src/ch02-03-functions.md:108 +msgid "" +"This example creates a function named `another_function` with two\n" +"parameters. The first parameter is named `x` and is an `felt252`. The second " +"is\n" +"named `y` and is type `felt252` too. The function then prints the content of " +"the felt `x` and then the content of the felt `y`." +msgstr "" +"这个例子创建了一个名为 `another_function` 的函数,它有两个\n" +"参数。第一个参数被命名为 `x`,类型是 `felt252`。第二个参数被命名为 `y`,也是 " +"`felt252` 类型。然后,该函数打印了 `x` 的内容,然后打印 `y` 的内容。" + +#: src/ch02-03-functions.md:112 +msgid "" +"Let’s try running this code. Replace the program currently in your " +"*functions*\n" +"project’s *src/lib.cairo* file with the preceding example and run it using " +"`cairo-run src/lib.cairo`:" +msgstr "" +"让我们试着运行这段代码。将目前在你的*functions*\n" +"项目的 *src/lib.cairo* 文件中的程序,并使用 `cairo-run src/lib.cairo` 来运行" +"它:" + +#: src/ch02-03-functions.md:115 +msgid "" +"```console\n" +"$ cairo-run src/lib.cairo\n" +"[DEBUG] (raw: 5)\n" +"[DEBUG] (raw: 6)\n" +"```" +msgstr "" +"```console\n" +"$ cairo-run src/lib.cairo\n" +"[DEBUG] (raw: 5)\n" +"[DEBUG] (raw: 6)\n" +"```" + +#: src/ch02-03-functions.md:121 +msgid "" +"Because we called the function with `5` as the value for `x` and `6` as\n" +"the value for `y`, the program output contains those values." +msgstr "" +"因为我们在调用函数时,将 `5` 作为 `x` 的值,将 `6` 作为 `y` 的值。\n" +"程序输出包含这些值。" + +#: src/ch02-03-functions.md:124 +msgid "### Statements and Expressions" +msgstr "### 语句和表达式" + +#: src/ch02-03-functions.md:126 +msgid "" +"Function bodies are made up of a series of statements optionally ending in " +"an\n" +"expression. So far, the functions we’ve covered haven’t included an ending\n" +"expression, but you have seen an expression as part of a statement. Because\n" +"Cairo is an expression-based language, this is an important distinction to\n" +"understand. Other languages don’t have the same distinctions, so let’s look " +"at\n" +"what statements and expressions are and how their differences affect the " +"bodies\n" +"of functions." +msgstr "" +"函数体由一系列的语句和一个可选的结尾表达式构成。\n" +"目前为止,我们提到的函数还不包含结尾表达式,\n" +"不过你已经见过作为语句一部分的表达式。因为 Cairo 是一门基于表达式\n" +"(expression-based)的语言,这是一个需要理解的(不同于其他语言)\n" +"重要区别。其他语言并没有这样的区别,所以让我们看看语句与表达式有什么区别以及" +"这些区别是如何影响函数体的。" + +#: src/ch02-03-functions.md:134 +msgid "" +"* **Statements** are instructions that perform some action and do not " +"return\n" +" a value.\n" +"* **Expressions** evaluate to a resultant value. Let’s look at some examples." +msgstr "" +"* **语句**(Statements)是执行一些操作但不返回值的指令。\n" +"* **表达式**(Expressions)计算并产生一个值。让我们看一些例子。" + +#: src/ch02-03-functions.md:138 +msgid "" +"We’ve actually already used statements and expressions. Creating a variable " +"and\n" +"assigning a value to it with the `let` keyword is a statement. In Listing " +"3-1,\n" +"`let y = 6;` is a statement." +msgstr "" +"实际上,我们已经使用过语句和表达式。\n" +"使用 `let` 关键字创建变量并绑定一个值是一个语句。在列表 3-1 中,`let y = 6;" +"`; 是一个语句。" + +#: src/ch02-03-functions.md:142 +msgid "" +"```rust\n" +"fn main() {\n" +" let y = 6;\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"fn main() {\n" +" let y = 6;\n" +"}\n" +"```" + +#: src/ch02-03-functions.md:148 +msgid "" +"Listing 3-1: A `main` function declaration " +"containing one statement" +msgstr "" +"列表3-1:一个包含一条语句的 `main` 函数声明" + +#: src/ch02-03-functions.md:150 +msgid "" +"Function definitions are also statements; the entire preceding example is a\n" +"statement in itself." +msgstr "函数定义也是语句,上面整个例子本身就是一个语句。" + +#: src/ch02-03-functions.md:153 +msgid "" +"Statements do not return values. Therefore, you can’t assign a `let` " +"statement\n" +"to another variable, as the following code tries to do; you’ll get an error:" +msgstr "" +"语句不返回值。因此,不能把 `let` 语句赋值给另一个变量,比如下面的例子尝试做\n" +"的,会产生一个错误:" + +#: src/ch02-03-functions.md:156 +msgid "" +"```rust,does_not_compile\n" +"fn main() {\n" +" let x = (let y = 6);\n" +"}\n" +"```" +msgstr "" +"``rust,does_not_compile\n" +"fn main() {\n" +" let x = (let y = 6);\n" +"}\n" +"```" + +#: src/ch02-03-functions.md:161 +msgid "When you run this program, the error you’ll get looks like this:" +msgstr "当你运行这个程序时,你将得到的错误看起来像这样:" + +#: src/ch02-03-functions.md:162 +msgid "" +"```console\n" +"$ cairo-run src/lib.cairo\n" +"error: Missing token TerminalRParen.\n" +" --> src/lib.cairo:2:14\n" +" let x = (let y = 6);\n" +" ^\n" +"\n" +"error: Missing token TerminalSemicolon.\n" +" --> src/lib.cairo:2:14\n" +" let x = (let y = 6);\n" +" ^\n" +"\n" +"error: Missing token TerminalSemicolon.\n" +" --> src/lib.cairo:2:14\n" +" let x = (let y = 6);\n" +" ^\n" +"\n" +"error: Skipped tokens. Expected: statement.\n" +" --> src/lib.cairo:2:14\n" +" let x = (let y = 6);\n" +"```" +msgstr "" +"```console\n" +"$ cairo-run src/lib.cairo\n" +"error: Missing token TerminalRParen.\n" +" --> src/lib.cairo:2:14\n" +" let x = (let y = 6);\n" +" ^\n" +"\n" +"error: Missing token TerminalSemicolon.\n" +" --> src/lib.cairo:2:14\n" +" let x = (let y = 6);\n" +" ^\n" +"\n" +"error: Missing token TerminalSemicolon.\n" +" --> src/lib.cairo:2:14\n" +" let x = (let y = 6);\n" +" ^\n" +"\n" +"error: Skipped tokens. Expected: statement.\n" +" --> src/lib.cairo:2:14\n" +" let x = (let y = 6);\n" +"```" + +#: src/ch02-03-functions.md:184 +msgid "" +"The `let y = 6` statement does not return a value, so there isn’t anything " +"for\n" +"`x` to bind to. This is different from what happens in other languages, such " +"as\n" +"C and Ruby, where the assignment returns the value of the assignment. In " +"those\n" +"languages, you can write `x = y = 6` and have both `x` and `y` have the " +"value\n" +"`6`; that is not the case in Cairo." +msgstr "" +"语句 `let y = 6` 没有返回一个值,所以没有任何东西让 `x` 与之绑定。这与其他语" +"言\n" +"中的情况不同,比如说 C 和 Ruby,其中赋值会返回赋值的值。在这些语言中,你可\n" +"以写 `x = y = 6`,让 `x`和 `y` 都有值 `6`;但在 Cairo 中不是这样的。" + +#: src/ch02-03-functions.md:190 +msgid "" +"Expressions evaluate to a value and make up most of the rest of the code " +"that\n" +"you’ll write in Cairo. Consider a math operation, such as `5 + 6`, which is " +"an\n" +"expression that evaluates to the value `11`. Expressions can be part of\n" +"statements: in Listing 3-1, the `6` in the statement `let y = 6;` is an\n" +"expression that evaluates to the value `6`. Calling a function is an\n" +"expression. A new scope block created with\n" +"curly brackets is an expression, for example:" +msgstr "" +"表达式会计算出一个值,并且你将编写的大部分 Cairo 代码是由表达式组成的。考虑\n" +"一个数学运算,比如 `5 + 6` ,这是一个表达式并计算出值 `11`。表达式可以是语" +"句\n" +"的一部分:在示例 3-1 中,语句 `let y = 6;` 中的 `6` 是一个表达式,它计算出的" +"值\n" +"是 `6` 。函数调用是一个表达式。宏调用是一个表达式。用大括号创建的一个新的块\n" +"作用域也是一个表达式,例如:" + +#: src/ch02-03-functions.md:199 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let y = {\n" +" let x = 3;\n" +" x + 1\n" +" };\n" +"\n" +" y.print();\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let y = {\n" +" let x = 3;\n" +" x + 1\n" +" };\n" +"\n" +" y.print();\n" +"}\n" +"```" + +#: src/ch02-03-functions.md:211 +msgid "This expression:" +msgstr "这个表达式:" + +#: src/ch02-03-functions.md:212 +msgid "" +"```rust\n" +"{\n" +" let x = 3;\n" +" x + 1\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"{\n" +" let x = 3;\n" +" x + 1\n" +"}\n" +"```" + +#: src/ch02-03-functions.md:218 +msgid "" +"is a block that, in this case, evaluates to `4`. That value gets bound to " +"`y`\n" +"as part of the `let` statement. Note that the `x + 1` line doesn’t have a\n" +"semicolon at the end, which is unlike most of the lines you’ve seen so far.\n" +"Expressions do not include ending semicolons. If you add a semicolon to the " +"end\n" +"of an expression, you turn it into a statement, and it will then not return " +"a\n" +"value. Keep this in mind as you explore function return values and " +"expressions\n" +"next." +msgstr "" +"是一个代码块,它的值是 `4`。这个值作为 `let` 语句的一部分被绑定到 `y` 上。注" +"意\n" +" `x + 1` 这一行在结尾没有分号,与你见过的大部分代码行不同。表达式的结尾没有\n" +"分号。如果在表达式的结尾加上分号,它就变成了语句,而语句不会返回值。在接下\n" +"来探索具有返回值的函数和表达式时要谨记这一点。" + +#: src/ch02-03-functions.md:225 +msgid "### Functions with Return Values" +msgstr "### 具有返回值的函数" + +#: src/ch02-03-functions.md:226 +msgid "" +"Functions can return values to the code that calls them. We don’t name " +"return\n" +"values, but we must declare their type after an arrow (`->`). In Cairo, the\n" +"return value of the function is synonymous with the value of the final\n" +"expression in the block of the body of a function. You can return early from " +"a\n" +"function by using the `return` keyword and specifying a value, but most\n" +"functions return the last expression implicitly. Here’s an example of a\n" +"function that returns a value:" +msgstr "" +"函数可以向调用它的代码返回值。我们并不对返回值命名,但要在箭头(`->`)后声明" +"它\n" +"的类型。在 Cairo 中,函数的返回值等同于函数体最后一个表达式的值。使用 \n" +"`return` 关键字和指定值,可从函数中提前返回;但大部分函数隐式的返回最后的表\n" +"达式。这是一个有返回值的函数的例子:" + +#: src/ch02-03-functions.md:234 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"fn five() -> u32 {\n" +" 5_u32\n" +"}\n" +"\n" +"fn main() {\n" +" let x = five();\n" +" x.print();\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"fn five() -> u32 {\n" +" 5_u32\n" +"}\n" +"\n" +"fn main() {\n" +" let x = five();\n" +" x.print();\n" +"}\n" +"```" + +#: src/ch02-03-functions.md:246 +msgid "" +"There are no function calls, or even `let` statements in the `five`\n" +"function—just the number `5` by itself. That’s a perfectly valid function " +"in\n" +"Cairo. Note that the function’s return type is specified too, as `-> u32`. " +"Try\n" +"running this code; the output should look like this:" +msgstr "" +"在 five 函数中没有函数调用、宏、甚至没有 `let` 语句 —— 只有数字 `5`。这在\n" +" Cairo 中是一个完全有效的函数。注意,也指定了函数返回值的类型,就是\n" +" `-> u32`。尝试运行代码;输出应该看起来像这样:" + +#: src/ch02-03-functions.md:254 +msgid "" +"The `5` in `five` is the function’s return value, which is why the return " +"type\n" +"is `u32`. Let’s examine this in more detail. There are two important bits:\n" +"first, the line `let x = five();` shows that we’re using the return value of " +"a\n" +"function to initialize a variable. Because the function `five` returns a " +"`5`,\n" +"that line is the same as the following:" +msgstr "" +"`five` 函数的返回值是 `5` ,所以返回值类型是 `u32`。让我们仔细检查一下这段" +"代\n" +"码。有两个重要的部分:首先,`let x = five();` 这一行表明我们使用函数的返回值" +"初\n" +"始化一个变量。因为 `five` 函数返回 `5`,这一行与如下代码相同:" + +#: src/ch02-03-functions.md:259 +msgid "" +"```rust\n" +"let x = 5;\n" +"```" +msgstr "" +"```rust\n" +"let x = 5;\n" +"```" + +#: src/ch02-03-functions.md:262 +msgid "" +"Second, the `five` function has no parameters and defines the type of the\n" +"return value, but the body of the function is a lonely `5` with no " +"semicolon\n" +"because it’s an expression whose value we want to return.\n" +"Let’s look at another example:" +msgstr "" +"第二,`five` 函数没有参数并定义了返回值的类型。不过函数体只有单单一个 `5` 也" +"没\n" +"有分号,因为这是一个表达式,我们想要返回它的值。\n" +"让我们看看另一个例子:" + +#: src/ch02-03-functions.md:267 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" let x = plus_one(5_u32);\n" +"\n" +" x.print();\n" +"}\n" +"\n" +"fn plus_one(x: u32) -> u32 {\n" +" x + 1_u32\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" let x = plus_one(5_u32);\n" +"\n" +" x.print();\n" +"}\n" +"\n" +"fn plus_one(x: u32) -> u32 {\n" +" x + 1_u32\n" +"}\n" +"```" + +#: src/ch02-03-functions.md:280 +msgid "" +"Running this code will print `[DEBUG] (raw: 6)`. But if " +"we place a\n" +"semicolon at the end of the line containing `x + 1`, changing it from an\n" +"expression to a statement, we’ll get an error:" +msgstr "" +"运行这段代码将打印 `[DEBUG] (raw: 6)`。但是如果在包含 `x + 1` 的行尾放置一" +"个\n" +"分号,把它从一个表达式变成一个语句,我们会看到一个错误:" + +#: src/ch02-03-functions.md:284 +msgid "" +"```rust,does_not_compile\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" let x = plus_one(5_u32);\n" +"\n" +" x.print();\n" +"}\n" +"\n" +"fn plus_one(x: u32) -> u32 {\n" +" x + 1_u32;\n" +"}\n" +"```" +msgstr "" +"```rust,does_not_compile\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" let x = plus_one(5_u32);\n" +"\n" +" x.print();\n" +"}\n" +"\n" +"fn plus_one(x: u32) -> u32 {\n" +" x + 1_u32;\n" +"}\n" +"```" + +#: src/ch02-03-functions.md:298 +msgid "Compiling this code produces an error, as follows:" +msgstr "编译这段代码会产生一个错误,如下所示:" + +#: src/ch02-03-functions.md:299 +msgid "" +"```console\n" +"error: Unexpected return type. Expected: \"core::integer::u32\", found: " +"\"()\".\n" +"```" +msgstr "" +"```console\n" +"error: Unexpected return type. Expected: \"core::integer::u32\", found: " +"\"()\".\n" +"```" + +#: src/ch02-03-functions.md:302 +msgid "" +"The main error message, `Unexpected return type`, reveals the core issue " +"with this\n" +"code. The definition of the function `plus_one` says that it will return an\n" +"`u32`, but statements don’t evaluate to a value, which is expressed by " +"`()`,\n" +"the unit type. Therefore, nothing is returned, which contradicts the " +"function\n" +"definition and results in an error." +msgstr "" +"主要的错误信息 `Unexpected return type` 揭示了该代码的核心问题。函数\n" +" `plus_one` 的定义说它将返回一个 `u32` 类型的值,但是语句并没有返回一个值,\n" +"这是由 `()`unit 类型表示的。因此,没有返回值,这与函数的定义相矛盾,导致了" +"错\n" +"误发生。" + +#: src/ch02-04-comments.md:1 +msgid "# Comments" +msgstr "# 注释" + +#: src/ch02-04-comments.md:3 +msgid "" +"In Cairo programs, you can include explanatory text within the code using " +"comments. To create a comment, use the // syntax, after which any text on " +"the same line will be ignored by the compiler." +msgstr "" +"在 Cairo 程序中,你可以使用注释在代码中加入解释性的文本。要创建一个注释,请\n" +"使用 // 语法,之后同一行的任何文本都会被编译器忽略。" + +#: src/ch02-04-comments.md:5 +msgid "" +"```rust\n" +"fn main() -> felt252 {\n" +" // start of the function\n" +" 1 + 4 // return the sum of 1 and 4\n" +"}\n" +"```" +msgstr "" +"````rust\n" +"fn main() -> felt252 {\n" +" //函数的开始\n" +" 1 + 4 // 返回1和4的总和\n" +"}\n" +"```" + +#: src/ch02-05-control-flow.md:1 +msgid "## Control Flow" +msgstr "## 控制流" + +#: src/ch02-05-control-flow.md:3 +msgid "" +"The ability to run some code depending on whether a condition is true and to " +"run some code repeatedly while a condition is true are basic building blocks " +"in most programming languages. The most common constructs that let you " +"control the flow of execution of Cairo code are if expressions and loops." +msgstr "" +"根据条件是否为真来决定是否执行某些代码,以及根据条件是否为真来重复运行一段\n" +"代码的能力是大部分编程语言的基本组成部分。Cairo 代码中最常见的用来控制执行\n" +"流的结构是 `if` 表达式和循环。" + +#: src/ch02-05-control-flow.md:5 +msgid "### `if` Expressions" +msgstr "### `if`表达式" + +#: src/ch02-05-control-flow.md:7 +msgid "" +"An if expression allows you to branch your code depending on conditions. You " +"provide a condition and then state, “If this condition is met, run this " +"block of code. If the condition is not met, do not run this block of code.”" +msgstr "" +"`if` 表达式允许根据条件执行不同的代码分支。你提供一个条件并表示 “如果条件满\n" +"足,运行这段代码;如果条件不满足,不运行这段代码。”" + +#: src/ch02-05-control-flow.md:11 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" let number = 3;\n" +"\n" +" if number == 5 {\n" +" 'condition was true'.print();\n" +" } else {\n" +" 'condition was false'.print();\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" let number = 3;\n" +"\n" +" if number == 5 {\n" +" 'condition was true'.print();\n" +" } else {\n" +" 'condition was false'.print();\n" +" }\n" +"}\n" +"```" + +#: src/ch02-05-control-flow.md:25 +msgid "" +"All `if` expressions start with the keyword `if`, followed by a condition. " +"In this case, the condition checks whether or not the variable `number` has " +"a value equal to 5. We place the block of code to execute if the condition " +"is `true` immediately after the condition inside curly brackets." +msgstr "" +"所有的 `if` 表达式都以关键字 `if` 开始,其后跟一个条件。在这个例子中,条件检" +"查\n" +"变量 `number` 的值是否等于 5。在条件为 `true` 时希望执行的代码块位于紧跟条" +"件\n" +"之后的大括号中。" + +#: src/ch02-05-control-flow.md:27 +msgid "" +"Optionally, we can also include an `else` expression, which we chose to do " +"here, to give the program an alternative block of code to execute should the " +"condition evaluate to `false`. If you don’t provide an `else` expression and " +"the condition is `false`, the program will just skip the `if` block and move " +"on to the next bit of code." +msgstr "" +"另外,我们也可以包含一个可选的 `else` 表达式来提供一个在条件为 `false` 时应当" +"执行的代码块,这里我们就这么做了。如果不提供 `else` 表达式并且条件为 `false` " +"时,程序会直接忽略 `if` 代码块并继续执行下面的代码。" + +#: src/ch02-05-control-flow.md:29 +msgid "Try running this code; you should see the following output:" +msgstr "尝试运行这段代码;你应该看到以下输出:" + +#: src/ch02-05-control-flow.md:31 +msgid "" +"```console\n" +"$ cairo-run main.cairo\n" +"[DEBUG]\tcondition was false\n" +"```" +msgstr "" +"```console\n" +"$ cairo-run main.cairo\n" +"[DEBUG]\tcondition was false\n" +"```" + +#: src/ch02-05-control-flow.md:36 +msgid "" +"Let’s try changing the value of `number` to a value that makes the condition " +"`true` to see what happens:" +msgstr "让我们试着改变 `number` 的值使条件为 `true` 时看看会发生什么:" + +#: src/ch02-05-control-flow.md:38 +msgid "" +"```rust\n" +" let number = 5;\n" +"```" +msgstr "" +"```rust\n" +" let number = 5;\n" +"```" + +#: src/ch02-05-control-flow.md:42 +msgid "" +"```console\n" +"$ cairo-run main.cairo\n" +"condition was true\n" +"```" +msgstr "" +"```console\n" +"$ cairo-run main.cairo\n" +"condition was true\n" +"```" + +#: src/ch02-05-control-flow.md:47 +msgid "" +"It’s also worth noting that the condition in this code must be a bool. If " +"the condition isn’t a bool, we’ll get an error." +msgstr "" +"还值得注意的是,这段代码中的条件必须是一个 `bool` 值。如果该条件不是 `bool` " +"值,我们会得到一个错误。" + +#: src/ch02-05-control-flow.md:49 +msgid "" +"```console\n" +"$ cairo-run main.cairo\n" +"thread 'main' panicked at 'Failed to specialize: `enum_match`. " +"Error: Could not specialize libfunc `enum_match` with generic_args: " +"[Type(ConcreteTypeId { id: 1, debug_name: None })]. Error: Provided generic " +"argument is unsupported.', crates/cairo-lang-sierra-generator/src/utils." +"rs:256:9\n" +"```" +msgstr "" +"```console\n" +"$ cairo-run main.cairo\n" +"thread 'main' panicked at 'Failed to specialize: `enum_match`. " +"Error: Could not specialize libfunc `enum_match` with generic_args: " +"[Type(ConcreteTypeId { id: 1, debug_name: None })]. Error: Provided generic " +"argument is unsupported.', crates/cairo-lang-sierra-generator/src/utils." +"rs:256:9\n" +"```" + +#: src/ch02-05-control-flow.md:54 +msgid "### Handling Multiple Conditions with `else if`" +msgstr "###用`else if`处理多个条件" + +#: src/ch02-05-control-flow.md:56 +msgid "" +"You can use multiple conditions by combining if and else in an else if " +"expression. For example:" +msgstr "" +"你可以通过在一个 else if 表达式中结合 if 和 else 来使用多个条件。比如说:" + +#: src/ch02-05-control-flow.md:60 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" let number = 3;\n" +"\n" +" if number == 12 {\n" +" 'number is 12'.print();\n" +" } else if number == 3 {\n" +" 'number is 3'.print();\n" +" } else if number - 2 == 1 {\n" +" 'number minus 2 is 1'.print();\n" +" } else {\n" +" 'number not found'.print();\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" let number = 3;\n" +"\n" +" if number == 12 {\n" +" 'number is 12'.print();\n" +" } else if number == 3 {\n" +" 'number is 3'.print();\n" +" } else if number - 2 == 1 {\n" +" 'number minus 2 is 1'.print();\n" +" } else {\n" +" 'number not found'.print();\n" +" }\n" +"}\n" +"```" + +#: src/ch02-05-control-flow.md:78 +msgid "" +"This program has four possible paths it can take. After running it, you " +"should see the following output:" +msgstr "这个程序有四种可能的路径。运行后,你应该看到以下输出:" + +#: src/ch02-05-control-flow.md:80 +msgid "" +"```console\n" +"[DEBUG]\tnumber is 3\n" +"```" +msgstr "" +"```console\n" +"[DEBUG]\tnumber is 3\n" +"```" + +#: src/ch02-05-control-flow.md:84 +msgid "" +"When this program executes, it checks each `if` expression in turn and " +"executes the first body for which the condition evaluates to `true`. Note " +"that even though `number - 2 == 1` is `true`, we don’t see the output " +"`number minus 2 is 1'.print()`, nor do we see the `number not found` text " +"from the `else` block. That’s because Cairo only executes the block for the " +"first true condition, and once it finds one, it doesn’t even check the rest. " +"Using too many `else if` expressions can clutter your code, so if you have " +"more than one, you might want to refactor your code. Chapter 5 describes a " +"powerful Cairo branching construct called `match` for these cases." +msgstr "" +"当执行这个程序时,它按顺序检查每个 `if` 表达式并执行第一个条件为 `true` 的代" +"码块。注意即使 6 可以被 2 整除,也不会输出 `number minus 2 is 1'.print()`,更" +"不会输出 `else` 块中的 `number not found`。原因是 Cairo 只会执行第一个条件为 " +"`true` 的代码块,并且一旦它找到一个以后,甚至都不会检查剩下的条件了。\n" +"\n" +"使用过多的 `else if` 表达式会使代码显得杂乱无章,所以如果有多于一个 `else " +"if` 表达式,最好重构代码。为此,第五章会介绍一个强大的 Cairo 分支结构" +"(branching construct),叫做 `match`。" + +#: src/ch02-05-control-flow.md:86 +msgid "### Using `if` in a `let` statement" +msgstr "###在 `let` 语句中使用 `if`" + +#: src/ch02-05-control-flow.md:88 +msgid "" +"Because if is an expression, we can use it on the right side of a let " +"statement to assign the outcome to a variable." +msgstr "" +"因为 if 是一个表达式,我们可以在 let 语句的右边使用它,将结果分配给一个变量。" + +#: src/ch02-05-control-flow.md:92 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" let condition = true;\n" +" let number = if condition {\n" +" 5\n" +" } else {\n" +" 6\n" +" };\n" +"\n" +" if number == 5 {\n" +" 'condition was true'.print();\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" let condition = true;\n" +" let number = if condition {\n" +" 5\n" +" } else {\n" +" 6\n" +" };\n" +"\n" +" if number == 5 {\n" +" 'condition was true'.print();\n" +" }\n" +"}\n" +"```" + +#: src/ch02-05-control-flow.md:109 +msgid "" +"```console\n" +"$ cairo-run main.cairo\n" +"[DEBUG]\tcondition was true\n" +"```" +msgstr "" +"```console\n" +"$ cairo-run main.cairo\n" +"[DEBUG]\tcondition was true\n" +"```" + +#: src/ch02-05-control-flow.md:114 +msgid "" +"The `number` variable will be bound to a value based on the outcome of the " +"`if` expression. Which will be 5 here." +msgstr "`number` 变量将会绑定到表示 `if` 表达式结果的值上。这里将是 5。" + +#: src/ch02-05-control-flow.md:116 +msgid "### Repetition with Loops" +msgstr "###使用循环重复执行" + +#: src/ch02-05-control-flow.md:118 +msgid "" +"It’s often useful to execute a block of code more than once. For this task, " +"Cairo provides a simple loop syntax, which will run through the code inside " +"the loop body to the end and then start immediately back at the beginning. " +"To experiment with loops, let’s create a new project called loops." +msgstr "" +"多次执行同一段代码是很常用的,Cairo 为此提供了多种 循环(loops)。一个循环执" +"行循环体中的代码直到结尾并紧接着回到开头继续执行。为了实验一下循环,让我们新" +"建一个叫做 loops 的项目。" + +#: src/ch02-05-control-flow.md:120 +msgid "Cairo only has one kind of loop for now: `loop`." +msgstr "Cairo 目前只有一种循环:`loop`。" + +#: src/ch02-05-control-flow.md:122 +msgid "#### Repeating Code with `loop`" +msgstr "#### 使用 `loop` 重复执行代码" + +#: src/ch02-05-control-flow.md:124 +msgid "" +"The `loop` keyword tells Cairo to execute a block of code over and over " +"again\n" +"forever or until you explicitly tell it to stop." +msgstr "`loop` 关键字告诉 Rust 一遍又一遍地执行一段代码直到你明确要求停止。" + +#: src/ch02-05-control-flow.md:127 +msgid "" +"As an example, change the _src/lib.rs_ file in your _loops_ directory to " +"look\n" +"like this:" +msgstr "作为一个例子,将你的_loops_目录下的_src/lib.rs_文件修改如下:" + +#: src/ch02-05-control-flow.md:132 +msgid "" +"```rust,ignore,does_not_compile\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let mut i:usize = 0;\n" +" loop {\n" +" if i > 10{\n" +" break();\n" +" }\n" +" 'again!'.print();\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust,ignore,does_not_compile\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let mut i:usize = 0;\n" +" loop {\n" +" if i > 10{\n" +" break();\n" +" }\n" +" 'again!'.print();\n" +" }\n" +"}\n" +"```" + +#: src/ch02-05-control-flow.md:145 +msgid "" +"When we run this program, we’ll see `again!` printed over and over " +"continuously\n" +"until we stop the program manually, because the stop condition is never " +"reached.\n" +"While the compiler prevents us from writing programs without a stop " +"condition (`break()` statement),\n" +"the stop condition might never be reached, resulting in an infinite loop.\n" +"Most terminals support the keyboard shortcut ctrl-" +"c to interrupt a program that is\n" +"stuck in a continual loop. Give it a try:" +msgstr "" +"当运行这个程序时,我们会看到连续的反复打印 `again!`,直到我们手动停止程序,\n" +"因为停止条件从未达到。\n" +"虽然编译器阻止我们编写没有停止条件的程序(`break()`语句),停止条件可能永远\n" +"不会达到,从而导致无限循环。\n" +"大多数终端支持键盘快捷键ctrl-c,以中断卡在\n" +"持续循环的程序。试一试吧:" + +#: src/ch02-05-control-flow.md:152 +msgid "" +"```console\n" +"❯ cairo-run src/lib.cairo --available-gas=20000000\n" +"[DEBUG]\tagain \t(raw: 418346264942)\n" +"\n" +"[DEBUG]\tagain \t(raw: 418346264942)\n" +"\n" +"[DEBUG]\tagain \t(raw: 418346264942)\n" +"\n" +"[DEBUG]\tagain \t(raw: 418346264942)\n" +"\n" +"Run panicked with err values: [375233589013918064796019]\n" +"Remaining gas: 1050\n" +"```" +msgstr "" +"```console\n" +"❯ cairo-run src/lib.cairo --available-gas=20000000\n" +"[DEBUG]\tagain \t(raw: 418346264942)\n" +"\n" +"[DEBUG]\tagain \t(raw: 418346264942)\n" +"\n" +"[DEBUG]\tagain \t(raw: 418346264942)\n" +"\n" +"[DEBUG]\tagain \t(raw: 418346264942)\n" +"\n" +"Run panicked with err values: [375233589013918064796019]\n" +"Remaining gas: 1050\n" +"```" + +#: src/ch02-05-control-flow.md:166 +msgid "" +"> Note: Cairo prevents us from running program with infinite loops by " +"including a gas meter. The gas meter is a mechanism that limits the amount " +"of computation that can be done in a program. By setting a value to the `--" +"available-gas` flag, we can set the maximum amount of gas available to the " +"program. Gas is a unit of measurements that expresses the computation cost " +"of an instruction. When the gas meter runs out, the program will stop. In " +"this case, the program panicked because it ran out of gas, as the stop " +"condition was never reached.\n" +"> It is particularly important in the context of smart contracts deployed on " +"Starknet, as it prevents from running infinite loops on the network.\n" +"> If you're writing a program that needs to run a loop, you will need to " +"execute it with the `--available-gas` flag set to a value that is large " +"enough to run the program." +msgstr "" +"> 注意:Cairo通过包含一个 gas 表来防止我们运行无限循环的程序。 gas 表是一种限" +"制程序中可进行的计算量的机制。通过给 `--available-gas` 标志设置一个值,我们可" +"以设置程序的最大可用 gas 量。gas 是一个计量单位,表示一条指令的计算成本。当煤" +"气表耗尽时,程序将停止。在这种情况下,程序因为 gas 耗尽而报错,尽管从未达到停" +"止条件。\n" +"> 对于部署在 Starknet 上的智能合约,它特别重要,因为它可以防止在网络上运行无" +"限循环。\n" +"> 如果你正在编写一个需要运行循环的程序,你需要在执行时将 `--available-gas` 标" +"志设置为一个足够大的值来运行该程序。" + +#: src/ch02-05-control-flow.md:170 +msgid "" +"To break out of a loop, you can place the `break()` statement within the " +"loop to tell the program when to stop\n" +"executing the loop. Let's fix the infinite loop by adding a making the stop " +"condition `i > 10` reachable." +msgstr "" +"要退出循环,您可以在循环内部放置 `break()` 语句,告诉程序何时停止执行循环。\n" +"通过使停止条件 `i > 10` 可达,来修复无限循环。" + +#: src/ch02-05-control-flow.md:173 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let mut i: usize = 0;\n" +" loop {\n" +" if i > 10 {\n" +" break ();\n" +" }\n" +" 'again'.print();\n" +" i += 1;\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let mut i: usize = 0;\n" +" loop {\n" +" if i > 10 {\n" +" break ();\n" +" }\n" +" 'again'.print();\n" +" i += 1;\n" +" }\n" +"}\n" +"```" + +#: src/ch02-05-control-flow.md:187 +msgid "#### Returning Values from Loops" +msgstr "#### 从循环中返回值" + +#: src/ch02-05-control-flow.md:189 +msgid "" +"One of the uses of a `loop` is to retry an operation you know might fail, " +"such\n" +"as checking whether an operation has succeeded. You might also need to pass\n" +"the result of that operation out of the loop to the rest of your code. To " +"do\n" +"this, you can add the value you want returned after the `break` expression " +"you\n" +"use to stop the loop; that value will be returned out of the loop so you " +"can\n" +"use it, as shown here:" +msgstr "" +"`loop` 的一个用例是重试可能会失败的操作,比如检查线程是否完成了任务。然而你\n" +"可能会需要将操作的结果传递给其它的代码。如果将返回值加入你用来停止循环的 \n" +"`break` 表达式,它会被停止的循环返回,如下所示:" + +#: src/ch02-05-control-flow.md:196 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let mut counter = 0;\n" +"\n" +" let result = loop {\n" +" if counter == 10 {\n" +" break counter * 2;\n" +" }\n" +" counter += 1;\n" +" };\n" +"\n" +" 'The result is '.print();\n" +" result.print();\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let mut counter = 0;\n" +"\n" +" let result = loop {\n" +" if counter == 10 {\n" +" break counter * 2;\n" +" }\n" +" counter += 1;\n" +" };\n" +"\n" +" 'The result is '.print();\n" +" result.print();\n" +"}\n" +"```" + +#: src/ch02-05-control-flow.md:213 +msgid "" +"Before the loop, we declare a variable named `counter` and initialize it to\n" +"`0`. Then we declare a variable named `result` to hold the value returned " +"from\n" +"the loop. On every iteration of the loop, we check whether the `counter` is " +"equal to `10`, and then add `1` to the `counter` variable.\n" +"When the condition is met, we use the `break` keyword with the value " +"`counter * 2`. After the loop, we use a\n" +"semicolon to end the statement that assigns the value to `result`. Finally, " +"we\n" +"print the value in `result`, which in this case is `20`." +msgstr "" +"在循环之前,我们声明一个名为 `counter` 的变量,并将其初始化为 `0`。然后我们声" +"明一个名为 `result` 的变量,用来保存从循环中返回的值。\n" +"在循环的每一次迭代中,我们检查 `counter` 是否等于 `10`,然后在 `counter` 变量" +"中加 `1`。当条件得到满足时,我们使用 `break` 关键字,其值为 `counter * 2`。在" +"循环之后,我们用一个\n" +"分号来结束给`result`赋值的语句。最后,我们打印`result`中的值,在本例中是" +"`20`。" + +#: src/ch02-06-common-collections.md:1 +msgid "## Common Collections" +msgstr "## ###常见的集合" + +#: src/ch02-06-common-collections.md:3 +msgid "" +"Cairo1 provides a set of common collection types that can be used to store " +"and manipulate data. These collections are designed to be efficient, " +"flexible, and easy to use. This section introduces the primary collection " +"types available in Cairo1: `Array` and `Felt252Dict` (coming soon)." +msgstr "" +"Cairo1提供了一套常用的集合类型,可用于存储和操作数据。这些集合被设计成高效、" +"灵活和易于使用。本节介绍了Cairo1中的主要集合类型:`Array`和`Felt252Dict`(即" +"将推出)。" + +#: src/ch02-06-common-collections.md:5 +msgid "### Array" +msgstr "### 阵列" + +#: src/ch02-06-common-collections.md:7 +msgid "" +"An array is a collection of elements of the same type. You can create and " +"use array methods by importing the `array::ArrayTrait` trait." +msgstr "" +"一个数组是相同类型元素的集合。你可以通过导入`array::ArrayTrait`特质来创建和使" +"用数组方法。" + +#: src/ch02-06-common-collections.md:9 +msgid "" +"An important thing to note is that arrays have limited modifications " +"options. Arrays are, in fact, queues whose values can't be modified.\n" +"This has to do with the fact that once a memory slot is written to, it " +"cannot be overwritten, but only read from it. You can only append items to " +"the end of an array and remove items from the front using `pop_front`." +msgstr "" +"需要注意的一个重要问题是,数组的修改选项有限。事实上,数组是队列,其值不能被" +"修改。\n" +"这与这样一个事实有关:一旦一个内存槽被写入,它就不能被覆盖,而只能从其中读" +"出。你只能用`pop_front`将项目追加到数组的末端,并从前面删除项目。" + +#: src/ch02-06-common-collections.md:12 +msgid "#### Creating an Array" +msgstr "#### 创建一个数组" + +#: src/ch02-06-common-collections.md:14 +msgid "" +"Creating an Array is done with the `ArrayTrait::new()` call. Here is an " +"example of creation of an array with 3 elements:" +msgstr "" +"创建一个数组是通过`ArrayTrait::new()`调用完成的。下面是一个创建3个元素的数组" +"的例子:" + +#: src/ch02-06-common-collections.md:16 +msgid "" +"```rust\n" +"use array::ArrayTrait;\n" +"\n" +"fn main() {\n" +" let mut a = ArrayTrait::new();\n" +" a.append(0);\n" +" a.append(1);\n" +" a.append(2);\n" +"}\n" +"```" +msgstr "" +"``rust\n" +"使用array::ArrayTrait;\n" +"\n" +"fn main() {\n" +" let mut a = ArrayTrait::new();\n" +" a.append(0);\n" +" a.append(1);\n" +" a.append(2);\n" +"}\n" +"```" + +#: src/ch02-06-common-collections.md:27 +msgid "" +"You can pass the expected type of items inside the array when instantiating " +"the array like this" +msgstr "你可以在实例化数组时传递数组内项目的预期类型,像这样" + +#: src/ch02-06-common-collections.md:29 +msgid "" +"```rust,\n" +"let mut arr = ArrayTrait::::new();\n" +"```" +msgstr "" +"``rust、\n" +"let mut arr = ArrayTrait::::new();\n" +"```" + +#: src/ch02-06-common-collections.md:33 +msgid "#### Updating an Array" +msgstr "#### 更新一个阵列" + +#: src/ch02-06-common-collections.md:35 +msgid "##### Adding Elements" +msgstr "##### 添加元素" + +#: src/ch02-06-common-collections.md:37 +msgid "" +"To add an element to the end of an array, you can use the `append()` method:" +msgstr "要在一个数组的末尾添加一个元素,可以使用`append()`方法:" + +#: src/ch02-06-common-collections.md:39 +msgid "" +"```rust\n" +" let mut a = ArrayTrait::new();\n" +" a.append(10);\n" +" a.append(1);\n" +" a.append(2);\n" +"```" +msgstr "" +"``rust\n" +" let mut a = ArrayTrait::new();\n" +" a.append(10);\n" +" a.append(1);\n" +" a.append(2);\n" +"```" + +#: src/ch02-06-common-collections.md:46 +msgid "##### Removing Elements" +msgstr "##### 移除元素" + +#: src/ch02-06-common-collections.md:48 +msgid "" +"To remove an element from the front of an array, you can use the " +"`pop_front()` method.\n" +"This method returns an `Option` containing the removed element, or `Option::" +"None` if the array is empty." +msgstr "" +"要从一个数组的前面移除一个元素,你可以使用`pop_front()`方法。\n" +"该方法返回一个包含被移除元素的`Option`,如果数组为空,则返回`Option::None`。" + +#: src/ch02-06-common-collections.md:51 +msgid "" +"```rust\n" +"use option::OptionTrait;\n" +"use array::ArrayTrait;\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" let mut a = ArrayTrait::new();\n" +" a.append(10);\n" +" a.append(1);\n" +" a.append(2);\n" +"\n" +" let first_value = a.pop_front().unwrap();\n" +" first_value.print(); // print '10'\n" +"}\n" +"```" +msgstr "" +"``rust\n" +"use option::OptionTrait;\n" +"use array::ArrayTrait;\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" let mut a = ArrayTrait::new();\n" +" a.append(10);\n" +" a.append(1);\n" +" a.append(2);\n" +"\n" +" let first_value = a.pop_front().unwrap();\n" +" first_value.print(); // 打印 '10' 。\n" +"}\n" +"```" + +#: src/ch02-06-common-collections.md:67 +msgid "" +"The above code will print `10` as we remove the first element that was added." +msgstr "上面的代码将打印`10`,因为我们删除了第一个被添加的元素。" + +#: src/ch02-06-common-collections.md:69 +msgid "" +"In Cairo, memory is immutable, which means that it is not possible to modify " +"the elements of an array once they've been added. You can only add elements " +"to the end of an array and remove elements from the front of an array. These " +"operations do not require memory mutation, as they involve updating pointers " +"rather than directly modifying the memory cells." +msgstr "" +"在Cairo中,内存是不可改变的,这意味着一旦数组中的元素被添加,就不可能修改它" +"们。你只能将元素添加到数组的末端,并从数组的前端移除元素。这些操作不需要内存" +"突变,因为它们涉及到更新指针而不是直接修改内存单元。" + +#: src/ch02-06-common-collections.md:71 +msgid "#### Reading Elements from an Array" +msgstr "#### 从一个数组中读取元素" + +#: src/ch02-06-common-collections.md:73 +msgid "" +"To access array elements, you can use `get()` or `at()` array methods that " +"return different types. Using `arr.at(index)` is equivalent to using the " +"subscripting operator `arr[index]`." +msgstr "" +"为了访问数组元素,你可以使用`get()`或`at()`数组方法,它们返回不同的类型。使用" +"`arr.at(index)`等同于使用下标操作符`arr[index]`。" + +#: src/ch02-06-common-collections.md:75 +msgid "" +"The `get` function returns an `Option>`, which means it returns an " +"option to a Box type (Cairo's smart-pointer type) containing a snapshot to " +"the element at the specified index if that element exists in the array. If " +"the element doesn't exist, `get` returns `None`. This method is useful when " +"you expect to access indices that may not be within the array's bounds and " +"want to handle such cases gracefully without panics. Snapshots will be " +"explained in more detail in the [References and Snapshots](ch03-02-" +"references-and-snapshots.md) chapter." +msgstr "" +"`get'函数返回一个`Option>,这意味着它返回一个Box类型(Cairo的智能指针" +"类型)的选项,包含一个指向指定索引的元素的快照,如果该元素在数组中存在。如果" +"该元素不存在,`get`返回`None'。当你期望访问可能不在数组范围内的索引,并且希望" +"优雅地处理这种情况而不发生恐慌时,这个方法很有用。快照将在[引用和快照]" +"(ch03-02-references-and-snapshots.md)章节中详细解释。" + +#: src/ch02-06-common-collections.md:77 +msgid "" +"The `at` function, on the other hand, directly returns a snapshot to the " +"element at the specified index using the `unbox()` operator to extract the " +"value stored in a box. If the index is out of bounds, a panic error occurs. " +"You should only use at when you want the program to panic if the provided " +"index is out of the array's bounds, which can prevent unexpected behavior." +msgstr "" +"另一方面,`at`函数直接返回一个快照到指定索引的元素,使用`unbox()`操作符来提取" +"存储在一个盒子里的值。如果索引超出了范围,就会发生一个恐慌性错误。你应该只在" +"希望程序在提供的索引超出数组的边界时发生恐慌时使用at,这样可以防止意外的行" +"为。" + +#: src/ch02-06-common-collections.md:79 +msgid "" +"In summary, use `at` when you want to panic on out-of-bounds access " +"attempts, and use `get` when you prefer to handle such cases gracefully " +"without panicking." +msgstr "" +"总之,当你想对越界访问尝试进行恐慌时,请使用`at`,而当你想优雅地处理这种情况" +"而不恐慌时,请使用`get`。" + +#: src/ch02-06-common-collections.md:81 +msgid "" +"```rust\n" +"use array::ArrayTrait;\n" +"fn main() {\n" +" let mut a = ArrayTrait::new();\n" +" a.append(0);\n" +" a.append(1);\n" +"\n" +" let first = *a.at(0_usize);\n" +" let second = *a.at(1_usize);\n" +"}\n" +"```" +msgstr "" +"``rust\n" +"使用array::ArrayTrait;\n" +"fn main() {\n" +" let mut a = ArrayTrait::new();\n" +" a.append(0);\n" +" a.append(1);\n" +"\n" +" let first = *a.at(0_usize);\n" +" let second = *a.at(1_usize);\n" +"}\n" +"```" + +#: src/ch02-06-common-collections.md:93 +msgid "" +"In this example, the variable named `first` will get the value `0` because " +"that\n" +"is the value at index `0` in the array. The variable named `second` will " +"get\n" +"the value `1` from index `1` in the array." +msgstr "" +"在这个例子中,名为`first'的变量将得到`0'的值,因为那是数组中索引`0'的值。\n" +"是数组中索引为`0'的值。名为`second'的变量将得到\n" +"从数组中的索引`1`处获得数值`1'。" + +#: src/ch02-06-common-collections.md:97 +msgid "Here is an example with the `get()` method:" +msgstr "下面是一个使用`get()`方法的例子:" + +#: src/ch02-06-common-collections.md:99 +msgid "" +"```rust\n" +"use array::ArrayTrait;\n" +"use box::BoxTrait;\n" +"fn main() -> u128 {\n" +" let mut arr = ArrayTrait::::new();\n" +" arr.append(100_u128);\n" +" let index_to_access =\n" +" 1_usize; // Change this value to see different results, what " +"would happen if the index doesn't exist ?\n" +" match arr.get(index_to_access) {\n" +" Option::Some(x) => {\n" +" *x.unbox() // Don't worry about * for now, if you are curious " +"see Chapter 3.2 #desnap operator\n" +" // It basically means \"transform what get(idx) " +"returned into a real value\"\n" +" },\n" +" Option::None(_) => {\n" +" let mut data = ArrayTrait::new();\n" +" data.append('out of bounds');\n" +" panic(data)\n" +" }\n" +" }\n" +"}\n" +"```" +msgstr "" +"``rust\n" +"use array::ArrayTrait;\n" +"使用box::BoxTrait;\n" +"fn main() -> u128 {\n" +" let mut arr = ArrayTrait::::new();\n" +" arr.append(100_u128);\n" +" 让index_to_access =\n" +" 1_usize; // 改变这个值可以看到不同的结果,如果索引不存在会发生什" +"么?\n" +" match arr.get(index_to_access) {\n" +" Option::Some(x) => {\n" +" *x.unbox() // 暂时不用担心*,如果你好奇的话,请看3.2章 #desnap操" +"作符\n" +" // 基本上意味着 \"将get(idx)返回的东西转换成一个真实" +"的值\"\n" +" },\n" +" 选项::None(_) => {\n" +" let mut data = ArrayTrait::new();\n" +" data.append('out of bounds');\n" +" panic(data)\n" +" }\n" +" }\n" +"}\n" +"```" + +#: src/ch02-06-common-collections.md:121 +msgid "#### Size related methods" +msgstr "#### 大小相关的方法" + +#: src/ch02-06-common-collections.md:123 +msgid "" +"To determine the number of elements in an array, use the `len()` method. The " +"return is of type `usize`." +msgstr "要确定一个数组中的元素数量,请使用`len()`方法。其返回值为`usize`类型。" + +#: src/ch02-06-common-collections.md:125 +msgid "" +"If you want to check if an array is empty or not, you can use the " +"`is_empty()` method, which returns `true` if the array is empty and `false` " +"otherwise." +msgstr "" +"如果你想检查一个数组是否为空,你可以使用`is_empty()`方法,如果数组为空,返回" +"`true`,否则返回`false`。" + +#: src/ch02-06-common-collections.md:127 +msgid "#### Storing multiple types with Enums" +msgstr "#### 用Enums存储多种类型" + +#: src/ch02-06-common-collections.md:129 +msgid "" +"If you want to store elements of different types in an array, you can use an " +"`Enum` to define a custom data type that can hold multiple types." +msgstr "" +"如果你想在一个数组中存储不同类型的元素,你可以使用`Enum`来定义一个可以容纳多" +"种类型的自定义数据类型。" + +#: src/ch02-06-common-collections.md:131 +msgid "" +"```rust\n" +"use array::ArrayTrait;\n" +"use traits::Into;\n" +"\n" +"#[derive(Copy, Drop)]\n" +"enum Data {\n" +" Integer: u128,\n" +" Felt: felt252,\n" +" Tuple: (u32, u32),\n" +"}\n" +"\n" +"fn main() {\n" +" let mut messages: Array = ArrayTrait::new();\n" +" messages.append(Data::Integer(100_u128));\n" +" messages.append(Data::Felt('hello world'));\n" +" messages.append(Data::Tuple((10_u32, 30_u32)));\n" +"}\n" +"```" +msgstr "" +"``rust\n" +"use array::ArrayTrait;\n" +"使用traits::Into;\n" +"\n" +"#[derive(Copy, Drop)]\n" +"enum Data {\n" +" 整数: u128、\n" +" Felt: felt252、\n" +" Tuple: (u32, u32)、\n" +"}\n" +"\n" +"fn main() {\n" +" let mut messages:Array = ArrayTrait::new();\n" +" messages.append(Data::Integer(100_u128));\n" +" messages.append(Data::Felt('hello world'));\n" +" messages.append(Data::Tuple((10_u32, 30_u32)) );\n" +"}\n" +"```" + +#: src/ch02-06-common-collections.md:150 +msgid "#### Span" +msgstr "#### 跨度" + +#: src/ch02-06-common-collections.md:152 +msgid "" +"`Span` is a struct that represents a snapshot of an `Array`. It is designed " +"to provide safe and controlled access to the elements of an array without " +"modifying the original array. Span is particularly useful for ensuring data " +"integrity and avoiding borrowing issues when passing arrays between " +"functions or when performing read-only operations (cf. [References and " +"Snapshots](ch03-02-references-and-snapshots.md))" +msgstr "" +"Span \"是一个结构,代表一个 \"数组 \"的快照。它被设计用来提供对数组元素的安全" +"和控制的访问,而不需要修改原始数组。Span对于确保数据的完整性和避免在函数间传" +"递数组或执行只读操作时的借用问题特别有用(参见[引用和快照](ch03-02-" +"references-and-snapshots.md))" + +#: src/ch02-06-common-collections.md:154 +msgid "" +"All methods provided by `Array` can also be used with `Span`, with the " +"exception of the `append()` method." +msgstr "" +"除了 \"append() \"方法外,\"Array \"提供的所有方法也可以用于 \"Span\"。" + +#: src/ch02-06-common-collections.md:156 +msgid "##### Turning an Array into span" +msgstr "##### 将一个数组变成跨度" + +#: src/ch02-06-common-collections.md:158 +msgid "To create a `Span` of an `Array`, call the `span()` method:" +msgstr "要创建一个 \"数组 \"的 \"跨度\",请调用 \"span() \"方法:" + +#: src/ch02-06-common-collections.md:160 +msgid "" +"```rust\n" +"let span = array.span();\n" +"```" +msgstr "" +"``rust\n" +"let span = array.span();\n" +"```" + +#: src/ch02-06-common-collections.md:164 src/ch04-03-method-syntax.md:286 +#: src/ch06-05-separating-modules-into-different-files.md:98 +msgid "## Summary" +msgstr "##摘要" + +#: src/ch02-06-common-collections.md:166 +msgid "" +"You made it! This was a sizable chapter: you learned about variables, data " +"types, functions, comments,\n" +"`if` expressions, loops, and common collections! To practice with the " +"concepts discussed in this chapter,\n" +"try building programs to do the following:" +msgstr "" +"你成功了!这是一个相当大的章节:你学习了变量、数据类型、函数、注释、\n" +"`if`表达式、循环和常见的集合!为了练习本章所讨论的概念、\n" +"试着建立程序来做以下事情:" + +#: src/ch02-06-common-collections.md:170 +msgid "" +"- Generate the _n_-th Fibonacci number.\n" +"- Compute the factorial of a number _n_." +msgstr "" +"- 产生第_n_个斐波那契数。\n" +"- 计算一个数字的阶乘_n_。" + +#: src/ch02-06-common-collections.md:173 +msgid "" +"When you’re ready to move on, we’ll talk about a concept that Cairo shares " +"with Rust and that _doesn’t_\n" +"commonly exist in other programming languages: ownership." +msgstr "" +"当你准备好继续前进时,我们将讨论一个Cairo与Rust共享的概念,而这个概念在其他编" +"程语言中并不常见。\n" +"在其他编程语言中通常不存在的概念:所有权。" + +#: src/ch03-00-understanding-ownership.md:1 +msgid "# Understanding Cairo's Ownership system" +msgstr "# 了解开罗的所有权制度" + +#: src/ch03-00-understanding-ownership.md:3 +msgid "" +"Cairo is a language built around a linear type system that allows us to\n" +"statically ensure that in every Cairo program, a value is used exactly " +"once.\n" +"This linear type system helps preventing runtime errors by ensuring that " +"operations that could cause such errors, such as writing twice to a memory " +"cell, are detected at compile time.\n" +"This is achieved by implementing an ownership system\n" +"and forbidding copying and dropping values by default. In this chapter, " +"we’ll\n" +"talk about Cairo's ownership system as well as references and snapshots." +msgstr "" +"Cairo是一种围绕着线性类型系统建立的语言,它允许我们\n" +"静态地确保在每个Cairo程序中,一个值只被使用一次。\n" +"这种线性类型系统有助于防止运行时错误,因为它可以确保在编译时检测到可能导致这" +"种错误的操作,如向一个内存单元写两次。\n" +"这是通过实施一个所有权系统来实现的\n" +"并在默认情况下禁止复制和丢弃数值。在本章中,我们将\n" +"讨论Cairo的所有权系统以及引用和快照。" + +#: src/ch03-01-what-is-ownership.md:1 +msgid "## What Is Ownership?" +msgstr "## 什么是所有权?" + +#: src/ch03-01-what-is-ownership.md:3 +msgid "" +"Cairo implements an ownership system to ensure the safety and correctness of " +"its compiled code.\n" +"The ownership mechanism complements the linear type system, which enforces " +"that objects are used exactly once.\n" +"This helps prevent common operations that can produce runtime errors, such " +"as illegal memory address\n" +"references or multiple writes to the same memory address, and ensures the " +"soundness of Cairo programs\n" +"by checking at compile time that all the dictionaries are squashed." +msgstr "" +"Cairo实现了一个所有权系统以确保其编译代码的安全性和正确性。\n" +"所有权机制是对线性类型系统的补充,该系统规定对象只能使用一次。\n" +"这有助于防止可能产生运行时错误的常见操作,如非法的内存地址\n" +"这有助于防止可能产生运行时错误的常见操作,如非法的内存地址引用或对同一内存地" +"址的多次写入,并确保Cairo程序的正确性\n" +"通过在编译时检查所有的字典是否被压扁来确保Cairo程序的合理性。" + +#: src/ch03-01-what-is-ownership.md:9 +msgid "" +"Now that we’re past basic Cairo syntax, we won’t include all the `fn main() " +"{`\n" +"code in examples, so if you’re following along, make sure to put the " +"following\n" +"examples inside a `main` function manually. As a result, our examples will " +"be a\n" +"bit more concise, letting us focus on the actual details rather than\n" +"boilerplate code." +msgstr "" +"现在我们已经过了Cairo的基本语法,我们不会在例子中包括所有的`fn main() {`的代" +"码。\n" +"所以如果你正在学习,请确保将下面的例子放在一个`main`函数中。因\n" +"此,我们的例子将更加简洁,让我们专注于实际的细节而不是样板代码。" + +#: src/ch03-01-what-is-ownership.md:15 +msgid "### Ownership Rules" +msgstr "###所有权规则" + +#: src/ch03-01-what-is-ownership.md:17 +msgid "" +"First, let’s take a look at the ownership rules. Keep these rules in mind as " +"we\n" +"work through the examples that illustrate them:" +msgstr "" +"首先,让我们看一下所有权规则。当我们通过说明这些规则的例子时,请牢记这\n" +"些规则,并通过例子来说明它们:" + +#: src/ch03-01-what-is-ownership.md:20 +msgid "" +"- Each value in Cairo has an _owner_.\n" +"- There can only be one owner at a time.\n" +"- When the owner goes out of scope, the value will be _dropped_." +msgstr "" +"- Cairo的每个值都有一个_所有者_。\n" +"- 在同一时间只能有一个所有者。\n" +"- 当所有者超出范围时,该值将被_丢弃_。" + +#: src/ch03-01-what-is-ownership.md:24 +msgid "### Variable Scope" +msgstr "### 可变范围" + +#: src/ch03-01-what-is-ownership.md:26 +msgid "" +"As a first example of ownership, we’ll look at the _scope_ of some " +"variables. A\n" +"scope is the range within a program for which an item is valid. Take the\n" +"following variable:" +msgstr "" +"作为所有权的第一个例子,我们来看看一些变量的_范围。A范围是指程序中某一\n" +"项目有效的范围。考虑以下变量:" + +#: src/ch03-01-what-is-ownership.md:30 +msgid "" +"```rust\n" +"let s = 'hello';\n" +"```" +msgstr "" +"``rust\n" +"let s = 'hello';\n" +"```" + +#: src/ch03-01-what-is-ownership.md:34 +msgid "" +"The variable `s` refers to a short string, where the value of the string is\n" +"hardcoded into the text of our program. The variable is valid from the point " +"at\n" +"which it’s declared until the end of the current _scope_. Listing 3-1 shows " +"a\n" +"program with comments annotating where the variable `s` would be valid." +msgstr "" +"变量`s`指的是一个短字符串,字符串的值被硬编码到我们的程序文本中。\n" +"硬编码到我们程序的文本中。这个变量从它被声明的那一刻起,一直到当前_scope_的结" +"束,都是有效的。\n" +"这个变量从它被声明的那一刻起一直到当前_scope_的结束都有效。清单3-1显示了一" +"个\n" +"程序,其中的注释说明了变量`s`的有效位置。" + +#: src/ch03-01-what-is-ownership.md:39 +msgid "" +"```rust\n" +" { // s is not valid here, it’s not yet declared\n" +" let s = 'hello'; // s is valid from this point forward\n" +"\n" +" // do stuff with s\n" +" } // this scope is now over, and s is no longer " +"valid\n" +"```" +msgstr "" +"``rust\n" +" { // s在这里是无效的,它还没有被声明。\n" +" let s = 'hello'; // s从现在开始是有效的\n" +"\n" +" // 对s做一些事情\n" +" } // 这个范围现在结束了,s不再有效了\n" +"```" + +#: src/ch03-01-what-is-ownership.md:47 +msgid "" +"Listing 3-1: A variable and the scope in which it " +"is\n" +"valid" +msgstr "" +"清单3-1:一个变量和它所处的范围\n" +"有效" + +#: src/ch03-01-what-is-ownership.md:50 +msgid "In other words, there are two important points in time here:" +msgstr "换句话说,这里有两个重要的时间点:" + +#: src/ch03-01-what-is-ownership.md:52 +msgid "" +"- When `s` comes _into_ scope, it is valid.\n" +"- It remains valid until it goes _out of_ scope." +msgstr "" +"- 当`s`进入_范围时,它是有效的。\n" +"- 它一直有效,直到它退出范围。" + +#: src/ch03-01-what-is-ownership.md:55 +msgid "" +"At this point, the relationship between scopes and when variables are valid " +"is\n" +"similar to that in other programming languages. Now we’ll build on top of " +"this\n" +"understanding by using the `Array` type we introduced in the [previous " +"chapter](ch02-06-common-collections.md)." +msgstr "" +"在这一点上,作用域和变量有效时间之间的关系与其他编程语言类似。\n" +"与其他编程语言中的关系相似。现在我们将在这个基础上\n" +"的理解,使用我们在[前一章](ch02-06-common-collections.md)中介绍的`Array`类" +"型。" + +#: src/ch03-01-what-is-ownership.md:59 +msgid "### Ownership with the `Array` Type" +msgstr "### 拥有 `Array` 类型的所有权" + +#: src/ch03-01-what-is-ownership.md:61 +msgid "" +"To illustrate the rules of ownership, we need a data type that is more " +"complex.\n" +"The types covered in the [“Data Types”][data-types] section\n" +"of Chapter 2 are of a known size, can be\n" +"quickly and trivially copied to make a new, independent instance if another\n" +"part of code needs to use the same value in a different scope, and can " +"easily\n" +"be dropped when they're no longer used. But what is the behavior with the " +"`Array` type whose size\n" +"is unknown at compile time and which can't be trivially copied ?" +msgstr "" +"为了说明所有权的规则,我们需要一个更复杂的数据类型。\n" +"第二章[\"数据类型\"][data-types]部分中所涉及的类型\n" +"中所涉及的类型都是已知大小的,可以快速而琐碎地复制成\n" +"如果另一部分代码需要使用相同的类型,可以快速地复制一个新的、独立的实例。\n" +"如果另一部分代码需要在不同的范围内使用相同的值,就可以快速、简单地复制一个新" +"的、独立的实例。\n" +"当它们不再被使用时可以很容易地被丢弃。但是对于 `Array` 类型的行为是什么?\n" +"在编译时是未知的,并且不能被简单地复制?" + +#: src/ch03-01-what-is-ownership.md:69 +msgid "Here is a short reminder of what an array looks like:" +msgstr "这里简单提醒一下数组的样子:" + +#: src/ch03-01-what-is-ownership.md:71 +msgid "" +"```rust\n" +"let mut arr = ArrayTrait::::new();\n" +"arr.append(1);\n" +"arr.append(2);\n" +"```" +msgstr "" +"``rust\n" +"let mut arr = ArrayTrait::::new();\n" +"arr.append(1);\n" +"arr.append(2);\n" +"```" + +#: src/ch03-01-what-is-ownership.md:77 +msgid "" +"So, how does the ownership system ensure that each cell is never written to " +"more than once?\n" +"Consider the following code, where we try to pass the same instance of an " +"array in two consecutive\n" +"function calls:" +msgstr "" +"那么,所有权系统如何确保每个单元格不会被写入超过一次?\n" +"考虑一下下面的代码,我们试图在两个连续的数组中传递同一个实例\n" +"函数调用中传递同一个数组实例:" + +#: src/ch03-01-what-is-ownership.md:81 +msgid "" +"```rust,does_not_compile\n" +"use array::ArrayTrait;\n" +"fn foo(arr: Array) {\n" +"}\n" +"\n" +"fn bar(arr:Array){\n" +"}\n" +"\n" +"fn main() {\n" +" let mut arr = ArrayTrait::::new();\n" +" foo(arr);\n" +" bar(arr);\n" +"}\n" +"```" +msgstr "" +"```rust,does_not_compile\n" +"use array::ArrayTrait;\n" +"fn foo(arr: Array) {\n" +"}\n" +"\n" +"fn bar(arr:Array){\n" +"}\n" +"\n" +"fn main() {\n" +" let mut arr = ArrayTrait::::new();\n" +" foo(arr);\n" +" bar(arr);\n" +"}\n" +"```" + +#: src/ch03-01-what-is-ownership.md:96 +msgid "" +"In this case, we try to pass the same array instance `arr` by value to the " +"functions `foo` and `bar`, which means\n" +"that the parameter used in both function calls is the same instance of the " +"array. If you append a value to the array\n" +"in `foo`, and then try to append another value to the same array in `bar`, " +"what would happen is that\n" +"you would attempt to try to write to the same memory cell twice, which is " +"not allowed in Cairo.\n" +"To prevent this, the ownership of the `arr` variable moves from the `main` " +"function to the `foo` function. When trying\n" +"to call `bar` with `arr` as a parameter, the ownership of `arr` was already " +"moved to the first call. The ownership\n" +"system thus prevents us from using the same instance of `arr` in `foo`." +msgstr "" +"在这种情况下,我们试图将同一个数组实例`arr`通过值传递给函数`foo`和`bar`,这意" +"味着两个函数调用的参数都是同一个数组实例。如果你在`foo`中向数组添加一个值,然" +"后在`bar`中向数组添加一个值\n" +"中向数组追加一个值,然后试图在`bar`中向同一个数组追加另一个值,会发生什么" +"呢?\n" +"你会试图向同一个内存单元写两次,这在Cairo中是不允许的。\n" +"为了防止这种情况,`arr`变量的所有权从`main`函数转移到`foo`函数。当试\n" +"图以`arr`为参数调用`bar`时,`arr`的所有权已经被转移到第一次调用时。所\n" +"有权系统因此阻止我们在`foo`中使用相同的`arr`实例。" + +#: src/ch03-01-what-is-ownership.md:104 +msgid "Running the code above will result in a compile-time error:" +msgstr "运行上面的代码将导致一个编译时错误:" + +#: src/ch03-01-what-is-ownership.md:106 +msgid "" +"```console\n" +"error: Variable was previously moved. Trait has no implementation in " +"context: core::traits::Copy::>\n" +" --> array.cairo:6:9\n" +" let mut arr = ArrayTrait::::new();\n" +" ^*****^\n" +"```" +msgstr "" +"```console\n" +"error: Variable was previously moved. Trait has no implementation in " +"context: core::traits::Copy::>\n" +" --> array.cairo:6:9\n" +" let mut arr = ArrayTrait::::new();\n" +" ^*****^\n" +"```" + +#: src/ch03-01-what-is-ownership.md:113 +msgid "### The `Copy` Trait" +msgstr "### `Copy` 特性" + +#: src/ch03-01-what-is-ownership.md:115 +msgid "" +"If a type implements the `Copy` trait, passing it to a function will not " +"move the ownership of the value to the function called, but will instead " +"pass a copy of the value.\n" +"You can implement the `Copy` trait on your type by adding the " +"`#[derive(Copy)]` annotation to your type definition. However, Cairo won't " +"allow a type to be annotated with Copy if the type itself or any of its " +"components don't implement the Copy trait.\n" +"While Arrays and Dictionaries can't be copied, custom types that don't " +"contain either of them can be." +msgstr "" +"如果一个类型实现了`Copy'特性,把它传递给一个函数将不会把值的所有权转移给被调" +"用的函数,而是传递一个值的副本。\n" +"你可以通过在你的类型定义中添加`#[derive(Copy)]`注解来实现`Copy`特性。然而,如" +"果一个类型本身或其任何组件没有实现Copy特性,Cairo将不允许该类型被注解为" +"Copy。\n" +"虽然数组和字典不能被复制,但不包含它们的自定义类型可以被复制。" + +#: src/ch03-01-what-is-ownership.md:119 +msgid "" +"```rust\n" +"#[derive(Copy, Drop)]\n" +"struct Point {\n" +" x: u128,\n" +" y: u128,\n" +"}\n" +"\n" +"fn main() {\n" +" let p1 = Point { x: 5, y: 10 };\n" +" foo(p1);\n" +" foo(p1);\n" +"}\n" +"\n" +"fn foo(p: Point) {\n" +" // do something with p\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[derive(Copy, Drop)]\n" +"struct Point {\n" +" x: u128,\n" +" y: u128,\n" +"}\n" +"\n" +"fn main() {\n" +" let p1 = Point { x: 5, y: 10 };\n" +" foo(p1);\n" +" foo(p1);\n" +"}\n" +"\n" +"fn foo(p: Point) {\n" +" // do something with p\n" +"}\n" +"```" + +#: src/ch03-01-what-is-ownership.md:137 +msgid "" +"In this example, we can pass `p1` twice to the foo function because the " +"`Point` type implements the `Copy` trait. This means that when we pass `p1` " +"to `foo`, we are actually passing a copy of `p1`, and the ownership of `p1` " +"remains with the main function.\n" +"If you remove the `Copy` trait derivation from the `Point` type, you will " +"get a compile-time error when trying to compile the code." +msgstr "" +"在这个例子中,我们可以向foo函数传递两次`p1`,因为`Point`类型实现了" +"`Copy`trait。这意味着当我们把`p1`传递给`foo`时,我们实际上是在传递`p1`的副" +"本,而`p1`的所有权仍然属于主函数。\n" +"如果你从`Point`类型中删除`Copy`trait的派生,当你试图编译代码时,你会得到一个" +"编译时错误。" + +#: src/ch03-01-what-is-ownership.md:140 +msgid "" +"_Don't worry about the `Struct` keyword. We will introduce this in [Chapter " +"4](ch04-00-using-structs-to-structure-related-data.md)._" +msgstr "" +"_不要担心`Struct`关键字。我们将在[第四章](ch04-00-using-structs-to-structure-" +"related-data.md)中介绍_" + +#: src/ch03-01-what-is-ownership.md:142 +msgid "### The `Drop` Trait" +msgstr "### `Drop` Trait" + +#: src/ch03-01-what-is-ownership.md:144 +msgid "" +"You may have noticed that the `Point` type in the previous example also " +"implements the `Drop` trait. In Cairo, a value cannot go out of scope unless " +"it has been previously moved.\n" +"For example, the following code will not compile, because the struct `A` is " +"not moved before it goes out of scope:" +msgstr "" +"你可能已经注意到,前面例子中的`Point`类型也实现了`Drop`特性。在Cairo中,一个" +"值不能超出范围,除非它之前被移动过。\n" +"例如,下面的代码将无法编译,因为结构体`A`在超出范围之前没有被移动:" + +#: src/ch03-01-what-is-ownership.md:147 +msgid "" +"```rust,does_not_compile\n" +"struct A {}\n" +"\n" +"fn main() {\n" +" A {}; // error: Value not dropped.\n" +"}\n" +"```" +msgstr "" +"```rust,does_not_compile\n" +"struct A {}\n" +"\n" +"fn main() {\n" +" A {}; // error: Value not dropped.\n" +"}\n" +"```" + +#: src/ch03-01-what-is-ownership.md:155 +msgid "" +"This is to ensure the soundness of Cairo programs. Soundness refers to the " +"fact that if a\n" +"statement during the execution of the program is false, no cheating prover " +"can convince an\n" +"honest verifier that it is true. In our case, we want to ensure the " +"consistency of\n" +"consecutive dictionary key updates during program execution, which is only " +"checked when\n" +"the dictionaries are`squashed` - which moves the ownership of the dictionary " +"to the\n" +"`squash` method, thus allowing the dictionary to go out of scope. Unsquashed " +"dictionaries\n" +"are dangerous, as a malicious prover could prove the correctness of " +"inconsistent updates." +msgstr "" +"这是为了确保Cairo程序的健全性。健全性指的是,如果在程序执行过程中的一个语句是" +"假的,任何作弊的验证者都不可能说服一个诚实的验证者相信它是真的。\n" +"在我们的案例中,我们要确保程序执行过程中连续的字典钥匙更新的一致性。\n" +"这只有在词典被`squashed'时才会进行检查--它将词典的所有权转移到了`squash`方" +"法,从而允许字典超出范围。未被压缩的字典是危险的,因为恶意的证明者可以证明不" +"一致的更新的正确性。" + +#: src/ch03-01-what-is-ownership.md:163 +msgid "" +"However, types that implement the `Drop` trait are allowed to go out of " +"scope without being explicitly moved. When a value of a type that implements " +"the `Drop` trait goes out of scope, the `Drop` implementation is called on " +"the type, which moves the value to the `drop` function, allowing it to go " +"out of scope - This is what we call \"dropping\" a value.\n" +"It is important to note that the implementation of drop is a \"no-op\", " +"meaning that it doesn't perform any actions other than allowing the value to " +"go out of scope." +msgstr "" +"然而,实现了`Drop`特性的类型被允许超出范围而不被明确移动。当一个实现了" +"`Drop'特性的类型的值超出范围时,`Drop'的实现会被调用,它将值移动到`drop'函数" +"中,允许它超出范围--这就是我们所说的 \"放弃 \"一个值。\n" +"值得注意的是,drop的实现是一个 \"no-op\",也就是说,除了允许值离开作用域之" +"外,它不执行任何其他操作。" + +#: src/ch03-01-what-is-ownership.md:166 +msgid "" +"The `Drop` implementation can be derived for all types, allowing them to be " +"dropped when goint out of scope, except for dictionaries (`Felt252Dict`) and " +"types containing dictionaries.\n" +"For example, the following code compiles:" +msgstr "" +"`Drop`的实现可以为所有类型派生,允许它们在超出范围时被丢弃,除了字典" +"(`Felt252Dict`)和包含字典的类型。\n" +"例如,下面的代码可以编译:" + +#: src/ch03-01-what-is-ownership.md:169 +msgid "" +"```rust\n" +"#[derive(Drop)]\n" +"struct A {}\n" +"\n" +"fn main() {\n" +" A {}; // Now there is no error.\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[derive(Drop)]\n" +"struct A {}\n" +"\n" +"fn main() {\n" +" A {}; // Now there is no error.\n" +"}\n" +"```" + +#: src/ch03-01-what-is-ownership.md:178 +msgid "### The `Destruct` Trait" +msgstr "### `Destruct`特性" + +#: src/ch03-01-what-is-ownership.md:180 +msgid "" +"Manually calling the `squash` method on a dictionary is not very convenient, " +"and it is easy to forget to do so. To make it easier to use dictionaries, " +"Cairo provides the `Destruct` trait, which allows you to specify the " +"behavior of a type when it goes out of scope. While Dictionaries don't " +"implement the `Drop` trait, they do implement the `Destruct` trait, which " +"allows them to automatically be `squashed` when they go out of scope. This " +"means that you can use dictionaries without having to manually call the " +"`squash` method." +msgstr "" +"手动调用字典上的 `squash` 方法不是很方便,而且很容易忘记这样做。为了方便使用" +"字典,Cairo 提供了 `Destruct` 特质,它允许你指定一个类型超出范围时的行为。虽" +"然字典没有实现`Drop'特性,但它们确实实现了`Destruct'特性,这允许它们在超出范" +"围时自动被`squashed'。这意味着你可以使用字典而不需要手动调用`squash`方法。" + +#: src/ch03-01-what-is-ownership.md:182 +msgid "" +"Consider the following example, in which we define a custom type that " +"contains a dictionary:" +msgstr "考虑下面的例子,在这个例子中,我们定义了一个包含字典的自定义类型:" + +#: src/ch03-01-what-is-ownership.md:184 +msgid "" +"```rust,does_not_compile\n" +"use dict::Felt252DictTrait;\n" +"\n" +"struct A {\n" +" dict: Felt252Dict\n" +"}\n" +"\n" +"fn main() {\n" +" A {\n" +" dict: Felt252DictTrait::new()\n" +" };\n" +"}\n" +"```" +msgstr "" +"```rust,does_not_compile\n" +"use dict::Felt252DictTrait;\n" +"\n" +"struct A {\n" +" dict: Felt252Dict\n" +"}\n" +"\n" +"fn main() {\n" +" A {\n" +" dict: Felt252DictTrait::new()\n" +" };\n" +"}\n" +"```" + +#: src/ch03-01-what-is-ownership.md:198 +msgid "If you try to run this code, you will get a compile-time error:" +msgstr "如果你试图运行这段代码,你会得到一个编译时错误:" + +#: src/ch03-01-what-is-ownership.md:200 +msgid "" +"```console\n" +"error: Variable not dropped. Trait has no implementation in context: core::" +"traits::Drop::. Trait has no implementation in context: " +"core::traits::Destruct::.\n" +" --> temp7.cairo:7:5\n" +" A {\n" +" ^*^\n" +"```" +msgstr "" +"```console\n" +"error: Variable not dropped. Trait has no implementation in context: core::" +"traits::Drop::. Trait has no implementation in context: " +"core::traits::Destruct::.\n" +" --> temp7.cairo:7:5\n" +" A {\n" +" ^*^\n" +"```" + +#: src/ch03-01-what-is-ownership.md:207 +msgid "" +"When A goes out of scope, it can't be dropped as it implements neither the " +"`Drop` (as it contains a dictionary and can't `derive(Drop)`) nor the " +"`Destruct` trait. To fix this, we can derive the `Destruct` trait " +"implementation for the `A` type:" +msgstr "" +"当A超出范围时,它不能被丢弃,因为它既没有实现`Drop`(因为它包含一个字典,不能" +"`derive(Drop)`)也没有实现`Destruct`特性。为了解决这个问题,我们可以为`A`类型" +"派生出`Destruct`特质的实现:" + +#: src/ch03-01-what-is-ownership.md:209 +msgid "" +"```rust\n" +"use dict::Felt252DictTrait;\n" +"\n" +"#[derive(Destruct)]\n" +"struct A {\n" +" dict: Felt252Dict\n" +"}\n" +"\n" +"fn main() {\n" +" A {\n" +" dict: Felt252DictTrait::new()\n" +" }; // No error here\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use dict::Felt252DictTrait;\n" +"\n" +"#[derive(Destruct)]\n" +"struct A {\n" +" dict: Felt252Dict\n" +"}\n" +"\n" +"fn main() {\n" +" A {\n" +" dict: Felt252DictTrait::new()\n" +" }; // No error here\n" +"}\n" +"```" + +#: src/ch03-01-what-is-ownership.md:224 +msgid "" +"Now, when `A` goes out of scope, its dictionary will be automatically " +"`squashed`, and the program will compile." +msgstr "现在,当`A`超出范围时,它的字典将被自动`squashed`,并且程序将被编译。" + +#: src/ch03-01-what-is-ownership.md:226 +msgid "### Copy Array data with Clone" +msgstr "###用克隆复制数组数据" + +#: src/ch03-01-what-is-ownership.md:228 +msgid "" +"If we _do_ want to deeply copy the data of an `Array`, we can use a common " +"method called `clone`. We’ll discuss method syntax in Chapter 5, but because " +"methods are a common feature in many\n" +"programming languages, you’ve probably seen them before." +msgstr "" +"如果我们确实想深入复制一个 \"数组 \"的数据,我们可以使用一个叫做 \"克隆 \"的" +"普通方法。我们将在第5章中讨论方法的语法,但由于方法是许多编程语言中的一个共同" +"特征,你可能已经见过了。\n" +"但由于方法是许多编程语言的共同特征,你可能已经见过它们了。" + +#: src/ch03-01-what-is-ownership.md:231 +msgid "Here’s an example of the `clone` method in action." +msgstr "下面是一个 `clone` 方法的实例。" + +#: src/ch03-01-what-is-ownership.md:233 +msgid "" +"> Note: in the following example, we need to import the `Clone` trait from " +"the corelib `clone` module, and its implementation for the array type from " +"the `array` module." +msgstr "" +"> 注意:在下面的例子中,我们需要从corelib的`clone`模块中导入`clone`特质,并从" +"`array`模块中导入其对数组类型的实现。" + +#: src/ch03-01-what-is-ownership.md:235 +msgid "" +"```rust\n" +"use array::ArrayTrait;\n" +"use clone::Clone;\n" +"use array::ArrayTCloneImpl;\n" +"...\n" +"let arr1 = ArrayTrait::::new();\n" +"let arr2 = arr1.clone();\n" +"\n" +"```" +msgstr "" +"``rust\n" +"use array::ArrayTrait;\n" +"use clone::Clone;\n" +"use array::ArrayTCloneImpl;\n" +"...\n" +"let arr1 = ArrayTrait::::new();\n" +"let arr2 = arr1.clone();\n" +"\n" +"```" + +#: src/ch03-01-what-is-ownership.md:245 +msgid "" +"> Note: you will need to run `cairo-run` with the `--available-gas=2000000` " +"option to run this example, because it uses a loop and must be ran with a " +"gas limit." +msgstr "" +"> 注意:你需要用`--可用气体=2000000`选项运行`cairo-run`来运行这个例子,因为它" +"使用了一个循环,必须用气体限制来运行。" + +#: src/ch03-01-what-is-ownership.md:247 +msgid "" +"When you see a call to `clone`, you know that some arbitrary code is being\n" +"executed and that code may be expensive. It’s a visual indicator that " +"something\n" +"different is going on." +msgstr "" +"当你看到对`clone'的调用时,你知道一些任意的代码正在被执行。\n" +"执行,而这些代码可能是昂贵的。这是一个视觉指标,表明有一些\n" +"不同的事情正在发生。" + +#: src/ch03-01-what-is-ownership.md:251 +msgid "### Ownership and Functions" +msgstr "###所有权与函数" + +#: src/ch03-01-what-is-ownership.md:253 +msgid "" +"Passing a variable to a function will either move it or copy it. As seen in " +"the Array section, passing an `Array` as a function parameter transfers its " +"ownership; let's see what happens with other types." +msgstr "" +"将一个变量传递给一个函数,要么移动它,要么复制它。正如在数组部分所看到的,将 " +"`Array` 作为一个函数参数传递给它的所有权;让我们看看其他类型会发生什么。" + +#: src/ch03-01-what-is-ownership.md:255 +msgid "" +"Listing 3-3 has an example with some annotations\n" +"showing where variables go into and out of scope." +msgstr "" +"清单3-3有一个带有一些注释的例子\n" +"显示了变量进入和离开范围的位置。" + +#: src/ch03-01-what-is-ownership.md:258 src/ch03-01-what-is-ownership.md:300 +#: src/ch03-01-what-is-ownership.md:353 +msgid "Filename: src/main.cairo" +msgstr "文件名: src/main.cairo" + +#: src/ch03-01-what-is-ownership.md:260 +msgid "" +"```rust\n" +"#[derive(Drop)]\n" +"struct MyStruct{}\n" +"\n" +"fn main() {\n" +" let my_struct = MyStruct{}; // my_struct comes into scope\n" +"\n" +" takes_ownership(my_struct); // my_struct's value moves into the " +"function...\n" +" // ... and so is no longer valid here\n" +"\n" +" let x = 5_u128; // x comes into scope\n" +"\n" +" makes_copy(x); // x would move into the function,\n" +" // but u128 implements Copy, so it is " +"okay to still\n" +" // use x afterward\n" +"\n" +"} // Here, x goes out of scope and is " +"dropped.\n" +"\n" +"\n" +"fn takes_ownership(some_struct: MyStruct) { // some_struct comes into scope\n" +"} // Here, some_struct goes out of scope and `drop` is called.\n" +"\n" +"fn makes_copy(some_uinteger: u128) { // some_uinteger comes into scope\n" +"} // Here, some_integer goes out of scope and is dropped.\n" +"```" +msgstr "" +"```rust\n" +"#[derive(Drop)]\n" +"struct MyStruct{}\n" +"\n" +"fn main() {\n" +" let my_struct = MyStruct{}; // my_struct comes into scope\n" +"\n" +" takes_ownership(my_struct); // my_struct's value moves into the " +"function...\n" +" // ... and so is no longer valid here\n" +"\n" +" let x = 5_u128; // x comes into scope\n" +"\n" +" makes_copy(x); // x would move into the function,\n" +" // but u128 implements Copy, so it is " +"okay to still\n" +" // use x afterward\n" +"\n" +"} // Here, x goes out of scope and is " +"dropped.\n" +"\n" +"\n" +"fn takes_ownership(some_struct: MyStruct) { // some_struct comes into scope\n" +"} // Here, some_struct goes out of scope and `drop` is called.\n" +"\n" +"fn makes_copy(some_uinteger: u128) { // some_uinteger comes into scope\n" +"} // Here, some_integer goes out of scope and is dropped.\n" +"```" + +#: src/ch03-01-what-is-ownership.md:286 +msgid "" +"Listing 3-3: Functions with ownership and scope\n" +"annotated" +msgstr "" +"清单3-3:具有所有权与作用域的函数\n" +"有注释的" + +#: src/ch03-01-what-is-ownership.md:289 +msgid "" +"If we tried to use `my_struct` after the call to `takes_ownership`, Cairo " +"would throw a\n" +"compile-time error. These static checks protect us from mistakes. Try " +"adding\n" +"code to `main` that uses `my_struct` and `x` to see where you can use them " +"and where\n" +"the ownership rules prevent you from doing so." +msgstr "" +"如果我们试图在调用`takes_ownership'之后使用`my_struct',Cairo会抛出一个\n" +"编译时错误。这些静态检查可以保护我们不犯错误。试着在`main`中加入\n" +"在`main`中添加使用`my_struct`和`x`的代码,看看哪里可以使用它们,哪里\n" +"所有权规则将会阻止你这样做。" + +#: src/ch03-01-what-is-ownership.md:294 +msgid "### Return Values and Scope" +msgstr "### 返回值与作用域" + +#: src/ch03-01-what-is-ownership.md:296 +msgid "" +"Returning values can also transfer ownership. Listing 3-4 shows an example " +"of a\n" +"function that returns some value, with similar annotations as those in " +"Listing\n" +"4-3." +msgstr "" +"返回值也可以转移所有权。示例3-4显示了一个例子\n" +"该函数返回一些值,其注释与示例4-3中的相似。" + +#: src/ch03-01-what-is-ownership.md:302 +msgid "" +"```rust\n" +"#[derive(Drop)]\n" +"struct A{}\n" +"\n" +"fn main() {\n" +" let a1 = gives_ownership(); // gives_ownership moves its " +"return\n" +" // value into a1\n" +"\n" +" let a2 = A{}; // a2 comes into scope\n" +"\n" +" let a3 = takes_and_gives_back(a2); // a2 is moved into\n" +" // takes_and_gives_back, which " +"also\n" +" // moves its return value into a3\n" +"\n" +"} // Here, a3 goes out of scope and is dropped. a2 was moved, so nothing\n" +" // happens. a1 goes out of scope and is dropped.\n" +"\n" +"fn gives_ownership() -> A { // gives_ownership will move its\n" +" // return value into the function\n" +" // that calls it\n" +"\n" +" let some_a = A{}; // some_a comes into scope\n" +"\n" +" some_a // some_a is returned and\n" +" // moves ownership to the calling\n" +" // function\n" +"}\n" +"\n" +"// This function takes an instance some_a of A and returns it\n" +"fn takes_and_gives_back(some_a: A) -> A { // some_a comes into\n" +" // scope\n" +"\n" +" some_a // some_a is returned and moves\n" +" // ownership to the calling\n" +" // function\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[derive(Drop)]\n" +"struct A{}\n" +"\n" +"fn main() {\n" +" let a1 = gives_ownership(); // gives_ownership moves its " +"return\n" +" // value into a1\n" +"\n" +" let a2 = A{}; // a2 comes into scope\n" +"\n" +" let a3 = takes_and_gives_back(a2); // a2 is moved into\n" +" // takes_and_gives_back, which " +"also\n" +" // moves its return value into a3\n" +"\n" +"} // Here, a3 goes out of scope and is dropped. a2 was moved, so nothing\n" +" // happens. a1 goes out of scope and is dropped.\n" +"\n" +"fn gives_ownership() -> A { // gives_ownership will move its\n" +" // return value into the function\n" +" // that calls it\n" +"\n" +" let some_a = A{}; // some_a comes into scope\n" +"\n" +" some_a // some_a is returned and\n" +" // moves ownership to the calling\n" +" // function\n" +"}\n" +"\n" +"// This function takes an instance some_a of A and returns it\n" +"fn takes_and_gives_back(some_a: A) -> A { // some_a comes into\n" +" // scope\n" +"\n" +" some_a // some_a is returned and moves\n" +" // ownership to the calling\n" +" // function\n" +"}\n" +"```" + +#: src/ch03-01-what-is-ownership.md:340 +msgid "" +"Listing 3-4: Transferring ownership of return\n" +"values" +msgstr "" +"清单3-4:转移返回值的所有权\n" +"" + +#: src/ch03-01-what-is-ownership.md:343 +msgid "" +"When a variable goes out of scope, its value is dropped, unless ownership of " +"the value has been moved to another variable." +msgstr "" +"当一个变量超出作用域时,它的值会被丢弃,除非值的所有权被转移到另一个变量上。" + +#: src/ch03-01-what-is-ownership.md:345 +msgid "" +"While this works, taking ownership and then returning ownership with every\n" +"function is a bit tedious. What if we want to let a function use a value " +"but\n" +"not take ownership? It’s quite annoying that anything we pass in also needs " +"to\n" +"be passed back if we want to use it again, in addition to any data " +"resulting\n" +"from the body of the function that we might want to return as well." +msgstr "" +"虽然这样是可以的,但是在每一个函数中都获取所有权并接着返回所有权有些啰嗦。\n" +"如果我们想要函数使用一个值但不获取所有权该怎么办呢?如果我们还要接着使\n" +"用它的话,每次都传进去再返回来就有点烦人了,除此之外,我们也可能想返回\n" +"函数体中产生的一些数据。" + +#: src/ch03-01-what-is-ownership.md:351 +msgid "" +"Cairo does let us return multiple values using a tuple, as shown in Listing " +"3-5." +msgstr "Cairo确实让我们可以使用一个元组返回多个值,如示例3-5所示。" + +#: src/ch03-01-what-is-ownership.md:355 +msgid "" +"```rust\n" +"use array::ArrayTrait;\n" +"fn main() {\n" +" let arr1 = ArrayTrait::::new();\n" +"\n" +" let (arr2, len) = calculate_length(arr1);\n" +"}\n" +"\n" +"fn calculate_length(arr: Array) -> (Array, usize) {\n" +" let length = arr.len(); // len() returns the length of an array\n" +"\n" +" (arr, length)\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use array::ArrayTrait;\n" +"fn main() {\n" +" let arr1 = ArrayTrait::::new();\n" +"\n" +" let (arr2, len) = calculate_length(arr1);\n" +"}\n" +"\n" +"fn calculate_length(arr: Array) -> (Array, usize) {\n" +" let length = arr.len(); // len() returns the length of an array\n" +"\n" +" (arr, length)\n" +"}\n" +"```" + +#: src/ch03-01-what-is-ownership.md:370 +msgid "" +"Listing 3-5: Returning ownership of parameters" +msgstr "清单3-5:返回参数的所有权" + +#: src/ch03-01-what-is-ownership.md:372 +msgid "" +"But this is too much ceremony and a lot of work for a concept that should " +"be\n" +"common. Luckily for us, Cairo has two features for using a value without\n" +"transferring ownership, called _references_ and _snapshots_." +msgstr "" +"但是,对于一个应该是很普遍的概念来说,这样的仪式和工作太多。\n" +"寻常。幸运的是,Cairo有两个功能可以在不转移所有权的情况下使用一个值。\n" +"转移所有权,称为_references_和_snapshots_。" + +#: src/ch03-02-references-and-snapshots.md:1 +msgid "## References and Snapshots" +msgstr "## 参考资料和快照" + +#: src/ch03-02-references-and-snapshots.md:3 +msgid "" +"The issue with the tuple code in Listing 3-5 is that we have to return the\n" +"`Array` to the calling function so we can still use the `Array` after the\n" +"call to `calculate_length`, because the `Array` was moved into\n" +"`calculate_length`." +msgstr "" +"清单3-5中元组代码的问题是,我们必须返回\n" +"`Array`返回给调用的函数,这样我们在调用`calculate_length`后仍然可以使用" +"`Array`。\n" +"因为 \"Array \"被移到了`calculate_length`中.\n" +"`calculate_length`中。" + +#: src/ch03-02-references-and-snapshots.md:8 +msgid "### Snapshots" +msgstr "###快照" + +#: src/ch03-02-references-and-snapshots.md:10 +msgid "" +"Instead, we can provide a _snapshot_ of the `Array` value. In Cairo, a " +"snapshot\n" +"is an immutable view of a value at a certain point in time. In the previous " +"chapter,\n" +"we talked about how Cairo's ownership system prevents us from using a value " +"after\n" +"we've moved it, protecting us from potentially writing twice to the same " +"memory cell when\n" +"appending values to arrays. However, it's not very convenient. Let's see how " +"we can retain ownership\n" +"of the value in the calling function using snapshots." +msgstr "" +"相反,我们可以提供一个`Array`值的_快照_。在Cairo,一个快照是一个在某个时\n" +"间点上的不可改变的值的视图。在上一章中,我们谈到了Cairo的所有权系统是\n" +"如何防止我们在移动一个值后使用它,从而防止我们在向数组添加值时不会潜在\n" +"地多次写入相同的内存单元。\n" +"然而,这不是很方便。让我们看看如何使用快照在调用函数中保留值的所有权。" + +#: src/ch03-02-references-and-snapshots.md:17 +msgid "" +"Here is how you would define and use a `calculate_length` function that " +"takes a\n" +"snapshot to an array as a parameter instead of taking ownership of the " +"underlying value. In this example,\n" +"the `calculate_length` function returns the length of the array passed as " +"parameter.\n" +"As we're passing it as a snapshot, which is an immutable view of the array, " +"we can be sure that\n" +"the `calculate_length` function will not mutate the array, and ownership of " +"the array is kept in the main function." +msgstr "" +"下面是你如何定义和使用一个`计算长度`函数,它以一个快照作为参数,而不是获取底" +"层值的所有权。在这个例子中、\n" +"`calculate_length`函数返回作为参数的数组的长度。\n" +"因为我们是以快照的形式传递的,这是一个不可改变的数组视图,我们可以确定\n" +"`calculate_length`函数不会改变数组,数组的所有权被保留在主函数中。" + +#: src/ch03-02-references-and-snapshots.md:25 +msgid "" +"```rust\n" +"use array::ArrayTrait;\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" let mut arr1 = ArrayTrait::::new();\n" +" let first_snapshot = @arr1; // Take a snapshot of `arr1` at this point " +"in time\n" +" arr1.append(1_u128); // Mutate `arr1` by appending a value\n" +" let first_length = calculate_length(first_snapshot); // Calculate the " +"length of the array when the snapshot was taken\n" +" let second_length = calculate_length(@arr1); // Calculate the current " +"length of the array\n" +" first_length.print();\n" +" second_length.print();\n" +"}\n" +"\n" +"fn calculate_length(arr: @Array) -> usize {\n" +" arr.len()\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use array::ArrayTrait;\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" let mut arr1 = ArrayTrait::::new();\n" +" let first_snapshot = @arr1; // Take a snapshot of `arr1` at this point " +"in time\n" +" arr1.append(1_u128); // Mutate `arr1` by appending a value\n" +" let first_length = calculate_length(first_snapshot); // Calculate the " +"length of the array when the snapshot was taken\n" +" let second_length = calculate_length(@arr1); // Calculate the current " +"length of the array\n" +" first_length.print();\n" +" second_length.print();\n" +"}\n" +"\n" +"fn calculate_length(arr: @Array) -> usize {\n" +" arr.len()\n" +"}\n" +"```" + +#: src/ch03-02-references-and-snapshots.md:44 +msgid "" +"> Note: It is only possible to call the `len()` method on an array snapshot " +"because it is defined as such in the `ArrayTrait` trait. If you try to call " +"a method that is not defined for snapshots on a snapshot, you will get a " +"compilation error. However, you can call methods expecting a snapshot on non-" +"snapshot types." +msgstr "" +"> 注意:只有在数组快照上才能调用 `len()` 方法,因为它在 `ArrayTrait` 特质中被" +"定义成这样。如果你试图在一个快照上调用一个没有为快照定义的方法,你会得到一个" +"编译错误。然而,你可以在非快照类型上调用期望有快照的方法。" + +#: src/ch03-02-references-and-snapshots.md:46 +msgid "The output of this program is:" +msgstr "这个程序的输出是:" + +#: src/ch03-02-references-and-snapshots.md:48 +msgid "" +"```console\n" +"[DEBUG]\t \t(raw: 0)\n" +"\n" +"[DEBUG]\t \t(raw: 1)\n" +"\n" +"Run completed successfully, returning []\n" +"```" +msgstr "" +"```console\n" +"[DEBUG]\t \t(raw: 0)\n" +"\n" +"[DEBUG]\t \t(raw: 1)\n" +"\n" +"Run completed successfully, returning []\n" +"```" + +#: src/ch03-02-references-and-snapshots.md:56 +msgid "" +"First, notice that all the tuple code in the variable declaration and the " +"function return value is gone. Second, note\n" +"that we pass `@arr1` into `calculate_length` and, in its definition, we take " +"`@Array` rather than `Array`." +msgstr "" +"首先,注意到变量声明和函数返回值中的所有元组代码都消失了。第二,注意\n" +"我们把`@arr1`传入`calculate_length`,在它的定义中,我们采用`@Array`,而" +"不是`Array`。" + +#: src/ch03-02-references-and-snapshots.md:59 +msgid "Let’s take a closer look at the function call here:" +msgstr "让我们仔细看一下这里的函数调用:" + +#: src/ch03-02-references-and-snapshots.md:61 +msgid "" +"```rust\n" +"let mut arr1 = ArrayTrait::::new();\n" +"let second_length = calculate_length(@arr1); // Calculate the current length " +"of the array\n" +"```" +msgstr "" +"``rust\n" +"let mut arr1 = ArrayTrait::::new();\n" +"let second_length = calculate_length(@arr1); // 计算数组的当前长度\n" +"```" + +#: src/ch03-02-references-and-snapshots.md:66 +msgid "" +"The `@arr1` syntax lets us create a snapshot of the value in `arr1`. Because " +"a snapshot is an immutable view of a value, the value it points to cannot be " +"modified through the snapshot, and the value it refers to will not be " +"dropped once the snapshot stops being used." +msgstr "" +"`@arr1`语法让我们为`arr1`中的值创建一个快照。因为快照是一个值的不可改变的视" +"图,它所指向的值不能通过快照被修改,而且一旦快照停止使用,它所指向的值也不会" +"被丢弃。" + +#: src/ch03-02-references-and-snapshots.md:68 +msgid "" +"Similarly, the signature of the function uses `@` to indicate that the type " +"of the parameter `arr` is a snapshot. Let’s add some explanatory annotations:" +msgstr "" +"同样,函数的签名使用`@`来表示参数`arr`的类型是一个快照。让我们添加一些解释性" +"的注解:" + +#: src/ch03-02-references-and-snapshots.md:70 +msgid "" +"```rust\n" +"fn calculate_length(array_snapshot: @Array) -> usize { // " +"array_snapshot is a snapshot of an Array\n" +" array_snapshot.len()\n" +"} // Here, array_snapshot goes out of scope and is dropped.\n" +"// However, because it is only a view of what the original array `arr` " +"contains, the original `arr` can still be used.\n" +"```" +msgstr "" +"``rust\n" +"fn calculate_length(array_snapshot: @Array) -> usize { // " +"array_snapshot是一个数组的快照。\n" +" array_snapshot.len()\n" +"}// 这里,array_snapshot超出了范围,被丢弃了。\n" +"// 但是,因为它只是原始数组`arr`所包含的视图,原始`arr`仍然可以被使用。\n" +"```" + +#: src/ch03-02-references-and-snapshots.md:77 +msgid "" +"The scope in which the variable `array_snapshot` is valid is the same as any " +"function parameter’s scope, but the underlying value of the snapshot is not " +"dropped when `array_snapshot` stops being used. When functions have " +"snapshots as parameters instead of the actual values, we won’t need to " +"return the values in order to give back ownership of the original value, " +"because we never had it." +msgstr "" +"变量`array_snapshot`的有效范围与任何函数参数的范围相同,但当`array_snapshot`" +"停止使用时,快照的底层值不会被丢弃。当函数有快照作为参数而不是实际的值时,我" +"们将不需要返回值以归还原始值的所有权,因为我们从未拥有过它。" + +#: src/ch03-02-references-and-snapshots.md:79 +msgid "" +"Snapshots can be converted back into regular values using the `desnap` " +"operator `*`, as long as the value type is copyable (which is not the case " +"for Arrays, as they don't implement `Copy`). In the following example, we " +"want to calculate the area of a rectangle, but we don't want to take " +"ownership of the rectangle in the `calculate_area` function, because we " +"might want to use the rectangle again after the function call. Since our " +"function doesn't mutate the rectangle instance, we can pass the snapshot of " +"the rectangle to the function, and then transform the snapshots back into " +"values using the `desnap` operator `*`." +msgstr "" +"快照可以通过`desnap`操作符`*`转换回常规值,只要值的类型是可复制的(数组不是这" +"样,因为它们没有实现`Copy`)。在下面的例子中,我们想计算一个矩形的面积,但我" +"们不想在`calculate_area`函数中占有这个矩形的所有权,因为我们可能想在函数调用" +"后再次使用这个矩形。由于我们的函数不会改变矩形实例,我们可以将矩形的快照传递" +"给函数,然后用`desnap`操作符`*`将快照转化回数值。" + +#: src/ch03-02-references-and-snapshots.md:81 +msgid "" +"The snapshot type is always copyable and droppable, so that you can use it " +"multiple times without worrying about ownership transfers." +msgstr "" +"快照类型始终是可复制和可删除的,因此你可以多次使用它而不必担心所有权的转移。" + +#: src/ch03-02-references-and-snapshots.md:83 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"#[derive(Copy,Drop)]\n" +"struct Rectangle {\n" +" height: u64,\n" +" width: u64,\n" +"}\n" +"\n" +"fn main(){\n" +" let rec = Rectangle{height:3_u64, width:10_u64};\n" +" let area = calculate_area(@rec);\n" +" area.print();\n" +"\n" +"}\n" +"\n" +"fn calculate_area(rec: @Rectangle) -> u64 {\n" +" // As rec is a snapshot to a Rectangle, its fields are also snapshots of " +"the fields types.\n" +" // We need to transform the snapshots back into values using the desnap " +"operator `*`.\n" +" // This is only possible if the type is copyable, which is the case for " +"u64.\n" +" // Here, `*` is used for both multiplying the height and width and for " +"desnapping the snapshots.\n" +" *rec.height * *rec.width\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"#[derive(Copy,Drop)]\n" +"struct Rectangle {\n" +" height: u64,\n" +" width: u64,\n" +"}\n" +"\n" +"fn main(){\n" +" let rec = Rectangle{height:3_u64, width:10_u64};\n" +" let area = calculate_area(@rec);\n" +" area.print();\n" +"\n" +"}\n" +"\n" +"fn calculate_area(rec: @Rectangle) -> u64 {\n" +" // As rec is a snapshot to a Rectangle, its fields are also snapshots of " +"the fields types.\n" +" // We need to transform the snapshots back into values using the desnap " +"operator `*`.\n" +" // This is only possible if the type is copyable, which is the case for " +"u64.\n" +" // Here, `*` is used for both multiplying the height and width and for " +"desnapping the snapshots.\n" +" *rec.height * *rec.width\n" +"}\n" +"```" + +#: src/ch03-02-references-and-snapshots.md:108 +msgid "" +"But, what happens if we try to modify something we’re passing as snapshot? " +"Try the code in\n" +"Listing 3-6. Spoiler alert: it doesn’t work!" +msgstr "" +"但是,如果我们试图修改我们作为快照传递的东西会发生什么?试试下面的代码\n" +"示例3-6。剧透一下:它不起作用!" + +#: src/ch03-02-references-and-snapshots.md:113 +msgid "" +"```rust,does_not_compile\n" +"#[derive(Copy,Drop)]\n" +"struct Rectangle {\n" +" height: u64,\n" +" width: u64,\n" +"}\n" +"\n" +"fn main(){\n" +" let rec = Rectangle{height:3_u64, width:10_u64};\n" +" flip(@rec);\n" +"}\n" +"\n" +"fn flip(rec: @Rectangle) {\n" +" let temp = rec.height;\n" +" rec.height = rec.width;\n" +" rec.width = temp;\n" +"}\n" +"```" +msgstr "" +"```rust,does_not_compile\n" +"#[derive(Copy,Drop)]\n" +"struct Rectangle {\n" +" height: u64,\n" +" width: u64,\n" +"}\n" +"\n" +"fn main(){\n" +" let rec = Rectangle{height:3_u64, width:10_u64};\n" +" flip(@rec);\n" +"}\n" +"\n" +"fn flip(rec: @Rectangle) {\n" +" let temp = rec.height;\n" +" rec.height = rec.width;\n" +" rec.width = temp;\n" +"}\n" +"```" + +#: src/ch03-02-references-and-snapshots.md:132 +msgid "" +"Listing 3-6: Attempting to modify a snapshot value" +msgstr "示例3-6:试图修改一个快照值" + +#: src/ch03-02-references-and-snapshots.md:134 +msgid "Here’s the error:" +msgstr "这里有一个错误:" + +#: src/ch03-02-references-and-snapshots.md:136 +msgid "" +"```console\n" +"error: Invalid left-hand side of assignment.\n" +" --> ownership.cairo:15:5\n" +" rec.height = rec.width;\n" +" ^********^\n" +"```" +msgstr "" +"```console\n" +"error: Invalid left-hand side of assignment.\n" +" --> ownership.cairo:15:5\n" +" rec.height = rec.width;\n" +" ^********^\n" +"```" + +#: src/ch03-02-references-and-snapshots.md:143 +msgid "The compiler prevents us from modifying values associated to snapshots." +msgstr "编译器阻止我们修改与快照相关的值。" + +#: src/ch03-02-references-and-snapshots.md:145 +msgid "### Mutable References" +msgstr "### 可变的参考资料" + +#: src/ch03-02-references-and-snapshots.md:147 +msgid "" +"We can achieve the behavior we want in Listing 3-6 by using a _mutable " +"reference_ instead of a snapshot. Mutable references are actually mutable " +"values passed to a function that are implicitly returned at the end of the " +"function, returning ownership to the calling context. By doing so, they " +"allow you to mutate the value passed while keeping ownership of it by " +"returning it automatically at the end of the execution.\n" +"In Cairo, a parameter can be passed as _mutable reference_ using the `ref` " +"modifier." +msgstr "" +"在清单3-6中,我们可以通过使用_mutable reference_而不是快照来实现我们想要的行" +"为。可变引用实际上是传递给函数的可变值,在函数结束时被隐式返回,将所有权返回" +"给调用的上下文。通过这样做,它们允许你对传递的值进行改变,同时通过在执行结束" +"时自动返回来保持对它的所有权。\n" +"在Cairo中,一个参数可以使用`ref`修饰符作为_mutable reference_传递。" + +#: src/ch03-02-references-and-snapshots.md:150 +msgid "" +"> **Note**: In Cairo, a parameter can only be passed as _mutable reference_ " +"using the `ref` modifier if the variable is declared as mutable with `mut`." +msgstr "" +"> **注意**:在Cairo中,只有在变量用`mut`声明为可变的情况下,才能使用`ref`修饰" +"符将参数作为可变的引用传递。" + +#: src/ch03-02-references-and-snapshots.md:152 +msgid "" +"In Listing 3-7, we use a mutable reference to modify the value of the " +"`height` and `width` fields of the `Rectangle` instance in the `flip` " +"function." +msgstr "" +"在示例3-7中,我们使用一个可变的引用来修改`Rectangle`实例在`flip`函数中的" +"`height`和`width`字段的值。" + +#: src/ch03-02-references-and-snapshots.md:154 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"#[derive(Copy, Drop)]\n" +"struct Rectangle {\n" +" height: u64,\n" +" width: u64,\n" +"}\n" +"\n" +"fn main() {\n" +" let mut rec = Rectangle { height: 3_u64, width: 10_u64 };\n" +" flip(ref rec);\n" +" rec.height.print();\n" +" rec.width.print();\n" +"}\n" +"\n" +"fn flip(ref rec: Rectangle) {\n" +" let temp = rec.height;\n" +" rec.height = rec.width;\n" +" rec.width = temp;\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"#[derive(Copy, Drop)]\n" +"struct Rectangle {\n" +" height: u64,\n" +" width: u64,\n" +"}\n" +"\n" +"fn main() {\n" +" let mut rec = Rectangle { height: 3_u64, width: 10_u64 };\n" +" flip(ref rec);\n" +" rec.height.print();\n" +" rec.width.print();\n" +"}\n" +"\n" +"fn flip(ref rec: Rectangle) {\n" +" let temp = rec.height;\n" +" rec.height = rec.width;\n" +" rec.width = temp;\n" +"}\n" +"```" + +#: src/ch03-02-references-and-snapshots.md:176 +msgid "" +"Listing 3-7: Use of a mutable reference to modify a " +"value" +msgstr "" +"清单 3-7:使用一个可变的引用来修改一个值" + +#: src/ch03-02-references-and-snapshots.md:178 +msgid "" +"First, we change `rec` to be `mut`. Then we pass a mutable reference of " +"`rec` into `flip` with `ref rec`, and update the function signature to " +"accept a mutable reference with `ref rec: Rectangle`. This makes it very " +"clear that the `flip` function will mutate the value of the `Rectangle` " +"instance passed as parameter." +msgstr "" +"首先,我们把`rec`改成`mut`。然后我们用 `ref rec` 将 `rec` 的可变引用传入 " +"`flip` ,并更新函数签名,用 `ref rec: Rectangle`接受可变引用。这很清楚地表" +"明,`flip`函数将改变作为参数传递的`Rectangle`实例的值。" + +#: src/ch03-02-references-and-snapshots.md:180 +msgid "The output of the program is:" +msgstr "程序的输出是:" + +#: src/ch03-02-references-and-snapshots.md:182 +msgid "" +"```console\n" +"[DEBUG]\n" +" (raw: 10)\n" +"\n" +"[DEBUG]\t (raw: 3)\n" +"```" +msgstr "" +"```console\n" +"[DEBUG]\n" +" (raw: 10)\n" +"\n" +"[DEBUG]\t (raw: 3)\n" +"```" + +#: src/ch03-02-references-and-snapshots.md:189 +msgid "" +"As expected, the `height` and `width` fields of the `rec` variable have been " +"swapped." +msgstr "正如预期的那样, `rec` 变量的 `height` 和 `width` 字段被调换了。" + +#: src/ch03-02-references-and-snapshots.md:191 +msgid "### Small recap" +msgstr "###小结" + +#: src/ch03-02-references-and-snapshots.md:193 +msgid "" +"Let’s recap what we’ve discussed about ownership, snapshots, and references:" +msgstr "让我们回顾一下我们已经讨论过的关于所有权、快照和引用的内容:" + +#: src/ch03-02-references-and-snapshots.md:195 +msgid "" +"- At any given time, a variable can only have one owner.\n" +"- You can pass a variable by-value, by-snapshot, or by-reference to a " +"function.\n" +"- If you pass-by-value, ownership of the variable is transferred to the " +"function.\n" +"- If you want to keep ownership of the variable and know that your function " +"won’t mutate it, you can pass it as a snapshot with `@`.\n" +"- If you want to keep ownership of the variable and know that your function " +"will mutate it, you can pass it as a mutable reference with `ref`." +msgstr "" +"- 在任何时候,一个变量只能有一个所有者。\n" +"- 你可以将一个变量以值的方式、以快照的方式、或以引用的方式传递给一个函数。\n" +"- 如果你按值传递,变量的所有权就会转移到函数中。\n" +"- 如果你想保留变量的所有权,并且知道你的函数不会改变它,你可以用`@`把它作为一" +"个快照传递。\n" +"- 如果你想保留变量的所有权,并且知道你的函数会改变它,你可以用`ref`把它作为一" +"个可改变的引用来传递。" + +#: src/ch04-00-using-structs-to-structure-related-data.md:1 +msgid "# Using Structs to Structure Related Data" +msgstr "# 使用结构体组织相关联的数据" + +#: src/ch04-00-using-structs-to-structure-related-data.md:3 +msgid "" +"A struct, or structure, is a custom data type that lets you package together " +"and name multiple related values that make up a meaningful group. If you’re " +"familiar with an object-oriented language, a struct is like an object’s data " +"attributes. In this chapter, we’ll compare and contrast tuples with structs " +"to build on what you already know and demonstrate when structs are a better " +"way to group data." +msgstr "" +"_struct_,或称_structure_,是一种自定义的数据类型,允许你包装和命名多个相关的" +"值,从而形成一个有意义的组合。如果你熟悉一门面向对象语言,struct 就像对象中的" +"数据属性。在本章中,我们会对元组和结构体进行比较和对比。在你已经知道的基础" +"上,以证明结构是一种更好的数据分组方式。" + +#: src/ch04-00-using-structs-to-structure-related-data.md:5 +msgid "" +"We’ll demonstrate how to define and instantiate structs. We’ll discuss how " +"to define associated functions, especially the kind of associated functions " +"called methods, to specify behavior associated with a struct type. Structs " +"and enums (discussed in the next chapter) are the building blocks for " +"creating new types in your program’s domain to take full advantage of " +"Cairo's compile-time type checking." +msgstr "" +"我们还将演示如何定义和实例化结构体,并讨论如何定义关联函数,特别是被称为 方" +"法 的那种关联函数,以指定与结构体类型相关的行为。你可以在程序中基于结构体和枚" +"举(enum)(将在下一章讨论)创建新类型,以充分利用 Cairo 的编译时类型检查。" + +#: src/ch04-01-defining-and-instantiating-structs.md:1 +msgid "# Defining and Instantiating Structs" +msgstr "# 结构体的定义和实例化" + +#: src/ch04-01-defining-and-instantiating-structs.md:3 +msgid "" +"Structs are similar to tuples, discussed in [The Data Types](ch02-02-data-" +"types.md) section, in that both hold multiple related values. Like tuples, " +"the pieces of a struct can be different types. Unlike with tuples, in a " +"struct you’ll name each piece of data so it’s clear what the values mean. " +"Adding these names means that structs are more flexible than tuples: you " +"don’t have to rely on the order of the data to specify or access the values " +"of an instance." +msgstr "" +"结构与[数据类型](ch02-02-data-types.md)一节中讨论的元组类似,它们都包含多个相" +"关的值。和元组一样,结构体的每一部分可以是不同类型。但不同于元组,结构体需要" +"命名各部分数据以便能清楚的表明其值的意义。由于有了这些名字,结构体比元组更灵" +"活:不需要依赖顺序来指定或访问实例中的值。" + +#: src/ch04-01-defining-and-instantiating-structs.md:5 +msgid "" +"To define a struct, we enter the keyword `struct` and name the entire " +"struct. A struct’s name should describe the significance of the pieces of " +"data being grouped together. Then, inside curly brackets, we define the " +"names and types of the pieces of data, which we call fields. For example, " +"Listing 4-1 shows a struct that stores information about a user account." +msgstr "" +"定义结构体,需要使用 `struct` 关键字并为整个结构体提供一个名字。结构体的名字" +"需要描述它所组合的数据的意义。接着,在大括号中,定义每一部分数据的名字和类" +"型,我们称为 字段(field)。例如,示例 4-1 展示了一个存储用户账号信息的结构" +"体。" + +#: src/ch04-01-defining-and-instantiating-structs.md:7 +#: src/ch04-01-defining-and-instantiating-structs.md:26 +#: src/ch04-01-defining-and-instantiating-structs.md:50 +#: src/ch04-01-defining-and-instantiating-structs.md:72 +#: src/ch04-01-defining-and-instantiating-structs.md:93 +msgid "Filename: structs.cairo" +msgstr "文件名:structs.cairo" + +#: src/ch04-01-defining-and-instantiating-structs.md:9 +msgid "" +"```rust\n" +"#[derive(Copy, Drop)]\n" +"struct User {\n" +" active: bool,\n" +" username: felt252,\n" +" email: felt252,\n" +" sign_in_count: u64,\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[derive(Copy, Drop)]\n" +"struct User {\n" +" active: bool,\n" +" username: felt252,\n" +" email: felt252,\n" +" sign_in_count: u64,\n" +"}\n" +"```" + +#: src/ch04-01-defining-and-instantiating-structs.md:19 +msgid "Listing 4-1: A `User` struct definition" +msgstr "示例4-1:一个 `User` 结构定义" + +#: src/ch04-01-defining-and-instantiating-structs.md:21 +msgid "" +"To use a struct after we’ve defined it, we create an _instance_ of that " +"struct by specifying concrete values for each of the fields.\n" +"We create an instance by stating the name of the struct and then add curly " +"brackets containing _key: value_ pairs, where the keys are the names of the " +"fields and the values are the data we want to store in those fields. We " +"don’t have to specify the fields in the same order in which we declared them " +"in the struct. In other words, the struct definition is like a general " +"template for the type, and instances fill in that template with particular " +"data to create values of the type." +msgstr "" +"一旦定义了结构体后,为了使用它,通过为每个字段指定具体值来创建这个结构体的 *" +"实例*。\n" +"我们创建一个实例需要以结构体的名字开头,接着在大括号中使用 `key: value` 键 - " +"值对的形式提供字段,其中 key 是字段的名字,value 是需要存储在字段中的数据值。" +"实例中字段的顺序不需要和它们在结构体中声明的顺序一致。换句话说,结构体的定义" +"就像一个类型的通用模板,而实例则会在这个模板中放入特定数据来创建这个类型的" +"值。" + +#: src/ch04-01-defining-and-instantiating-structs.md:24 +msgid "For example, we can declare a particular user as shown in Listing 4-2." +msgstr "例如,我们可以如示例4-2所示声明一个特定的用户。" + +#: src/ch04-01-defining-and-instantiating-structs.md:28 +msgid "" +"```rust\n" +"#[derive(Copy, Drop)]\n" +"struct User {\n" +" active: bool,\n" +" username: felt252,\n" +" email: felt252,\n" +" sign_in_count: u64,\n" +"}\n" +"fn main() {\n" +" let user1 = User {\n" +" active: true,\n" +" username: 'someusername123',\n" +" email: 'someone@example.com',\n" +" sign_in_count: 1_u64,\n" +" };\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[derive(Copy, Drop)]\n" +"struct User {\n" +" active: bool,\n" +" username: felt252,\n" +" email: felt252,\n" +" sign_in_count: u64,\n" +"}\n" +"fn main() {\n" +" let user1 = User {\n" +" active: true,\n" +" username: 'someusername123',\n" +" email: 'someone@example.com',\n" +" sign_in_count: 1_u64,\n" +" };\n" +"}\n" +"```" + +#: src/ch04-01-defining-and-instantiating-structs.md:46 +msgid "" +"Listing 4-2: Creating an instance of the `User` " +"struct" +msgstr "示例4-2:创建一个`用户`结构的实例" + +#: src/ch04-01-defining-and-instantiating-structs.md:48 +msgid "" +"To get a specific value from a struct, we use dot notation. For example, to " +"access this user’s email address, we use `user1.email`. If the instance is " +"mutable, we can change a value by using the dot notation and assigning into " +"a particular field. Listing 4-3 shows how to change the value in the `email` " +"field of a mutable `User` instance." +msgstr "" +"为了从结构体中获取某个特定的值,可以使用点号。举个例子,想要用户的邮箱地址," +"可以用 `user1.email`。如果结构体的实例是可变的,我们可以使用点号并为对应的字" +"段赋值。示例 4-3 展示了如何改变一个可变的 `User` 实例中 `email` 字段的值。" + +#: src/ch04-01-defining-and-instantiating-structs.md:52 +msgid "" +"```rust,does_not_compile\n" +"fn main() {\n" +" let mut user1 = User {\n" +" active: true,\n" +" username: 'someusername123',\n" +" email: 'someone@example.com',\n" +" sign_in_count: 1_u64,\n" +" };\n" +" user1.email = 'anotheremail@example.com';\n" +"}\n" +"```" +msgstr "" +"```rust,does_not_compile\n" +"fn main() {\n" +" let mut user1 = User {\n" +" active: true,\n" +" username: 'someusername123',\n" +" email: 'someone@example.com',\n" +" sign_in_count: 1_u64,\n" +" };\n" +" user1.email = 'anotheremail@example.com';\n" +"}\n" +"```" + +#: src/ch04-01-defining-and-instantiating-structs.md:64 +msgid "" +"Listing 4-3: Changing the value in the email field " +"of a `User` instance" +msgstr "" +"示例4-3:改变`用户`实例的电子邮件字段中的值" + +#: src/ch04-01-defining-and-instantiating-structs.md:66 +msgid "" +"Note that the entire instance must be mutable; Cairo doesn’t allow us to " +"mark only certain fields as mutable." +msgstr "注意,整个实例必须是可变的;Cairo不允许我们只把某些字段标记为可变的。" + +#: src/ch04-01-defining-and-instantiating-structs.md:68 +msgid "" +"As with any expression, we can construct a new instance of the struct as the " +"last expression in the function body to implicitly return that new instance." +msgstr "" +"与任何表达式一样,我们可以在函数主体的最后一个表达式中构造一个新的结构体实" +"例,以隐式返回该新实例。" + +#: src/ch04-01-defining-and-instantiating-structs.md:70 +msgid "" +"Listing 4-4 shows a `build_user` function that returns a `User` instance " +"with the given email and username. The `active` field gets the value of " +"`true`, and the `sign_in_count` gets a value of `1`." +msgstr "" +"清单4-4显示了一个`build_user`函数,该函数返回一个`User`实例,并给出了电子邮件" +"和用户名。`active`字段的值为`true`,`sign_in_count`的值为`1`。" + +#: src/ch04-01-defining-and-instantiating-structs.md:74 +msgid "" +"```rust\n" +"fn build_user(email: felt252, username: felt252) -> User {\n" +" User {\n" +" active: true,\n" +" username: username,\n" +" email: email,\n" +" sign_in_count: 1,\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"fn build_user(email: felt252, username: felt252) -> User {\n" +" User {\n" +" active: true,\n" +" username: username,\n" +" email: email,\n" +" sign_in_count: 1,\n" +" }\n" +"}\n" +"```" + +#: src/ch04-01-defining-and-instantiating-structs.md:85 +msgid "" +"Listing 4-4: A `build_user` function that takes an " +"email and username and returns a `User` instance" +msgstr "" +"示例4-4:一个`build_user`函数,接收电子邮件和用户名," +"并返回一个`User`实例" + +#: src/ch04-01-defining-and-instantiating-structs.md:87 +msgid "" +"It makes sense to name the function parameters with the same name as the " +"struct fields, but having to repeat the `email` and `username` field names " +"and variables is a bit tedious. If the struct had more fields, repeating " +"each name would get even more annoying. Luckily, there’s a convenient " +"shorthand!" +msgstr "" +"为函数参数起与结构体字段相同的名字是可以理解的,但必须重复`email`和`username`" +"字段的名称和变量就有点乏味了。如果结构体有更多字段,重复每个名称就更加烦人" +"了。幸运的是,有一个方便的简写语法!" + +#: src/ch04-01-defining-and-instantiating-structs.md:89 +msgid "## Using the Field Init Shorthand" +msgstr "##使用字段初始化简写语法" + +#: src/ch04-01-defining-and-instantiating-structs.md:91 +msgid "" +"Because the parameter names and the struct field names are exactly the same " +"in Listing 4-4, we can use the field init shorthand syntax to rewrite " +"`build_user` so it behaves exactly the same but doesn’t have the repetition " +"of `username` and `email`, as shown in Listing 4-5." +msgstr "" +"因为示例 5-4 中的参数名与字段名都完全相同,我们可以使用字段初始化简写语法" +"(field init shorthand)来重写 `build_user`,这样其行为与之前完全相同,不过无" +"需重复 `username` 和 `email` 了,如示例 5-5 所示。" + +#: src/ch04-01-defining-and-instantiating-structs.md:95 +msgid "" +"```rust\n" +"fn build_user(email: felt252, username: felt252) -> User {\n" +" User {\n" +" active: true,\n" +" username,\n" +" email,\n" +" sign_in_count: 1_u64,\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"fn build_user(email: felt252, username: felt252) -> User {\n" +" User {\n" +" active: true,\n" +" username,\n" +" email,\n" +" sign_in_count: 1_u64,\n" +" }\n" +"}\n" +"```" + +#: src/ch04-01-defining-and-instantiating-structs.md:106 +msgid "" +"Listing 4-5: A `build_user` function that uses field " +"init shorthand because the `username` and `email` parameters have the same " +"name as struct fields" +msgstr "" +"清单4-5: `build_user`函数使用了字段初始化简写语法,因" +"为`username`和`email`参数与结构体字段同名," + +#: src/ch04-01-defining-and-instantiating-structs.md:108 +msgid "" +"Here, we’re creating a new instance of the `User` struct, which has a field " +"named `email`. We want to set the `email` field’s value to the value in the " +"`email` parameter of the `build_user` function. Because the `email` field " +"and the `email` parameter have the same name, we only need to write `email` " +"rather than `email: email`." +msgstr "" +"这里,我们正在创建一个新的 `User` 结构体实例,它有一个名为 `email`的字段。我" +"们希望将`email`字段的值设置为`build_user`函数的`email`参数中的值。因为`email`" +"字段和`email`参数有相同的名字,我们只需要写`email`而不是`email: email`。" + +#: src/ch04-02-an-example-program-using-structs.md:1 +msgid "# An Example Program Using Structs" +msgstr "# 结构体示例程序" + +#: src/ch04-02-an-example-program-using-structs.md:3 +msgid "" +"To understand when we might want to use structs, let’s write a program that " +"calculates the area of a rectangle. We’ll start by using single variables, " +"and then refactor the program until we’re using structs instead." +msgstr "" +"为了理解何时会需要使用结构体,让我们编写一个计算长方形面积的程序。我们会从单" +"独的变量开始,接着重构程序直到使用结构体替代他们为止。" + +#: src/ch04-02-an-example-program-using-structs.md:5 +msgid "" +"Let’s make a new project with Scarb called _rectangles_ that will take the " +"width and height of a rectangle specified in pixels and calculate the area " +"of the rectangle. Listing 4-6 shows a short program with one way of doing " +"exactly that in our project’s _src/lib.cairo_." +msgstr "" +"让我们用Scarb做一个名为_rectangles_的新项目,它获取以像素为单位的长方形的宽度" +"和高度,并计算出长方形的面积。清单4-6显示了位于项目中的_src/lib.cairo_中的小" +"程序,它刚刚好实现此功能。" + +#: src/ch04-02-an-example-program-using-structs.md:9 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let width1 = 30_u64;\n" +" let height1 = 10_u64;\n" +" let area = area(width1, height1);\n" +" area.print();\n" +"}\n" +"\n" +"fn area(width: u64, height: u64) -> u64 {\n" +" width * height\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let width1 = 30_u64;\n" +" let height1 = 10_u64;\n" +" let area = area(width1, height1);\n" +" area.print();\n" +"}\n" +"\n" +"fn area(width: u64, height: u64) -> u64 {\n" +" width * height\n" +"}\n" +"```" + +#: src/ch04-02-an-example-program-using-structs.md:23 +msgid "" +"Listing 4-6: Calculating the area of a rectangle " +"specified by separate width and height variables" +msgstr "" +"示例4-6:通过分别指定长方形的宽和高的变量来计算长方形" +"面积" + +#: src/ch04-02-an-example-program-using-structs.md:25 +msgid "Now run the program with `cairo-run src/lib.cairo`:" +msgstr "现在用`cairo-run src/lib.cairo`运行该程序:" + +#: src/ch04-02-an-example-program-using-structs.md:27 +msgid "" +"```bash\n" +"$ cairo-run src/lib.cairo\n" +"[DEBUG] , (raw: 300)\n" +"\n" +"Run completed successfully, returning []\n" +"```" +msgstr "" +"```bash\n" +"$ cairo-run src/lib.cairo\n" +"[DEBUG] , (raw: 300)\n" +"\n" +"Run completed successfully, returning []\n" +"```" + +#: src/ch04-02-an-example-program-using-structs.md:34 +msgid "" +"This code succeeds in figuring out the area of the rectangle by calling the " +"`area` function with each dimension, but we can do more to make this code " +"clear and readable." +msgstr "" +"这段代码通过调用每个维度的`area`函数,成功地算出了矩形的面积,但我们仍然可以" +"修改这段代码来使它的意义更加明确,并且增加可读性。" + +#: src/ch04-02-an-example-program-using-structs.md:36 +msgid "The issue with this code is evident in the signature of `area`:" +msgstr "这段代码的问题在 `area` 的签名中很明显:" + +#: src/ch04-02-an-example-program-using-structs.md:38 +msgid "" +"```rust\n" +"fn area(width: u64, height: u64) -> u64 {\n" +"```" +msgstr "" +"``rust\n" +"fn area(width: u64, height: u64) -> u64 {\n" +"```" + +#: src/ch04-02-an-example-program-using-structs.md:42 +msgid "" +"The `area` function is supposed to calculate the area of one rectangle, but " +"the function we wrote has two parameters, and it’s not clear anywhere in our " +"program that the parameters are related. It would be more readable and more " +"manageable to group width and height together. We’ve already discussed one " +"way we might do that in [Chapter 3](ch02-02-data-types.html#the-tuple-type): " +"using tuples." +msgstr "" +"`area`函数应该是计算一个矩形的面积,但是我们写的函数有两个参数,而且在我们的" +"程序中没有任何地方明确说明这些参数的关系。如果把宽度和高度放在一起,会更有可" +"读性,也更容易管理。我们已经在[第三章](ch02-02-data-types.html#the-tuple-" +"type)中讨论了一种我们可以做到的方法:使用元组。" + +#: src/ch04-02-an-example-program-using-structs.md:44 +msgid "## Refactoring with Tuples" +msgstr "## 使用元组重构" + +#: src/ch04-02-an-example-program-using-structs.md:46 +msgid "Listing 4-7 shows another version of our program that uses tuples." +msgstr "清单4-7显示了我们使用元组的另一个程序版本。" + +#: src/ch04-02-an-example-program-using-structs.md:50 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let rectangle = (30_u64, 10_u64);\n" +" let area = area(rectangle);\n" +" area.print(); // print out the area\n" +"}\n" +"\n" +"fn area(dimension: (u64, u64)) -> u64 {\n" +" let (x,y) = dimension;\n" +" x * y\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"fn main() {\n" +" let rectangle = (30_u64, 10_u64);\n" +" let area = area(rectangle);\n" +" area.print(); // print out the area\n" +"}\n" +"\n" +"fn area(dimension: (u64, u64)) -> u64 {\n" +" let (x,y) = dimension;\n" +" x * y\n" +"}\n" +"```" + +#: src/ch04-02-an-example-program-using-structs.md:64 +msgid "" +"Listing 4-7: Specifying the width and height of the " +"rectangle with a tuple" +msgstr "示例4-7:用一个元组指定矩形的宽度和高度" + +#: src/ch04-02-an-example-program-using-structs.md:66 +msgid "" +"In one way, this program is better. Tuples let us add a bit of structure, " +"and we’re now passing just one argument. But in another way, this version is " +"less clear: tuples don’t name their elements, so we have to index into the " +"parts of the tuple, making our calculation less obvious." +msgstr "" +"在某种程度上说,这个程序更好一点了。元组帮助我们增加了一些结构性,并且现在只" +"需传一个参数。不过在另一方面,这个版本却有一点不明确了:元组并没有给出元素的" +"名称,所以计算变得更费解了,因为不得不使用索引来获取元组的每一部分。" + +#: src/ch04-02-an-example-program-using-structs.md:68 +msgid "" +"Mixing up the width and height wouldn’t matter for the area calculation, but " +"if we want to calculate the difference, it would matter! We would have to " +"keep in mind that `width` is the tuple index `0` and `height` is the tuple " +"index `1`. This would be even harder for someone else to figure out and keep " +"in mind if they were to use our code. Because we haven’t conveyed the " +"meaning of our data in our code, it’s now easier to introduce errors." +msgstr "" +"混淆宽度和高度对于计算面积来说并不重要,但是如果我们想计算差值,那就很重要" +"了。我们必须记住 `width` 是元组索引`0`, `height` 是元组索引`1`。如果其他人要" +"使用这些代码,他们必须要搞清楚这一点,并也要牢记于心。很容易忘记或者混淆这些" +"值而造成错误,因为我们没有在代码中传达数据的意图。" + +#: src/ch04-02-an-example-program-using-structs.md:70 +msgid "## Refactoring with Structs: Adding More Meaning" +msgstr "## 使用结构体重构:赋予更多意义" + +#: src/ch04-02-an-example-program-using-structs.md:72 +msgid "" +"We use structs to add meaning by labeling the data. We can transform the " +"tuple we’re using into a struct with a name for the whole as well as names " +"for the parts." +msgstr "" +"我们使用结构体为数据命名来为其赋予意义。我们可以将我们正在使用的元组转换成一" +"个有整体名称而且每个部分也有对应名字的结构体。" + +#: src/ch04-02-an-example-program-using-structs.md:76 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"struct Rectangle {\n" +" width: u64,\n" +" height: u64,\n" +"}\n" +"\n" +"fn main() {\n" +" let rectangle = Rectangle {\n" +" width: 30_u64,\n" +" height: 10_u64,\n" +" };\n" +" let area = area(rectangle);\n" +" area.print(); // print out the area\n" +"}\n" +"\n" +"fn area(rectangle: Rectangle) -> u64 {\n" +" rectangle.width * rectangle.height\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"struct Rectangle {\n" +" width: u64,\n" +" height: u64,\n" +"}\n" +"\n" +"fn main() {\n" +" let rectangle = Rectangle {\n" +" width: 30_u64,\n" +" height: 10_u64,\n" +" };\n" +" let area = area(rectangle);\n" +" area.print(); // print out the area\n" +"}\n" +"\n" +"fn area(rectangle: Rectangle) -> u64 {\n" +" rectangle.width * rectangle.height\n" +"}\n" +"```" + +#: src/ch04-02-an-example-program-using-structs.md:98 +msgid "" +"Listing 4-8: Defining a `Rectangle` struct" +msgstr "示例 4-8:定义一个`Rectangle`结构" + +#: src/ch04-02-an-example-program-using-structs.md:100 +msgid "" +"Here we’ve defined a struct and named it `Rectangle`. Inside the curly " +"brackets, we defined the fields as `width` and `height`, both of which have " +"type `u64`. Then, in `main`, we created a particular instance of `Rectangle` " +"that has a width of `30` and a height of `10`. Our `area` function is now " +"defined with one parameter, which we’ve named `rectangle` which is of type " +"`Rectangle` struct. We can then access the fields of the instance with dot " +"notation, and it gives descriptive names to the values rather than using the " +"tuple index values of `0` and `1`." +msgstr "" +"这里我们定义了一个结构,并将其命名为 `Rectangle`。在大括号中,我们将字段定义" +"为 `width` 和 `height`,它们的类型都是 `u64`。然后,在`main`中,我们创建了一" +"个`Rectangle`的特殊实例,它的宽度是`30`,高度是`10`。我们的 `area`函数现在定" +"义了一个名为 `rectangle`参数,它是`Rectangle`结构类型。然后我们可以用点符号来" +"访问实例的字段,它给这些值起了描述性的名字,而不是使用`0`和`1`的元组索引值。" +"结构体胜在更清晰明了。" + +#: src/ch04-02-an-example-program-using-structs.md:102 +msgid "## Adding Useful Functionality with Trait" +msgstr "##用Trait增加实用功能" + +#: src/ch04-02-an-example-program-using-structs.md:104 +msgid "" +"It’d be useful to be able to print an instance of `Rectangle` while we’re " +"debugging our program and see the values for all its fields. Listing 4-9 " +"tries using the `print` as we have used in previous chapters. This won’t " +"work." +msgstr "" +"在调试程序时打印出 `Rectangle` 实例来查看其所有字段的值非常有用。示例 4-9 像" +"前面章节那样尝试使用 `print`。但这并不管用。" + +#: src/ch04-02-an-example-program-using-structs.md:108 +msgid "" +"```rust,does_not_compile\n" +"use debug::PrintTrait;\n" +"\n" +"struct Rectangle {\n" +" width: u64,\n" +" height: u64,\n" +"}\n" +"\n" +"fn main() {\n" +" let rectangle = Rectangle {\n" +" width: 30_u64,\n" +" height: 10_u64,\n" +" };\n" +" rectangle.print();\n" +"}\n" +"```" +msgstr "" +"```rust,does_not_compile\n" +"use debug::PrintTrait;\n" +"\n" +"struct Rectangle {\n" +" width: u64,\n" +" height: u64,\n" +"}\n" +"\n" +"fn main() {\n" +" let rectangle = Rectangle {\n" +" width: 30_u64,\n" +" height: 10_u64,\n" +" };\n" +" rectangle.print();\n" +"}\n" +"```" + +#: src/ch04-02-an-example-program-using-structs.md:125 +msgid "" +"Listing 4-9: Attempting to print a `Rectangle` " +"instance" +msgstr "示例 4-9:试图打印一个 `Rectangle`实例" + +#: src/ch04-02-an-example-program-using-structs.md:127 +msgid "When we compile this code, we get an error with this message:" +msgstr "当我们编译这段代码时,我们得到了一个错误,有这样的信息:" + +#: src/ch04-02-an-example-program-using-structs.md:129 +msgid "" +"```bash\n" +"$ cairo-compile src/lib.cairo\n" +"error: Method `print` not found on type \"../src::Rectangle\". Did you " +"import the correct trait and impl?\n" +" --> lib.cairo:16:15\n" +" rectangle.print();\n" +" ^***^\n" +"\n" +"Error: Compilation failed.\n" +"```" +msgstr "" +"```bash\n" +"$ cairo-compile src/lib.cairo\n" +"error: Method `print` not found on type \"../src::Rectangle\". Did you " +"import the correct trait and impl?\n" +" --> lib.cairo:16:15\n" +" rectangle.print();\n" +" ^***^\n" +"\n" +"Error: Compilation failed.\n" +"```" + +#: src/ch04-02-an-example-program-using-structs.md:139 +msgid "" +"The `print` trait is implemented for many data types, but not for the " +"`Rectangle` struct. We can fix this by implementing the `PrintTrait` trait " +"on `Rectangle` as shown in Listing 4-10.\n" +"To learn more about traits, see [Traits in Cairo](ch07-02-traits-in-cairo." +"md)." +msgstr "" +"许多数据类型都实现了 `print` 特性,但 `Rectangle` 结构没有。我们可以通过在" +"`Rectangle`上实现`PrintTrait`trait来解决这个问题,如示例4-10所示。\n" +"要了解更多关于traits的信息,请参阅[Traits in Cairo](ch07-02-traits-in-cairo." +"md)。" + +#: src/ch04-02-an-example-program-using-structs.md:144 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"struct Rectangle {\n" +" width: u64,\n" +" height: u64,\n" +"}\n" +"\n" +"fn main() {\n" +" let rectangle = Rectangle {\n" +" width: 30_u64,\n" +" height: 10_u64,\n" +" };\n" +" rectangle.print();\n" +"}\n" +"\n" +"impl RectanglePrintImpl of PrintTrait {\n" +" fn print(self: Rectangle) {\n" +" self.width.print();\n" +" self.height.print();\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"struct Rectangle {\n" +" width: u64,\n" +" height: u64,\n" +"}\n" +"\n" +"fn main() {\n" +" let rectangle = Rectangle {\n" +" width: 30_u64,\n" +" height: 10_u64,\n" +" };\n" +" rectangle.print();\n" +"}\n" +"\n" +"impl RectanglePrintImpl of PrintTrait {\n" +" fn print(self: Rectangle) {\n" +" self.width.print();\n" +" self.height.print();\n" +" }\n" +"}\n" +"```" + +#: src/ch04-02-an-example-program-using-structs.md:168 +msgid "" +"Listing 4-10: Implementing the `PrintTrait` trait on " +"`Rectangle`" +msgstr "" +"示例4-10:在`Rectangle`上实现`PrintTrait`属性" + +#: src/ch04-02-an-example-program-using-structs.md:170 +msgid "" +"Nice! It’s not the prettiest output, but it shows the values of all the " +"fields for this instance, which would definitely help during debugging." +msgstr "" +"很好!这不是最漂亮的输出,但它显示了这个实例的所有字段的值,这在调试时肯定会有" +"帮助。" + +#: src/ch04-03-method-syntax.md:1 +msgid "## Method Syntax" +msgstr "##方法语法" + +#: src/ch04-03-method-syntax.md:3 +msgid "" +"_Methods_ are similar to functions: we declare them with the `fn` keyword " +"and a\n" +"name, they can have parameters and a return value, and they contain some " +"code\n" +"that’s run when the method is called from somewhere else. Unlike functions,\n" +"methods are defined within the context of a type and their first parameter " +"is\n" +"always `self`, which represents the instance of the type the method is " +"being\n" +"called on. For those familiar with Rust, Cairo's approach might be " +"confusing,\n" +"as methods cannot be defined directly on types. Instead, you must define a " +"trait\n" +"and an implementation associated with the type for which the method is " +"intended." +msgstr "" +"_方法_(method)与函数类似:它们使用 `fn` 关键字和名称声明,可以拥有参数和返" +"回值,同时包含在某处调用该方法时会执行的代码。不过方法与函数是不同的,因为它" +"们在结构体的上下文中被定义,并且它们第一个参数总是 `self`,它代表调用该方法的" +"结构体实例。\n" +"对于那些熟悉Rust的人来说,Cairo的方法可能会令人困惑,因为方法不能被直接定\n" +"义在类型上。相反,你必须定义一个trait和一个与该方法所在类型相关的实现。" + +#: src/ch04-03-method-syntax.md:12 +msgid "### Defining Methods" +msgstr "### 定义方法" + +#: src/ch04-03-method-syntax.md:14 +msgid "" +"Let’s change the `area` function that has a `Rectangle` instance as a " +"parameter\n" +"and instead make an `area` method defined on the `RectangleTrait` trait, as " +"shown\n" +"in Listing 5-13." +msgstr "" +"让我们把前面实现的获取一个 `Rectangle` 实例作为参数的 `area` 函数,\n" +"改写成一个定义于 `RectangleTrait` trait 上的 `area` 方法,如示例5-13所示。" + +#: src/ch04-03-method-syntax.md:20 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"#[derive(Copy, Drop)]\n" +"struct Rectangle {\n" +" width: u64,\n" +" height: u64,\n" +"}\n" +"\n" +"trait RectangleTrait {\n" +" fn area(self: @Rectangle) -> u64;\n" +"}\n" +"\n" +"impl RectangleImpl of RectangleTrait {\n" +" fn area(self: @Rectangle) -> u64 {\n" +" (*self.width) * (*self.height)\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let rect1 = Rectangle { width: 30_u64, height: 50_u64, };\n" +"\n" +" rect1.area().print();\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"#[derive(Copy, Drop)]\n" +"struct Rectangle {\n" +" width: u64,\n" +" height: u64,\n" +"}\n" +"\n" +"trait RectangleTrait {\n" +" fn area(self: @Rectangle) -> u64;\n" +"}\n" +"\n" +"impl RectangleImpl of RectangleTrait {\n" +" fn area(self: @Rectangle) -> u64 {\n" +" (*self.width) * (*self.height)\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let rect1 = Rectangle { width: 30_u64, height: 50_u64, };\n" +"\n" +" rect1.area().print();\n" +"}\n" +"```" + +#: src/ch04-03-method-syntax.md:45 +msgid "" +"Listing 4-13: Defining an `area` method to use on " +"the\n" +"`Rectangle` " +msgstr "" +"示例4-13:定义一个用在`Rectangle` 上的 `area` 方法 " + +#: src/ch04-03-method-syntax.md:48 +msgid "" +"To define the function within the context of `Rectangle`, we start by " +"definining a `trait`\n" +"block with the signature of the method that we want to implement. Traits are " +"not linked to\n" +"a specific type; only the `self` parameter of the method defines which type " +"it can be used\n" +"with. Then, we define an `impl` (implementation) block for `RectangleTrait`, " +"that defines\n" +"the behavior of the methods implemented. Everything within this `impl` block " +"will be\n" +"associated with the type of the `self` parameter of the method called. While " +"it is technically\n" +"possible to define methods for multiple types within the same `impl` block, " +"it is not\n" +"a recommended practice, as it can lead to confusion. We recommend that the " +"type of the `self` parameter\n" +"stays consistent within the same `impl` block.\n" +"Then we move the `area` function within the `impl` curly brackets and change " +"the first (and in this case, only)\n" +"parameter to be `self` in the signature and everywhere within the body. In\n" +"`main`, where we called the `area` function and passed `rect1` as an " +"argument,\n" +"we can instead use the _method syntax_ to call the `area` method on our " +"`Rectangle`\n" +"instance. The method syntax goes after an instance: we add a dot followed " +"by\n" +"the method name, parentheses, and any arguments." +msgstr "" +"为了使函数定义于 `Rectangle` 的上下文中,我们开始了一个 `trait` 块,其中包含" +"我们想要实现的方法的签名。\n" +"Traits 并不与一个特定的类型所链接;只有方法的 `self` 参数定义了它可以用于哪种" +"类型。然后,我们为 `RectangleTrait` 定义一个 `impl`(实现)块,它定义了实现的" +"方法的行为。\n" +"这个 `impl` 块中的所有内容都将与被调用方法的 `self` 参数的类型相关。虽然在技" +"术上可以在同一个 `impl` 块中定义多种类型的方法,但这并不是一个值得推荐的做" +"法。\n" +"因为它可能会导致混乱。我们建议`self`参数的类型在同一个 `impl` 块中保持一" +"致。\n" +"然后我们将`area`函数移到`impl`大括号内,并在签名和正文的所有地方将第一个(在" +"本例中是唯一的)参数改为`self`。在`main`中,我们调用`area`函数并传递`rect1`作" +"为参数、\n" +"\n" +"我们可以使用_method syntax_在我们的`Rectangle`实例上调用`area`方法。\n" +"方法语法获取一个实例并加上一个点号,后跟方法名、圆括号以及任何参数。" + +#: src/ch04-03-method-syntax.md:64 +msgid "" +"Methods must have a parameter named `self` of the type they will be applied " +"to for their first parameter.\n" +"Note that we used the `@` snapshot operator in front of the `Rectangle` type " +"in the function signature.\n" +"By doing so, we indicate that this method takes an immutable snapshot of the " +"`Rectangle` instance, which is\n" +"automatically created by the compiler when passing the instance to the " +"method.\n" +"Methods can take ownership of `self`, use `self` with snapshots as we’ve " +"done here, or use a mutable reference to `self`\n" +"using the `ref self: T` syntax." +msgstr "" +"方法必须有一个名为 `self` 的类型参数作为它们将要应用的类型的第一个参数。请注" +"意,我们在函数签名中在 `Rectangle` 类型前面使用了 `@` 快照运算符。这样做,我" +"们表示此方法获取 `Rectangle` 实例的不可变快照,编译器在将实例传递给该方法时会" +"自动创建。方法可以获取 `self` 实例的所有权,像我们在这里所做的那样使用快照的 " +"`self`,或使用 `ref self: T` 语法使用 `self` 的可变引用。" + +#: src/ch04-03-method-syntax.md:71 +msgid "" +"We chose `self: @Rectangle` here for the same reason we used `@Rectangle` in " +"the function\n" +"version: we don’t want to take ownership, and we just want to read the data " +"in\n" +"the struct, not write to it. If we wanted to change the instance that we’ve\n" +"called the method on as part of what the method does, we’d use `ref self: " +"Rectangle` as\n" +"the first parameter. Having a method that takes ownership of the instance " +"by\n" +"using just `self` as the first parameter is rare; this technique is usually\n" +"used when the method transforms `self` into something else and you want to\n" +"prevent the caller from using the original instance after the transformation." +msgstr "" +"我们在这里选择 `self: @Rectangle` 与函数版本中使用 `@Rectangle` 的原因相同:" +"我们不想要所有权,只是想读取结构体中的数据,而不是对它进行写入。如果我们想要" +"作为方法的一部分更改调用方法的实例,我们将使用 `ref self: Rectangle` 作为第一" +"个参数。通过仅使用 `self` 作为第一个参数来使方法获取实例的所有权是很少见的;" +"这种技术通常用在当方法将 `self` 转换成别的实例的时候,这时我们想要防止调用者" +"在转换之后使用原始的实例。" + +#: src/ch04-03-method-syntax.md:80 +msgid "" +"Observe the use of the desnap operator `*` within the area method when " +"accessing the struct's members.\n" +"This is necessary because the struct is passed as a snapshot, and all of its " +"field values are of type `@T`,\n" +"requiring them to be desnapped in order to manipulate them." +msgstr "" +"在访问结构体的成员时,请注意在区域方法中使用desnap操作符`*`。\n" +"这是必要的,因为该结构是以快照形式传递的,其所有字段值都是`@T`类型、\n" +"需要对它们进行解快照,以便对其进行操作。" + +#: src/ch04-03-method-syntax.md:84 +msgid "" +"The main reason for using methods instead of functions is for organization " +"and code clarity. We’ve put all the things we can do with an instance of a " +"type in one combination of `trait` & `impl` blocks, rather than making " +"future users\n" +"of our code search for capabilities of `Rectangle` in various places in the\n" +"library we provide. However, we can define multiple combinations of `trait` " +"& `impl` blocks for the same type at different places, which can be useful " +"for a more granular code organization. For example, you could implement\n" +"the `Add` trait for your type in one `impl` block, and the `Sub` trait in " +"another block." +msgstr "" +"使用方法而不是函数的主要原因是为了组织和代码的清晰性。我们把所有我们能对一个" +"类型的实例做的操作都放在一组`trait'和`impl'块的组合中,而不是让未来的用户在我" +"们提供的库中的不同地方搜索 `Rectangle`的功能。\n" +"然而,我们可以在不同的地方为同一类型定义多个`trait'和`impl'块的组合,这对更细" +"化的代码组织很有用。例如,你可以在一个`impl`块中为你的类型实现 `impl`trait ," +"在另一个块中实现 `Sub`trait 。" + +#: src/ch04-03-method-syntax.md:89 +msgid "" +"Note that we can choose to give a method the same name as one of the " +"struct’s\n" +"fields. For example, we can define a method on `Rectangle` that is also " +"named\n" +"`width`:" +msgstr "" +"请注意,我们可以选择将方法的名称与结构中的一个字段相同。例如,我们可以在 " +"`Rectangle` 上定义一个方法,并命名为`width`:" + +#: src/ch04-03-method-syntax.md:95 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"#[derive(Copy, Drop)]\n" +"struct Rectangle {\n" +" width: u64,\n" +" height: u64,\n" +"}\n" +"\n" +"trait RectangleTrait {\n" +" fn width(self: @Rectangle) -> bool;\n" +"}\n" +"\n" +"impl RectangleImpl of RectangleTrait {\n" +" fn width(self: @Rectangle) -> bool {\n" +" (*self.width) > 0_u64\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let rect1 = Rectangle { width: 30_u64, height: 50_u64, };\n" +" rect1.width().print();\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"#[derive(Copy, Drop)]\n" +"struct Rectangle {\n" +" width: u64,\n" +" height: u64,\n" +"}\n" +"\n" +"trait RectangleTrait {\n" +" fn width(self: @Rectangle) -> bool;\n" +"}\n" +"\n" +"impl RectangleImpl of RectangleTrait {\n" +" fn width(self: @Rectangle) -> bool {\n" +" (*self.width) > 0_u64\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let rect1 = Rectangle { width: 30_u64, height: 50_u64, };\n" +" rect1.width().print();\n" +"}\n" +"```" + +#: src/ch04-03-method-syntax.md:119 +msgid "" +"Here, we’re choosing to make the `width` method return `true` if the value " +"in\n" +"the instance’s `width` field is greater than `0` and `false` if the value " +"is\n" +"`0`: we can use a field within a method of the same name for any purpose. " +"In\n" +"`main`, when we follow `rect1.width` with parentheses, Cairo knows we mean " +"the\n" +"method `width`. When we don’t use parentheses, Cairo knows we mean the " +"field\n" +"`width`." +msgstr "" +"在这里,我们选择让`width`方法在实例的`width`字段中的值大于0时返回`true`,在值" +"为0时返回`false` :我们可以在同名方法的字段内使用任何目的。在`main`中,当我们" +"在`rect1.width`后面跟着括号时,Cairo知道我们意思是`width`方法。当我们不使用括" +"号时,Cairo知道我们指的是`width`字段。" + +#: src/ch04-03-method-syntax.md:126 +msgid "### Methods with More Parameters" +msgstr "###带有更多参数的方法" + +#: src/ch04-03-method-syntax.md:128 +msgid "" +"Let’s practice using methods by implementing a second method on the " +"`Rectangle`\n" +"struct. This time we want an instance of `Rectangle` to take another " +"instance\n" +"of `Rectangle` and return `true` if the second `Rectangle` can fit " +"completely\n" +"within `self` (the first `Rectangle`); otherwise, it should return `false`.\n" +"That is, once we’ve defined the `can_hold` method, we want to be able to " +"write\n" +"the program shown in Listing 5-14." +msgstr "" +"让我们通过在`Rectangle`结构体上实现第二个方法来练习使用方法。这次,我们希望让" +"`Rectangle`的实例接收另一个`Rectangle`的实例。如果第二个`Rectangle`可以完全适" +"应`self` (第一个`Rectangle`)就返回 `true` ; 否则,它应该返回`false`。也就是" +"说,一旦我们定义了`can_hold`方法,我们希望能够编写列表5-14中显示的程序。" + +#: src/ch04-03-method-syntax.md:137 +msgid "" +"```rust,does_not_compile\n" +"use debug::PrintTrait;\n" +"#[derive(Copy, Drop)]\n" +"struct Rectangle {\n" +" width: u64,\n" +" height: u64,\n" +"}\n" +"\n" +"fn main() {\n" +" let rect1 = Rectangle { width: 30_u64, height: 50_u64, };\n" +" let rect2 = Rectangle { width: 10_u64, height: 40_u64, };\n" +" let rect3 = Rectangle { width: 60_u64, height: 45_u64, };\n" +"\n" +" 'Can rect1 hold rect2?'.print();\n" +" rect1.can_hold(@rect2).print();\n" +"\n" +" 'Can rect1 hold rect3?'.print();\n" +" rect1.can_hold(@rect3).print();\n" +"}\n" +"```" +msgstr "" +"```rust,does_not_compile\n" +"use debug::PrintTrait;\n" +"#[derive(Copy, Drop)]\n" +"struct Rectangle {\n" +" width: u64,\n" +" height: u64,\n" +"}\n" +"\n" +"fn main() {\n" +" let rect1 = Rectangle { width: 30_u64, height: 50_u64, };\n" +" let rect2 = Rectangle { width: 10_u64, height: 40_u64, };\n" +" let rect3 = Rectangle { width: 60_u64, height: 45_u64, };\n" +"\n" +" 'Can rect1 hold rect2?'.print();\n" +" rect1.can_hold(@rect2).print();\n" +"\n" +" 'Can rect1 hold rect3?'.print();\n" +" rect1.can_hold(@rect3).print();\n" +"}\n" +"```" + +#: src/ch04-03-method-syntax.md:158 +msgid "" +"Listing 5-14: Using the as-yet-unwritten `can_hold`\n" +"method" +msgstr "" +"列表5-14:使用尚未编写的 \"can_hold\"方法" + +#: src/ch04-03-method-syntax.md:161 +msgid "" +"The expected output would look like the following because both dimensions " +"of\n" +"`rect2` are smaller than the dimensions of `rect1`, but `rect3` is wider " +"than\n" +"`rect1`:" +msgstr "" +"预期的输出结果如下,因为`rect2'的两个尺寸都小于`rect1'的尺寸。\n" +"`rect2`的尺寸都小于`rect1`的尺寸,但`rect3`的宽度大于\n" +"`rect1':" + +#: src/ch04-03-method-syntax.md:165 +msgid "" +"```text\n" +"❯ cairo-run src/lib.cairo\n" +"[DEBUG]\tCan rec1 hold rect2? \t(raw: " +"384675147322001379018464490539350216396261044799)\n" +"\n" +"[DEBUG]\ttrue \t(raw: 1953658213)\n" +"\n" +"[DEBUG]\tCan rect1 hold rect3? \t(raw: " +"384675147322001384331925548502381811111693612095)\n" +"\n" +"[DEBUG]\tfalse \t(raw: 439721161573)\n" +"\n" +"```" +msgstr "" +"```text\n" +"❯ cairo-run src/lib.cairo\n" +"[DEBUG]\tCan rec1 hold rect2? \t(raw: " +"384675147322001379018464490539350216396261044799)\n" +"\n" +"[DEBUG]\ttrue \t(raw: 1953658213)\n" +"\n" +"[DEBUG]\tCan rect1 hold rect3? \t(raw: " +"384675147322001384331925548502381811111693612095)\n" +"\n" +"[DEBUG]\tfalse \t(raw: 439721161573)\n" +"\n" +"```" + +#: src/ch04-03-method-syntax.md:177 +msgid "" +"We know we want to define a method, so it will be within the `trait " +"RectangleTrait`\n" +"and `impl RectangleImpl of RectangleTrait` blocks.\n" +"The method name will be `can_hold`, and it will take a snapshot\n" +"of another `Rectangle` as a parameter. We can tell what the type of the\n" +"parameter will be by looking at the code that calls the method:\n" +"`rect1.can_hold(@rect2)` passes in `@rect2`, which is a snapshot to\n" +"`rect2`, an instance of `Rectangle`. This makes sense because we only need " +"to\n" +"read `rect2` (rather than write, which would mean we’d need a mutable " +"borrow),\n" +"and we want `main` to retain ownership of `rect2` so we can use it again " +"after\n" +"calling the `can_hold` method. The return value of `can_hold` will be a\n" +"Boolean, and the implementation will check whether the width and height of\n" +"`self` are greater than the width and height of the other `Rectangle`,\n" +"respectively. Let’s add the new `can_hold` method to the `trait` and `impl` " +"blocks from\n" +"Listing 5-13, shown in Listing 5-15." +msgstr "" +"我们知道我们需要定义一个方法,所以它将在`trait RectangleTrait`和`impl " +"RectangleImpl of RectangleTrait` 块中。该方法名为 `can_hold`,它将接收另一个" +"`Rectangle`的快照作为参数。我们可以通过查看调用该方法的代码来确定参数的类型:" +"`rect1.can_hold(@rect2)`将`@rect2`作为快照传递给`rect2`,它是`Rectangle`的一" +"个实例。这是有意义的,因为我们只需要读取`rect2`(而不是写入,这意味着我们需要" +"一个可变借用),我们希望`main`保留对`rect2`的所有权,以便在调用`can_hold` 方" +"法后再次使用它。`can_hold` 的返回值将是一个布尔值,实现将检查`self`的宽度和高" +"度是否分别大于另一`Rectangle`的宽度和高度。让我们将新的`can_hold`方法添加到清" +"单5-13中的`trait`和`impl` 块中,如清单5-15所示。" + +#: src/ch04-03-method-syntax.md:194 +msgid "" +"```rust\n" +"trait RectangleTrait {\n" +" fn area(self: @Rectangle) -> u64;\n" +" fn can_hold(self: @Rectangle, other: @Rectangle) -> bool;\n" +"}\n" +"\n" +"impl RectangleImpl of RectangleTrait {\n" +" fn area(self: @Rectangle) -> u64 {\n" +" *self.width * *self.height\n" +" }\n" +"\n" +" fn can_hold(self: @Rectangle, other: @Rectangle) -> bool {\n" +" *self.width > *other.width & *self.height > *other.height\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"trait RectangleTrait {\n" +" fn area(self: @Rectangle) -> u64;\n" +" fn can_hold(self: @Rectangle, other: @Rectangle) -> bool;\n" +"}\n" +"\n" +"impl RectangleImpl of RectangleTrait {\n" +" fn area(self: @Rectangle) -> u64 {\n" +" *self.width * *self.height\n" +" }\n" +"\n" +" fn can_hold(self: @Rectangle, other: @Rectangle) -> bool {\n" +" *self.width > *other.width & *self.height > *other.height\n" +" }\n" +"}\n" +"```" + +#: src/ch04-03-method-syntax.md:211 +msgid "" +"Listing 5-15: Implementing the `can_hold` method on\n" +"`Rectangle` that takes another `Rectangle` instance as a parameter" +msgstr "" +"清单5-15: 在`Rectangle`上实现`can_hold`方法,该方法接" +"收另一个`Rectangle`实例作为参数" + +#: src/ch04-03-method-syntax.md:214 +msgid "" +"When we run this code with the `main` function in Listing 5-14, we’ll get " +"our\n" +"desired output. Methods can take multiple parameters that we add to the\n" +"signature after the `self` parameter, and those parameters work just like\n" +"parameters in functions." +msgstr "" +"当我们在Listing 5-14中的`main`函数中运行这段代码时,我们将得到我们想要的输" +"出。\n" +"方法可以使用多个参数,我们可以在`self`参数之后在函数签名中添加这些参数,\n" +"这些参数与函数中的参数工作原理相同。" + +#: src/ch04-03-method-syntax.md:219 +msgid "### Accessing implementation functions" +msgstr "###访问执行功能" + +#: src/ch04-03-method-syntax.md:221 +msgid "" +"All functions defined within a `trait` and `impl` block can be directly " +"addressed\n" +"using the `::` operator on the implementation name.\n" +"Functions in traits that aren’t methods are often used for constructors " +"that\n" +"will return a new instance of the struct. These are often called `new`, but\n" +"`new` isn’t a special name and isn’t built into the language. For example, " +"we\n" +"could choose to provide an associated function named `square` that would " +"have\n" +"one dimension parameter and use that as both width and height, thus making " +"it\n" +"easier to create a square `Rectangle` rather than having to specify the " +"same\n" +"value twice:" +msgstr "" +"所有在`trait`和`impl` 块中定义的功能可以直接使用`::` 运算符在实现名称上进行访" +"问。\n" +"在`trait`中的不是方法的函数通常用于构造函数,以返回一个结构体的新实例。\n" +"这些函数通常被称为`new`,但`new`不是一个特殊的名称,也不是内置到语言中的。\n" +"例如,我们可以选择提供一个名为`square` 的关联函数,它将具有一个维度参数,\n" +"并将其用作宽度和高度,从而更容易地创建一个正方形`Rectangle`,而不必指定两次相" +"同的值:" + +#: src/ch04-03-method-syntax.md:233 +msgid "" +"```rust\n" +"trait RectangleTrait {\n" +" fn square(size: u64) -> Rectangle;\n" +"}\n" +"\n" +"impl RectangleImpl of RectangleTrait {\n" +" fn square(size: u64) -> Rectangle {\n" +" Rectangle { width: size, height: size }\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"trait RectangleTrait {\n" +" fn square(size: u64) -> Rectangle;\n" +"}\n" +"\n" +"impl RectangleImpl of RectangleTrait {\n" +" fn square(size: u64) -> Rectangle {\n" +" Rectangle { width: size, height: size }\n" +" }\n" +"}\n" +"```" + +#: src/ch04-03-method-syntax.md:245 +msgid "" +"To call this function, we use the `::` syntax with the implementation name;\n" +"`let square = RectangleImpl::square(10_u64);` is an example. This function " +"is namespaced by\n" +"the implementation; the `::` syntax is used for both trait functions and\n" +"namespaces created by modules. We’ll discuss modules in [Chapter 7]" +"[modules]." +msgstr "" +"为了调用这个函数,我们使用`::`语法和实现名称;\n" +"`let square = RectangleImpl::square(10_u64);`是一个例子。这个函数的名字是由实" +"现所命名空间化;`::`语法用于trait函数和模块创建的命名空间。\n" +"命名空间。我们将在 [Chapter 7][modules]<!--ignore-->中讨论模块。" + +#: src/ch04-03-method-syntax.md:250 +msgid "" +"> Note: It is also possible to call this function using the trait name, with " +"`RectangleTrait::square(10_u64)`." +msgstr "" +"> 注意:也可以用trait名称来调用这个函数,用`RectangleTrait::square(10_u64)`。" + +#: src/ch04-03-method-syntax.md:252 +msgid "### Multiple `impl` Blocks" +msgstr "###多个`impl`块" + +#: src/ch04-03-method-syntax.md:254 +msgid "" +"Each struct is allowed to have multiple `trait` and `impl` blocks. For " +"example, Listing\n" +"5-15 is equivalent to the code shown in Listing 5-16, which has each method " +"in\n" +"its own `trait` and `impl` blocks." +msgstr "" +"每个结构体都可以有多个`trait` 和`impl`块。例如,示例5-15等价于示例5-16中展示" +"的代码,其中每个方法都有自己的`trait` 和`impl`块。" + +#: src/ch04-03-method-syntax.md:258 +msgid "" +"```rust\n" +"trait RectangleCalc {\n" +" fn area(self: @Rectangle) -> u64;\n" +"}\n" +"impl RectangleCalcImpl of RectangleCalc {\n" +" fn area(self: @Rectangle) -> u64 {\n" +" (*self.width) * (*self.height)\n" +" }\n" +"}\n" +"\n" +"trait RectangleCmp {\n" +" fn can_hold(self: @Rectangle, other: @Rectangle) -> bool;\n" +"}\n" +"\n" +"impl RectangleCmpImpl of RectangleCmp {\n" +" fn can_hold(self: @Rectangle, other: @Rectangle) -> bool {\n" +" *self.width > *other.width & *self.height > *other.height\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"trait RectangleCalc {\n" +" fn area(self: @Rectangle) -> u64;\n" +"}\n" +"impl RectangleCalcImpl of RectangleCalc {\n" +" fn area(self: @Rectangle) -> u64 {\n" +" (*self.width) * (*self.height)\n" +" }\n" +"}\n" +"\n" +"trait RectangleCmp {\n" +" fn can_hold(self: @Rectangle, other: @Rectangle) -> bool;\n" +"}\n" +"\n" +"impl RectangleCmpImpl of RectangleCmp {\n" +" fn can_hold(self: @Rectangle, other: @Rectangle) -> bool {\n" +" *self.width > *other.width & *self.height > *other.height\n" +" }\n" +"}\n" +"```" + +#: src/ch04-03-method-syntax.md:279 +msgid "" +"Listing 5-16: Rewriting Listing 5-15 using multiple " +"`impl`\n" +"blocks" +msgstr "" +"示例5-16:使用多个`impl`重写示例5-15\n" +"块" + +#: src/ch04-03-method-syntax.md:282 +msgid "" +"There’s no reason to separate these methods into multiple `trait` and `impl` " +"blocks here,\n" +"but this is valid syntax. We’ll see a case in which multiple blocks are\n" +"useful in [Chapter 7](ch07-00-generic-types-and-traits.md), where we discuss " +"generic types and traits." +msgstr "" +"这里没有理由把这些方法分成多个`trait`和`impl`块,\n" +"但这是有效的语法。我们将在[第7章](ch07-00-generic-types-and-traits.md)中看\n" +"到一个多块的情况,在那里我们讨论泛型和traits。" + +#: src/ch04-03-method-syntax.md:288 +msgid "" +"Structs let you create custom types that are meaningful for your domain. By\n" +"using structs, you can keep associated pieces of data connected to each " +"other\n" +"and name each piece to make your code clear. In `trait` and `impl` blocks, " +"you can define\n" +"methods, which are functions associated to a type and let you specify the " +"behavior that instances of your\n" +"type have." +msgstr "" +"结构体让你可以创建出在你的领域中有意义的自定义类型。\n" +"通过结构体,我们可以将相关联的数据片段联系起来并命名它们,这样可以使得代码更" +"加清晰。\n" +"在`trait`和`impl`块中,你可以定义与你的类型相关联的方法,而方法是一种相关联的" +"函数,让你指定结构体的实例所具有的行为。" + +#: src/ch04-03-method-syntax.md:294 +msgid "" +"But structs aren’t the only way you can create custom types: let’s turn to\n" +"Cairo’s enum feature to add another tool to your toolbox." +msgstr "" +"但结构体并不是创建自定义类型的唯一方法:让我们转向 Cairo 的枚举功能,为你的\n" +"工具箱再添一个工具。" + +#: src/ch05-00-enums-and-pattern-matching.md:1 +msgid "# Enums and Pattern Matching" +msgstr "# 枚举和模式匹配" + +#: src/ch05-01-enums.md:1 +msgid "# Enums" +msgstr "# 枚举" + +#: src/ch05-01-enums.md:3 +msgid "" +"Enums, short for \"enumerations,\" are a way to define a custom data type " +"that consists of a fixed set of named values, called _variants_. Enums are " +"useful for representing a collection of related values where each value is " +"distinct and has a specific meaning." +msgstr "" +"本章介绍 \"枚举\"(enumerations),也被称作 enums,是一种自定义数据类型的方" +"式,它由一组固定的命名值组成,称为_variants_。枚举对于表示相关值的集合非常有" +"用,其中每个值都是不同的,并且有特定的含义。" + +#: src/ch05-01-enums.md:5 +msgid "## Enum Variants and Values" +msgstr "## 枚举变量和值" + +#: src/ch05-01-enums.md:7 +msgid "Here's a simple example of an enum:" +msgstr "下面是一个枚举的简单例子:" + +#: src/ch05-01-enums.md:9 +msgid "" +"```rs\n" +"#[derive(Drop)]\n" +"enum Direction {\n" +" North: (),\n" +" East: (),\n" +" South: (),\n" +" West: (),\n" +"}\n" +"\n" +"```" +msgstr "" +"```rs\n" +"#[derive(Drop)]\n" +"enum Direction {\n" +" North:()、\n" +" East: ()、\n" +" South: ()、\n" +" West: ()、\n" +"}\n" +"\n" +"```" + +#: src/ch05-01-enums.md:20 +msgid "" +"Unlike other languages like Rust, every variant has a type. In this example, " +"we've defined an enum called `Direction` with four variants: `North`, " +"`East`, `South`, and `West`. The naming convention is to use PascalCase for " +"enum variants. Each variant represents a distinct value of the Direction " +"type and is associated with a unit type `()`. One variant can be " +"instantiated using this syntax:" +msgstr "" +"与Rust等其他语言不同,每个变体都有一个类型。在这个例子中,我们定义了一个叫做 " +"`Direction`的枚举,有四个变量:`North`, `East`, `South`, 和 `West`。命名惯例" +"是使用PascalCase来表示枚举变量。每个变量代表方向类型的一个不同的值,并与一个" +"unit类型`()`相关。一个变量可以使用这种语法进行实例化:" + +#: src/ch05-01-enums.md:22 +msgid "" +"```rs\n" +"let direction = Direction::North(());\n" +"```" +msgstr "" +"````rs\n" +"let direction = Direction::North(());\n" +"```" + +#: src/ch05-01-enums.md:26 +msgid "" +"It's easy to write code that acts differently depending on the variant of an " +"enum instance, in this example to run specific code according to a " +"Direction. You can learn more about it on the [The Match Control Flow " +"Construct page](ch05-02-the-match-control-flow-construct.md)." +msgstr "" +"写代码很容易根据枚举实例的变量而采取不同的行动,在这个例子中,根据一个方向来" +"运行特定的代码。你可以在 [match 控制流结构](ch05-02-the-match-control-flow-" +"construct.md)页面上了解更多信息。" + +#: src/ch05-01-enums.md:28 +msgid "## Enums Combined with Custom Types" +msgstr "## 枚举与自定义类型相结合" + +#: src/ch05-01-enums.md:30 +msgid "" +"Enums can also be used to store more interesting data associated with each " +"variant. For example:" +msgstr "枚举也可以用来存储与每个变体相关的更有趣的数据。比如说:" + +#: src/ch05-01-enums.md:32 +msgid "" +"```rs\n" +"#[derive(Drop)]\n" +"enum Message {\n" +" Quit : (),\n" +" Echo : felt252,\n" +" Move : (u128, u128),\n" +"}\n" +"```" +msgstr "" +"```rs\n" +"#[derive(Drop)]\n" +"enum Message {\n" +" Quit : ()、\n" +" Echo : felt252、\n" +" Move : (u128, u128)、\n" +"}\n" +"```" + +#: src/ch05-01-enums.md:41 +msgid "" +"In this example, the `Message` enum has three variants: `Quit`, `Echo` and " +"`Move`, all with different types:" +msgstr "" +"在这个例子中,`Message'枚举有三个变体:`Quit'、`Echo'和`Move',都有不同的类" +"型:" + +#: src/ch05-01-enums.md:43 +msgid "" +"- `Quit` is the unit type - it has no data associated with it at all.\n" +"- `Echo` is a single felt.\n" +"- `Move` is a tuple of two u128 values." +msgstr "" +"- `Quit'是unit类型 - 它完全没有与之相关的数据。\n" +"- `Echo'是一个单一的felt。\n" +"- `Move'是一个由两个u128值组成的tuple。" + +#: src/ch05-01-enums.md:47 +msgid "" +"You could even use a Struct or another Enum you defined inside one of your " +"Enum variants." +msgstr "你甚至可以在你的一个枚举变量中使用一个结构体或另一个你定义的枚举。" + +#: src/ch05-01-enums.md:49 +msgid "## Trait Implementations for Enums" +msgstr "## 枚举的Trait实现" + +#: src/ch05-01-enums.md:51 +msgid "" +"In Cairo, you can define traits and implement them for your custom enums. " +"This allows you to define methods and behaviors associated with the enum. " +"Here's an example of defining a trait and implementing it for the previous " +"`Message` enum:" +msgstr "" +"在Cairo中,你可以为你的自定义枚举定义traits并实现它们。这允许你定义与枚举相关" +"的方法和行为。下面是一个定义trait并为之前的 `Message` 枚举实现的例子:" + +#: src/ch05-01-enums.md:53 +msgid "" +"```rs\n" +"trait Processing {\n" +" fn process(self: Message);\n" +"}\n" +"\n" +"impl ProcessingImpl of Processing {\n" +" fn process(self: Message) {\n" +" match self {\n" +" Message::Quit(()) => {\n" +" 'quitting'.print();\n" +" },\n" +" Message::Echo(value) => {\n" +" value.print();\n" +" },\n" +" Message::Move((x, y)) => {\n" +" 'moving'.print();\n" +" },\n" +" }\n" +" }\n" +"}\n" +"```" +msgstr "" +"````rs\n" +"trait Processing {\n" +" fn process(self: Message);\n" +"}\n" +"\n" +"impl ProcessingImpl of Processing {\n" +" fn process(self: Message) {\n" +" match self {\n" +" Message::Quit(()) => {\n" +" 'quitting'.print();\n" +" },\n" +" Message::Echo(value) => {\n" +" value.print();\n" +" },\n" +" Message::Move((x, y)) => {\n" +" 'moving'.print();\n" +" },\n" +" }\n" +" }\n" +"}\n" +"```" + +#: src/ch05-01-enums.md:75 +msgid "" +"In this example, we implemented the `Processing` trait for `Message`. Here " +"is how it could be used to process a Quit message:" +msgstr "" +"在这个例子中,我们为`Message`实现了`Processing` trait。下面是如何用它来处理一" +"条退出消息:" + +#: src/ch05-01-enums.md:77 +msgid "" +"```rust\n" +"let msg: Message = Message::Quit(());\n" +"msg.process();\n" +"```" +msgstr "" +"```rust\n" +"let msg: Message = Message::Quit(());\n" +"msg.process();\n" +"```" + +#: src/ch05-01-enums.md:82 +msgid "Running this code would print `quitting`." +msgstr "运行这段代码会打印出 `quitting`。" + +#: src/ch05-01-enums.md:84 +msgid "## The Option Enum and Its Advantages" +msgstr "## 选项枚举及其优势" + +#: src/ch05-01-enums.md:86 +msgid "" +"The Option enum is a standard Cairo enum that represents the concept of an " +"optional value. It has two variants: `Some: T` and `None: ()`. `Some: T ` " +"indicates that there's a value of type `T`, while `None` represents the " +"absence of a value." +msgstr "" +"Option枚举是一个标准的Cairo枚举,表示一个可选值的概念。它有两个变量:`Some:" +"T \"和 \"None: ()\"。`Some:T`表示有一个`T`类型的值,而`None`表示没有一个值。" + +#: src/ch05-01-enums.md:88 +msgid "" +"```rs\n" +"enum Option {\n" +" Some: T,\n" +" None: (),\n" +"}\n" +"```" +msgstr "" +"```rs\n" +"enum Option {\n" +" Some: T,\n" +" None: (),\n" +"}\n" +"```" + +#: src/ch05-01-enums.md:95 +msgid "" +"The `Option` enum is helpful because it allows you to explicitly represent " +"the possibility of a value being absent, making your code more expressive " +"and easier to reason about. Using `Option` can also help prevent bugs caused " +"by using uninitialized or unexpected `null` values." +msgstr "" +"`Option` 枚举很有帮助,因为它允许你明确地表示一个值不存在的可能性,使你的代码" +"更具表现力,更容易推理。使用 `Option` 也可以帮助防止因使用未初始化的或意外的 " +"`null` 值而引起的错误。" + +#: src/ch05-01-enums.md:97 +msgid "" +"To give you an example, here is a function which returns the index of the " +"first element of an array with a given value, or None if the element is not " +"present." +msgstr "" +"为了给你一个例子,这里有一个函数,它返回一个给定值的数组中第一个元素的索引," +"如果该元素不存在则返回None。" + +#: src/ch05-01-enums.md:99 +msgid "We are demonstrating two approaches for the above function:" +msgstr "我们为上述函数演示了两种方法:" + +#: src/ch05-01-enums.md:101 +msgid "" +"- Recursive Approach `find_value_recursive`\n" +"- Iterative Approach `find_value_iterative`" +msgstr "" +"- 递归法 `find_value_recursive`。\n" +"- 迭代法 `find_value_iterative`。" + +#: src/ch05-01-enums.md:104 +msgid "" +"> Note: in the future it would be nice to replace this example by something " +"simpler using a loop and without gas related code." +msgstr "> 注意:将来最好能用循环和无需 gas 的相关代码的简单示例替换此示例。" + +#: src/ch05-01-enums.md:106 +msgid "" +"```rust\n" +"use array::ArrayTrait;\n" +"use debug::PrintTrait;\n" +"fn find_value_recursive(arr: @Array, value: felt252, index: usize) -" +"> Option {\n" +" match gas::withdraw_gas() {\n" +" Option::Some(_) => {},\n" +" Option::None(_) => {\n" +" let mut data = ArrayTrait::new();\n" +" data.append('OOG');\n" +" panic(data);\n" +" },\n" +" }\n" +"\n" +" if index >= arr.len() {\n" +" return Option::None(());\n" +" }\n" +"\n" +" if *arr.at(index) == value {\n" +" return Option::Some(index);\n" +" }\n" +"\n" +" find_value_recursive(arr, value, index + 1_usize)\n" +"}\n" +"\n" +"fn find_value_iterative(arr: @Array, value: felt252) -> " +"Option {\n" +" let length = arr.len();\n" +" let mut index = 0_usize;\n" +" let mut found: Option = Option::None(());\n" +" loop {\n" +" if index < length {\n" +" if *arr.at(index) == value {\n" +" found = Option::Some(index);\n" +" break ();\n" +" }\n" +" } else {\n" +" break ();\n" +" }\n" +" index += 1_usize;\n" +" };\n" +" return found;\n" +"}\n" +"\n" +"#[test]\n" +"#[available_gas(999999)]\n" +"fn test_increase_amount() {\n" +" let mut my_array = ArrayTrait::new();\n" +" my_array.append(3);\n" +" my_array.append(7);\n" +" my_array.append(2);\n" +" my_array.append(5);\n" +"\n" +" let value_to_find = 7;\n" +" let result = find_value_recursive(@my_array, value_to_find, 0_usize);\n" +" let result_i = find_value_iterative(@my_array, value_to_find);\n" +"\n" +"\n" +" match result {\n" +" Option::Some(index) => {\n" +" if index == 1_usize {\n" +" 'it worked'.print();\n" +" }\n" +" },\n" +" Option::None(()) => {\n" +" 'not found'.print();\n" +" },\n" +" }\n" +" match result_i {\n" +" Option::Some(index) => {\n" +" if index == 1_usize {\n" +" 'it worked'.print();\n" +" }\n" +" },\n" +" Option::None(()) => {\n" +" 'not found'.print();\n" +" },\n" +" }\n" +"}\n" +"\n" +"```" +msgstr "" +"```rust\n" +"use array::ArrayTrait;\n" +"use debug::PrintTrait;\n" +"fn find_value_recursive(arr: @Array, value: felt252, index: usize) -" +"> Option {\n" +" match gas::withdraw_gas() {\n" +" Option::Some(_) => {},\n" +" Option::None(_) => {\n" +" let mut data = ArrayTrait::new();\n" +" data.append('OOG');\n" +" panic(data);\n" +" },\n" +" }\n" +"\n" +" if index >= arr.len() {\n" +" return Option::None(());\n" +" }\n" +"\n" +" if *arr.at(index) == value {\n" +" return Option::Some(index);\n" +" }\n" +"\n" +" find_value_recursive(arr, value, index + 1_usize)\n" +"}\n" +"\n" +"fn find_value_iterative(arr: @Array, value: felt252) -> " +"Option {\n" +" let length = arr.len();\n" +" let mut index = 0_usize;\n" +" let mut found: Option = Option::None(());\n" +" loop {\n" +" if index < length {\n" +" if *arr.at(index) == value {\n" +" found = Option::Some(index);\n" +" break ();\n" +" }\n" +" } else {\n" +" break ();\n" +" }\n" +" index += 1_usize;\n" +" };\n" +" return found;\n" +"}\n" +"\n" +"#[test]\n" +"#[available_gas(999999)]\n" +"fn test_increase_amount() {\n" +" let mut my_array = ArrayTrait::new();\n" +" my_array.append(3);\n" +" my_array.append(7);\n" +" my_array.append(2);\n" +" my_array.append(5);\n" +"\n" +" let value_to_find = 7;\n" +" let result = find_value_recursive(@my_array, value_to_find, 0_usize);\n" +" let result_i = find_value_iterative(@my_array, value_to_find);\n" +"\n" +"\n" +" match result {\n" +" Option::Some(index) => {\n" +" if index == 1_usize {\n" +" 'it worked'.print();\n" +" }\n" +" },\n" +" Option::None(()) => {\n" +" 'not found'.print();\n" +" },\n" +" }\n" +" match result_i {\n" +" Option::Some(index) => {\n" +" if index == 1_usize {\n" +" 'it worked'.print();\n" +" }\n" +" },\n" +" Option::None(()) => {\n" +" 'not found'.print();\n" +" },\n" +" }\n" +"}\n" +"\n" +"```" + +#: src/ch05-01-enums.md:186 +msgid "Running this code would print `it worked`." +msgstr "运行这段代码会打印出 `it worked`。" + +#: src/ch05-02-the-match-control-flow-construct.md:1 +msgid "# The Match Control Flow Construct" +msgstr "# match控制流结构" + +#: src/ch05-02-the-match-control-flow-construct.md:3 +msgid "" +"" +msgstr "<!-- TODO:更新以下段落中提到的第18章(关于模式和模式匹配章节)-->" + +#: src/ch05-02-the-match-control-flow-construct.md:5 +msgid "" +"Cairo has an extremely powerful control flow construct called `match` that " +"allows you to compare a value against a series of patterns and then execute " +"code based on which pattern matches. Patterns can be made up of literal " +"values, variable names, wildcards, and many other things. The power of match " +"comes from the expressiveness of the patterns and the fact that the compiler " +"confirms that all possible cases are handled." +msgstr "" +"Cairo 有一个非常强大的控制流结构,叫做 `match`,它允许你将一个值与一系列的模" +"式进行比较,然后根据模式的匹配情况执行代码。模式可以由字面值、变量名、通配符" +"和许多其他东西组成。match 的力量来自于模式的表达性,以及编译器确认所有可能的" +"情况都得到了处理的事实。" + +#: src/ch05-02-the-match-control-flow-construct.md:7 +msgid "" +"Think of a match expression as being like a coin-sorting machine: coins " +"slide down a track with variously sized holes along it, and each coin falls " +"through the first hole it encounters that it fits into. In the same way, " +"values go through each pattern in a match, and at the first pattern the " +"value “fits”, the value falls into the associated code block to be used " +"during execution." +msgstr "" +"可以把 match 表达式想象成一台硬币分类机:硬币沿着有各种大小的孔的轨道滑下,每" +"枚硬币都从它遇到的第一个适合它的孔中落下。以同样的方式,值穿过 match 中的每个" +"模式,在值 “fits” 的第一个模式中,值落入相关的代码块,在执行中使用。" + +#: src/ch05-02-the-match-control-flow-construct.md:9 +msgid "" +"Speaking of coins, let’s use them as an example using match! We can write a " +"function that takes an unknown US coin and, in a similar way as the counting " +"machine, determines which coin it is and returns its value in cents, as " +"shown in Listing 5-3." +msgstr "" +"说到硬币,让我们用它们作为一个例子,使用 match 我们可以写一个函数,接收一个未" +"知的美国硬币,并以类似于点钞机的方式,确定它是哪种硬币,并返回其价值(美" +"分),如清单5-3所示。" + +#: src/ch05-02-the-match-control-flow-construct.md:11 +msgid "" +"```rust\n" +"enum Coin {\n" +" Penny: (),\n" +" Nickel: (),\n" +" Dime: (),\n" +" Quarter: (),\n" +"}\n" +"\n" +"fn value_in_cents(coin: Coin) -> felt252 {\n" +" match coin {\n" +" Coin::Penny(_) => 1,\n" +" Coin::Nickel(_) => 5,\n" +" Coin::Dime(_) => 10,\n" +" Coin::Quarter(_) => 25,\n" +" }\n" +"}\n" +"```" +msgstr "" +"``rust\n" +"enum Coin {\n" +" Penny: ()、\n" +" Nickel: ()、\n" +" Dime: ()、\n" +" Quarter: ()、\n" +"}\n" +"\n" +"fn value_in_cents(coin: Coin) -> felt252 {\n" +" match coin {\n" +" Coin::Penny(_) => 1、\n" +" Coin::Nickel(_) => 5、\n" +" Coin::Dime(_) => 10、\n" +" Coin::Quarter(_) => 25、\n" +" }\n" +"\n" +"```" + +#: src/ch05-02-the-match-control-flow-construct.md:29 +msgid "" +"Listing 5-3: An enum and a match expression that has the variants of the " +"enum as its patterns" +msgstr "清单5-3:一个枚举和一个将枚举的变量作为其模式的 match 表达式" + +#: src/ch05-02-the-match-control-flow-construct.md:31 +msgid "" +"Let’s break down the `match` in the `value_in_cents` function. First we list " +"the `match` keyword followed by an expression, which in this case is the " +"value `coin`. This seems very similar to a conditional expression used with " +"if, but there’s a big difference: with if, the condition needs to evaluate " +"to a Boolean value, but here it can be any type. The type of coin in this " +"example is the `Coin` enum that we defined on the first line." +msgstr "" +"让我们来分析一下 `value_in_cents' 函数中的 `match'。首先,我们列出了 `match' " +"关键字,后面是一个表达式,在本例中是 `coin' 值。这似乎与使用 if 的条件表达式" +"非常相似,但有一个很大的区别:在 if 中,条件需要求值为一个布尔值,但在这里它" +"可以是任何类型。本例中硬币的类型是我们在第一行定义的 `Coin` 枚举。" + +#: src/ch05-02-the-match-control-flow-construct.md:33 +msgid "" +"Next are the `match` arms. An arm has two parts: a pattern and some code. " +"The first arm here has a pattern that is the value `Coin::Penny(_)` and then " +"the `=>` operator that separates the pattern and the code to run. The code " +"in this case is just the value `1`. Each arm is separated from the next with " +"a comma." +msgstr "" +"接下来是 `match` 分支。一个分支有两个部分:一个模式和一些代码。这里的第一个分" +"支有一个模式,就是值 `Coin::Penny(_)`,然后是`=>`操作符,把模式和要运行的代码" +"分开。本例中的代码只是值 `1'。每个分支都用逗号与下一个分支隔开。" + +#: src/ch05-02-the-match-control-flow-construct.md:35 +msgid "" +"When the `match` expression executes, it compares the resultant value " +"against the pattern of each arm, in order. If a pattern matches the value, " +"the code associated with that pattern is executed. If that pattern doesn’t " +"match the value, execution continues to the next arm, much as in a coin-" +"sorting machine. We can have as many arms as we need: in the above example, " +"our match has four arms." +msgstr "" +"当 `match` 表达式执行时,它将结果值与每个分支的模式进行比较,依次进行。如果一" +"个模式与值匹配,则执行与该模式相关的代码。如果该模式不匹配该值,则继续执行下" +"一个分支,就像硬币排序机一样。我们可以根据自己的需要有多少个分支:在上面的例" +"子中,我们的匹配有四个分支。" + +#: src/ch05-02-the-match-control-flow-construct.md:37 +msgid "In Cairo, the order of the arms must follow the same order as the enum." +msgstr "在 Cairo,分支的顺序必须遵循与枚举相同的顺序。" + +#: src/ch05-02-the-match-control-flow-construct.md:39 +msgid "" +"The code associated with each arm is an expression, and the resultant value " +"of the expression in the matching arm is the value that gets returned for " +"the entire match expression." +msgstr "" +"与每个 match 相关的代码是一个表达式,而 match 分支中表达式的结果值是整个 " +"match 表达式被返回的值。" + +#: src/ch05-02-the-match-control-flow-construct.md:41 +msgid "" +"We don’t typically use curly brackets if the match arm code is short, as it " +"is in our example where each arm just returns a value. If you want to run " +"multiple lines of code in a match arm, you must use curly brackets, with a " +"comma following the arm. For example, the following code prints “Lucky " +"penny!” every time the method is called with a `Coin::Penny(())`, but still " +"returns the last value of the block, `1`:" +msgstr "" +"如果 match 分支的代码很短,我们通常不使用大括号,就像在我们的示例中一样,每个" +"分支只是返回一个值。如果你想在一个 match 分支中运行多行代码,你必须使用大括" +"号,在 match 分支后面加一个逗号。例如,下面的代码在每次调用 `Coin::" +"Penny(())` 方法时都会打印出 “Lucky penny!”,但仍然返回区块的最后一个值 `1`:" + +#: src/ch05-02-the-match-control-flow-construct.md:43 +msgid "" +"```rust\n" +"fn value_in_cents(coin: Coin) -> felt252 {\n" +" match coin {\n" +" Coin::Penny(_) => {\n" +" ('Lucky penny!').print();\n" +" 1\n" +" },\n" +" Coin::Nickel(_) => 5,\n" +" Coin::Dime(_) => 10,\n" +" Coin::Quarter(_)=> 25,\n" +" }\n" +"}\n" +"```" +msgstr "" +"``rust\n" +"fn value_in_cents(coin: Coin) -> felt252 {\n" +" match coin {\n" +" Coin::Penny(_) => {\n" +" ('Lucky penny!').print();\n" +" 1\n" +" },\n" +" Coin::Nickel(_) => 5、\n" +" Coin::Dime(_) => 10、\n" +" Coin::Quarter(_)=> 25、\n" +" }\n" +"\n" +"```" + +#: src/ch05-02-the-match-control-flow-construct.md:57 +msgid "## Patterns That Bind to Values" +msgstr "## 绑定价值的模式" + +#: src/ch05-02-the-match-control-flow-construct.md:59 +msgid "" +"Another useful feature of match arms is that they can bind to the parts of " +"the values that match the pattern. This is how we can extract values out of " +"enum variants." +msgstr "" +"match分支的另一个有用的特点是它们可以绑定到值中与模式相匹配的部分。这就是我们" +"如何从枚举变量中提取数值的方法。" + +#: src/ch05-02-the-match-control-flow-construct.md:61 +msgid "" +"As an example, let’s change one of our enum variants to hold data inside it. " +"From 1999 through 2008, the United States minted quarters with different " +"designs for each of the 50 states on one side. No other coins got state " +"designs, so only quarters have this extra value. We can add this information " +"to our `enum` by changing the `Quarter` variant to include a `UsState` value " +"stored inside it, which we’ve done in Listing 5-4." +msgstr "" +"作为一个例子,让我们改变我们的一个枚举变量,在它里面保存数据。从1999年到2008" +"年,美国铸造了25分硬币,其中一面为50个州的不同设计。其他硬币没有州的设计,所" +"以只有25分硬币有这个额外的价值。我们可以通过改变 `Quarter` 变量,使其包含一个" +"`UsState` 的值,从而将这个信息添加到我们的 `enum` 中,我们在清单5-4中已经这样" +"做了。" + +#: src/ch05-02-the-match-control-flow-construct.md:63 +msgid "" +"```rust\n" +"#[derive(Drop)]\n" +"enum UsState {\n" +" Alabama: (),\n" +" Alaska: (),\n" +"}\n" +"\n" +"#[derive(Drop)]\n" +"enum Coin {\n" +" Penny: (),\n" +" Nickel: (),\n" +" Dime: (),\n" +" Quarter: (UsState),\n" +"}\n" +"```" +msgstr "" +"``rust\n" +"#[derive(Drop)]\n" +"enum UsState {\n" +" Alabama: ()、\n" +" Alaska: ()、\n" +"}\n" +"\n" +"#[derive(Drop)]\n" +"enum Coin {\n" +" Penny: ()、\n" +" Nickel: ()、\n" +" Dime: ()、\n" +" Quarter: (UsState)、\n" +"}\n" +"```" + +#: src/ch05-02-the-match-control-flow-construct.md:79 +msgid "" +"Listing 5-4: A `Coin` enum in which the `Quarter` variant also holds a " +"`UsState` value" +msgstr "" +"列表5-4: 一个 `Coin` 枚举,其中 `Quarter` 变量也持有一个 `UsState` 值。" + +#: src/ch05-02-the-match-control-flow-construct.md:81 +msgid "" +"Let’s imagine that a friend is trying to collect all 50 state quarters. " +"While we sort our loose change by coin type, we’ll also call out the name of " +"the state associated with each quarter so that if it’s one our friend " +"doesn’t have, they can add it to their collection." +msgstr "" +"让我们想象一下,一个朋友正试图收集所有50个州的硬币。当我们按硬币类型对零钱进" +"行分类时,我们也会叫出与每个25分硬币相关的州名,这样如果是我们的朋友没有的," +"他们就可以把它加入他们的集合。" + +#: src/ch05-02-the-match-control-flow-construct.md:83 +msgid "" +"In the match expression for this code, we add a variable called `state` to " +"the pattern that matches values of the variant `Coin::Quarter`. When a " +"`Coin::Quarter` matches, the `state` variable will bind to the value of that " +"quarter’s state. Then we can use `state` in the code for that arm, like so:" +msgstr "" +"在这段代码的match表达式中,我们在模式中添加了一个叫做 `state` 的变量,用来匹" +"配变量 `Coin::Quarter` 的值。当 `Coin::Quarter` 匹配时,`state` 变量将与该季" +"度的状态值绑定。然后我们可以在该分支的代码中使用 `state`,像这样:" + +#: src/ch05-02-the-match-control-flow-construct.md:85 +msgid "" +"```rust\n" +"fn value_in_cents(coin: Coin) -> felt252 {\n" +" match coin {\n" +" Coin::Penny(_) => 1,\n" +" Coin::Nickel(_) => 5,\n" +" Coin::Dime(_) => 10,\n" +" Coin::Quarter(state)=> {\n" +" state.print();\n" +" 25\n" +" },\n" +" }\n" +"}\n" +"```" +msgstr "" +"``rust\n" +"fn value_in_cents(coin: Coin) -> felt252 {\n" +" match coin {\n" +" Coin::Penny(_) => 1、\n" +" Coin::Nickel(_) => 5、\n" +" Coin::Dime(_) => 10、\n" +" Coin::Quarter(state)=> {\n" +" state.print();\n" +" 25\n" +" },\n" +" }\n" +"}\n" +"```" + +#: src/ch05-02-the-match-control-flow-construct.md:99 +msgid "" +"To print the value of a variant of an enum in Cairo, we need to add an " +"implementation for the `print` function for the `debug::PrintTrait`:" +msgstr "" +"为了在 Cairo 打印一个枚举的变量的值,我们需要为`debug::PrintTrait` 添加一个 " +"`print` 函数的实现:" + +#: src/ch05-02-the-match-control-flow-construct.md:101 +msgid "" +"```rust\n" +"impl UsStatePrintImpl of PrintTrait:: {\n" +" fn print(self: UsState) {\n" +" match self {\n" +" UsState::Alabama(_) => ('Alabama').print(),\n" +" UsState::Alaska(_) => ('Alaska').print(),\n" +" }\n" +" }\n" +"}\n" +"```" +msgstr "" +"``rust\n" +"impl UsStatePrintImpl of PrintTrait:: {\n" +" fn print(self: UsState) {\n" +" match self {\n" +" UsState::Alabama(_) => ('Alabama').print()、\n" +" UsState::Alaska(_) => ('Alaska').print()、\n" +" }\n" +" }\n" +"}\n" +"```" + +#: src/ch05-02-the-match-control-flow-construct.md:112 +msgid "" +"If we were to call `value_in_cents(Coin::Quarter(UsState::Alaska(())))`, " +"`coin` would be `Coin::Quarter(UsState::Alaska())`. When we compare that " +"value with each of the match arms, none of them match until we reach `Coin::" +"Quarter(state)`. At that point, the binding for state will be the value " +"`UsState::Alaska()`. We can then use that binding in the `PrintTrait`, thus " +"getting the inner state value out of the `Coin` enum variant for `Quarter`." +msgstr "" +"如果我们调用 `value_in_cents(Coin::quarter(UsState::Alaska(())))`,`coin` 将" +"是 `Coin::quarter(UsState::Alaska())`。当我们将该值与每个匹配臂进行比较时,没" +"有一个匹配,直到我们到达 `Coin::Quarter(state)`。在这一点上,state 的绑定将" +"是 `UsState::Alaska()` 的值。然后我们可以在 `PrintTrait' 中使用该绑定,从而" +"从 `Coin' 枚举变量中获得 `Quarter' 的内部状态值。" + +#: src/ch05-02-the-match-control-flow-construct.md:114 +msgid "## Matching with Options" +msgstr "##用选项进行匹配" + +#: src/ch05-02-the-match-control-flow-construct.md:116 +msgid "" +"In the previous section, we wanted to get the inner `T` value out of the " +"`Some` case when using `Option`; we can also handle `Option` using " +"`match`, as we did with the `Coin` enum! Instead of comparing coins, we’ll " +"compare the variants of `Option`, but the way the `match` expression " +"works remains the same. You can use Options by importing the `option::" +"OptionTrait` trait." +msgstr "" +"在上一节中,我们想在使用 `Option` 时从 `Some` 情况下得到内部的 `T` 值;我" +"们也可以使用`match` 来处理 `Option`,就像我们对 `Coin` 枚举所做的那样!我们" +"不比较代币,而是比较 `Option` 的变量,但 `match` 表达式的工作方式保持不" +"变。你可以通过导入 `option::OptionTrait` trait来使用Option。" + +#: src/ch05-02-the-match-control-flow-construct.md:118 +msgid "" +"Let’s say we want to write a function that takes an `Option` and, if " +"there’s a value inside, adds `1_u8` to that value. If there isn’t a value " +"inside, the function should return the `None` value and not attempt to " +"perform any operations." +msgstr "" +"假设我们想写一个函数,接收一个 `Option`,如果里面有一个值,就把 `1_u8` 加" +"到这个值上。如果里面没有一个值,这个函数应该返回 `None` 值,并且不试图执行任" +"何操作。" + +#: src/ch05-02-the-match-control-flow-construct.md:120 +msgid "" +"This function is very easy to write, thanks to match, and will look like " +"Listing 5-5." +msgstr "这个函数非常容易编写,这要归功于 match,它看起来像清单5-5。" + +#: src/ch05-02-the-match-control-flow-construct.md:122 +msgid "" +"```rust\n" +"use option::OptionTrait;\n" +"use debug::PrintTrait;\n" +"\n" +"fn plus_one(x: Option) -> Option {\n" +" match x {\n" +" Option::Some(val) => Option::Some(val + 1_u8),\n" +" Option::None(_) => Option::None(()),\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let five: Option = Option::Some(5_u8);\n" +" let six: Option = plus_one(five);\n" +" six.unwrap().print();\n" +" let none = plus_one(Option::None(()));\n" +" none.unwrap().print();\n" +"}\n" +"```" +msgstr "" +"``rust\n" +"use option::OptionTrait;\n" +"use debug::PrintTrait;\n" +"\n" +"fn plus_one(x: Option) -> Option {\n" +" match x {\n" +" Option::Some(val) => Option::Some(val + 1_u8)、\n" +" Option::None(_) => Option::None(())、\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let five:Option = Option::Some(5_u8);\n" +" let six:Option = plus_one(five);\n" +" six.unwrap().print();\n" +" let none = plus_one(Option::None(()));\n" +" none.unwrap().print();\n" +"}\n" +"```" + +#: src/ch05-02-the-match-control-flow-construct.md:142 +msgid "Listing 5-5: A function that uses a match expression on an `Option`" +msgstr "清单5-5:一个在 \"选项\"上使用匹配表达式的函数。" + +#: src/ch05-02-the-match-control-flow-construct.md:144 +msgid "" +"Note that your arms must respect the same order as the enum defined in the " +"`OptionTrait` of the core Cairo lib." +msgstr "" +"注意,你的分支必须尊重与核心Cairo库的`OptionTrait`中定义的枚举相同的顺序。" + +#: src/ch05-02-the-match-control-flow-construct.md:146 +msgid "" +"```rust\n" +" enum Option {\n" +" Some: T,\n" +" None: (),\n" +" }\n" +"```" +msgstr "" +"``rust\n" +" enum Option {\n" +" Some: T,\n" +" None: ()、\n" +" }\n" +"```" + +#: src/ch05-02-the-match-control-flow-construct.md:153 +msgid "" +"Let’s examine the first execution of `plus_one` in more detail. When we call " +"`plus_one(five)`, the variable `x` in the body of `plus_one` will have the " +"value `Some(5_u8)`. We then compare that against each match arm:" +msgstr "" +"让我们更详细地检查 `plus_one` 的第一次执行。当我们调用 `plus_one(five)` 时," +"`plus_one` 主体中的变量 `x` 的值是 `Some(5_u8)`。然后我们将其与每个匹配分支进" +"行比较:" + +#: src/ch05-02-the-match-control-flow-construct.md:155 +#: src/ch05-02-the-match-control-flow-construct.md:163 +msgid "" +"```rust\n" +" Option::Some(val) => Option::Some(val + 1_u8),\n" +"```" +msgstr "" +"``rust\n" +" Option::Some(val) => Option::Some(val + 1_u8)、\n" +"```" + +#: src/ch05-02-the-match-control-flow-construct.md:159 +msgid "" +"Does `Option::Some(5_u8)` value match the pattern `Option::Some(val)`? It " +"does! We have the same variant. The `val` binds to the value contained in " +"`Option::Some`, so `val` takes the value `5_u8`. The code in the match arm " +"is then executed, so we add `1_u8` to the value of `val` and create a new " +"`Option::Some` value with our total `6_u8` inside. Because the first arm " +"matched, no other arms are compared." +msgstr "" +"`Option::Some(5_u8)` 值是否符合`Option::Some(val)`的模式?是的!我们有相同的变" +"量。`val` 与 `Option::Some` 中包含的值绑定,所以 `val` 取值为 `5_u8` 。然后执" +"行匹配分支中的代码,所以我们在 `val` 的值上加上 `1_u8`,并创建一个新的 " +"`Option::Some` 值,里面有我们的总数 `6_u8` 。因为第一个分支的匹配,没有其他分" +"支被比较。" + +#: src/ch05-02-the-match-control-flow-construct.md:161 +msgid "" +"Now let’s consider the second call of `plus_one` in our main function, where " +"`x` is `Option::None(())`. We enter the match and compare to the first arm:" +msgstr "" +"现在让我们考虑在我们的主函数中对 `plus_one` 的第二次调用,其中 `x` 是" +"`Option::None(())`。我们进入匹配,并与第一个分支进行比较:" + +#: src/ch05-02-the-match-control-flow-construct.md:167 +msgid "" +"The `Option::Some(val)` value doesn’t match the pattern `Option::None`, so " +"we continue to the next arm:" +msgstr "" +"`Option::Some(val)` 的值不符合 `Option::None` 的模式,所以我们继续到下一个分" +"支:" + +#: src/ch05-02-the-match-control-flow-construct.md:169 +msgid "" +"```rust\n" +" Option::None(_) => Option::None(()),\n" +"```" +msgstr "" +"``rust\n" +" Option::None(_) => Option::None(() )、\n" +"```" + +#: src/ch05-02-the-match-control-flow-construct.md:173 +msgid "" +"It matches! There’s no value to add to, so the program stops and returns the " +"`Option::None(())` value on the right side of `=>`." +msgstr "" +"它是匹配的!没有值可以添加,所以程序停止,并返回 `=>` 右边的 `Option::" +"None(())` 值。" + +#: src/ch05-02-the-match-control-flow-construct.md:175 +msgid "" +"Combining `match` and enums is useful in many situations. You’ll see this " +"pattern a lot in Cairo code: `match` against an enum, bind a variable to the " +"data inside, and then execute code based on it. It’s a bit tricky at first, " +"but once you get used to it, you’ll wish you had it in all languages. It’s " +"consistently a user favorite." +msgstr "" +"结合 `match` 和枚举在很多情况下都很有用。你会在 Cairo 的代码中经常看到这种模" +"式:`match` 针对一个枚举,将一个变量与里面的数据绑定,然后根据它来执行代码。" +"一开始有点棘手,但一旦你习惯了,你会希望所有语言都有这种模式。它一直是用户的" +"最爱。" + +#: src/ch05-02-the-match-control-flow-construct.md:177 +msgid "## Matches Are Exhaustive" +msgstr "## 匹配是穷尽的" + +#: src/ch05-02-the-match-control-flow-construct.md:179 +msgid "" +"There’s one other aspect of match we need to discuss: the arms’ patterns " +"must cover all possibilities. Consider this version of our `plus_one` " +"function, which has a bug and won’t compile:" +msgstr "" +"我们还需要讨论匹配的另一个方面:武器的模式必须涵盖所有的可能性。考虑一下这个" +"版本的`plus_one`函数,它有一个错误,无法编译:" + +#: src/ch05-02-the-match-control-flow-construct.md:181 +msgid "" +"```bash\n" +"$ cairo-run src/test.cairo\n" +" error: Unsupported match. Currently, matches require one arm per " +"variant,\n" +" in the order of variant definition.\n" +" --> test.cairo:34:5\n" +" match x {\n" +" ^*******^\n" +" Error: failed to compile: ./src/test.cairo\n" +"```" +msgstr "" +"```bash\n" +"$ cairo-run src/test.cairo\n" +" error: Unsupported match. Currently, matches require one arm per " +"variant,\n" +" in the order of variant definition.\n" +" --> test.cairo:34:5\n" +" match x {\n" +" ^*******^\n" +" Error: failed to compile: ./src/test.cairo\n" +"```" + +#: src/ch05-02-the-match-control-flow-construct.md:191 +msgid "" +"Cairo knows that we didn’t cover every possible case, and even knows which " +"pattern we forgot! Matches in Cairo are exhaustive: we must exhaust every " +"last possibility in order for the code to be valid. Especially in the case " +"of `Option`, when Cairo prevents us from forgetting to explicitly handle " +"the `None` case, it protects us from assuming that we have a value when we " +"might have null, thus making the billion-dollar mistake discussed earlier " +"impossible." +msgstr "" +"Cairo 知道我们没有涵盖所有可能的情况,甚至知道我们忘记了哪种模式!Cairo 中的" +"匹配是穷举性的:我们必须穷举每一种最后的可能性,这样代码才是有效的。特别是在 " +"`Option` 的情况下,当 Cairo 防止我们忘记明确处理 `None` 的情况时,它保护我" +"们不会在可能有 null 的情况下假设我们有一个值,从而使前面讨论的十亿美元的错误" +"成为可能。" + +#: src/ch05-02-the-match-control-flow-construct.md:193 +msgid "## Match 0 and the \\_ Placeholder" +msgstr "## Match 0 与 \\_ 占位符" + +#: src/ch05-02-the-match-control-flow-construct.md:195 +msgid "" +"Using enums, we can also take special actions for a few particular values, " +"but for all other values take one default action. Currently only `0` and the " +"`_`operator are supported." +msgstr "" +"使用枚举,我们也可以对一些特定的值采取特殊的操作,但对所有其他的值采取一个默" +"认的操作。目前只支持 `0` 和 `_` 操作符。" + +#: src/ch05-02-the-match-control-flow-construct.md:197 +msgid "" +"Imagine we’re implementing a game where, you get a random number between 0 " +"and 7. If you have 0, you win. For all other values you loose. Here's a " +"match that implements that logic, with the number hardcoded rather than a " +"random value." +msgstr "" +"想象一下,我们正在实现一个游戏,你得到一个 0 到 7 之间的随机数字。如果你有 " +"0,你就赢了。若是所有其他的值,你就输了。这里有一个实现该逻辑的 match,数字是" +"硬编码的,而不是随机值。" + +#: src/ch05-02-the-match-control-flow-construct.md:199 +msgid "" +"```rust\n" +"fn did_i_win(nb: felt252) {\n" +" match nb {\n" +" 0 => ('You won!').print(),\n" +" _ => ('You lost...').print(),\n" +" }\n" +"}\n" +"```" +msgstr "" +"````rust\n" +"fn did_i_win(nb: felt252) {\n" +" match nb {\n" +" 0 => ('You won!').print()、\n" +" _ => ('You lost...').print()、\n" +" }\n" +"}\n" +"```" + +#: src/ch05-02-the-match-control-flow-construct.md:208 +msgid "" +"The first arm, the pattern is the literal values 0. For the last arm that " +"covers every other possible value, the pattern is the character `_`. This " +"code compiles, even though we haven’t listed all the possible values a " +"`felt252` can have, because the last pattern will match all values not " +"specifically listed. This catch-all pattern meets the requirement that " +"`match` must be exhaustive. Note that we have to put the catch-all arm last " +"because the patterns are evaluated in order. If we put the catch-all arm " +"earlier, the other arms would never run, so Cairo will warn us if we add " +"arms after a catch-all!" +msgstr "" +"第一条分支,模式是字面值 0。对于涵盖了所有其他可能的值的最后一条分支,其模式" +"是字符 `_`。尽管我们没有列出 `felt252` 可能具有的所有值,但这段代码仍然可以编" +"译,因为最后一个模式将匹配所有没有特别列出的值。这个通配模式满足了 `match` 必" +"须被穷尽的要求。请注意,我们必须把通配分支放在最后,因为模式是按顺序评估的。" +"如果我们把通配分支放在前面,其他的分支就不会运行,所以如果我们在通配分支之后" +"添加分支,Cairo 会警告我们!" + +#: src/ch05-02-the-match-control-flow-construct.md:210 +msgid "" +"" +msgstr "<!-- TODO:可能需要将本章的结尾与模式和匹配章节联系起来-->" + +#: src/ch06-00-managing-cairo-projects-with-packages-crates-and-modules.md:1 +msgid "# Managing Cairo Projects with Packages, Crates and Modules" +msgstr "# 使用包、Crate 和模块管理Cairo项目" + +#: src/ch06-00-managing-cairo-projects-with-packages-crates-and-modules.md:3 +msgid "" +"As you write large programs, organizing your code will become increasingly\n" +"important. By grouping related functionality and separating code with " +"distinct\n" +"features, you’ll clarify where to find code that implements a particular\n" +"feature and where to go to change how a feature works." +msgstr "" +"当你编写大型程序时,组织你的代码将变得越来越重要。\n" +"通过对相关的功能进行分组,并将具有不同功能的代码分开,你就可以清楚地知道在哪" +"里可以找到实现某一特定的代码,以及到哪里去改变一个功能的工作方式。" + +#: src/ch06-00-managing-cairo-projects-with-packages-crates-and-modules.md:8 +msgid "" +"The programs we’ve written so far have been in one module in one file. As a\n" +"project grows, you should organize code by splitting it into multiple " +"modules\n" +"and then multiple files. As a package grows, you can extract parts into\n" +"separate crates that become external dependencies. This chapter covers all\n" +"these techniques." +msgstr "" +"到目前为止,我们所写的程序都是在一个文件中的一个模块中。\n" +"伴随着项目的增长,你应该通过将代码分解为多个模块和多个文件来组织代码。\n" +"伴随着包的增长,你可以将包中的部分代码提取出来,做成独立的 crate,这些 crate " +"则作为外部依赖项。\n" +"本章将会涵盖所有这些概念。" + +#: src/ch06-00-managing-cairo-projects-with-packages-crates-and-modules.md:14 +msgid "" +"We’ll also discuss encapsulating implementation details, which lets you " +"reuse\n" +"code at a higher level: once you’ve implemented an operation, other code " +"can\n" +"call your code without having to know how the\n" +"implementation works." +msgstr "" +"我们也会讨论封装来实现细节,这可以使你更高级地重用代码:你实现了一个操作后," +"其他的代码可以通过该代码的公共接口来进行调用,而不需要知道它是如何实现的。" + +#: src/ch06-00-managing-cairo-projects-with-packages-crates-and-modules.md:19 +msgid "" +"A related concept is scope: the nested context in which code is written has " +"a\n" +"set of names that are defined as “in scope.” When reading, writing, and\n" +"compiling code, programmers and compilers need to know whether a particular\n" +"name at a particular spot refers to a variable, function, struct, enum, " +"module,\n" +"constant, or other item and what that item means. You can create scopes and\n" +"change which names are in or out of scope. You can’t have two items with " +"the\n" +"same name in the same scope." +msgstr "" +"这里有一个需要说明的概念 “作用域(scope)”:代码所在的嵌套上下文有一组定义为 " +"“in scope” 的名称。当阅读、编写和编译代码时,程序员和编译器需要知道特定位置的" +"特定名称是否引用了变量、函数、结构体、枚举、模块、常量或者其他有意义的项。你" +"可以创建作用域,以及改变哪些名称在作用域内还是作用域外。同一个作用域内不能拥" +"有两个相同名称的项。" + +#: src/ch06-00-managing-cairo-projects-with-packages-crates-and-modules.md:27 +msgid "" +"Cairo has a number of features that allow you to manage your code’s\n" +"organization. These features, sometimes\n" +"collectively referred to as the _module system_, include:" +msgstr "" +"Cairo有许多功能可以让你管理代码的组织。这些功能。这有时被称为 “模块系统(the " +"module system)”,包括:" + +#: src/ch06-00-managing-cairo-projects-with-packages-crates-and-modules.md:31 +msgid "" +"- **Packages:** A Scarb feature that lets you build, test, and share crates\n" +"- **Crates:** A tree of modules that corresponds to a single compilation " +"unit.\n" +" It has a root directory, and a root module defined at the file `lib.cairo` " +"under this directory.\n" +"- **Modules** and **use:** Let you control the organization and scope of " +"items.\n" +"- **Paths:** A way of naming an item, such as a struct, function, or module" +msgstr "" +"- **Packages:** Scarb的一个功能,可以让你建立、测试和分享crates。\n" +"- **Crates:** 一个模块的树形结构,对应于一个单一的编译单元。\n" +" 它有一个根目录,并在该目录下的`lib.cairo`文件中定义了一个根模块。\n" +"- **Modules** 和 **use:** 允许你控制组织结构和作用域。\n" +"- **Paths:** 一个命名例如结构体、函数或模块等项的方式" + +#: src/ch06-00-managing-cairo-projects-with-packages-crates-and-modules.md:37 +msgid "" +"In this chapter, we’ll cover all these features, discuss how they interact, " +"and\n" +"explain how to use them to manage scope. By the end, you should have a " +"solid\n" +"understanding of the module system and be able to work with scopes like a " +"pro!" +msgstr "" +"在这一章中,我们将介绍所有这些特性,讨论它们如何相互作用,以及解释如何使用它" +"们来管理作用域。到最后,你应该对模块系统有一个扎实的理解,并且能够像专家一样" +"使用作用域了!" + +#: src/ch06-01-packages-and-crates.md:1 +msgid "# Packages and Crates" +msgstr "# 包和 Crate" + +#: src/ch06-01-packages-and-crates.md:3 +msgid "## What is a crate?" +msgstr "## 什么是crate?" + +#: src/ch06-01-packages-and-crates.md:4 +msgid "" +"A crate is the smallest amount of code that the Cairo compiler considers at " +"a time. Even if you run `cairo-compile` rather than `scarb build` and pass a " +"single source code file, the compiler considers that file to be a crate. " +"Crates can contain modules, and the modules may be defined in other files " +"that get compiled with the crate, as will be discussed in the subsequent " +"sections." +msgstr "" +"Crate是Cairo在编译时最小的代码单位。即使你运行 `cairo-compile` 而不是 `scarb " +"build` 并传递一个源代码文件,编译器还是会将那个文件认作一个 crate。Crate可以" +"包含模块,这些模块可以在其他文件中定义,并与Crate一起被编译,这将在后面的章节" +"中讨论。" + +#: src/ch06-01-packages-and-crates.md:6 +msgid "## What is the crate root?" +msgstr "## 什么是crate root?" + +#: src/ch06-01-packages-and-crates.md:7 +msgid "" +"The crate root is the `lib.cairo` source file that the Cairo compiler starts " +"from and makes up the root module of your crate (we’ll explain modules in " +"depth in the [“Defining Modules to Control Scope”](./ch06-02-defining-" +"modules-to-control-scope.md) section)." +msgstr "" +"Crate root根是`lib.cairo`源文件,Cairo编译器从该文件开始,并构成你的crate的根" +"模块(我们将在[“定义模块来控制作用域”](./ch06-02-defining-modules-to-control-" +"scope.md)部分深入解释模块)。" + +#: src/ch06-01-packages-and-crates.md:9 +msgid "## What is a package?" +msgstr "## 什么是包?" + +#: src/ch06-01-packages-and-crates.md:10 +msgid "" +"A cairo package is a bundle of one or more crates with a Scarb.toml file " +"that describes how to build those crates. This enables the splitting of code " +"into smaller, reusable parts and facilitates more structured dependency " +"management." +msgstr "" +"一个cairo包是一个由一个或多个crate组成的集合,其中的Scarb.toml文件描述如何构" +"建这些板块。这使得代码被分割成更小的、可重复使用的部分,并有利于更有条理的依" +"赖管理。" + +#: src/ch06-01-packages-and-crates.md:12 +msgid "## Creating a Package with Scarb" +msgstr "## 用Scarb创建一个包" + +#: src/ch06-01-packages-and-crates.md:14 +msgid "" +"You can create a new Cairo package using the scarb command-line tool. To " +"create a new package, run the following command:" +msgstr "" +"你可以使用scarb命令行工具创建一个新的Cairo包。要创建一个新的软件包,运行以下" +"命令:" + +#: src/ch06-01-packages-and-crates.md:16 +msgid "" +"```bash\n" +"scarb new my_package\n" +"```" +msgstr "" +"```bash\n" +"scarb new my_package\n" +"```" + +#: src/ch06-01-packages-and-crates.md:20 +msgid "" +"This command will generate a new package directory named `my_package` with " +"the following structure:" +msgstr "该命令将生成一个名为`my_package`的新软件包目录,其结构如下:" + +#: src/ch06-01-packages-and-crates.md:22 +msgid "" +"```\n" +"my_package/\n" +"├── Scarb.toml\n" +"└── src\n" +" └── lib.cairo\n" +"```" +msgstr "" +"```\n" +"my_package/\n" +"├── Scarb.toml\n" +"└── src\n" +" └── lib.cairo\n" +"```" + +#: src/ch06-01-packages-and-crates.md:29 +msgid "" +"- `src/` is the main directory where all the Cairo source files for the " +"package will be stored.\n" +"- `lib.cairo` is the default root module of the crate, which is also the " +"main entry point of the package. By default, it is empty.\n" +"- `Scarb.toml` is the package manifest file, which contains metadata and " +"configuration options for the package, such as dependencies, package name, " +"version, and authors. You can find documentation about it on the [scarb " +"reference](https://docs.swmansion.com/scarb/docs/reference/manifest)." +msgstr "" +"- `src/`是主目录,包的所有Cairo源文件将存放在这里。\n" +"- `lib.cairo`是crate的默认根模块,也是包的主要入口点。默认情况下,它是空" +"的。\n" +"- `Scarb.toml`是包清单文件,它包含包的元数据和配置选项,如依赖关系、包名称、" +"版本和作者。你可以在[scarb reference](https://docs.swmansion.com/scarb/docs/" +"reference/manifest)上找到关于它的文档。" + +#: src/ch06-01-packages-and-crates.md:33 +msgid "" +"```toml\n" +"[package]\n" +"name = \"my_package\"\n" +"version = \"0.1.0\"\n" +"\n" +"[dependencies]\n" +"# foo = { path = \"vendor/foo\" }\n" +"```" +msgstr "" +"```toml\n" +"[package]\n" +"name = \"my_package\"\n" +"version = \"0.1.0\"\n" +"\n" +"[dependencies]\n" +"# foo = { path = \"vendor/foo\" }\n" +"```" + +#: src/ch06-01-packages-and-crates.md:42 +msgid "" +"As you develop your package, you may want to organize your code into " +"multiple Cairo source files. You can do this by creating additional `.cairo` " +"files within the `src` directory or its subdirectories." +msgstr "" +"当你开发你的包时,你可能想把你的代码组织成多个Cairo源文件。你可以通过在`src`" +"目录或其子目录下创建额外的`.cairo`文件来做到这一点。" + +#: src/ch06-02-defining-modules-to-control-scope.md:1 +msgid "## Defining Modules to Control Scope" +msgstr "## 定义模块以控制作用域" + +#: src/ch06-02-defining-modules-to-control-scope.md:3 +msgid "" +"In this section, we’ll talk about modules and other parts of the module " +"system,\n" +"namely _paths_ that allow you to name items and the `use` keyword that " +"brings a\n" +"path into scope." +msgstr "" +"在本节,我们将讨论模块和其它一些关于模块系统的部分,如允许你命名项的 路径" +"(_paths_);用来将路径引入作用域的`use`关键字。" + +#: src/ch06-02-defining-modules-to-control-scope.md:7 +msgid "" +"First, we’re going to start with a list of rules for easy reference when " +"you’re\n" +"organizing your code in the future. Then we’ll explain each of the rules in\n" +"detail." +msgstr "" +"首先,我们将从一系列的规则开始,在你未来组织代码的时候,这些规则可被用作简单" +"的参考。接下来我们将会详细的解释每条规则。" + +#: src/ch06-02-defining-modules-to-control-scope.md:11 +msgid "### Modules Cheat Sheet" +msgstr "### 模块小抄" + +#: src/ch06-02-defining-modules-to-control-scope.md:13 +msgid "" +"Here we provide a quick reference on how modules, paths and the `use` " +"keyword\n" +"work in the compiler, and how most developers organize their\n" +"code. We’ll be going through examples of each of these rules throughout " +"this\n" +"chapter, but this is a great place to refer to as a reminder of how modules\n" +"work. You can create a new Scarb project with `scarb new backyard` to follow " +"along." +msgstr "" +"这里我们提供一个简单的参考,用来解释模块、路径、 `use`关键词如何在编译器中工" +"作,以及大部分开发者如何组织他们的代码。我们将在本章节中举例说明每条规则,不" +"过这是一个解释模块工作方式的良好参考。你可以用`scarb new backyard`创建一个新" +"的Scarb项目来跟随。" + +#: src/ch06-02-defining-modules-to-control-scope.md:19 +msgid "" +"- **Start from the crate root**: When compiling a crate, the compiler first\n" +" looks in the crate root file (_src/lib.cairo_) for code to compile.\n" +"- **Declaring modules**: In the crate root file, you can declare new " +"modules;\n" +" say, you declare a “garden” module with `mod garden;`. The compiler will " +"look\n" +" for the module’s code in these places:\n" +"\n" +" - Inline, within curly brackets that replace the semicolon following `mod " +"garden;`.\n" +"\n" +" ```rust\n" +" // crate root file (lib.cairo)\n" +" mod garden {\n" +" // code defining the garden module goes here\n" +" }\n" +" ```\n" +"\n" +"- In the file _src/garden.cairo_\n" +"- **Declaring submodules**: In any file other than the crate root, you can\n" +" declare submodules. For example, you might declare `mod vegetables;` in\n" +" _src/garden.cairo_. The compiler will look for the submodule’s code within " +"the\n" +" directory named for the parent module in these places:\n" +"\n" +" - Inline, directly following `mod vegetables`, within curly brackets " +"instead\n" +" of the semicolon.\n" +"\n" +" ```rust\n" +" // src/garden.cairo file\n" +" mod vegetables {\n" +" // code defining the vegetables submodule goes here\n" +" }\n" +" ```\n" +"\n" +" - In the file _src/garden/vegetables.cairo_\n" +"\n" +"- **Paths to code in modules**: Once a module is part of your crate, you " +"can\n" +" refer to code in that module from anywhere else in that same crate, using " +"the path\n" +" to the code. For example, an `Asparagus` type in the garden vegetables " +"module would be found at\n" +" `backyard::garden::vegetables::Asparagus`.\n" +"- **The `use` keyword**: Within a scope, the `use` keyword creates shortcuts " +"to\n" +" items to reduce repetition of long paths. In any scope that can refer to\n" +" `backyard::garden::vegetables::Asparagus`, you can create a shortcut with\n" +" `use backyard::garden::vegetables::Asparagus;` and from then on you only " +"need to\n" +" write `Asparagus` to make use of that type in the scope." +msgstr "" +"- **从 crate 根节点开始**:当编译一个 crate, 编译器首先在 crate 根文件(_src/" +"lib.cairo_)中寻找要编译的代码。\n" +"- **声明模块:**:在 crate 根文件中,你可以声明新的模块;\n" +" 例如,你用`mod garden;`声明一个 “garden”模块。编译器会在下列路径中寻找模块" +"代码:\n" +"\n" +" - 内联,在大括号中,当`mod garden`后方不是一个分号而是一个大括号\n" +"\n" +" ```rust\n" +" // crate root file (lib.cairo)\n" +" mod garden {\n" +" // code defining the garden module goes here\n" +" }\n" +" ```\n" +"\n" +"- 在文件 _src/garden.cairo_ 中\n" +"- **声明子模块**:在除了 crate 根节点以外的其他文件中,你可以定义子模块。例" +"如,你可以在以下文件中声明 `mod vegetables;`。\n" +" _src/garden.cairo_ 。编译器会在以父模块命名的目录中寻找子模块代码: \n" +"\n" +" - 内联,直接跟在`mod vegetables`后面,用大括号代替分号\n" +"\n" +" ```rust\n" +" // src/garden.cairo file\n" +" mod vegetables {\n" +" // code defining the vegetables submodule goes here\n" +" }\n" +" ```\n" +"\n" +" - 在文件 _src/garden/vegetables.cairo_ 中\n" +"\n" +"- **模块中的代码路径**:一旦一个模块是你 crate 的一部分,你可以在隐私规则允许" +"的前提下,从同一个 crate 内的任意地方,通过代码路径引用该模块的代码。举例而" +"言,一个 garden vegetables 模块下的`Asparagus`类型可以在`backyard::garden::" +"vegetables::Asparagus`被找到。\n" +"- **`use`关键字**:在一个作用域内,`use`关键字创建了一个成员的快捷方式,用来" +"减少长路径的重复。在任何可以引用`backyard::garden::vegetables::Asparagus`的作" +"用域,你可以通过 `use backyard::garden::vegetables::Asparagus;`创建一个快捷方" +"式,然后你就可以在作用域中只写`Asparagus`来使用该类型。" + +#: src/ch06-02-defining-modules-to-control-scope.md:62 +msgid "" +"Here we create a crate named `backyard` that illustrates these rules. The\n" +"crate’s directory, also named `backyard`, contains these files and " +"directories:" +msgstr "" +"这里我们创建一个名为`backyard`的crate 来说明这些规则。该 crate 的路径同样命名" +"为`backyard`,该路径包含了这些文件和目录:" + +#: src/ch06-02-defining-modules-to-control-scope.md:65 +msgid "" +"```text\n" +"backyard/\n" +"├── Scarb.toml\n" +"├── cairo_project.toml\n" +"└── src\n" +" ├── garden\n" +" │   └── vegetables.cairo\n" +" ├── garden.cairo\n" +" └── lib.cairo\n" +"```" +msgstr "" +"```text\n" +"backyard/\n" +"├── Scarb.toml\n" +"├── cairo_project.toml\n" +"└── src\n" +" ├── garden\n" +" │   └── vegetables.cairo\n" +" ├── garden.cairo\n" +" └── lib.cairo\n" +"```" + +#: src/ch06-02-defining-modules-to-control-scope.md:76 +msgid "" +"> Note: You will notice here a `cairo_project.toml` file.\n" +"> This is the configuration file for \"vanilla\" Cairo projects (i.e. not " +"managed by Scarb),\n" +"> which is required to run the `cairo-run .` command to run the code of the " +"crate.\n" +"> It is required until Scarb implements this feature. The content of the " +"file is:\n" +">\n" +"> ```toml\n" +"> [crate_roots]\n" +"> backyard = \"src\"\n" +"> ```\n" +">\n" +"> and indicates that the crate named \"backyard\" is located in the `src` " +"directory." +msgstr "" +"> 注意:你会注意到这里有一个`cairo_project.toml`文件。\n" +"> 这是 通常的Cairo项目的配置文件(即不由Scarb管理)、\n" +"> 这是运行`cairo-run .`命令来运行crate的代码所需要的。\n" +"> 在Scarb实现这一功能之前,它是必需的。该文件的内容是:\n" +">\n" +"> ```toml\n" +"> [crate_roots]\n" +"> backyard = “src”\n" +"> ```\n" +">\n" +"> 它表示名为 \"backyard \"的板块位于`src`目录下。" + +#: src/ch06-02-defining-modules-to-control-scope.md:88 +msgid "The crate root file in this case is _src/lib.cairo_, and it contains:" +msgstr "在这种情况下,crate根文件是 _src/lib.cairo_ ,它包含:" + +#: src/ch06-02-defining-modules-to-control-scope.md:92 +msgid "" +"```rust,does_not_compile\n" +"use garden::vegetables::Asparagus;\n" +"\n" +"mod garden;\n" +"\n" +"fn main(){\n" +" let Asparagus = Asparagus{};\n" +"}\n" +"\n" +"\n" +"```" +msgstr "" +"```rust,does_not_compile\n" +"use garden::vegetables::Asparagus;\n" +"\n" +"mod garden;\n" +"\n" +"fn main(){\n" +" let Asparagus = Asparagus{};\n" +"}\n" +"\n" +"\n" +"```" + +#: src/ch06-02-defining-modules-to-control-scope.md:104 +msgid "" +"The `mod garden;` line tells the compiler to include the code it finds in " +"_src/garden.cairo_, which is:" +msgstr "`mod garden;`行告诉编译器包括它在 _src/garden.cairo_ 中发现的代码是:" + +#: src/ch06-02-defining-modules-to-control-scope.md:106 +msgid "Filename: src/garden.cairo" +msgstr "文件名: src/garden.cairo" + +#: src/ch06-02-defining-modules-to-control-scope.md:108 +msgid "" +"```rust\n" +"mod vegetables;\n" +"```" +msgstr "" +"```rust\n" +"mod vegetables;\n" +"```" + +#: src/ch06-02-defining-modules-to-control-scope.md:112 +msgid "" +"Here, `mod vegetables;` means the code in _src/garden/vegetables.cairo_ is\n" +"included too. That code is:" +msgstr "" +"这里,`mod vegetables;`意味着 _src/garden/vegetables.cairo_ 中的代码也被包括" +"在内。这段代码是:" + +#: src/ch06-02-defining-modules-to-control-scope.md:115 +msgid "" +"```rust\n" +"#[derive(Copy,Drop)]\n" +"struct Asparagus{}\n" +"```" +msgstr "" +"```rust\n" +"#[derive(Copy,Drop)]\n" +"struct Asparagus{}\n" +"```" + +#: src/ch06-02-defining-modules-to-control-scope.md:120 +msgid "" +"The line `use garden::vegetables::Asparagus;` lets us use bring the " +"`Asparagus` type into scope,\n" +"so we can use it in the `main` function." +msgstr "" +"这行`use garden::vecants::Asparagus;`让我们把`Asparagus`类型带入作用域、所以" +"我们可以在`main`函数中使用它。" + +#: src/ch06-02-defining-modules-to-control-scope.md:123 +msgid "" +"Now let’s get into the details of these rules and demonstrate them in action!" +msgstr "现在让我们深入了解这些规则的细节并在实际中演示它们!" + +#: src/ch06-02-defining-modules-to-control-scope.md:125 +msgid "### Grouping Related Code in Modules" +msgstr "### 在模块中对相关代码进行分组" + +#: src/ch06-02-defining-modules-to-control-scope.md:127 +msgid "" +"_Modules_ let us organize code within a crate for readability and easy " +"reuse.\n" +"As an example, let’s write a library crate that provides the functionality " +"of a\n" +"restaurant. We’ll define the signatures of functions but leave their bodies\n" +"empty to concentrate on the organization of the code, rather than the\n" +"implementation of a restaurant." +msgstr "" +"_模块_ 让我们可以将一个 crate 中的代码进行分组,以提高可读性与重用性。\n" +"作为一个例子,让我们写一个crate,提供一个餐馆的机能。我们将定义函数的签名,但" +"将其主体留空,以专注于代码的组织,而不是餐馆的实现。" + +#: src/ch06-02-defining-modules-to-control-scope.md:133 +msgid "" +"In the restaurant industry, some parts of a restaurant are referred to as\n" +"_front of house_ and others as _back of house_. Front of house is where\n" +"customers are; this encompasses where the hosts seat customers, servers " +"take\n" +"orders and payment, and bartenders make drinks. Back of house is where the\n" +"chefs and cooks work in the kitchen, dishwashers clean up, and managers do\n" +"administrative work." +msgstr "" +"在餐饮业,餐馆中会有一些地方被称之为 前台(_front of house_),还有另外一些地" +"方被称之为 后台(_back of house_)。\n" +"前台是招待顾客的地方,在这里,店主可以为顾客安排座位,服务员接受顾客下单和付" +"款,调酒师会制作饮品。\n" +"后台则是由厨师工作的厨房,洗碗工的工作地点,以及经理做行政工作的地方组成。" + +#: src/ch06-02-defining-modules-to-control-scope.md:140 +msgid "" +"To structure our crate in this way, we can organize its functions into " +"nested\n" +"modules. Create a new package named `restaurant` by running `scarb new " +"restaurant`; then enter the code in Listing 6-1 into _src/lib.cairo_ to\n" +"define some modules and function signatures. Here’s the front of house " +"section:" +msgstr "" +"我们可以将函数放置到嵌套的模块中,来使我们的 crate 结构与实际的餐厅结构相" +"同。\n" +"通过运行 `scarb new restaurant`创建一个名为 `restaurant`的新包;然后将清单6-1" +"中的代码输入 _src/lib.cairo_ ,以定义一些模块和函数签名。这里是前台的部分:" + +#: src/ch06-02-defining-modules-to-control-scope.md:146 +msgid "" +"```rust\n" +"mod front_of_house {\n" +" mod hosting {\n" +" fn add_to_waitlist() {}\n" +"\n" +" fn seat_at_table() {}\n" +" }\n" +"\n" +" mod serving {\n" +" fn take_order() {}\n" +"\n" +" fn serve_order() {}\n" +"\n" +" fn take_payment() {}\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"mod front_of_house {\n" +" mod hosting {\n" +" fn add_to_waitlist() {}\n" +"\n" +" fn seat_at_table() {}\n" +" }\n" +"\n" +" mod serving {\n" +" fn take_order() {}\n" +"\n" +" fn serve_order() {}\n" +"\n" +" fn take_payment() {}\n" +" }\n" +"}\n" +"```" + +#: src/ch06-02-defining-modules-to-control-scope.md:164 +msgid "" +"Listing 6-1: A `front_of_house` module containing " +"other\n" +"modules that then contain functions" +msgstr "" +"清单6-1:一个 `front_of_house`模块包含其他的模块,而" +"这些模块又包含了函数" + +#: src/ch06-02-defining-modules-to-control-scope.md:167 +msgid "" +"We define a module with the `mod` keyword followed by the name of the " +"module\n" +"(in this case, `front_of_house`). The body of the module then goes inside " +"curly\n" +"brackets. Inside modules, we can place other modules, as in this case with " +"the\n" +"modules `hosting` and `serving`. Modules can also hold definitions for " +"other\n" +"items, such as structs, enums, constants, traits, and—as in Listing\n" +"6-1—functions." +msgstr "" +"我们定义一个模块,是以 `mod`关键字为起始,然后指定模块的名字(本例中叫做 " +"`front_of_house`),并且用花括号包围模块的主体。在模块内,我们还可以定义其他" +"的模块,就像本例中的 `hosting` 和 `serving` 模块。模块还可以保存一些定义的其" +"他项,比如结构体、枚举、常量、特性、以及列表中6-1中展示的函数。" + +#: src/ch06-02-defining-modules-to-control-scope.md:174 +msgid "" +"By using modules, we can group related definitions together and name why\n" +"they’re related. Programmers using this code can navigate the code based on " +"the\n" +"groups rather than having to read through all the definitions, making it " +"easier\n" +"to find the definitions relevant to them. Programmers adding new " +"functionality\n" +"to this code would know where to place the code to keep the program " +"organized." +msgstr "" +"通过使用模块,我们可以将相关的定义分组到一起,并指出他们为什么相关。程序员可" +"以通过使用这段代码,更加容易地找到他们想要的定义,因为他们可以基于分组来对代" +"码进行导航,而不需要阅读所有的定义。\n" +"程序员向这段代码中添加一个新的功能时,他们也会知道代码应该放置在何处,可以保" +"持程序的组织性。" + +#: src/ch06-02-defining-modules-to-control-scope.md:180 +msgid "" +"Earlier, we mentioned that _src/lib.cairo_ is called the crate\n" +"root. The reason for this name is that the content of this file form a " +"module named after the crate name at the root of the crate’s module " +"structure,\n" +"known as the _module tree_." +msgstr "" +"在前面我们提到了,_src/lib.cairo_ 叫做 crate 根。之所以这样叫它是因为这个文" +"件的内容在 crate 模块结构的根组成了一个名为 crate 的模块,该结构被称为 模块树" +"( _module tree_ )。" + +#: src/ch06-02-defining-modules-to-control-scope.md:184 +msgid "Listing 6-2 shows the module tree for the structure in Listing 6-1." +msgstr "清单6-2显示了清单6-1中结构的模块树。" + +#: src/ch06-02-defining-modules-to-control-scope.md:186 +msgid "" +"```text\n" +"restaurant\n" +" └── front_of_house\n" +" ├── hosting\n" +" │ ├── add_to_waitlist\n" +" │ └── seat_at_table\n" +" └── serving\n" +" ├── take_order\n" +" ├── serve_order\n" +" └── take_payment\n" +"```" +msgstr "" +"```text\n" +"restaurant\n" +" └── front_of_house\n" +" ├── hosting\n" +" │ ├── add_to_waitlist\n" +" │ └── seat_at_table\n" +" └── serving\n" +" ├── take_order\n" +" ├── serve_order\n" +" └── take_payment\n" +"```" + +#: src/ch06-02-defining-modules-to-control-scope.md:198 +msgid "" +"Listing 6-2: The module tree for the code in " +"Listing\n" +"6-1" +msgstr "清单6-2:清单6-1中代码的模块树" + +#: src/ch06-02-defining-modules-to-control-scope.md:201 +msgid "" +"This tree shows how some of the modules nest inside one another; for " +"example,\n" +"`hosting` nests inside `front_of_house`. The tree also shows that some " +"modules\n" +"are _siblings_ to each other, meaning they’re defined in the same module;\n" +"`hosting` and `serving` are siblings defined within `front_of_house`. If " +"module\n" +"A is contained inside module B, we say that module A is the _child_ of " +"module B\n" +"and that module B is the _parent_ of module A. Notice that the entire " +"module\n" +"tree is rooted under the explicit name of the crate `restaurant`." +msgstr "" +"这个树展示了一些模块是如何被嵌入到另一个模块的(例如,`hosting` 嵌套在 " +"`front_of_house` 中)。这个树还展示了一些模块是互为 兄弟( _siblings_ )的," +"这意味着它们定义在同一模块中( `hosting` 和 `serving` 被一起定义在 " +"_front_of_house_ 中)。继续沿用家庭关系的比喻,如果一个模块 A 被包含在模块 B " +"中,我们将模块 A 称为模块 B 的 子( _child_ ),模块 B 则是模块 A 的 父" +"( _parent_ )。注意,整个模块树都植根于名为 `restaurant` crate的隐式模块下。" + +#: src/ch06-02-defining-modules-to-control-scope.md:209 +msgid "" +"The module tree might remind you of the filesystem’s directory tree on your\n" +"computer; this is a very apt comparison! Just like directories in a " +"filesystem,\n" +"you use modules to organize your code. And just like files in a directory, " +"we\n" +"need a way to find our modules." +msgstr "" +"这个模块树可能会令你想起电脑上文件系统的目录树;这是一个非常恰当的类比!就像" +"文件系统的目录,你可以使用模块来组织你的代码。并且,就像目录中的文件,我们需" +"要一种方法来找到模块。" + +#: src/ch06-03-paths-for-referring-to-an-item-in-the-module-tree.md:1 +msgid "## Paths for Referring to an Item in the Module Tree" +msgstr "## 引用模块项目的路径" + +#: src/ch06-03-paths-for-referring-to-an-item-in-the-module-tree.md:3 +msgid "" +"To show Cairo where to find an item in a module tree, we use a path in the " +"same way we use a path when navigating a filesystem. To call a function, we " +"need to know its path." +msgstr "" +"为了告诉Cairo如何在模块树中找到一个项目,我们使用路径的方式,就像在文件系统使" +"用路径一样。为了调用一个函数,我们需要知道它的路径。" + +#: src/ch06-03-paths-for-referring-to-an-item-in-the-module-tree.md:5 +msgid "A path can take two forms:" +msgstr "路径可以有两种形式:" + +#: src/ch06-03-paths-for-referring-to-an-item-in-the-module-tree.md:7 +msgid "" +"- An _absolute path_ is the full path starting from a crate root. The " +"absolute path begins with the crate name.\n" +"- A _relative path_ starts from the current module.\n" +"\n" +" Both absolute and relative paths are followed by one or more identifiers\n" +" separated by double colons (`::`)." +msgstr "" +"- 绝对路径( _absolute path_ )是以 crate 根(root)开头的全路径。绝对路径以 " +"crate 名开头。\n" +"- 相对路径( _relative path_ )是从当前模块开始的。\n" +"\n" +"绝对路径和相对路径后面都有一个或多个标识符用双冒号(`::`)分开。" + +#: src/ch06-03-paths-for-referring-to-an-item-in-the-module-tree.md:13 +msgid "" +"To illustrate this notion let's take back our example Listing 6-1 for the " +"restaurant we used in the last chapter. We have a crate named `restaurant` " +"in which we have a module named `front_of_house` that contains a module " +"named `hosting`. The `hosting` module contains a function named " +"`add_to_waitlist`. We want to call the `add_to_waitlist` function from the " +"`eat_at_restaurant` function. We need to tell Cairo the path to the " +"`add_to_waitlist` function so it can find it." +msgstr "" +"为了说明这个概念,让我们回到我们在上一章使用的餐厅的例子清单6-1。我们有一个名" +"为 `restaurant`的crate,其中有一个名为`front_of_house`的模块,包含一个名为 " +"`hosting`的模块。`hosting`模块包含一个名为 `add_to_waitlist`的函数。我们想从" +"`eat_at_restaurant`函数中调用`add_to_waitlist`函数。我们需要告诉Cairo " +"`add_to_waitlist`函数的路径,以便它能找到它。" + +#: src/ch06-03-paths-for-referring-to-an-item-in-the-module-tree.md:17 +msgid "" +"```rust\n" +"mod front_of_house {\n" +" mod hosting {\n" +" fn add_to_waitlist() {}\n" +"\n" +" fn seat_at_table() {}\n" +" }\n" +"\n" +" mod serving {\n" +" fn take_order() {}\n" +"\n" +" fn serve_order() {}\n" +"\n" +" fn take_payment() {}\n" +" }\n" +"}\n" +"\n" +"\n" +"pub fn eat_at_restaurant() {\n" +" // Absolute path\n" +" restaurant::front_of_house::hosting::add_to_waitlist(); // ✅ Compiles\n" +"\n" +" // Relative path\n" +" front_of_house::hosting::add_to_waitlist(); // ✅ Compiles\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"mod front_of_house {\n" +" mod hosting {\n" +" fn add_to_waitlist() {}\n" +"\n" +" fn seat_at_table() {}\n" +" }\n" +"\n" +" mod serving {\n" +" fn take_order() {}\n" +"\n" +" fn serve_order() {}\n" +"\n" +" fn take_payment() {}\n" +" }\n" +"}\n" +"\n" +"\n" +"pub fn eat_at_restaurant() {\n" +" // Absolute path\n" +" restaurant::front_of_house::hosting::add_to_waitlist(); // ✅ Compiles\n" +"\n" +" // Relative path\n" +" front_of_house::hosting::add_to_waitlist(); // ✅ Compiles\n" +"}\n" +"```" + +#: src/ch06-03-paths-for-referring-to-an-item-in-the-module-tree.md:44 +msgid "" +"Listing 6-3: Calling the `add_to_waitlist` function " +"using absolute and relative paths" +msgstr "" +"清单6-3:使用绝对和相对路径调用`add_to_waitlist`函数" +"" + +#: src/ch06-03-paths-for-referring-to-an-item-in-the-module-tree.md:46 +msgid "" +"The first time we call the `add_to_waitlist` function in " +"`eat_at_restaurant`,\n" +"we use an absolute path. The `add_to_waitlist` function is defined in the " +"same\n" +"crate as `eat_at_restaurant`. In Cairo, absolute paths start from the crate " +"root, which you need to refer to by using the crate name." +msgstr "" +"我们第一次调用`eat_at_restaurant`中的`add_to_waitlist`函数时、使用了一个绝对" +"路径。`add_to_waitlist`函数与`eat_at_restaurant`定义在同一个crate中。在Cairo" +"中,绝对路径从crate根开始,你需要用crate的名字来引用它。" + +#: src/ch06-03-paths-for-referring-to-an-item-in-the-module-tree.md:50 +msgid "" +"The second time we call `add_to_waitlist`, we use a relative path. The path " +"starts with `front_of_house`, the name of the module\n" +"defined at the same level of the module tree as `eat_at_restaurant`. Here " +"the\n" +"filesystem equivalent would be using the path\n" +"`./front_of_house/hosting/add_to_waitlist`. Starting with a module name " +"means\n" +"that the path is relative to the current module." +msgstr "" +"第二次我们调用 add_to_waitlist时,使用的是相对路径。这个路径以 " +"`front_of_house` 为起始,这个模块在模块树中,与 `eat_at_restaurant` 定义在同" +"一层级。\n" +"与之等价的文件系统路径就是 `./front_of_house/hosting/add_to_waitlist`。以模块" +"名开头意味着该路径是相对路径。" + +#: src/ch06-03-paths-for-referring-to-an-item-in-the-module-tree.md:56 +msgid "### Starting Relative Paths with `super`" +msgstr "### 使用 `super` 起始的相对路径" + +#: src/ch06-03-paths-for-referring-to-an-item-in-the-module-tree.md:58 +msgid "" +"Choosing whether to use a `super` or not is a decision you’ll make\n" +"based on your project, and depends on whether you’re more likely to move " +"item\n" +"definition code separately from or together with the code that uses the item." +msgstr "" +"选择是否使用 `super`将根据你的项目具体情况来决定。\n" +"并取决于你是否更有可能将项目定义的代码是与使用该项目的代码分开还是放在一起。" + +#: src/ch06-03-paths-for-referring-to-an-item-in-the-module-tree.md:64 +msgid "" +"```rust\n" +"fn deliver_order() {}\n" +"\n" +"mod back_of_house {\n" +" fn fix_incorrect_order() {\n" +" cook_order();\n" +" super::deliver_order();\n" +" }\n" +"\n" +" fn cook_order() {}\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"fn deliver_order() {}\n" +"\n" +"mod back_of_house {\n" +" fn fix_incorrect_order() {\n" +" cook_order();\n" +" super::deliver_order();\n" +" }\n" +"\n" +" fn cook_order() {}\n" +"}\n" +"```" + +#: src/ch06-03-paths-for-referring-to-an-item-in-the-module-tree.md:77 +msgid "" +"Listing 6-4: Calling a function using a relative " +"path starting with super" +msgstr "" +"清单6-4:使用以super开头的相对路径调用一个函数" + +#: src/ch06-03-paths-for-referring-to-an-item-in-the-module-tree.md:79 +msgid "" +"Here you can see directly that you access a parent's module easily using " +"`super`, which wasn't the case previously." +msgstr "" +"在这里你可以直接看到,和之前的例子不同,在这你可以使用`super`轻松地访问父级的" +"模块。" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:1 +msgid "# Bringing Paths into Scope with the `use` Keyword" +msgstr "# 使用 `use` 关键字将路径引入作用域" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:3 +msgid "" +"Having to write out the paths to call functions can feel inconvenient and " +"repetitive. Fortunately, there’s a way to simplify this process: we can " +"create a shortcut to a path with the `use` keyword once, and then use the " +"shorter name everywhere else in the scope." +msgstr "" +"不得不编写路径来调用函数显得不便且重复。幸运的是,有一种方法可以简化这个过" +"程:我们可以用`use`关键字创建一个路径的快捷方式,然后在作用域内的其他地方使用" +"这个较短的名字。" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:5 +msgid "" +"In Listing 6-5, we bring the `restaurant::front_of_house::hosting` module " +"into the\n" +"scope of the `eat_at_restaurant` function so we only have to specify\n" +"`hosting::add_to_waitlist` to call the `add_to_waitlist` function in\n" +"`eat_at_restaurant`." +msgstr "" +"在清单6-5中,我们把`restaurant::front_of_house::hosting`模块带入到作用域内," +"所以我们只需要指定 `hosting::add_to_waitlist` 来调用`eat_at_restaurant`中的" +"`add_to_waitlist` 函数。" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:12 +msgid "" +"```rust\n" +"mod front_of_house {\n" +" mod hosting {\n" +" fn add_to_waitlist() {}\n" +" }\n" +"}\n" +"\n" +"use restaurant::front_of_house::hosting;\n" +"\n" +"fn eat_at_restaurant() {\n" +" hosting::add_to_waitlist(); // ✅ Shorter path\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"mod front_of_house {\n" +" mod hosting {\n" +" fn add_to_waitlist() {}\n" +" }\n" +"}\n" +"\n" +"use restaurant::front_of_house::hosting;\n" +"\n" +"fn eat_at_restaurant() {\n" +" hosting::add_to_waitlist(); // ✅ Shorter path\n" +"}\n" +"```" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:26 +msgid "" +"Listing 6-5: Bringing a module into scope with\n" +"`use`" +msgstr "" +"清单 6-5: 用 \"使用 \"将一个模块带入范围。\n" +"使用" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:29 +msgid "" +"Adding use and a path in a scope is similar to creating a symbolic link in " +"the filesystem. By adding `use restaurant::front_of_house::hosting` in the " +"crate root, hosting is now a valid name in that scope, just as though the " +"`hosting` module had been defined in the crate root." +msgstr "" +"在作用域中添加 use 和路径类似于在文件系统中创建一个软连接(符号连接," +"symbolic link)。通过在 crate 根中添加 `use restaurant::front_of_house::" +"hosting`,hosting 现在是该作用域中的一个有效名称,就像在 crate 根中定义了" +"`hosting`模块一样。" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:31 +msgid "" +"Note that `use` only creates the shortcut for the particular scope in which " +"the `use` occurs. Listing 6-6 moves the `eat_at_restaurant` function into a " +"new\n" +"child module named `customer`, which is then a different scope than the " +"`use`\n" +"statement, so the function body won’t compile:" +msgstr "" +"注意 `use` 只能创建 `use` 所在的特定作用域内的短路径。清单 6-6 将 " +"`eat_at_restaurant` 函数移到一个新的子模块中,这又是一个不同于 `use` 语句的" +"作用域,所以函数体不能编译:" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:37 +msgid "" +"```rust\n" +"mod front_of_house {\n" +" mod hosting {\n" +" fn add_to_waitlist() {}\n" +" }\n" +"}\n" +"\n" +"use restaurant::front_of_house::hosting;\n" +"\n" +"mod customer {\n" +" fn eat_at_restaurant() {\n" +" hosting::add_to_waitlist();\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"mod front_of_house {\n" +" mod hosting {\n" +" fn add_to_waitlist() {}\n" +" }\n" +"}\n" +"\n" +"use restaurant::front_of_house::hosting;\n" +"\n" +"mod customer {\n" +" fn eat_at_restaurant() {\n" +" hosting::add_to_waitlist();\n" +" }\n" +"}\n" +"```" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:53 +msgid "" +"Listing 6-6: A `use` statement only applies in the " +"scope\n" +"it’s in" +msgstr "" +"清单6-6:一个 `use`语句只适用于它所在的作用域" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:56 +msgid "" +"The compiler error shows that the shortcut no longer applies within the\n" +"`customer` module:" +msgstr "编译器错误显示短路径不在适用于 `customer` 模块中:" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:59 +msgid "" +"```console\n" +"❯ scarb build\n" +"error: Identifier not found.\n" +" --> lib.cairo:11:9\n" +" hosting::add_to_waitlist();\n" +" ^*****^\n" +"```" +msgstr "" +"```console\n" +"❯ scarb build\n" +"error: Identifier not found.\n" +" --> lib.cairo:11:9\n" +" hosting::add_to_waitlist();\n" +" ^*****^\n" +"```" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:67 +msgid "## Creating Idiomatic `use` Paths" +msgstr "## 创建惯用的 `use` 路径" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:69 +msgid "" +"In Listing 6-5, you might have wondered why we specified `use\n" +"restaurant::front_of_house::hosting` and then called `hosting::" +"add_to_waitlist` in\n" +"`eat_at_restaurant` rather than specifying the `use` path all the way out " +"to\n" +"the `add_to_waitlist` function to achieve the same result, as in Listing 6-7." +msgstr "" +"在清单6-5中,你可能想知道为什么我们指定`restaurant::front_of_house::" +"hosting`,然后调用`eat_at_restaurant`中的`hosting::add_to_waitlist`,而不是通" +"过指定一直到\n" +"`add_to_waitlist`函数的 `use` 路径来得到相同的结果,如清单6-7。" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:76 +msgid "" +"```rust\n" +"mod front_of_house {\n" +" pub mod hosting {\n" +" pub fn add_to_waitlist() {}\n" +" }\n" +"}\n" +"\n" +"use restaurant::front_of_house::hosting::add_to_waitlist;\n" +"\n" +"pub fn eat_at_restaurant() {\n" +" add_to_waitlist();\n" +"}\n" +"\n" +"```" +msgstr "" +"```rust\n" +"mod front_of_house {\n" +" pub mod hosting {\n" +" pub fn add_to_waitlist() {}\n" +" }\n" +"}\n" +"\n" +"use restaurant::front_of_house::hosting::add_to_waitlist;\n" +"\n" +"pub fn eat_at_restaurant() {\n" +" add_to_waitlist();\n" +"}\n" +"\n" +"```" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:91 +msgid "" +"Listing 6-7: Bringing the `add_to_waitlist` " +"function\n" +"into scope with `use`, which is unidiomatic" +msgstr "" +"清单6-7:使用 `use` 将 `add_to_waitlist` 函数引入作用" +"域,这并不符合习惯" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:94 +msgid "" +"Although both Listing 6-5 and 6-7 accomplish the same task, Listing 6-5 is\n" +"the idiomatic way to bring a function into scope with `use`. Bringing the\n" +"function’s parent module into scope with `use` means we have to specify the\n" +"parent module when calling the function. Specifying the parent module when\n" +"calling the function makes it clear that the function isn’t locally defined\n" +"while still minimizing repetition of the full path. The code in Listing 6-7 " +"is\n" +"unclear as to where `add_to_waitlist` is defined." +msgstr "" +"尽管清单6-5和6-7都完成了相同的任务,但示例 6-5 是使用 use 将函数引入作用域的" +"习惯用法。要想使用 `use` 将函数的父模块引入作用域,我们必须在调用函数时指定父" +"模块,这样可以清晰地表明函数不是在本地定义的,同时使完整路径的重复度最小化。" +"示例 6-7 中的代码不清楚 `add_to_waitlist` 是在哪里被定义的。" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:102 +msgid "" +"On the other hand, when bringing in structs, enums, traits, and other items " +"with `use`,\n" +"it’s idiomatic to specify the full path. Listing 6-8 shows the idiomatic " +"way\n" +"to bring the core library’s `ArrayTrait` trait into the scope." +msgstr "" +"另一方面,使用 `use` 引入结构体、枚举和其他项时,习惯是指定它们的完整路径。示" +"例 6-8 展示了将核心库的 `ArrayTrait` 特质带入作用域。" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:106 +msgid "" +"```rust\n" +"use array::ArrayTrait;\n" +"\n" +"fn main() {\n" +" let mut arr = ArrayTrait::new();\n" +" arr.append(1);\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use array::ArrayTrait;\n" +"\n" +"fn main() {\n" +" let mut arr = ArrayTrait::new();\n" +" arr.append(1);\n" +"}\n" +"```" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:115 +msgid "" +"Listing 6-8: Bringing `ArrayTrait` into scope in an\n" +"idiomatic way" +msgstr "" +"清单6-8:将`ArrayTrait`引入作用域的习惯用法式" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:118 +msgid "" +"There’s no strong reason behind this idiom: it’s just the convention that " +"has\n" +"emerged in the Rust community, and folks have gotten used to reading and " +"writing Rust code this way.\n" +"As Cairo shares many idioms with Rust, we follow this convention as well." +msgstr "" +"这种习惯用法背后没有什么硬性要求:它只是一种惯例,人们已经习惯了以这种方式阅" +"读和编写 Rust 代码。它只是在Rust社区中出现的惯例。\n" +"由于Cairo与Rust共享许多惯例,我们也遵循这一惯例。" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:122 +msgid "" +"The exception to this idiom is if we’re bringing two items with the same " +"name\n" +"into scope with `use` statements, because Cairo doesn’t allow that." +msgstr "" +"这个习惯用法有一个例外,那就是我们想使用 `use` 语句将两个具有相同名称的项带入" +"作用域,因为Cairo不允许这样做。" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:125 +msgid "### Providing New Names with the `as` Keyword" +msgstr "### 使用 as 关键字提供新的名称" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:127 +msgid "" +"There’s another solution to the problem of bringing two types of the same " +"name\n" +"into the same scope with `use`: after the path, we can specify `as` and a " +"new\n" +"local name, or _alias_, for the type. Listing 6-9 shows how you can rename " +"an import with `as`:" +msgstr "" +"使用 `use` 将两个同名类型引入同一作用域这个问题还有另一个解决办法:在这个类型" +"的路径后面,我们使用 `as` 指定一个新的本地名称或者别名( _alias_ )。清单6-9" +"显示了如何用`as`重命名一个导入:" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:133 +msgid "" +"```rust\n" +"use array::ArrayTrait as Arr;\n" +"\n" +"fn main(){\n" +" let mut arr = Arr::new(); // ArrayTrait was renamed to Arr\n" +" arr.append(1);\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use array::ArrayTrait as Arr;\n" +"\n" +"fn main(){\n" +" let mut arr = Arr::new(); // ArrayTrait was renamed to Arr\n" +" arr.append(1);\n" +"}\n" +"```" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:142 +msgid "" +"Listing 6-9: Renaming a trait when it’s brought " +"into\n" +"scope with the `as` keyword" +msgstr "" +"清单 6-9:使用 `as` 关键字重命名引入作用域的类型" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:145 +msgid "" +"Here, we brought `ArrayTrait` into scope with the alias `Arr`. We can now " +"access the trait's methods with the `Arr` identifier." +msgstr "" +"在这里,我们用别名`Arr`将`ArrayTrait`带入作用域。现在我们可以用`Arr`标识符来" +"访问该trait的方法。" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:147 +msgid "## Re-exporting Names in Module Files" +msgstr "## 在模块文件中重导出名称" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:149 +msgid "" +"When we bring a name into scope with the `use` keyword, the name available " +"in\n" +"the new scope can be imported as if it had been defined in that code’s " +"scope.\n" +"This technique is called _re-exporting_ because we’re bringing an item into " +"scope,\n" +"but also making that item available for others to bring into their scope." +msgstr "" +"当我们用`use`关键字将一个名字带入作用域时,在新的作用域中也能够正常使用这个名" +"称,就好像它本来就在当前作用域一样。\n" +"这种技术被称为 重导出( _re-exporting_ ),因为我们将一个项目带入作用域、但同" +"时也使这个项目可以被其他人带入他们的作用域。" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:154 +msgid "" +"For example, let's re-export the `add_to_waitlist` function in the " +"restaurant example:" +msgstr "下面这个例子,让我们重新导出餐厅例子中的`add_to_waitlist`函数:" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:158 +msgid "" +"```rs\n" +"mod front_of_house {\n" +" mod hosting {\n" +" fn add_to_waitlist() {}\n" +" }\n" +"}\n" +"\n" +"use restaurant::front_of_house::hosting;\n" +"\n" +"fn eat_at_restaurant() {\n" +" hosting::add_to_waitlist();\n" +"}\n" +"```" +msgstr "" +"```rs\n" +"mod front_of_house {\n" +" mod hosting {\n" +" fn add_to_waitlist() {}\n" +" }\n" +"}\n" +"\n" +"use restaurant::front_of_house::hosting;\n" +"\n" +"fn eat_at_restaurant() {\n" +" hosting::add_to_waitlist();\n" +"}\n" +"```" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:172 +msgid "" +"Listing 6-10: Making a name available for any code " +"to use\n" +"from a new scope with `pub use`" +msgstr "" +"清单6-10:通过 `pub use` 使名称可从新作用域中被导入至" +"任何代码。" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:175 +msgid "" +"Before this change, external code would have to call the `add_to_waitlist`\n" +"function by using the path\n" +"`restaurant::front_of_house::hosting::add_to_waitlist()`. Now that this " +"`use`\n" +"has re-exported the `hosting` module from the root module, external code\n" +"can now use the path `restaurant::hosting::add_to_waitlist()` instead." +msgstr "" +"在这个修改之前,外部代码需要使用路径 `restaurant::front_of_house::hosting::" +"add_to_waitlist()` 来调用 `add_to_waitlist` 函数。\n" +"现在这个 `use` 从根模块重导出了 `hosting` 模块,外部代码现在可以使用路径 " +"`restaurant::hosting::add_to_waitlist()` 。" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:181 +msgid "" +"Re-exporting is useful when the internal structure of your code is " +"different\n" +"from how programmers calling your code would think about the domain. For\n" +"example, in this restaurant metaphor, the people running the restaurant " +"think\n" +"about “front of house” and “back of house.” But customers visiting a " +"restaurant\n" +"probably won’t think about the parts of the restaurant in those terms. With\n" +"`use`, we can write our code with one structure but expose a different\n" +"structure. Doing so makes our library well organized for programmers working " +"on\n" +"the library and programmers calling the library." +msgstr "" +"当你代码的内部结构与调用你代码的程序员所想象的结构不同时,重导出会很有用。\n" +"例如,在这个餐馆的比喻中,经营餐馆的人会想到“前台”和“后台”。但顾客在光顾一家" +"餐馆时,可能不会以这些术语来考虑餐馆的各个部分。\n" +"使用 `use`,我们可以使用一种结构编写代码,却将不同的结构形式暴露出来。这样做" +"使我们的库井井有条,也使开发这个库的程序员和调用这个库的程序员都更加方便。" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:190 +msgid "## Using External Packages in Cairo with Scarb" +msgstr "## 在Cairo使用外部包与Scarb" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:192 +msgid "" +"You might need to use external packages to leverage the functionality " +"provided by the community. To use an external package in your project with " +"Scarb, follow these steps:" +msgstr "" +"你可能需要使用外部包来利用社区提供的功能。要在你的项目中使用Scarb的外部包,请" +"遵循以下步骤:" + +#: src/ch06-04-bringing-paths-into-scope-with-the-use-keyword.md:194 +msgid "" +"> The dependencies system is still a work in progress. You can check the " +"official [documentation](https://docs.swmansion.com/scarb/docs/guides/" +"dependencies)." +msgstr "" +"> 依赖关系系统仍然是一项正在进行的工作。你可以查看官方的[文档](https://docs." +"swmansion.com/scarb/docs/guides/dependencies)。" + +#: src/ch06-05-separating-modules-into-different-files.md:1 +msgid "## Separating Modules into Different Files" +msgstr "## 将模块拆分成多个文件" + +#: src/ch06-05-separating-modules-into-different-files.md:3 +msgid "" +"So far, all the examples in this chapter defined multiple modules in one " +"file.\n" +"When modules get large, you might want to move their definitions to a " +"separate\n" +"file to make the code easier to navigate." +msgstr "" +"到目前为止,本章所有的例子都在一个文件中定义多个模块。当模块变得更大时,你可" +"能想要将它们的定义移动到单独的文件中,从而使代码更容易阅读。" + +#: src/ch06-05-separating-modules-into-different-files.md:7 +msgid "" +"For example, let’s start from the code in Listing 6-10 that had multiple\n" +"restaurant modules. We’ll extract modules into files instead of having all " +"the\n" +"modules defined in the crate root file. In this case, the crate root file " +"is\n" +"_src/lib.cairo_." +msgstr "" +"例如,我们从示例6-10中的代码开始,我们会将模块提取到各自的文件中,而不是将所" +"有模块都定义到 crate 根文件中。在这里,crate 根文件是 _src/lib.cairo_ 。" + +#: src/ch06-05-separating-modules-into-different-files.md:12 +msgid "" +"First, we’ll extract the `front_of_house` module to its own file. Remove " +"the\n" +"code inside the curly brackets for the `front_of_house` module, leaving " +"only\n" +"the `mod front_of_house;` declaration, so that _src/lib.cairo_ contains the " +"code\n" +"shown in Listing 6-11. Note that this won’t compile until we create the\n" +"_src/front_of_house.cairo_ file in Listing 6-12." +msgstr "" +"首先将 `front_of_house` 模块提取到其自己的文件中。删除 `front_of_house` 模块" +"的大括号中的代码,只留下 `mod front_of_house;` 声明,这样 _src/lib.cairo_ 就" +"包含了代码\n" +"如清单6-11所示。注意直到创建示例 6-12 中的 _src/front_of_house.cairo_ 文件之" +"前代码都不能编译。" + +#: src/ch06-05-separating-modules-into-different-files.md:20 +msgid "" +"```rust\n" +"mod front_of_house;\n" +"\n" +"use restaurant::front_of_house::hosting;\n" +"\n" +"pub fn eat_at_restaurant() {\n" +" hosting::add_to_waitlist();\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"mod front_of_house;\n" +"\n" +"use restaurant::front_of_house::hosting;\n" +"\n" +"pub fn eat_at_restaurant() {\n" +" hosting::add_to_waitlist();\n" +"}\n" +"```" + +#: src/ch06-05-separating-modules-into-different-files.md:30 +msgid "" +"Listing 6-11: Declaring the `front_of_house` module " +"whose\n" +"body will be in _src/front_of_house.cairo_" +msgstr "" +"清单6-11:声明`front_of_house` 模块,其主体将在 _src/" +"front_of_house.cairo_ 中。" + +#: src/ch06-05-separating-modules-into-different-files.md:33 +msgid "" +"Next, place the code that was in the curly brackets into a new file named\n" +"_src/front_of_house.cairo_, as shown in Listing 6-12. The compiler knows to " +"look\n" +"in this file because it came across the module declaration in the crate " +"root\n" +"with the name `front_of_house`." +msgstr "" +"接下来将之前大括号内的代码放入一个名叫 _src/front_of_house.cairo_ 的新文件" +"中,如示例 6-12所示。因为编译器找到了 crate 根中名叫 `front_of_house` 的模块" +"声明,它就知道去搜寻这个文件。" + +#: src/ch06-05-separating-modules-into-different-files.md:38 +#: src/ch06-05-separating-modules-into-different-files.md:66 +msgid "Filename: src/front_of_house.cairo" +msgstr "文件名: src/front_of_house.cairo" + +#: src/ch06-05-separating-modules-into-different-files.md:40 +msgid "" +"```rust,\n" +"mod hosting {\n" +" fn add_to_waitlist() {}\n" +"}\n" +"```" +msgstr "" +"```rust,\n" +"mod hosting {\n" +" fn add_to_waitlist() {}\n" +"}\n" +"```" + +#: src/ch06-05-separating-modules-into-different-files.md:46 +msgid "" +"Listing 6-12: Definitions inside the " +"`front_of_house`\n" +"module in _src/front_of_house.cairo_" +msgstr "" +"清单 6-12:在 _src/front_of_house.cairo_ 中定义 " +"`front_of_house` 模块。" + +#: src/ch06-05-separating-modules-into-different-files.md:49 +msgid "" +"Note that you only need to load a file using a `mod` declaration _once_ in " +"your\n" +"module tree. Once the compiler knows the file is part of the project (and " +"knows\n" +"where in the module tree the code resides because of where you’ve put the " +"`mod`\n" +"statement), other files in your project should refer to the loaded file’s " +"code\n" +"using a path to where it was declared, as covered in the [“Paths for " +"Referring\n" +"to an Item in the Module Tree”][paths] section. In other " +"words,\n" +"`mod` is _not_ an “include” operation that you may have seen in other\n" +"programming languages." +msgstr "" +"注意你只需在模块树中的某处使用一次 mod 声明就可以加载这个文件。\n" +"一旦编译器知道了这个文件是项目的一部分(并且通过 mod 语句的位置知道了代码在模" +"块树中的位置),项目中的其他文件应该使用其所声明的位置的路径来引用那个文件的" +"代码,\n" +"这在 [引用模块项目的路径](ch06-03-paths-for-referring-to-an-item-in-the-" +"module-tree.md)部分有讲到。\n" +"换句话说,mod 不是 你可能会在其他编程语言中看到的 “include” 操作。" + +#: src/ch06-05-separating-modules-into-different-files.md:58 +msgid "" +"Next, we’ll extract the `hosting` module to its own file. The process is a " +"bit\n" +"different because `hosting` is a child module of `front_of_house`, not of " +"the\n" +"root module. We’ll place the file for `hosting` in a new directory that will " +"be\n" +"named for its ancestors in the module tree, in this case _src/front_of_house/" +"_." +msgstr "" +"接下来我们同样将 `hosting` 模块提取到自己的文件中。这个过程会有所不同,因为 " +"`hosting` 是 `front_of_house` 的子模块而不是根模块。我们将 `hosting` 的文件放" +"在与模块树中它的父级模块同名的目录中,在这里是 _src/front_of_house/_ 。" + +#: src/ch06-05-separating-modules-into-different-files.md:63 +msgid "" +"To start moving `hosting`, we change _src/front_of_house.cairo_ to contain " +"only the\n" +"declaration of the `hosting` module:" +msgstr "" +"为了移动 `hosting`,修改 _src/front_of_house.cairo_ 使之仅包含 `hosting` 模" +"块的声明:" + +#: src/ch06-05-separating-modules-into-different-files.md:68 +msgid "" +"```rust\n" +"mod hosting;\n" +"```" +msgstr "" +"```rust\n" +"mod hosting;\n" +"```" + +#: src/ch06-05-separating-modules-into-different-files.md:72 +msgid "" +"Then we create a _src/front_of_house_ directory and a file _hosting.cairo_ " +"to\n" +"contain the definitions made in the `hosting` module:" +msgstr "" +"接着我们创建一个 _src/front_of_house_ 目录和一个包含 `hosting` 模块定义的 " +"_hosting.cairo_ 文件:" + +#: src/ch06-05-separating-modules-into-different-files.md:75 +msgid "" +"Filename: src/front_of_house/hosting.cairo" +msgstr "" +"文件名: src/front_of_house/hosting.cairo" + +#: src/ch06-05-separating-modules-into-different-files.md:77 +msgid "" +"```rust\n" +"pub fn add_to_waitlist() {}\n" +"```" +msgstr "" +"```rust\n" +"pub fn add_to_waitlist() {}\n" +"```" + +#: src/ch06-05-separating-modules-into-different-files.md:81 +msgid "" +"If we instead put _hosting.cairo_ in the _src_ directory, the compiler " +"would\n" +"expect the _hosting.cairo_ code to be in a `hosting` module declared in the " +"crate\n" +"root, and not declared as a child of the `front_of_house` module. The\n" +"compiler’s rules for which files to check for which modules’ code means the\n" +"directories and files more closely match the module tree." +msgstr "" +"如果将 _hosting.cairo_ 放在 _src_ 目录,编译器会认为 `hosting` 模块中的 " +"_hosting.cairo_ 的代码声明于 crate 根,而不是声明为 `front_of_house` 的子模" +"块。\n" +"编译器所遵循的哪些文件对应哪些模块的代码的规则,意味着目录和文件更接近于模块" +"树。" + +#: src/ch06-05-separating-modules-into-different-files.md:87 +msgid "" +"We’ve moved each module’s code to a separate file, and the module tree " +"remains\n" +"the same. The function calls in `eat_at_restaurant` will work without any\n" +"modification, even though the definitions live in different files. This\n" +"technique lets you move modules to new files as they grow in size." +msgstr "" +"我们将各个模块的代码移动到独立文件了,同时模块树依旧相同。\n" +"`eat_at_restaurant` 中的函数调用也无需修改继续保持有效,即便其定义存在于不同" +"的文件中。\n" +"这个技巧让你可以在模块代码增长时,将它们移动到新文件中。" + +#: src/ch06-05-separating-modules-into-different-files.md:92 +msgid "" +"Note that the `use restaurant::front_of_house::hosting` statement in\n" +"_src/lib.cairo_ also hasn’t changed, nor does `use` have any impact on what " +"files\n" +"are compiled as part of the crate. The `mod` keyword declares modules, and " +"Cairo\n" +"looks in a file with the same name as the module for the code that goes " +"into\n" +"that module." +msgstr "" +"注意,_src/lib.cairo_中的 `use restaurant::front_of_house::hosting` 语句是没" +"有改变的,在文件作为 crate 的一部分而编译时,`use` 不会有任何影响。\n" +"`mod` 关键字声明了模块,Cairo 会在与模块同名的文件中查找模块的代码。" + +#: src/ch06-05-separating-modules-into-different-files.md:100 +msgid "" +"Cairo lets you split a package into multiple crates and a crate into " +"modules\n" +"so you can refer to items defined in one module from another module. You can " +"do\n" +"this by specifying absolute or relative paths. These paths can be brought " +"into\n" +"scope with a `use` statement so you can use a shorter path for multiple uses " +"of\n" +"the item in that scope. Module code is public by default." +msgstr "" +"Cairo 提供了将包分成多个 crate,将 crate 分成模块,以及通过指定绝对或相对路径" +"从一个模块引用另一个模块中定义的项的方式。\n" +"你可以通过使用 `use` 语句将路径引入作用域,这样在多次使用时可以使用更短的路" +"径。模块定义的代码默认是公有的。" + +#: src/ch06-05-separating-modules-into-different-files.md:106 +msgid "" +"In the next chapter, we’ll look at some collection data structures in the\n" +"standard library that you can use in your neatly organized code." +msgstr "" +"在下一章中,让我们看看一些标准库提供的集合数据类型,你可以利用它们编写出漂亮" +"整洁的代码。" + +#: src/ch07-00-generic-types-and-traits.md:1 +msgid "# Generic Types and Traits" +msgstr "# 泛型和Trait" + +#: src/ch07-00-generic-types-and-traits.md:3 +msgid "" +"Every programming language has tools for effectively handling the " +"duplication of concepts. In Cairo, one such tool is generics: abstract stand-" +"ins for concrete types or other properties. We can express the behaviour of " +"generics or how they relate to other generics without knowing what will be " +"in their place when compiling and running the code." +msgstr "" +"每一个编程语言都有高效处理重复概念的工具。在 Cairo 中其工具之一就是 泛型" +"(generics)。泛型是具体类型或其他属性的抽象替代。我们可以表达泛型的属性,比" +"如他们的行为或如何与其他泛型相关联,而不需要在编写和编译代码时知道他们在这里" +"实际上代表什么。" + +#: src/ch07-00-generic-types-and-traits.md:5 +msgid "" +"Functions, structs, enums and traits can incorporate generic types as part " +"of their definition instead of a concrete types like `u32` or " +"`ContractAddress`." +msgstr "" +"函数、结构体、枚举和特征可以将泛型作为其定义的一部分,而不是像`u32`或" +"`ContractAddress`这样的具体类型。" + +#: src/ch07-00-generic-types-and-traits.md:7 +msgid "" +"Generics allow us to replace specific types with a placeholder that " +"represents multiple types to remove code duplication." +msgstr "" +"泛型允许我们用一个代表多种类型的占位符来替换特定的类型,以消除代码的重复。" + +#: src/ch07-00-generic-types-and-traits.md:9 +msgid "" +"For each concrete type that replaces a generic type the compiler creates a " +"new definition, reducing development time for the programmer, but code " +"duplication at compile level still exists. This may be of importance if you " +"are writing Starknet contracts and using a generic for multiple types which " +"will cause contract size to increment." +msgstr "" +"对于每一个取代泛型的具体类型,编译器都会创建一个新的定义,从而减少程序员的开" +"发时间,但在编译层面上的代码重复仍然存在。如果你正在编写Starknet合约,并为多" +"个类型使用一个泛型,这将导致合约大小的增加,这可能是很重要的。" + +#: src/ch07-00-generic-types-and-traits.md:11 +msgid "" +"Then you’ll learn how to use traits to define behavior in a generic way. You " +"can combine traits with generic types to constrain a generic type to accept " +"only those types that have a particular behavior, as opposed to just any " +"type." +msgstr "" +"之后你将学习 trait,这是一个定义泛型行为的方法。trait 可以与泛型结合来将泛型" +"限制为只接受拥有特定行为的类型,而不是任意类型。" + +#: src/ch07-01-generic-data-types.md:1 +msgid "# Generic Data Types" +msgstr "# 泛型数据类型" + +#: src/ch07-01-generic-data-types.md:3 +msgid "" +"We use generics to create definitions for item declarations, such as structs " +"and functions, which we can then use with many different concrete data " +"types. In Cairo we can use generics when defining functions, structs, enums, " +"traits, implementations and methods! In this chapter we are going to take a " +"look on how to effectively use generic types with all of them." +msgstr "" +"我们可以使用泛型为像函数签名或结构体这样的项创建定义,这样它们就可以用于多种" +"不同的具体数据类型。在Cairo中,我们可以在定义函数、结构、枚举、特征、实现和方" +"法时使用泛型!在本章中,我们将看看如何有效地使用所有的泛型。" + +#: src/ch07-01-generic-data-types.md:5 +msgid "## Generic Functions" +msgstr "## 在函数定义中使用泛型" + +#: src/ch07-01-generic-data-types.md:7 +msgid "" +"When defining a function that uses generics, we place the generics in the " +"function signature, where we would usually specify the data types of the " +"parameter and return value. For example, imagine we want to create a " +"function which given two `Array` of items, will return the largest one. If " +"we need to perform this operations for lists of different types, then we " +"would have to redefine the function each time. Luckily we can implement the " +"function once using generics and move on to other tasks." +msgstr "" +"当定义一个使用泛型的函数时,本来在函数签名中指定参数和返回值的类型的地方,会" +"改用泛型来表示。例如,假设我们想创建一个函数,给定两个 \"Array \"项,将返回最" +"大的一个。如果我们需要对不同类型的列表进行这种操作,那么我们就必须每次都重新" +"定义这个函数。幸运的是,我们可以使用泛型来实现这个函数,然后继续完成其他任" +"务。" + +#: src/ch07-01-generic-data-types.md:9 +msgid "" +"```rust,does_not_compile\n" +"// This code does not compile!\n" +"\n" +"use array::ArrayTrait;\n" +"\n" +"// Specify generic type T between the angulars\n" +"fn largest_list(l1: Array, l2: Array) -> Array {\n" +" if l1.len() > l2.len() {\n" +" l1\n" +" } else {\n" +" l2\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut l1 = ArrayTrait::new();\n" +" let mut l2 = ArrayTrait::new();\n" +"\n" +" l1.append(1);\n" +" l1.append(2);\n" +"\n" +" l2.append(3);\n" +" l2.append(4);\n" +" l2.append(5);\n" +"\n" +" // There is no need to specify the concrete type of T because\n" +" // it is inferred by the compiler\n" +" let l3 = largest_list(l1, l2);\n" +"}\n" +"```" +msgstr "" +"```rust,does_not_compile\n" +"// This code does not compile!\n" +"\n" +"use array::ArrayTrait;\n" +"\n" +"// Specify generic type T between the angulars\n" +"fn largest_list(l1: Array, l2: Array) -> Array {\n" +" if l1.len() > l2.len() {\n" +" l1\n" +" } else {\n" +" l2\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut l1 = ArrayTrait::new();\n" +" let mut l2 = ArrayTrait::new();\n" +"\n" +" l1.append(1);\n" +" l1.append(2);\n" +"\n" +" l2.append(3);\n" +" l2.append(4);\n" +" l2.append(5);\n" +"\n" +" // There is no need to specify the concrete type of T because\n" +" // it is inferred by the compiler\n" +" let l3 = largest_list(l1, l2);\n" +"}\n" +"```" + +#: src/ch07-01-generic-data-types.md:40 +msgid "" +"The `largest_list` function compares two lists of the same type and returns " +"the one with more elements and drops the other. If you compile the previous " +"code, you will notice that it will fail with an error saying that there are " +"no traits defined for droping an array of a generic type. This happens " +"because the compiler has no way to guarantee that an `Array` is droppable " +"when executing the `main` function. In order to drop an array of `T`, the " +"compiler must first know how to drop `T`. This can be fixed by specifiying " +"in the function signature of `largest_list` that `T` must implement the drop " +"trait. The correct function definition of `largest_list` is as follows:" +msgstr "" +"`largest_list`函数比较了两个相同类型的列表,并返回具有更多元素的那一个,并丢" +"弃另一个。如果你编译前面的代码,你会注意到它会出错,说没有为丢弃一个通用类型" +"的数组定义特征。这是因为编译器没有办法保证在执行`main`函数时,`Array`是可" +"以丢弃的。为了丢弃一个`T`的数组,编译器必须首先知道如何丢弃`T`。这可以通过在" +"`largest_list`的函数签名中规定`T`必须实现drop trait来解决。`largest_list`的正" +"确函数定义如下:" + +#: src/ch07-01-generic-data-types.md:42 +msgid "" +"```rust\n" +"fn largest_list>(l1: Array, l2: Array) -> " +"Array {\n" +" if l1.len() > l2.len() {\n" +" l1\n" +" } else {\n" +" l2\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"fn largest_list>(l1: Array, l2: Array) -> " +"Array {\n" +" if l1.len() > l2.len() {\n" +" l1\n" +" } else {\n" +" l2\n" +" }\n" +"}\n" +"```" + +#: src/ch07-01-generic-data-types.md:52 +msgid "" +"The new `largest_list` function includes in its definition the requirement " +"that whatever generic type is placed there, it must be droppable. The `main` " +"function remains unchanged, the compiler is smart enough to deduct which " +"concrete type is being used and if it implements the `Drop` trait." +msgstr "" +"新的`largest_list`函数在其定义中包含了一个要求,即无论什么泛型被放在那里,它" +"都必须是可丢弃的。`main`函数保持不变,编译器足够聪明,可以得出正在使用的具体" +"类型以及它是否实现了`Drop`这个trait。" + +#: src/ch07-01-generic-data-types.md:54 +msgid "### Constraints for Generic Types" +msgstr "### 范型的约束" + +#: src/ch07-01-generic-data-types.md:56 +msgid "" +"When defining generic types, it is useful to have information about them. " +"Knowing which traits a generic type implements allow us to use them more " +"effectively in a functions logic at the cost of constraining the generic " +"types that can be used with the function. We saw an example of this " +"previously by adding the `TDrop` implementation as part of the generic " +"arguments of `largest_list`. While `TDrop` was added to satisfy the " +"compilers requirements, we can also add constraints to benefit our function " +"logic." +msgstr "" +"在定义泛型的时候,掌握关于它们的信息是很有用的。知道一个泛型实现了哪些trait," +"可以让我们在函数逻辑中更有效地使用它们,代价是限制了可以与函数一起使用的泛" +"型。我们之前看到了一个例子,就是将`TDrop`的实现作为`largest_list`的泛型参数的" +"一部分。虽然 `TDrop`是为了满足编译器的要求而添加的,但我们也可以添加一些约束" +"条件以有利于我们的函数逻辑。" + +#: src/ch07-01-generic-data-types.md:58 +msgid "" +"Imagine that we want, given a list of elements of some generic type `T`, " +"find the smallest element among them. Initially, we know that for an element " +"of type `T` to be comparable, it must implement the `PartialOrd` trait. The " +"resulting function would be:" +msgstr "" +"想象一下,我们想,给定一个通用类型`T`的元素列表,找到其中最小的元素。首先,我" +"们知道要使一个`T`类型的元素具有可比性,它必须实现`PartialOrd`这个trait。由此" +"产生的函数将是:" + +#: src/ch07-01-generic-data-types.md:60 +msgid "" +"```rust,does_not_compile\n" +"// This code does not compile!\n" +"use array:ArrayTrait;\n" +"\n" +"// Given a list of T get the smallest one.\n" +"// The PartialOrd trait implements comparison operations for T\n" +"fn smallest_element>(list: @Array) -> " +"T {\n" +" // This represents the smallest element through the iteration\n" +" // Notice that we use the desnap (*) operator\n" +" let mut smallest = *list[0_usize];\n" +"\n" +" // The index we will use to move through the list\n" +" let mut index = 1_usize;\n" +"\n" +" // Iterate through the whole list storing the smallest\n" +" loop {\n" +" if index >= list.len(){\n" +" break smallest;\n" +" }\n" +" if *list[index] < smallest {\n" +" smallest = *list[index];\n" +" }\n" +" index = index + 1;\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut list = ArrayTrait::new();\n" +" list.append(5_u8);\n" +" list.append(3_u8);\n" +" list.append(10_u8);\n" +"\n" +" // We need to specify that we are passing a snapshot of `list` as an " +"argument\n" +" let s = smallest_element(@list);\n" +" assert(s == 3_u8, 0);\n" +"\n" +"}\n" +"```" +msgstr "" +"```rust,does_not_compile\n" +"// This code does not compile!\n" +"use array:ArrayTrait;\n" +"\n" +"// Given a list of T get the smallest one.\n" +"// The PartialOrd trait implements comparison operations for T\n" +"fn smallest_element>(list: @Array) -> " +"T {\n" +" // This represents the smallest element through the iteration\n" +" // Notice that we use the desnap (*) operator\n" +" let mut smallest = *list[0_usize];\n" +"\n" +" // The index we will use to move through the list\n" +" let mut index = 1_usize;\n" +"\n" +" // Iterate through the whole list storing the smallest\n" +" loop {\n" +" if index >= list.len(){\n" +" break smallest;\n" +" }\n" +" if *list[index] < smallest {\n" +" smallest = *list[index];\n" +" }\n" +" index = index + 1;\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut list = ArrayTrait::new();\n" +" list.append(5_u8);\n" +" list.append(3_u8);\n" +" list.append(10_u8);\n" +"\n" +" // We need to specify that we are passing a snapshot of `list` as an " +"argument\n" +" let s = smallest_element(@list);\n" +" assert(s == 3_u8, 0);\n" +"\n" +"}\n" +"```" + +#: src/ch07-01-generic-data-types.md:99 +msgid "" +"The `smallest_element` function uses a generic type `T` that implements the " +"`PartialOrd` trait, takes an snapshot of an `Array` as a parameter and " +"returns a copy of the smallest element. Because the parameter is of type " +"`@Array`, we no longer need to drop it at the end of the execution and so " +"we don't require to implement the `Drop` trait for `T` as well. Why it does " +"not compile then?" +msgstr "" +"`smallest_element`函数使用一个实现了`PartialOrd`的trait的通用类型`T`,接收一" +"个`Array`的快照作为参数并返回最小元素的副本。因为参数是`@Array`的类型," +"我们不再需要在执行结束时丢弃它,所以我们不需要为`T`实现`Drop`特性。那为什么它" +"不能编译呢?" + +#: src/ch07-01-generic-data-types.md:101 +msgid "" +"When indexing on `list`, the value results in a snap of the indexed element, " +"unless `PartialOrd` is implemented for `@T` we need to desnap the element " +"using `*`. The `*` operation requires a copy from `@T` to`T`, which means " +"that `T` needs to implement the `Copy` trait. After copying an element of " +"type `@T` to `T`, there are now variables with type `T` that need to be " +"dropped, requiring for `T` to implement the `Drop` trait as well. We must " +"then add both `Drop` and `Copy` traits implementation for the function to be " +"correct. After updating the`smallest_element` function the resulting code " +"would be:" +msgstr "" +"当对`list`进行索引时,其结果是对被索引的元素进行快照,除非`@T`实现了" +"`PartialOrd`,否则我们需要使用 `*` 对元素进行解快照。`*` 操作需要从`@T`复制到" +"`T`,这意味着`T`需要实现`Copy`特性。在复制了一个`@T`类型的元素到`T`之后,现在" +"有`T`类型的变量需要被删除,这就要求`T`也要实现`Drop`特性。然后我们必须同时添" +"加`Drop'和`Copy'特性的实现,以使该函数正确。在更新`smallest_element`函数后," +"产生的代码将是:" + +#: src/ch07-01-generic-data-types.md:103 +msgid "" +"```rs\n" +"fn smallest_element, impl TCopy: Copy, " +"impl TDrop: Drop>(list: @Array) -> T {\n" +" let mut smallest = *list[0_usize];\n" +" let mut index = 1_usize;\n" +" loop {\n" +" if index >= list.len(){\n" +" break smallest;\n" +" }\n" +" if *list[index] < smallest {\n" +" smallest = *list[index];\n" +" }\n" +" index = index + 1;\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rs\n" +"fn smallest_element, impl TCopy: Copy, " +"impl TDrop: Drop>(list: @Array) -> T {\n" +" let mut smallest = *list[0_usize];\n" +" let mut index = 1_usize;\n" +" loop {\n" +" if index >= list.len(){\n" +" break smallest;\n" +" }\n" +" if *list[index] < smallest {\n" +" smallest = *list[index];\n" +" }\n" +" index = index + 1;\n" +" }\n" +"}\n" +"```" + +#: src/ch07-01-generic-data-types.md:119 +msgid "## Structs" +msgstr "## 结构体定义中的泛型" + +#: src/ch07-01-generic-data-types.md:121 +msgid "" +"We can also define structs to use a generic type parameter for one or more " +"fields using the `<>` syntax, similar to function definitions. First we " +"declare the name of the type parameter inside the angle brackets just after " +"the name of the struct. Then we use the generic type in the struct " +"definition where we would otherwise specify concrete data types. The next " +"code example shows the definition `Wallet` which has a `balance` field of " +"type `T`." +msgstr "" +"我们也可以使用类似于函数定义的`<>` 语法来定义结构,它包含一个或多个泛型参数类" +"型字段。首先,必须在结构体名称后面的尖括号中声明泛型参数的名称,接着在结构体" +"定义中可以指定具体数据类型的位置使用泛型类型。下一个代码示例显示了 " +"`Wallet` 的定义,它有一个 `balance`字段,类型为 `T`。" + +#: src/ch07-01-generic-data-types.md:123 +msgid "" +"```rust,does_not_compile\n" +"// This code does not compile!\n" +"\n" +"#[derive(Drop)]\n" +"struct Wallet {\n" +" balance: T,\n" +"}\n" +"\n" +"\n" +"fn main() {\n" +" let w = Wallet{ balance: 3_u128};\n" +"}\n" +"```" +msgstr "" +"```rust,does_not_compile\n" +"// This code does not compile!\n" +"\n" +"#[derive(Drop)]\n" +"struct Wallet {\n" +" balance: T,\n" +"}\n" +"\n" +"\n" +"fn main() {\n" +" let w = Wallet{ balance: 3_u128};\n" +"}\n" +"```" + +#: src/ch07-01-generic-data-types.md:137 +msgid "" +"Compiling the above code would error due to the `derive` macro not working " +"well with generics. When using generic types is best to directly write the " +"traits you want to use:" +msgstr "" +"由于`derive`宏在泛型中不能正常工作,编译上述代码会出错。当使用泛型时,最好直" +"接编写你想使用的特性:" + +#: src/ch07-01-generic-data-types.md:139 +msgid "" +"" +msgstr "" +"" + +#: src/ch07-01-generic-data-types.md:141 +msgid "" +"```rust\n" +"struct Wallet {\n" +" balance: T,\n" +"}\n" +"\n" +"impl WalletDrop> of Drop>;\n" +"\n" +"fn main() {\n" +" let w = Wallet { balance: 3_u128 };\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"struct Wallet {\n" +" balance: T,\n" +"}\n" +"\n" +"impl WalletDrop> of Drop>;\n" +"\n" +"fn main() {\n" +" let w = Wallet { balance: 3_u128 };\n" +"}\n" +"```" + +#: src/ch07-01-generic-data-types.md:153 +msgid "" +"We avoid using the `derive` macro for `Drop` implementation of `Wallet` and " +"instead define our own `WalletDrop` implementation. Notice that we must " +"define, just like functions, an additional generic type for `WalletDrop` " +"saying that `T` implements the `Drop` trait as well. We are basically saying " +"that the struct `Wallet` is droppable as long as `T` is also droppable." +msgstr "" +"应该避免使用`derive`宏来实现`Wallet`的`Drop`,而是定义我们自己的`WalletDrop`" +"实现。注意,我们必须像定义函数一样,为`WalletDrop`定义一个额外的泛型`T`并且也" +"实现了`Drop`特性。这基本上是在说,只要`T`也是可丢弃的,那么`钱包`这个结构" +"就是可丢弃的。" + +#: src/ch07-01-generic-data-types.md:155 +msgid "" +"Finally, if we want to add a field to `Wallet` representing its Cairo " +"address and we want that field to be different than `T` but generic as well, " +"we can simply add another generic type between the `<>`:" +msgstr "" +"最后,如果我们想给`Wallet`添加一个代表其Cairo地址的字段,并且我们希望这个字段" +"是与`T`不同的另一个泛型,我们可以简单地在`<>`之间添加另一个泛型:" + +#: src/ch07-01-generic-data-types.md:157 +msgid "" +"```rust\n" +"struct Wallet {\n" +" balance: T,\n" +" address: U,\n" +"}\n" +"\n" +"impl WalletDrop, U, impl UDrop: Drop> of " +"Drop>;\n" +"\n" +"fn main() {\n" +" let w = Wallet { balance: 3_u128, address: 14 };\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"struct Wallet {\n" +" balance: T,\n" +" address: U,\n" +"}\n" +"\n" +"impl WalletDrop, U, impl UDrop: Drop> of " +"Drop>;\n" +"\n" +"fn main() {\n" +" let w = Wallet { balance: 3_u128, address: 14 };\n" +"}\n" +"```" + +#: src/ch07-01-generic-data-types.md:170 +msgid "" +"We add to `Wallet` struct definiton a new generic type `U` and then assign " +"this type to the new field member `address`.\n" +"Then we adapt the `WalletDrop` trait to work with the new generic type `U`. " +"Notice that when initializing the struct inside `main` it automatically " +"infers that `T` is a `u128` and `U` is a `felt252` and since they are both " +"droppable, `Wallet` is droppable as well!" +msgstr "" +"我们在`Wallet`结构定义中添加一个新的泛型`U`,然后将这个类型分配给新的字段成员" +"`address`。\n" +"然后我们调整 `WalletDrop`的trait,使其与新的泛型 \"U \"一起工作。注意,在初始" +"化`main'中的结构时,它会自动推断出`T`是`u128`,`U`是`felt252`,由于它们都是可" +"丢弃的,所以`Wallet`也是可丢弃的!" + +#: src/ch07-01-generic-data-types.md:173 +msgid "## Enums" +msgstr "## 枚举定义中的泛型" + +#: src/ch07-01-generic-data-types.md:175 +msgid "" +"As we did with structs, we can define enums to hold generic data types in " +"their variants. For example the `Option` enum provided by the Cairo core " +"library:" +msgstr "" +"和结构体类似,枚举也可以在成员中存放泛型数据类型。例如,Cairo核心库提供的" +"`Option`枚举:" + +#: src/ch07-01-generic-data-types.md:177 +msgid "" +"```rust\n" +"enum Option {\n" +" Some(T),\n" +" None,\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"enum Option {\n" +" Some(T),\n" +" None,\n" +"}\n" +"```" + +#: src/ch07-01-generic-data-types.md:184 +msgid "" +"The `Option` enum is generic over a type `T` and has two variants: " +"`Some`, which holds one value of type `T` and `None` that doesn't hold any " +"value. By using the `Option` enum, it is possible for us to express the " +"abstract concept of an optional value and because the value has a generic " +"type `T` we can use this abstraction with any type." +msgstr "" +"如你所见 `Option` 是一个拥有泛型 `T` 的枚举,它有两个成员:`Some`,它存放" +"了一个类型 `T` 的值,和不存在任何值的`None`。通过 `Option` 枚举可以表达有" +"一个可能的值的抽象概念,同时因为 `Option` 是泛型的,无论这个可能的值是什么" +"类型都可以使用这个抽象。" + +#: src/ch07-01-generic-data-types.md:186 +msgid "" +"Enums can use multiple generic types as well, like definition of the " +"`Result` enum that the core library provides:" +msgstr "枚举也可以拥有多个泛型类型,比如核心库提供的`Result`枚举的定义:" + +#: src/ch07-01-generic-data-types.md:188 src/ch09-02-error-handling.md:11 +msgid "" +"```rust\n" +"enum Result {\n" +" Ok(T),\n" +" Err(E),\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"enum Result {\n" +" Ok(T),\n" +" Err(E),\n" +"}\n" +"```" + +#: src/ch07-01-generic-data-types.md:195 src/ch09-02-error-handling.md:18 +msgid "" +"The `Result` enum has two generic types, `T` and `E`, and two " +"variants: `Ok` which holds the value of type `T` and `Err` which holds the " +"value of type `E`. This definition makes it convenient to use the `Result` " +"enum anywhere we have an operation that might succeed (by returning a value " +"of type `T`) or fail (by returning a value of type `E`)." +msgstr "" +"`Result`枚举有两个泛型类型,`T`和`E`,以及两个成员:`Ok`,存放`T`类型的" +"值,`Err`,存放`E`类型的值。这个定义使得我们可以在任何地方使用`Result`枚举," +"该操作可能成功(返回`T`类型的值)或失败(返回`E`类型的值)。" + +#: src/ch07-01-generic-data-types.md:197 +msgid "## Generic Methods" +msgstr "## 方法定义中的泛型" + +#: src/ch07-01-generic-data-types.md:199 +msgid "" +"We can implement methods on structs and enums, and use the generic types in " +"their definition, too. Using our previous definition of `Wallet` struct, " +"we define a `balance` method for it:" +msgstr "" +"我们可以在结构和枚举上实现方法,也可以在其定义中使用泛型。在之前定义的" +"`Wallet`结构体上为其定义一个`balance` 方法:" + +#: src/ch07-01-generic-data-types.md:201 +msgid "" +"```rust\n" +"struct Wallet {\n" +" balance: T,\n" +"}\n" +"\n" +"impl WalletDrop> of Drop>;\n" +"impl WalletCopy> of Copy>;\n" +"\n" +"trait WalletTrait {\n" +" fn balance(self: @Wallet) -> T;\n" +"}\n" +"\n" +"impl WalletImpl> of WalletTrait {\n" +" fn balance(self: @Wallet) -> T {\n" +" return *self.balance;\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let w = Wallet { balance: 50 };\n" +" assert(w.balance() == 50, 0);\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"struct Wallet {\n" +" balance: T,\n" +"}\n" +"\n" +"impl WalletDrop> of Drop>;\n" +"impl WalletCopy> of Copy>;\n" +"\n" +"trait WalletTrait {\n" +" fn balance(self: @Wallet) -> T;\n" +"}\n" +"\n" +"impl WalletImpl> of WalletTrait {\n" +" fn balance(self: @Wallet) -> T {\n" +" return *self.balance;\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let w = Wallet { balance: 50 };\n" +" assert(w.balance() == 50, 0);\n" +"}\n" +"```" + +#: src/ch07-01-generic-data-types.md:225 +msgid "" +"We first define `WalletTrait` trait using a generic type `T` which " +"defines a method that returns a snapshot of the field `address` from " +"`Wallet`. Then we give an implementation for the trait in `WalletImpl`. " +"Note that you need to include a generic type in both definitions of the " +"trait and the implementation." +msgstr "" +"我们首先定义了`WalletTrait`trait,使用一个泛型`T`,它定义了一个方法,从" +"`Wallet`中返回字段`address`的快照。然后我们在`WalletImpl`中给出该trait的实" +"现。请注意,你需要在trait的定义和实现中都包含一个泛型。" + +#: src/ch07-01-generic-data-types.md:227 +msgid "" +"We can also specify constraints on generic types when defining methods on " +"the type. We could, for example, implement methods only for `Wallet` " +"instances rather than `Wallet`. In the code example we define an " +"implementation for wallets which have a concrete type of `u128` for the " +"`balance` field." +msgstr "" +"在定义类型上的方法时,我们也可以指定对泛型的约束。例如,我们可以只为" +"`Wallet`实例而不是`Wallet`实现方法。在代码示例中,我们为钱包定义了一" +"个实现,这些钱包的`balance`字段的具体类型为`u128`。" + +#: src/ch07-01-generic-data-types.md:229 +msgid "" +"```rust\n" +"struct Wallet {\n" +" balance: T,\n" +"}\n" +"impl WalletDrop> of Drop>;\n" +"impl WalletCopy> of Copy>;\n" +"/// Generic trait for wallets\n" +"trait WalletTrait {\n" +" fn balance(self: @Wallet) -> T;\n" +"}\n" +"\n" +"impl WalletImpl> of WalletTrait {\n" +" fn balance(self: @Wallet) -> T {\n" +" return *self.balance;\n" +" }\n" +"}\n" +"\n" +"/// Trait for wallets of type u128\n" +"trait WalletReceiveTrait {\n" +" fn receive(ref self: Wallet, value: u128);\n" +"}\n" +"\n" +"impl WalletReceiveImpl of WalletReceiveTrait {\n" +" fn receive(ref self: Wallet, value: u128) {\n" +" self.balance += value;\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut w = Wallet { balance: 50_u128 };\n" +" assert(w.balance() == 50_u128, 0);\n" +"\n" +" w.receive(100_u128);\n" +" assert(w.balance() == 150_u128, 0);\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"struct Wallet {\n" +" balance: T,\n" +"}\n" +"impl WalletDrop> of Drop>;\n" +"impl WalletCopy> of Copy>;\n" +"/// Generic trait for wallets\n" +"trait WalletTrait {\n" +" fn balance(self: @Wallet) -> T;\n" +"}\n" +"\n" +"impl WalletImpl> of WalletTrait {\n" +" fn balance(self: @Wallet) -> T {\n" +" return *self.balance;\n" +" }\n" +"}\n" +"\n" +"/// Trait for wallets of type u128\n" +"trait WalletReceiveTrait {\n" +" fn receive(ref self: Wallet, value: u128);\n" +"}\n" +"\n" +"impl WalletReceiveImpl of WalletReceiveTrait {\n" +" fn receive(ref self: Wallet, value: u128) {\n" +" self.balance += value;\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut w = Wallet { balance: 50_u128 };\n" +" assert(w.balance() == 50_u128, 0);\n" +"\n" +" w.receive(100_u128);\n" +" assert(w.balance() == 150_u128, 0);\n" +"}\n" +"```" + +#: src/ch07-01-generic-data-types.md:266 +msgid "" +"The new method `receive` increments the size of the balance of any instance " +"of a `Wallet`. Notice that we changed the `main` function making `w` a " +"mutable variable in order for it to be able to update its balance. If we " +"were to change the initialization of `w` by changing the type of `balance` " +"the previous code wouldn't compile." +msgstr "" +"新的方法`receive`增加了`Wallet`的实例的余额大小。请注意,我们改变了" +"`main`函数,使`w`成为一个可变的变量,以便它能够更新其余额。如果我们通过改变" +"`balance`的类型来改变`w`的初始化,那么之前的代码就不能编译了。" + +#: src/ch07-01-generic-data-types.md:268 +msgid "" +"Cairo allows us to define generic methods inside generic traits as well. " +"Using the past implementation from `Wallet` we are going to define a " +"trait that picks two wallets of different generic types and create a new one " +"with a generic type of each. First, lets rewrite the struct definiton:" +msgstr "" +"Cairo也允许我们在泛型trait中定义泛型方法。在之前的 \"Wallet\"的实现上定" +"义一个trait,用来选取两个不同泛型的钱包,并创建一个拥有两者泛型新的钱包。首" +"先,让我们重写结构体定义:" + +#: src/ch07-01-generic-data-types.md:270 +msgid "" +"```rust\n" +"struct Wallet {\n" +" balance: T,\n" +" address: U,\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"struct Wallet {\n" +" balance: T,\n" +" address: U,\n" +"}\n" +"```" + +#: src/ch07-01-generic-data-types.md:277 +msgid "Next we are going to naively define the mixup trait and implementation:" +msgstr "接下来,我们将初步地定义混合trait和其实现:" + +#: src/ch07-01-generic-data-types.md:279 +msgid "" +"```rust\n" +"// This does not compile!\n" +"trait WalletMixTrait {\n" +" fn mixup(self: Wallet, other: Wallet) -> " +"Wallet;\n" +"}\n" +"\n" +"impl WalletMixImpl of WalletMixTrait {\n" +" fn mixup(self: Wallet, other: Wallet) -> " +"Wallet {\n" +" Wallet { balance: self.balance, address: other.address }\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"// This does not compile!\n" +"trait WalletMixTrait {\n" +" fn mixup(self: Wallet, other: Wallet) -> " +"Wallet;\n" +"}\n" +"\n" +"impl WalletMixImpl of WalletMixTrait {\n" +" fn mixup(self: Wallet, other: Wallet) -> " +"Wallet {\n" +" Wallet { balance: self.balance, address: other.address }\n" +" }\n" +"}\n" +"```" + +#: src/ch07-01-generic-data-types.md:292 +msgid "" +"We are creating a trait `WalletMixTrait` with the `mixup` " +"methods which given an instance of `Wallet` and `Wallet` " +"creates a new `Wallet`. As `mixup` signature specify, both `self` " +"and `other` are getting dropped at the end of the function, which is the " +"reason for this code not to compile. If you have been following from the " +"start until now you would know that we must add a requirement for all the " +"generic types specifiying that they will implement the `Drop` trait in order " +"for the compiler to know how to drop instances of `Wallet`. The " +"updated implementation is as follow:" +msgstr "" +"我们正在创建一个trait`WalletMixTrait`,其中有`mixup`方法,给" +"定一个`Wallet`和`Wallet`的实例,创建一个新的`Wallet。" +"正如`mixup`签名所指定的,`self`和`other`都在函数的结尾处被丢弃,这就是这段代" +"码不能编译的原因。如果你从开始到现在一直没掉队,你会知道我们必须为所有的泛型" +"添加一个`Drop`trait的实现,以便编译器知道如何丢弃`Wallet`的实例。更新后" +"的实现如下:" + +#: src/ch07-01-generic-data-types.md:294 +msgid "" +"```rust\n" +"trait WalletMixTrait {\n" +" fn mixup, U2, impl U2Drop: Drop>(\n" +" self: Wallet, other: Wallet\n" +" ) -> Wallet;\n" +"}\n" +"\n" +"impl WalletMixImpl, U1, impl U1Drop: Drop> of " +"WalletMixTrait {\n" +" fn mixup, U2, impl U2Drop: Drop>(\n" +" self: Wallet, other: Wallet\n" +" ) -> Wallet {\n" +" Wallet { balance: self.balance, address: other.address }\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"trait WalletMixTrait {\n" +" fn mixup, U2, impl U2Drop: Drop>(\n" +" self: Wallet, other: Wallet\n" +" ) -> Wallet;\n" +"}\n" +"\n" +"impl WalletMixImpl, U1, impl U1Drop: Drop> of " +"WalletMixTrait {\n" +" fn mixup, U2, impl U2Drop: Drop>(\n" +" self: Wallet, other: Wallet\n" +" ) -> Wallet {\n" +" Wallet { balance: self.balance, address: other.address }\n" +" }\n" +"}\n" +"```" + +#: src/ch07-01-generic-data-types.md:310 +msgid "" +"We add the requirements for `T1` and `U1` to be droppable on `WalletMixImpl` " +"declaration. Then we do the same for `T2` and `U2`, this time as part of " +"`mixup` signature. We can now try the `mixup` function:" +msgstr "" +"我们在 `WalletMixImpl`\"的声明中添加了 `T1`和 `U1`的可丢弃trait。然后我们对" +"`T2`和`U2`做同样的处理,这次是作为`mixup`签名的一部分。现在我们可以尝试使用" +"`mixup` 函数了:" + +#: src/ch07-01-generic-data-types.md:312 +msgid "" +"```rs, does_not_compile\n" +"fn main() {\n" +" let w1 = Wallet { balance: true, address: 10_u128 };\n" +" let w2 = Wallet { balance: 32, address: 100_u8 };\n" +"\n" +" let w3 = w1.mixup(w2);\n" +"\n" +" assert(w3.balance == true, 0);\n" +" assert(w3.address == 100_u8, 0);\n" +"}\n" +"```" +msgstr "" +"```rs, does_not_compile\n" +"fn main() {\n" +" let w1 = Wallet { balance: true, address: 10_u128 };\n" +" let w2 = Wallet { balance: 32, address: 100_u8 };\n" +"\n" +" let w3 = w1.mixup(w2);\n" +"\n" +" assert(w3.balance == true, 0);\n" +" assert(w3.address == 100_u8, 0);\n" +"}\n" +"```" + +#: src/ch07-01-generic-data-types.md:324 +msgid "" +"We first create two instances: one of `Wallet` and the other of " +"`Wallet`. Then, we call `mixup` and create a new `Wallet` instance." +msgstr "" +"我们首先创建两个实例:一个是 `Wallet`,另一个是`Wallet`。然后,我们调用`mixup`并创建一个新的`Wallet`实例。" + +#: src/ch07-02-traits-in-cairo.md:1 +msgid "# Traits in Cairo" +msgstr "# Cairo中的Trait" + +#: src/ch07-02-traits-in-cairo.md:3 +msgid "" +"Traits specify functionality blueprints that can be implemented. The " +"blueprint specification includes a set of function signatures containing " +"type annotations for the parameters and return value. This sets a standard " +"to implement the specific functionality." +msgstr "" +"Trait(译注:也被称为特性,但本译文中将跟随rust中文的习惯,直接使用英文原单" +"词)定义了可以实现的功能蓝图的规范。蓝图规范包括一组包含参数和返回值类型注释" +"的函数签名。这为实现特定的功能设定了一个标准。(译注:trait 类似于其他语言中" +"的常被称为 接口(interfaces)的功能,虽然有一些不同。)" + +#: src/ch07-02-traits-in-cairo.md:5 +msgid "## Defining a Trait" +msgstr "## 定义一个Trait" + +#: src/ch07-02-traits-in-cairo.md:7 +msgid "" +"To define a trait, you use the keyword `trait` followed by the name of the " +"trait in `PascalCase` then the function signatures in a pair of curly braces." +msgstr "" +"要定义一个Trait,你可以使用关键字`trait`,后面是以`PascalCase`书写的trait名" +"称,然后是一对大括号内的函数签名。" + +#: src/ch07-02-traits-in-cairo.md:9 +msgid "" +"For example, let's say that we have multiple structs representing shapes. We " +"want our application to be able to perform geometry operations on these " +"shapes, So we define a trait `ShapeGeometry` that contains a blueprint to " +"implement geometry operations on a shape like this:" +msgstr "" +"例如,假设我们有多个代表形状的结构体。我们希望我们的应用程序能够对这些形状进" +"行几何操作,所以我们定义了一个trait`ShapeGeometry`,它包含一个蓝图来实现对形" +"状的几何操作:" + +#: src/ch07-02-traits-in-cairo.md:11 +msgid "" +"```rust\n" +"trait ShapeGeometry {\n" +" fn boundary(self: Rectangle) -> u64;\n" +" fn area(self: Rectangle) -> u64;\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"trait ShapeGeometry {\n" +" fn boundary(self: Rectangle) -> u64;\n" +" fn area(self: Rectangle) -> u64;\n" +"}\n" +"```" + +#: src/ch07-02-traits-in-cairo.md:18 +msgid "" +"Here our trait `ShapeGeometry` declares signatures for two methods " +"`boundary` and `area`. When implemented, both these functions should return " +"a `u64` and accept parameters as specified by the trait." +msgstr "" +"这里我们的trait `ShapeGeometry`声明了两个方法的签名`boundary`和`area`。当编写" +"实现时,这两个函数都应该返回一个`u64',并接受trait所规定的参数。" + +#: src/ch07-02-traits-in-cairo.md:20 +msgid "## Implementing a Trait" +msgstr "## 实现一个trait" + +#: src/ch07-02-traits-in-cairo.md:22 +msgid "" +"A trait can be implemented using `impl` keyword with the name of your " +"implementation followed by `of` then the name of trait being implemented. " +"Here's an example implementing `ShapeGeometry` trait." +msgstr "" +"一个trait可以用`impl`关键字来实现,在你的实现名称后面加上`of`,然后是被实现的" +"trait的名称。下面是一个实现`ShapeGeometry`trait的例子。" + +#: src/ch07-02-traits-in-cairo.md:24 +msgid "" +"```rust\n" +"impl RectangleGeometry of ShapeGeometry {\n" +"\tfn boundary(self: Rectangle) -> u64 {\n" +" 2_u64 * (self.height + self.width)\n" +" }\n" +"\tfn area(self: Rectangle) -> u64 {\n" +"\t\tself.height * self.width\n" +"\t}\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"impl RectangleGeometry of ShapeGeometry {\n" +"\tfn boundary(self: Rectangle) -> u64 {\n" +" 2_u64 * (self.height + self.width)\n" +" }\n" +"\tfn area(self: Rectangle) -> u64 {\n" +"\t\tself.height * self.width\n" +"\t}\n" +"}\n" +"```" + +#: src/ch07-02-traits-in-cairo.md:35 +msgid "" +"In the code above, `RectangleGeometry` implements the trait `ShapeGeometry` " +"defining what the methods `boundary` and `area` should do. Note that the " +"function parameters and return value types are identical to the trait " +"specification." +msgstr "" +"在上面的代码中,`RectangleGeometry'实现了`ShapeGeometry'的trait,定义了" +"`boundary'和`area'方法应该做什么。请注意,函数参数和返回值的类型与trait所定义" +"的规范是相同的。" + +#: src/ch07-02-traits-in-cairo.md:37 +msgid "## Parameter `self`" +msgstr "## 参数 `self`" + +#: src/ch07-02-traits-in-cairo.md:39 +msgid "" +"In the example above, `self` is a special parameter. When a parameter with " +"name `self` is used, the implemented functions are also [attached to the " +"instances of the type as methods](ch04-03-method-syntax.md#defining-" +"methods). Here's an illustration," +msgstr "" +"在上面的例子中,`self`是一个特殊参数。当使用名称为`self`的参数时,实现的函数" +"也会[作为方法附加到类型的实例上](ch04-03-method-syntax.md#defining-methods)。" +"下面是一个演示、" + +#: src/ch07-02-traits-in-cairo.md:41 +msgid "" +"When the `ShapeGeometry` trait is implemented, the function `area` from the " +"`ShapeGeometry` trait can be called in two ways:" +msgstr "" +"当 \"ShapeGeometry \"特质被实现时,\"ShapeGeometry \"特质中的函数 \"area \"可" +"以通过两种方式被调用:" + +#: src/ch07-02-traits-in-cairo.md:43 +msgid "" +"```rust\n" +"let rect = Rectangle { ... }; // Rectangle instantiation\n" +"\n" +"// First way, as a method on the struct instance\n" +"let area1 = rect.area();\n" +"// Second way, from the implementation\n" +"let area2 = RectangleGeometry::area(rect);\n" +"// `area1` has same value as `area2`\n" +"area1.print();\n" +"area2.print();\n" +"```" +msgstr "" +"```rust\n" +"let rect = Rectangle { ... }; // Rectangle instantiation\n" +"\n" +"// First way, as a method on the struct instance\n" +"let area1 = rect.area();\n" +"// Second way, from the implementation\n" +"let area2 = RectangleGeometry::area(rect);\n" +"// `area1` has same value as `area2`\n" +"area1.print();\n" +"area2.print();\n" +"```" + +#: src/ch07-02-traits-in-cairo.md:55 +msgid "" +"And the implementation of the `area` method will be accessed via the `self` " +"parameter." +msgstr "之后我们可以通过 `self`参数访问`area`方法的实现。" + +#: src/ch07-02-traits-in-cairo.md:57 +msgid "## Generic Traits" +msgstr "## 泛型Traits" + +#: src/ch07-02-traits-in-cairo.md:59 +msgid "" +"Usually we want to write a trait when we want multiple types to implement a " +"functionality in a standard way. However, in the example above the " +"signatures are static and cannot be used for multiple types. To do this, we " +"use generic types when defining traits." +msgstr "" +"通常情况下,当我们希望多个类型以标准的方式实现一个功能时,我们要写一个trait。" +"然而,在上面的例子中,签名是静态的,不能用于多种类型。为了做到这一点,我们在" +"定义特质时使用泛型。" + +#: src/ch07-02-traits-in-cairo.md:61 +msgid "" +"In the example below, we use generic type `T` and our method signatures can " +"use this alias which can be provided during implementation." +msgstr "" +"在下面的例子中,我们使用泛型`T`,我们的方法签名可以使用由实现提供这个别名。" + +#: src/ch07-02-traits-in-cairo.md:63 +msgid "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"#[derive(Copy,Drop)]\n" +"struct Rectangle{\n" +" height: u64,\n" +" width: u64,\n" +"}\n" +"\n" +"#[derive(Copy,Drop)]\n" +"struct Circle{\n" +" radius: u64,\n" +"}\n" +"\n" +"// Here T is an alias type which will be provided buring implementation\n" +"trait ShapeGeometry {\n" +" fn boundary(self: T) -> u64;\n" +" fn area(self: T) -> u64;\n" +"}\n" +"\n" +"// Implementation RectangleGeometry passes in \n" +"// to implement the trait for that type\n" +"impl RectangleGeometry of ShapeGeometry {\n" +" fn boundary(self: Rectangle) -> u64 {\n" +" 2_u64 * (self.height + self.width)\n" +" }\n" +" fn area(self: Rectangle) -> u64 {\n" +" self.height * self.width\n" +" }\n" +"}\n" +"\n" +"// We might have another struct Circle\n" +"// which can use the same trait spec\n" +"impl CircleGeometry of ShapeGeometry {\n" +" fn boundary(self: Circle) -> u64 {\n" +" (2_u64 * 314_u64 * self.radius) / 100_u64\n" +" }\n" +" fn area(self: Circle) -> u64 {\n" +" (314_u64 * self.radius * self.radius) / 100_u64\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let rect = Rectangle { height: 5_u64, width: 7_u64 };\n" +" rect.area().print(); // 35\n" +" rect.boundary().print(); // 24\n" +"\n" +" let circ = Circle { radius: 5_u64 };\n" +" circ.area().print(); // 78\n" +" circ.boundary().print(); // 31\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use debug::PrintTrait;\n" +"\n" +"#[derive(Copy,Drop)]\n" +"struct Rectangle{\n" +" height: u64,\n" +" width: u64,\n" +"}\n" +"\n" +"#[derive(Copy,Drop)]\n" +"struct Circle{\n" +" radius: u64,\n" +"}\n" +"\n" +"// Here T is an alias type which will be provided buring implementation\n" +"trait ShapeGeometry {\n" +" fn boundary(self: T) -> u64;\n" +" fn area(self: T) -> u64;\n" +"}\n" +"\n" +"// Implementation RectangleGeometry passes in \n" +"// to implement the trait for that type\n" +"impl RectangleGeometry of ShapeGeometry {\n" +" fn boundary(self: Rectangle) -> u64 {\n" +" 2_u64 * (self.height + self.width)\n" +" }\n" +" fn area(self: Rectangle) -> u64 {\n" +" self.height * self.width\n" +" }\n" +"}\n" +"\n" +"// We might have another struct Circle\n" +"// which can use the same trait spec\n" +"impl CircleGeometry of ShapeGeometry {\n" +" fn boundary(self: Circle) -> u64 {\n" +" (2_u64 * 314_u64 * self.radius) / 100_u64\n" +" }\n" +" fn area(self: Circle) -> u64 {\n" +" (314_u64 * self.radius * self.radius) / 100_u64\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let rect = Rectangle { height: 5_u64, width: 7_u64 };\n" +" rect.area().print(); // 35\n" +" rect.boundary().print(); // 24\n" +"\n" +" let circ = Circle { radius: 5_u64 };\n" +" circ.area().print(); // 78\n" +" circ.boundary().print(); // 31\n" +"}\n" +"```" + +#: src/ch07-02-traits-in-cairo.md:116 +msgid "## Managing and using external trait implementations" +msgstr "## 管理和使用外部trait的实现" + +#: src/ch07-02-traits-in-cairo.md:118 +msgid "" +"To use traits methods, you need to make sure the correct traits/" +"implementation(s) are imported. In the code above we imported `PrintTrait` " +"from `debug` with `use debug::PrintTrait;` to use the `print()` methods on " +"supported types." +msgstr "" +"要使用trait的方法,你需要确保导入了正确的 traits以及它的实现。在上面的代码" +"中,我们从`debug`中导入了`PrintTrait`,并使用`use debug::PrintTrait;`以在支持" +"的类型上使用`print()`方法。" + +#: src/ch07-02-traits-in-cairo.md:120 +msgid "" +"In some cases you might need to import not only the trait but also the " +"implementation if they are declared in separate modules.\n" +"If `CircleGeometry` was in a separate module/file `circle` then to use " +"`boundary` on `circ: Circle`, we'd need to import `CircleGeometry` in " +"addition to `ShapeGeometry`." +msgstr "" +"在某些情况下,如果它们被声明在不同的模块中,你可能不仅需要导入trait,还需要导" +"入实现。\n" +"如果`CircleGeometry`是在一个单独的模块/文件`circle`中,那么要在`circ: Circle`" +"上使用`boundary`,我们就需要在 `ShapeGeometry`之外再导入 `CircleGeometry`。" + +#: src/ch07-02-traits-in-cairo.md:123 +msgid "If the code was organised into modules like this," +msgstr "如果代码被如下般组织成模块:" + +#: src/ch07-02-traits-in-cairo.md:125 +msgid "" +"```rust, does_not_compile\n" +"use debug::PrintTrait;\n" +"\n" +"// struct Circle { ... } and struct Rectangle { ... }\n" +"\n" +"mod geometry {\n" +" use super::Rectangle;\n" +" trait ShapeGeometry {\n" +" // ...\n" +" }\n" +"\n" +" impl RectangleGeometry of ShapeGeometry:: {\n" +" // ...\n" +" }\n" +"}\n" +"\n" +"// Could be in a different file\n" +"mod circle {\n" +" use super::geometry::ShapeGeometry;\n" +" use super::Circle;\n" +" impl CircleGeometry of ShapeGeometry:: {\n" +" // ...\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let rect = Rectangle { height: 5_u64, width: 7_u64 };\n" +" let circ = Circle { radius: 5_u64 };\n" +" // Fails with this error\n" +" // Method `area` not found on... Did you import the correct trait and " +"impl?\n" +" rect.area().print();\n" +" circ.area().print();\n" +"}\n" +"```" +msgstr "" +"```rust, does_not_compile\n" +"use debug::PrintTrait;\n" +"\n" +"// struct Circle { ... } and struct Rectangle { ... }\n" +"\n" +"mod geometry {\n" +" use super::Rectangle;\n" +" trait ShapeGeometry {\n" +" // ...\n" +" }\n" +"\n" +" impl RectangleGeometry of ShapeGeometry:: {\n" +" // ...\n" +" }\n" +"}\n" +"\n" +"// Could be in a different file\n" +"mod circle {\n" +" use super::geometry::ShapeGeometry;\n" +" use super::Circle;\n" +" impl CircleGeometry of ShapeGeometry:: {\n" +" // ...\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let rect = Rectangle { height: 5_u64, width: 7_u64 };\n" +" let circ = Circle { radius: 5_u64 };\n" +" // Fails with this error\n" +" // Method `area` not found on... Did you import the correct trait and " +"impl?\n" +" rect.area().print();\n" +" circ.area().print();\n" +"}\n" +"```" + +#: src/ch07-02-traits-in-cairo.md:160 +msgid "To make it work, in addition to," +msgstr "为了使其发挥作用,除此之外、" + +#: src/ch07-02-traits-in-cairo.md:162 +msgid "" +"```rust\n" +"use geometry::ShapeGeometry;\n" +"```" +msgstr "" +"```rust\n" +"use geometry::ShapeGeometry;\n" +"```" + +#: src/ch07-02-traits-in-cairo.md:166 +msgid "you might also need to use `CircleGeometry`," +msgstr "你可能还需要使用`CircleGeometry`、" + +#: src/ch07-02-traits-in-cairo.md:168 +msgid "" +"```rust\n" +"use circle::CircleGeometry\n" +"```" +msgstr "" +"```rust\n" +"use circle::CircleGeometry;\n" +"```" + +#: src/ch08-00-testing-cairo-programs.md:1 +msgid "# Testing Cairo Programs" +msgstr "# 测试Cairo 程序" + +#: src/ch08-01-how-to-write-tests.md:1 +msgid "# How To Write Tests" +msgstr "# 如何编写测试" + +#: src/ch08-01-how-to-write-tests.md:3 +msgid "## The Anatomy of a Test Function" +msgstr "## 测试函数的剖析" + +#: src/ch08-01-how-to-write-tests.md:5 +msgid "" +"Tests are Cairo functions that verify that the non-test code is functioning " +"in the expected manner. The bodies of test functions typically perform these " +"three actions:" +msgstr "" +"测试是Cairo函数,用于验证非测试代码是否以预期方式运行。测试函数的主体通常执行" +"这三个动作:" + +#: src/ch08-01-how-to-write-tests.md:7 +msgid "" +"- Set up any needed data or state.\n" +"- Run the code you want to test.\n" +"- Assert the results are what you expect." +msgstr "" +"- 设置任何需要的数据或状态。\n" +"- 运行你想测试的代码。\n" +"- 断言结果与你期望的一样。" + +#: src/ch08-01-how-to-write-tests.md:11 +msgid "" +"Let’s look at the features Cairo provides specifically for writing tests " +"that take these actions, which include the `test` attribute, the `assert` " +"function, and and the `should_panic` attribute." +msgstr "" +"让我们看看Cairo专门为编写执行这些测试提供的功能,其中包括`test`属性、`assert`" +"函数和`should_panic`属性。" + +#: src/ch08-01-how-to-write-tests.md:13 +msgid "### The Anatomy of a Test Function" +msgstr "### 一个测试函数的剖析" + +#: src/ch08-01-how-to-write-tests.md:15 +msgid "" +"At its simplest, a test in Cairo is a function that’s annotated with the " +"`test` attribute. Attributes are metadata about pieces of Cairo code; one " +"example is the derive attribute we used with structs in Chapter 4. To change " +"a function into a test function, add `#[test]` on the line before `fn`. When " +"you run your tests with the `cairo-test` command, Cairo builds a test runner " +"binary that runs the annotated functions and reports on whether each test " +"function passes or fails." +msgstr "" +"最简单的Cairo中的测试是一个带有`test`属性注释的函数。属性是关于Cairo代码片段" +"的元数据;一个例子是我们在第4章中对结构体使用的derive属性。要把一个函数变成测" +"试函数,在 `fn`前的一行加上 `#[test]`。当你用`cairo-test`命令运行你的测试时," +"Cairo会建立一个测试运行器的二进制文件,运行被标注了的函数,并报告每个测试函数" +"的通过或失败。" + +#: src/ch08-01-how-to-write-tests.md:17 +msgid "" +"Let's create a new project called `adder` that will add two numbers using " +"Scarb with the command `scarb new adder`:" +msgstr "" +"让我们创建一个名为 `adder`的将两个数字相加的新项目,用`scarb new adder`”命" +"令:" + +#: src/ch08-01-how-to-write-tests.md:19 +msgid "" +"```shell\n" +"adder\n" +"├── cairo_project.toml\n" +"├── Scarb.toml\n" +"└── src\n" +" └── lib.cairo\n" +"```" +msgstr "" +"```shell\n" +"adder\n" +"├── cairo_project.toml\n" +"├── Scarb.toml\n" +"└── src\n" +" └── lib.cairo\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:27 src/ch08-02-test-organization.md:51 +msgid "" +msgstr "" + +#: src/ch08-01-how-to-write-tests.md:29 +msgid "" +"> Note: You will notice here a `cairo_project.toml` file.\n" +"> This is the configuration file for \"vanilla\" Cairo projects (i.e. not " +"managed by Scarb),\n" +"> which is required to run the `cairo-test .` command to run the code of the " +"crate.\n" +"> It is required until Scarb implements this feature. The content of the " +"file is:\n" +">\n" +"> ```toml\n" +"> [crate_roots]\n" +"> adder = \"src\"\n" +"> ```\n" +">\n" +"> and indicates that the crate named \"adder\" is located in the `src` " +"directory." +msgstr "" +"> 注意:你会注意到这里有一个`cairo_project.toml`文件。\n" +"> 这是 普通的Cairo项目的配置文件(即不由Scarb管理)、\n" +"> 在运行`cairo-test .`命令来运行crate的代码需要这个文件。\n" +"> 在Scarb实现这一功能之前,它是必需的。该文件的内容是:\n" +">\n" +"> ```toml\n" +"> [crate_roots]\n" +"> adder = “src”\n" +"> ```\n" +">\n" +"> 该文件指出,名为 \"adder \"的crate位于`src`目录下。" + +#: src/ch08-01-how-to-write-tests.md:41 +msgid "In _lib.cairo_, let's add a first test, as shown in Listing 8-1." +msgstr "在 _lib.cairo_ 中,让我们添加第一个测试,如清单8-1所示。" + +#: src/ch08-01-how-to-write-tests.md:43 src/ch08-01-how-to-write-tests.md:79 +#: src/ch08-01-how-to-write-tests.md:140 src/ch08-01-how-to-write-tests.md:162 +#: src/ch08-01-how-to-write-tests.md:201 src/ch08-01-how-to-write-tests.md:274 +#: src/ch08-01-how-to-write-tests.md:355 src/ch08-02-test-organization.md:19 +#: src/ch09-01-unrecoverable-errors-with-panic.md:9 +msgid "Filename: lib.cairo" +msgstr "文件名:lib.cairo" + +#: src/ch08-01-how-to-write-tests.md:45 src/ch08-02-test-organization.md:21 +msgid "" +"```rust\n" +"#[cfg(test)]\n" +"mod tests {\n" +" #[test]\n" +" fn it_works() {\n" +" let result = 2 + 2;\n" +" assert(result == 4, 'result is not 4');\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[cfg(test)]\n" +"mod tests {\n" +" #[test]\n" +" fn it_works() {\n" +" let result = 2 + 2;\n" +" assert(result == 4, ‘result is not 4’);\n" +" }\n" +"}\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:56 +msgid "Listing 8-1: A test module and function" +msgstr "清单8-1:一个测试模块和函数" + +#: src/ch08-01-how-to-write-tests.md:58 +msgid "" +"For now, let’s ignore the top two lines and focus on the function. Note the " +"`#[test]` annotation: this attribute indicates this is a test function, so " +"the test runner knows to treat this function as a test. We might also have " +"non-test functions in the tests module to help set up common scenarios or " +"perform common operations, so we always need to indicate which functions are " +"tests." +msgstr "" +"现在,让我们忽略最上面的两行,专注于这个函数。注意`#[test]`标注:这个属性表明" +"这是一个测试函数,所以测试运行器知道要把这个函数当作一个测试。我们可能在测试" +"模块中也有非测试函数,以帮助设置常见的场景或执行常见的操作,所以我们总是需要" +"指出哪些函数是测试的。" + +#: src/ch08-01-how-to-write-tests.md:60 +msgid "" +"The example function body uses the `assert` function, which contains the " +"result of adding 2 and 2, equals 4. This assertion serves as an example of " +"the format for a typical test. Let’s run it to see that this test passes." +msgstr "" +"这个例子的函数体使用了`assert`函数,它包含了2和2相加的结果,等于4。这个断言是" +"一个典型测试格式范例。让我们运行它,看看这个测试是否通过。" + +#: src/ch08-01-how-to-write-tests.md:62 +msgid "" +"The `cairo-test .` command runs all tests in our project, as shown in " +"Listing 8-2." +msgstr "用`cairo-test .`命令运行我们项目中的所有测试,如清单8-2所示。" + +#: src/ch08-01-how-to-write-tests.md:64 +msgid "" +"```shell\n" +"$ cairo-test .\n" +"running 1 tests\n" +"test adder::lib::tests::it_works ... ok\n" +"test result: ok. 1 passed; 0 failed; 0 ignored; 0 filtered out;\n" +"```" +msgstr "" +"```shell\n" +"$ cairo-test .\n" +"running 1 tests\n" +"test adder::lib::tests::it_works … ok\n" +"test result: ok. 1 passed; 0 failed; 0 ignored; 0 filtered out;\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:71 +msgid "Listing 8-2: The output from running a test" +msgstr "清单8-2:运行一个测试的输出结果" + +#: src/ch08-01-how-to-write-tests.md:73 +msgid "" +"`cairo-test` compiled and ran the test. We see the line `running 1 tests`. " +"The next line shows the name of the generated test function, called " +"`it_works`, and that the result of running that test is `ok`. The overall " +"summary `test result: ok.` means that all the tests passed, and the portion " +"that reads `1 passed; 0 failed` totals the number of tests that passed or " +"failed." +msgstr "" +"`cairo-test`编译并运行了测试。我们看到一行`running 1 tests`。下一行显示了生成" +"的测试函数的名称,叫做`it_works`,运行该测试的结果是`ok`。总体摘要`test " +"result: ok.`意味着所有的测试都通过了,`1 passed; 0 failed` 的部分展示了通过或" +"失败的测试的总数。" + +#: src/ch08-01-how-to-write-tests.md:75 +msgid "" +"It’s possible to mark a test as ignored so it doesn’t run in a particular " +"instance; we’ll cover that in the [Ignoring Some Tests Unless Specifically " +"Requested](#ignoring-some-tests-unless-specifically-requested) section later " +"in this chapter. Because we haven’t done that here, the summary shows `0 " +"ignored`. We can also pass an argument to the `cairo-test` command to run " +"only a test whose name matches a string; this is called filtering and we’ll " +"cover that in the [Running Single Tests](#running-single-tests) section. We " +"also haven’t filtered the tests being run, so the end of the summary shows " +"`0 filtered out`." +msgstr "" +"我们可以把一个测试标记为忽略,这样它就不会在一个特定的实例中运行;我们将在本" +"章后面的[忽略一些测试,除非特别要求](#ignoring-some-tests-unless-" +"specifically-requested)一节中介绍。因为我们在这里没有这样做,所以摘要中显示 " +"`0 ignored`。我们也可以给`cairo-test`命令传递一个参数,只运行名称与某个字符串" +"相匹配的测试;这叫做过滤,我们将在[运行单个测试](#running-single-test)一节中" +"介绍。我们也没有对正在运行的测试进行过滤,所以总结的最后显示`0 filtered " +"out`。" + +#: src/ch08-01-how-to-write-tests.md:77 +msgid "" +"Let’s start to customize the test to our own needs. First change the name of " +"the `it_works` function to a different name, such as `exploration`, like so:" +msgstr "" +"让我们开始根据我们自己的需要定制测试。首先将`it_works`函数的名称改为不同的名" +"称,例如`exploration`,像这样:" + +#: src/ch08-01-how-to-write-tests.md:81 +msgid "" +"```rust\n" +"#[cfg(test)]\n" +"mod tests {\n" +" #[test]\n" +" fn exploration() {\n" +" let result = 2 + 2;\n" +" assert(result == 4, 'result is not 4');\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[cfg(test)]\n" +"mod tests {\n" +" #[test]\n" +" fn exploration() {\n" +" let result = 2 + 2;\n" +" assert(result == 4, ‘result is not 4’);\n" +" }\n" +"}\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:92 +msgid "" +"Then run `cairo-test -- --path src` again. The output now shows " +"`exploration` instead of `it_works`:" +msgstr "" +"然后再次运行`cairo-test -- --path src`。现在输出显示的是 `exploration`而不是" +"`it_works`:" + +#: src/ch08-01-how-to-write-tests.md:94 +msgid "" +"```shell\n" +"$ cairo-test .\n" +"running 1 tests\n" +"test adder::lib::tests::exploration ... ok\n" +"test result: ok. 1 passed; 0 failed; 0 ignored; 0 filtered out;\n" +"```" +msgstr "" +"```shell\n" +"$ cairo-test .\n" +"running 1 tests\n" +"test adder::lib::tests::exploration … ok\n" +"test result: ok. 1 passed; 0 failed; 0 ignored; 0 filtered out;\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:101 +msgid "" +"Now we’ll add another test, but this time we’ll make a test that fails! " +"Tests fail when something in the test function panics. Each test is run in a " +"new thread, and when the main thread sees that a test thread has died, the " +"test is marked as failed. Enter the new test as a function named `another`, " +"so your _src/lib.cairo_ file looks like Listing 8-3." +msgstr "" +"现在我们将添加另一个测试,但这次我们要做一个失败的测试! 当测试函数中的某些东" +"西发生panic时,测试就会失败。每个测试都在一个新的线程中运行,当主线程看到一个" +"测试线程死亡时,该测试被标记为失败。将新的测试作为一个名为`another`的函数输" +"入,因此你的 _src/lib.cairo_ 文件看起来像清单8-3里一样。" + +#: src/ch08-01-how-to-write-tests.md:103 +msgid "" +"```rust\n" +"#[cfg(test)]\n" +"mod tests{\n" +" #[test]\n" +" fn another() {\n" +" let result = 2 + 2;\n" +" assert(result == 6, 'Make this test fail');\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[cfg(test)]\n" +"mod tests{\n" +" #[test]\n" +" fn another() {\n" +" let result = 2 + 2;\n" +" assert(result == 6, ‘Make this test fail’);\n" +" }\n" +"}\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:114 +msgid "Listing 8-3: Adding a second test that will fail" +msgstr "清单8-3:添加第二个测试(会失败的测试)" + +#: src/ch08-01-how-to-write-tests.md:116 +msgid "" +"```shell\n" +"$ cairo-test .\n" +"running 2 tests\n" +"test adder::lib::tests::exploration ... ok\n" +"test adder::lib::tests::another ... fail\n" +"failures:\n" +" adder::lib::tests::another - panicked with " +"[1725643816656041371866211894343434536761780588 ('Make this test fail'), ].\n" +"Error: test result: FAILED. 1 passed; 1 failed; 0 ignored\n" +"```" +msgstr "" +"```shell\n" +"$ cairo-test .\n" +"running 2 tests\n" +"test adder::lib::tests::exploration … ok\n" +"test adder::lib::tests::another … fail\n" +"failures:\n" +" adder::lib::tests::another - panicked with " +"[1725643816656041371866211894343434536761780588 (‘Make this test fail’), ].\n" +"Error: test result: FAILED. 1 passed; 1 failed; 0 ignored\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:126 +msgid "Listing 8-4: Test results when one test passes and one test fails" +msgstr "清单8-4:一个测试通过,一个测试失败时的测试结果" + +#: src/ch08-01-how-to-write-tests.md:128 +msgid "" +"Instead of `ok`, the line `adder::lib::tests::another` shows `fail`. A new " +"section appears between the individual results and the summary. It displays " +"the detailed reason for each test failure. In this case, we get the details " +"that `another` failed because it panicked with " +"`[1725643816656041371866211894343434536761780588 ('Make this test fail'), ]` " +"in the _src/lib.cairo_ file." +msgstr "" +"`adder::lib::test::another`这一行没有显示`ok`,而是显示`fail`。在单个结果和摘" +"要之间出现了一个新的部分。它显示了每个测试失败的详细原因。在这个例子中,我们" +"得到的细节在是 _src/lib.cairo_文件中`another`失败了,因为它发生了panic " +"`[1725643816656041371866211894343434536761780588 (‘Make this test " +"fail’), ]`。" + +#: src/ch08-01-how-to-write-tests.md:130 +msgid "" +"The summary line displays at the end: overall, our test result is `FAILED`. " +"We had one test pass and one test fail." +msgstr "" +"摘要行显示在最后:总的来说,我们的测试结果是`FAILED'。我们有一个测试通过,一" +"个测试失败。" + +#: src/ch08-01-how-to-write-tests.md:132 +msgid "" +"Now that you’ve seen what the test results look like in different scenarios, " +"let’s look at some functions that are useful in tests." +msgstr "" +"现在你已经看到了不同场景下的测试结果,让我们看看一些在测试中有用的函数。" + +#: src/ch08-01-how-to-write-tests.md:134 +msgid "## Checking Results with the assert function" +msgstr "## 用断言函数检查结果" + +#: src/ch08-01-how-to-write-tests.md:136 +msgid "" +"The `assert` function, provided by Cairo, is useful when you want to ensure " +"that some condition in a test evaluates to `true`. We give the `assert` " +"function a first argument that evaluates to a Boolean. If the value is " +"`true`, nothing happens and the test passes. If the value is `false`, the " +"assert function calls `panic()` to cause the test to fail with a message we " +"defined as the second argument of the `assert` function. Using the `assert` " +"function helps us check that our code is functioning in the way we intend." +msgstr "" +"Cairo提供的`assert`函数,在你想确保测试中的某些条件一定为`true`时非常有用。我" +"们给`assert`函数的第一个参数是一个布尔值。如果该值为`true`,则不会发生任何事" +"情,测试通过。如果值是 `false`,assert函数调用 `panic()`,导致测试失败,我们" +"定义的信息是 `assert`函数的第二个参数。使用`assert`函数可以帮助我们检查我们的" +"代码是否按照我们的意图运行。" + +#: src/ch08-01-how-to-write-tests.md:138 +msgid "" +"In [Chapter 4, Listing 5-15](ch04-03-method-syntax.md#multiple-impl-blocks), " +"we used a `Rectangle` struct and a `can_hold` method, which are repeated " +"here in Listing 8-5. Let’s put this code in the _src/lib.cairo_ file, then " +"write some tests for it using the `assert` function." +msgstr "" +"在[第4章,清单5-15](ch04-03-method-syntax.md#multiple-impl-blocks)中,我们使" +"用了一个`Rectangle`结构和一个`can_hold`方法,在清单8-5中重复了这些。让我们把" +"这段代码放在_src/lib.cairo_文件中,然后用`assert`函数为它写一些测试。" + +#: src/ch08-01-how-to-write-tests.md:142 +msgid "" +"```rust\n" +"trait RectangleTrait {\n" +" fn area(self: @Rectangle) -> u64;\n" +" fn can_hold(self: @Rectangle, other: @Rectangle) -> bool;\n" +"}\n" +"\n" +"impl RectangleImpl of RectangleTrait {\n" +" fn area(self: @Rectangle) -> u64 {\n" +" *self.width * *self.height\n" +" }\n" +" fn can_hold(self: @Rectangle, other: @Rectangle) -> bool {\n" +" *self.width > *other.width & *self.height > *other.height\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"trait RectangleTrait {\n" +" fn area(self: @Rectangle) -> u64;\n" +" fn can_hold(self: @Rectangle, other: @Rectangle) -> bool;\n" +"}\n" +"\n" +"impl RectangleImpl of RectangleTrait {\n" +" fn area(self: @Rectangle) -> u64 {\n" +" *self.width * *self.height\n" +" }\n" +" fn can_hold(self: @Rectangle, other: @Rectangle) -> bool {\n" +" *self.width > *other.width & *self.height > *other.height\n" +" }\n" +"}\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:158 +msgid "" +"Listing 8-5: Using the `Rectangle` struct and its `can_hold` method from " +"Chapter 5" +msgstr "清单8-5:使用第五章中的 `Rectangle`结构及其`can_hold`方法" + +#: src/ch08-01-how-to-write-tests.md:160 +msgid "" +"The `can_hold` method returns a `Boolean`, which means it’s a perfect use " +"case for the assert function. In Listing 8-6, we write a test that exercises " +"the `can_hold` method by creating a `Rectangle` instance that has a width of " +"`8_u64` and a height of `7_u64` and asserting that it can hold another " +"`Rectangle` instance that has a width of `5_u64` and a height of `1_u64`." +msgstr "" +"`can_hold`方法返回一个 `Boolean`,这意味着它是assert函数的一个完美用例。在清" +"单8-6中,我们写了一个测试,通过创建一个宽度为`8_u64`、高度为`7_u64`的" +"`Rectangle`实例,并断言它可以容纳另一个宽度为`5_u64`、高度为`1_u64`的" +"`Rectangle`实例,来测试`can_hold`方法。" + +#: src/ch08-01-how-to-write-tests.md:164 +msgid "" +"```rust\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::Rectangle;\n" +" use super::RectangleTrait;\n" +"\n" +" #[test]\n" +" fn larger_can_hold_smaller() {\n" +" let larger = Rectangle {\n" +" height: 7_u64,\n" +" width: 8_u64,\n" +" };\n" +" let smaller = Rectangle {\n" +" height: 1_u64,\n" +" width: 5_u64,\n" +" };\n" +"\n" +" assert(larger.can_hold(@smaller), 'rectangle cannot hold');\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::Rectangle;\n" +" use super::RectangleTrait;\n" +"\n" +" #[test]\n" +" fn larger_can_hold_smaller() {\n" +" let larger = Rectangle {\n" +" height: 7_u64,\n" +" width: 8_u64,\n" +" };\n" +" let smaller = Rectangle {\n" +" height: 1_u64,\n" +" width: 5_u64,\n" +" };\n" +"\n" +" assert(larger.can_hold(@smaller), ‘rectangle cannot hold’);\n" +" }\n" +"}\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:186 +msgid "" +"Listing 8-6: A test for `can_hold` that checks whether a larger rectangle " +"can indeed hold a smaller rectangle" +msgstr "" +"清单 8-6: `can_hold`的测试,检查一个较大的矩形是否真的可以容纳一个较小的矩形" + +#: src/ch08-01-how-to-write-tests.md:188 +msgid "" +"Note that we’ve added two new lines inside the tests module: `use super::" +"Rectangle;` and `use super::RectangleTrait;`. The tests module is a regular " +"module that follows the usual visibility rules. Because the tests module is " +"an inner module, we need to bring the code under test in the outer module " +"into the scope of the inner module." +msgstr "" +"注意,我们在测试模块中加入了两行新的内容:`use super::Rectangle;`和`use " +"super::RectangleTrait;`。测试模块是一个常规模块,遵循通常的可见性规则。因为测" +"试模块是一个内部模块,我们需要将外部模块中的被测代码引入内部模块的范围。" + +#: src/ch08-01-how-to-write-tests.md:190 +msgid "" +"We’ve named our test `larger_can_hold_smaller`, and we’ve created the two " +"`Rectangle` instances that we need. Then we called the assert function and " +"passed it the result of calling `larger.can_hold(@smaller)`. This expression " +"is supposed to return `true`, so our test should pass. Let’s find out!" +msgstr "" +"我们将我们的测试命名为`larger_can_hold_smaller`,并且创建了我们需要的两个" +"`Rectangle`实例。然后我们调用了assert函数,并将调用`larger." +"can_hold(@smaller)`的结果传给它。这个表达式应该返回 `true`,所以我们的测试应" +"该通过。让我们拭目以待吧!" + +#: src/ch08-01-how-to-write-tests.md:192 +msgid "" +"```shell\n" +"$ cairo-test .\n" +"running 1 tests\n" +"test adder::lib::tests::larger_can_hold_smaller ... ok\n" +"test result: ok. 1 passed; 0 failed; 0 ignored; 0 filtered out;\n" +"```" +msgstr "" +"```shell\n" +"$ cairo-test .\n" +"running 1 tests\n" +"test adder::lib::tests::larger_can_hold_smaller ... ok\n" +"test result: ok. 1 passed; 0 failed; 0 ignored; 0 filtered out;\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:199 +msgid "" +"It does pass! Let’s add another test, this time asserting that a smaller " +"rectangle cannot hold a larger rectangle:" +msgstr "" +"它确实通过了!让我们再增加一个测试,这次是断言一个较小的矩形不能容纳一个较大的" +"矩形:" + +#: src/ch08-01-how-to-write-tests.md:203 +msgid "" +"```rust\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::Rectangle;\n" +" use super::RectangleTrait;\n" +"\n" +" #[test]\n" +" fn larger_can_hold_smaller() {\n" +" // --snip--\n" +" }\n" +"\n" +" #[test]\n" +" fn smaller_cannot_hold_larger() {\n" +" let larger = Rectangle {\n" +" height: 7_u64,\n" +" width: 8_u64,\n" +" };\n" +" let smaller = Rectangle {\n" +" height: 1_u64,\n" +" width: 5_u64,\n" +" };\n" +"\n" +" assert(!smaller.can_hold(@larger), 'rectangle cannot hold');\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::Rectangle;\n" +" use super::RectangleTrait;\n" +"\n" +" #[test]\n" +" fn larger_can_hold_smaller() {\n" +" // —snip—\n" +" }\n" +"\n" +" #[test]\n" +" fn smaller_cannot_hold_larger() {\n" +" let larger = Rectangle {\n" +" height: 7_u64,\n" +" width: 8_u64,\n" +" };\n" +" let smaller = Rectangle {\n" +" height: 1_u64,\n" +" width: 5_u64,\n" +" };\n" +"\n" +" assert(!smaller.can_hold(@larger), ‘rectangle cannot hold’);\n" +" }\n" +"}\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:230 +msgid "" +"Because the correct result of the `can_hold` function in this case is " +"`false`, we need to negate that result before we pass it to the assert " +"function. As a result, our test will pass if `can_hold` returns false:" +msgstr "" +"因为在这种情况下,`can_hold`函数的正确结果是`false`,我们需要在传递给assert函" +"数之前否定这个结果。因此,如果`can_hold`返回false,我们的测试将通过:" + +#: src/ch08-01-how-to-write-tests.md:232 +msgid "" +"```shell\n" +"$ cairo-test .\n" +" running 2 tests\n" +" test adder::lib::tests::smaller_cannot_hold_larger ... ok\n" +" test adder::lib::tests::larger_can_hold_smaller ... ok\n" +" test result: ok. 2 passed; 0 failed; 0 ignored; 0 filtered out;\n" +"```" +msgstr "" +"```shell\n" +"$ cairo-test .\n" +" running 2 tests\n" +" test adder::lib::tests::smaller_cannot_hold_larger … ok\n" +" test adder::lib::tests::larger_can_hold_smaller … ok\n" +" test result: ok. 2 passed; 0 failed; 0 ignored; 0 filtered out;\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:240 +msgid "" +"Two tests that pass! Now let’s see what happens to our test results when we " +"introduce a bug in our code. We’ll change the implementation of the " +"`can_hold` method by replacing the greater-than sign with a less-than sign " +"when it compares the widths:" +msgstr "" +"两个测试都通过了!现在让我们看看当我们在代码中引入一个错误时,我们的测试结果会" +"怎样。我们将改变`can_hold`方法的实现,当它比较宽度时,将大于号替换为小于号:" + +#: src/ch08-01-how-to-write-tests.md:242 +msgid "" +"```rust\n" +"// --snip--\n" +"impl RectangleImpl of RectangleTrait {\n" +" fn can_hold(self: @Rectangle, other: @Rectangle) -> bool {\n" +" *self.width < *other.width & *self.height > *other.height\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"// —snip—\n" +"impl RectangleImpl of RectangleTrait {\n" +" fn can_hold(self: @Rectangle, other: @Rectangle) -> bool {\n" +" *self.width < *other.width & *self.height > *other.height\n" +" }\n" +"}\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:251 +msgid "Running the tests now produces the following:" +msgstr "现在运行测试产生以下结果:" + +#: src/ch08-01-how-to-write-tests.md:253 +msgid "" +"```shell\n" +"$ cairo-test .\n" +"running 2 tests\n" +"test adder::lib::tests::smaller_cannot_hold_larger ... ok\n" +"test adder::lib::tests::larger_can_hold_smaller ... fail\n" +"failures:\n" +" adder::lib::tests::larger_can_hold_smaller - panicked with " +"[167190012635530104759003347567405866263038433127524 ('rectangle cannot " +"hold'), ].\n" +"\n" +"Error: test result: FAILED. 1 passed; 1 failed; 0 ignored\n" +"```" +msgstr "" +"```shell\n" +"$ cairo-test .\n" +"running 2 tests\n" +"test adder::lib::tests::smaller_cannot_hold_larger … ok\n" +"test adder::lib::tests::larger_can_hold_smaller … fail\n" +"failures:\n" +" adder::lib::tests::larger_can_hold_smaller - panicked with " +"[167190012635530104759003347567405866263038433127524 (‘rectangle cannot " +"hold’), ].\n" +"\n" +"Error: test result: FAILED. 1 passed; 1 failed; 0 ignored\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:264 +msgid "" +"Our tests caught the bug! Because `larger.width` is `8_u64` and `smaller." +"width` is `5_u64`, the comparison of the widths in `can_hold` now returns " +"`false`: `8_u64` is not less than `5_u64`." +msgstr "" +"我们的测试发现了这个错误!因为`larger.width`是`8_u64`,`smaller.width`是" +"`5_u64`,`can_hold`中的宽度比较现在返回`false`:`8_u64`不比`5_u64`小。" + +#: src/ch08-01-how-to-write-tests.md:266 +msgid "## Checking for Panics with `should_panic`" +msgstr "## 用`should_panic`检查panic情况" + +#: src/ch08-01-how-to-write-tests.md:268 +msgid "" +"In addition to checking return values, it’s important to check that our code " +"handles error conditions as we expect. For example, consider the Guess type " +"in Listing 8-8. Other code that uses `Guess` depends on the guarantee that " +"`Guess` instances will contain only values between `1_u64` and `100_u64`. We " +"can write a test that ensures that attempting to create a `Guess` instance " +"with a value outside that range panics." +msgstr "" +"除了检查返回值之外,检查我们的代码是否按照我们所期望的那样处理错误条件也很重" +"要。例如,考虑清单8-8中的Guess类型。其他使用`Guess`的代码依赖于保证`Guess`实" +"例只包含`1_u64`和`100_u64`之间的值。我们可以写一个测试,以确保试图创建的" +"`Guess`实例的值不在这个范围内时,会发生panic。" + +#: src/ch08-01-how-to-write-tests.md:270 +msgid "" +"We do this by adding the attribute `should_panic` to our test function. The " +"test passes if the code inside the function panics; the test fails if the " +"code inside the function doesn’t panic." +msgstr "" +"我们通过在我们的测试函数中添加属性`should_panic`来做到这一点。如果函数中的代" +"码出现panic,则测试通过;如果函数中的代码没有出现panic,则测试失败。" + +#: src/ch08-01-how-to-write-tests.md:272 +msgid "" +"Listing 8-8 shows a test that checks that the error conditions of " +"`GuessTrait::new` happen when we expect them to." +msgstr "" +"清单8-8显示了一个测试,检查`GuessTrait::new`的错误条件是否在我们期望的时候发" +"生。" + +#: src/ch08-01-how-to-write-tests.md:276 +msgid "" +"```rust\n" +"use array::ArrayTrait;\n" +"\n" +"#[derive(Copy, Drop)]\n" +"struct Guess {\n" +" value: u64,\n" +"}\n" +"\n" +"trait GuessTrait {\n" +" fn new(value: u64) -> Guess;\n" +"}\n" +"\n" +"impl GuessImpl of GuessTrait {\n" +" fn new(value: u64) -> Guess {\n" +" if value < 1_u64 | value > 100 {\n" +" let mut data = ArrayTrait::new();\n" +" data.append('Guess must be >= 1 and <= 100');\n" +" panic(data);\n" +" }\n" +" Guess { value }\n" +" }\n" +"}\n" +"\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::Guess;\n" +" use super::GuessTrait;\n" +"\n" +" #[test]\n" +" #[should_panic]\n" +" fn greater_than_100() {\n" +" GuessTrait::new(200_u64);\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use array::ArrayTrait;\n" +"\n" +"#[derive(Copy, Drop)]\n" +"struct Guess {\n" +" value: u64,\n" +"}\n" +"\n" +"trait GuessTrait {\n" +" fn new(value: u64) -> Guess;\n" +"}\n" +"\n" +"impl GuessImpl of GuessTrait {\n" +" fn new(value: u64) -> Guess {\n" +" if value < 1_u64 | value > 100 {\n" +" let mut data = ArrayTrait::new();\n" +" data.append('Guess must be >= 1 and <= 100');\n" +" panic(data);\n" +" }\n" +" Guess { value }\n" +" }\n" +"}\n" +"\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::Guess;\n" +" use super::GuessTrait;\n" +"\n" +" #[test]\n" +" #[should_panic]\n" +" fn greater_than_100() {\n" +" GuessTrait::new(200_u64);\n" +" }\n" +"}\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:312 +msgid "Listing 8-8: Testing that a condition will cause a panic" +msgstr "清单8-8:测试一个条件是否会导致panic" + +#: src/ch08-01-how-to-write-tests.md:314 +msgid "" +"We place the `#[should_panic]` attribute after the `#[test]` attribute and " +"before the test function it applies to. Let’s look at the result when this " +"test passes:" +msgstr "" +"我们把`#[should_panic]`属性放在`#[test]`属性之后和它适用的测试函数之前。让我" +"们看一下这个测试通过后的结果:" + +#: src/ch08-01-how-to-write-tests.md:316 +msgid "" +"```shell\n" +"$ cairo-test .\n" +"running 1 tests\n" +"test adder::lib::tests::greater_than_100 ... ok\n" +"test result: ok. 1 passed; 0 failed; 0 ignored; 0 filtered out;\n" +"```" +msgstr "" +"```shell\n" +"$ cairo-test .\n" +"running 1 tests\n" +"test adder::lib::tests::greater_than_100 … ok\n" +"test result: ok. 1 passed; 0 failed; 0 ignored; 0 filtered out;\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:323 +msgid "" +"Looks good! Now let’s introduce a bug in our code by removing the condition " +"that the new function will panic if the value is greater than `100_u64`:" +msgstr "" +"看起来不错!现在让我们在代码中引入一个错误,删除新函数在值大于`100_u64`时将发" +"生panic的条件:" + +#: src/ch08-01-how-to-write-tests.md:325 +msgid "" +"```rust\n" +"// --snip--\n" +"impl GuessImpl of GuessTrait {\n" +" fn new(value: u64) -> Guess {\n" +" if value < 1_u64 {\n" +" let mut data = ArrayTrait::new();\n" +" data.append('Guess must be >= 1 and <= 100');\n" +" panic(data);\n" +" }\n" +"\n" +" Guess { value, }\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"// --snip--\n" +"impl GuessImpl of GuessTrait {\n" +" fn new(value: u64) -> Guess {\n" +" if value < 1_u64 {\n" +" let mut data = ArrayTrait::new();\n" +" data.append('Guess must be >= 1 and <= 100');\n" +" panic(data);\n" +" }\n" +"\n" +" Guess { value, }\n" +" }\n" +"}\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:340 +msgid "When we run the test in Listing 8-8, it will fail:" +msgstr "当我们运行清单8-8中的测试时,它将失败:" + +#: src/ch08-01-how-to-write-tests.md:342 +msgid "" +"```shell\n" +"$ cairo-test .\n" +"running 1 tests\n" +"test adder::lib::tests::greater_than_100 ... fail\n" +"failures:\n" +" adder::lib::tests::greater_than_100 - expected panic but finished " +"successfully.\n" +"Error: test result: FAILED. 0 passed; 1 failed; 0 ignored\n" +"```" +msgstr "" +"```shell\n" +"$ cairo-test .\n" +"running 1 tests\n" +"test adder::lib::tests::greater_than_100 ... fail\n" +"failures:\n" +" adder::lib::tests::greater_than_100 - expected panic but finished " +"successfully.\n" +"Error: test result: FAILED. 0 passed; 1 failed; 0 ignored\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:351 +msgid "" +"We don’t get a very helpful message in this case, but when we look at the " +"test function, we see that it’s annotated with `#[should_panic]`. The " +"failure we got means that the code in the test function did not cause a " +"panic." +msgstr "" +"在这种情况下,我们没有得到一个非常有用的消息,但是当我们看测试函数时,我们看" +"到它被注解为`#[should_panic]`。我们得到的失败意味着测试函数中的代码并没有引起" +"panic。" + +#: src/ch08-01-how-to-write-tests.md:353 +msgid "" +"Tests that use `should_panic` can be imprecise. A `should_panic` test would " +"pass even if the test panics for a different reason from the one we were " +"expecting. To make `should_panic` tests more precise, we can add an optional " +"expected parameter to the `should_panic` attribute. The test harness will " +"make sure that the failure message contains the provided text. For example, " +"consider the modified code for `Guess` in Listing 8-9 where the new function " +"panics with different messages depending on whether the value is too small " +"or too large." +msgstr "" +"使用`should_panic`的测试可能是不精确的。即使测试的panic原因与我们所期望的不" +"同, 但只要发生了panic,一个`should_panic`测试就一定会通过。为了使" +"`should_panic`测试更加精确,我们可以在`should_panic`属性中添加一个可选的预期" +"参数。该测试限制将确保故障信息包含所提供的文本。例如,考虑清单8-9中`Guess'的" +"修改后的代码,新函数根据数值过小或过大的情况,以不同的消息进行恐慌。" + +#: src/ch08-01-how-to-write-tests.md:357 +msgid "" +"```rust\n" +"// --snip--\n" +"impl GuessImpl of GuessTrait {\n" +" fn new(value: u64) -> Guess {\n" +" if value < 1_u64 {\n" +" let mut data = ArrayTrait::new();\n" +" data.append('Guess must be >= 1');\n" +" panic(data);\n" +" } else if value > 100_u64 {\n" +" let mut data = ArrayTrait::new();\n" +" data.append('Guess must be <= 100');\n" +" panic(data);\n" +" }\n" +"\n" +" Guess { value, }\n" +" }\n" +"}\n" +"\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::Guess;\n" +" use super::GuessTrait;\n" +"\n" +" #[test]\n" +" #[should_panic(expected: ('Guess must be <= 100', ))]\n" +" fn greater_than_100() {\n" +" GuessTrait::new(200_u64);\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"// --snip--\n" +"impl GuessImpl of GuessTrait {\n" +" fn new(value: u64) -> Guess {\n" +" if value < 1_u64 {\n" +" let mut data = ArrayTrait::new();\n" +" data.append('Guess must be >= 1');\n" +" panic(data);\n" +" } else if value > 100_u64 {\n" +" let mut data = ArrayTrait::new();\n" +" data.append('Guess must be <= 100');\n" +" panic(data);\n" +" }\n" +"\n" +" Guess { value, }\n" +" }\n" +"}\n" +"\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::Guess;\n" +" use super::GuessTrait;\n" +"\n" +" #[test]\n" +" #[should_panic(expected: ('Guess must be <= 100', ))]\n" +" fn greater_than_100() {\n" +" GuessTrait::new(200_u64);\n" +" }\n" +"}\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:388 +msgid "" +"Listing 8-9: Testing for a panic with a panic message containing the error " +"message string" +msgstr "清单8-9:用包含错误信息字符串的恐慌信息来测试panic" + +#: src/ch08-01-how-to-write-tests.md:390 +msgid "" +"This test will pass because the value we put in the `should_panic` " +"attribute’s expected parameter is the array of string of the message that " +"the `Guess::new` function panics with. We need to specify the entire panic " +"message that we expect." +msgstr "" +"这个测试将通过,因为我们放在`should_panic`属性的预期参数中的值是`Guess::new`" +"函数panic信息的字符串阵列。我们需要指定我们期望的整个panic信息。" + +#: src/ch08-01-how-to-write-tests.md:392 +msgid "" +"To see what happens when a `should_panic` test with an expected message " +"fails, let’s again introduce a bug into our code by swapping the bodies of " +"the if `value < 1_u64` and the else if `value > 100_u64` blocks:" +msgstr "" +"为了看看当一个带有预期信息的 `should_panic` 测试失败时会发生什么,让我们再次" +"把if `value < 1_u64`和else if `value > 100_u64`块的主体互换,从而在我们的代码" +"中引入一个错误:" + +#: src/ch08-01-how-to-write-tests.md:394 +msgid "" +"```rust\n" +"if value < 1_u64 {\n" +" let mut data = ArrayTrait::new();\n" +" data.append('Guess must be <= 100');\n" +" panic(data);\n" +"} else if value > 100_u64 {\n" +" let mut data = ArrayTrait::new();\n" +" data.append('Guess must be >= 1');\n" +" panic(data);\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"if value < 1_u64 {\n" +" let mut data = ArrayTrait::new();\n" +" data.append('Guess must be <= 100');\n" +" panic(data);\n" +"} else if value > 100_u64 {\n" +" let mut data = ArrayTrait::new();\n" +" data.append('Guess must be >= 1');\n" +" panic(data);\n" +"}\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:406 +msgid "This time when we run the `should_panic` test, it will fail:" +msgstr "这一次,当我们运行`should_panic`测试时,它将失败:" + +#: src/ch08-01-how-to-write-tests.md:408 +msgid "" +"```shell\n" +"$ cairo-test .\n" +"running 1 tests\n" +"test adder::lib::tests::greater_than_100 ... fail\n" +"failures:\n" +" adder::lib::tests::greater_than_100 - panicked with " +"[6224920189561486601619856539731839409791025 ('Guess must be >= 1'), ].\n" +"\n" +"Error: test result: FAILED. 0 passed; 1 failed; 0 ignored\n" +"```" +msgstr "" +"```shell\n" +"$ cairo-test .\n" +"running 1 tests\n" +"test adder::lib::tests::greater_than_100 … fail\n" +"failures:\n" +" adder::lib::tests::greater_than_100 - panicked with " +"[6224920189561486601619856539731839409791025 (‘Guess must be >= 1’), ].\n" +"\n" +"Error: test result: FAILED. 0 passed; 1 failed; 0 ignored\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:418 +msgid "" +"The failure message indicates that this test did indeed panic as we " +"expected, but the panic message did not include the expected string. The " +"panic message that we did get in this case was `Guess must be >= 1`. Now we " +"can start figuring out where our bug is!" +msgstr "" +"失败信息表明,这个测试确实像我们预期的那样发生了panic,但是panic信息不包括预" +"期的字符串。在这种情况下,我们得到的panic信息是 `Guess must be >= 1`。现在我" +"们可以开始找出我们的错误所在了!" + +#: src/ch08-01-how-to-write-tests.md:420 +msgid "## Running Single Tests" +msgstr "## 运行单一测试" + +#: src/ch08-01-how-to-write-tests.md:422 +msgid "" +"Sometimes, running a full test suite can take a long time. If you’re working " +"on code in a particular area, you might want to run only the tests " +"pertaining to that code. You can choose which tests to run by passing `cairo-" +"test` the name of the test you want to run as an argument." +msgstr "" +"有时,运行一个完整的测试套件可能需要很长的时间。如果你正在处理某个特定领域的" +"代码,你可能只想运行与该代码有关的测试。你可以通过传递`cairo-test`你想运行的" +"测试名称作为参数来选择运行哪些测试。" + +#: src/ch08-01-how-to-write-tests.md:424 +msgid "" +"To demonstrate how to run a single test, we’ll first create two tests " +"functions, as shown in Listing 8-10, and choose which ones to run." +msgstr "" +"为了演示如何运行一个测试,我们将首先创建两个测试函数,如清单8-10所示,并选择" +"运行哪一个。" + +#: src/ch08-01-how-to-write-tests.md:428 +msgid "" +"```rust\n" +"#[cfg(test)]\n" +"mod tests {\n" +" #[test]\n" +" fn add_two_and_two() {\n" +" let result = 2 + 2;\n" +" assert(result == 4, 'result is not 4');\n" +" }\n" +"\n" +" #[test]\n" +" fn add_three_and_two() {\n" +" let result = 3 + 2;\n" +" assert(result == 5, 'result is not 5');\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[cfg(test)]\n" +"mod tests {\n" +" #[test]\n" +" fn add_two_and_two() {\n" +" let result = 2 + 2;\n" +" assert(result == 4, ‘result is not 4’);\n" +" }\n" +"\n" +" #[test]\n" +" fn add_three_and_two() {\n" +" let result = 3 + 2;\n" +" assert(result == 5, ‘result is not 5’);\n" +" }\n" +"}\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:445 +msgid "Listing 8-10: Two tests with two different names" +msgstr "清单8-10:两个不同名称的测试" + +#: src/ch08-01-how-to-write-tests.md:447 +msgid "" +"We can pass the name of any test function to `cairo-test` to run only that " +"test using the `-f` flag:" +msgstr "" +"我们可以将任何测试函数的名称传递给`cairo-test`,以使用`-f` 标志只运行该测试:" + +#: src/ch08-01-how-to-write-tests.md:449 +msgid "" +"```shell\n" +"$ cairo-test . -f add_two_and_two\n" +"running 1 tests\n" +"test adder::lib::tests::add_two_and_two ... ok\n" +"test result: ok. 1 passed; 0 failed; 0 ignored; 1 filtered out;\n" +"```" +msgstr "" +"```shell\n" +"$ cairo-test . -f add_two_and_two\n" +"running 1 tests\n" +"test adder::lib::tests::add_two_and_two ... ok\n" +"test result: ok. 1 passed; 0 failed; 0 ignored; 1 filtered out;\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:456 +msgid "" +"Only the test with the name `add_two_and_two` ran; the other test didn’t " +"match that name. The test output lets us know we had one more test that " +"didn’t run by displaying 1 filtered out at the end." +msgstr "" +"只有名称为`add_two_and_two` 的测试被运行了,其他的测试不符合这个名称。测试输" +"出最后显示了1个测试被过滤掉,让我们知道我们还有一个测试没有运行。" + +#: src/ch08-01-how-to-write-tests.md:458 +msgid "" +"We can also specify part of a test name, and any test whose name contains " +"that value will be run." +msgstr "我们还可以指定测试名称的一部分,任何名称包含该值的测试都将被运行。" + +#: src/ch08-01-how-to-write-tests.md:460 +msgid "## Ignoring Some Tests Unless Specifically Requested" +msgstr "## 在非特别指定时,忽略一些测试" + +#: src/ch08-01-how-to-write-tests.md:462 +msgid "" +"Sometimes a few specific tests can be very time-consuming to execute, so you " +"might want to exclude them during most runs of `cairo-test`. Rather than " +"listing as arguments all tests you do want to run, you can instead annotate " +"the time-consuming tests using the `ignore` attribute to exclude them, as " +"shown here:" +msgstr "" +"有时一些特定的测试执行起来非常耗时,所以你可能想在大多数`cairo-test`的运行中" +"排除它们。与其将所有你想运行的测试列为参数,不如使用`ignore` 属性对耗时的测试" +"进行注释,将其排除在外,如图所示:" + +#: src/ch08-01-how-to-write-tests.md:466 +msgid "" +"```rust\n" +"#[cfg(test)]\n" +"mod tests {\n" +" #[test]\n" +" fn it_works() {\n" +" let result = 2 + 2;\n" +" assert(result == 4, 'result is not 4');\n" +" }\n" +"\n" +" #[test]\n" +" #[ignore]\n" +" fn expensive_test() {\n" +" // code that takes an hour to run\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[cfg(test)]\n" +"mod tests {\n" +" #[test]\n" +" fn it_works() {\n" +" let result = 2 + 2;\n" +" assert(result == 4, ‘result is not 4’);\n" +" }\n" +"\n" +" #[test]\n" +" #[ignore]\n" +" fn expensive_test() {\n" +" // code that takes an hour to run\n" +" }\n" +"}\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:483 +msgid "" +"After `#[test]` we add the `#[ignore]` line to the test we want to exclude. " +"Now when we run our tests, `it_works` runs, but `expensive_test` doesn’t:" +msgstr "" +"对于想要排除的测试,我们在 `#[test]`之后,添加了 `#[ignore]`行。现在,当我们" +"运行我们的测试时,`it_works`会运行,但`expensive_test`不会:" + +#: src/ch08-01-how-to-write-tests.md:485 +msgid "" +"```shell\n" +"$ cairo-test .\n" +"running 2 tests\n" +"test adder::lib::tests::expensive_test ... ignored\n" +"test adder::lib::tests::it_works ... ok\n" +"test result: ok. 1 passed; 0 failed; 1 ignored; 0 filtered out;\n" +"```" +msgstr "" +"```shell\n" +"$ cairo-test .\n" +"running 2 tests\n" +"test adder::lib::tests::expensive_test ... ignored\n" +"test adder::lib::tests::it_works ... ok\n" +"test result: ok. 1 passed; 0 failed; 1 ignored; 0 filtered out;\n" +"```" + +#: src/ch08-01-how-to-write-tests.md:493 +msgid "The `expensive_test` function is listed as ignored." +msgstr "`expensive_test`函数被列为`ignored`。" + +#: src/ch08-01-how-to-write-tests.md:495 +msgid "" +"When you’re at a point where it makes sense to check the results of the " +"ignored tests and you have time to wait for the results, you can run `cairo-" +"test --include-ignored` to run all tests whether they’re ignored or not." +msgstr "" +"当你到了需要检查被忽略的测试结果的时候,而且你有时间等待测试结果,你可以运行" +"`cairo-test --include-ignored`来运行所有的测试,无论它们是否被标记忽略。" + +#: src/ch08-02-test-organization.md:1 +msgid "# Testing Organization" +msgstr "# 测试的组织结构" + +#: src/ch08-02-test-organization.md:3 +msgid "" +"We'll think about tests in terms of two main categories: unit tests and " +"integration tests. Unit tests are small and more focused, testing one module " +"in isolation at a time, and can test private functions. Integration tests " +"use your code in the same way any other external code would, using only the " +"public interface and potentially exercising multiple modules per test." +msgstr "" +"我们倾向于根据测试的两个主要分类来考虑问题:单元测试和集成测试。单元测试" +"(unit tests)与 集成测试(integration tests)。单元测试倾向于更小而更集中," +"在隔离的环境中一次测试一个模块,或者是测试私有接口。而集成测试对于你的代码来" +"说则完全是外部的。它们与其他外部代码一样,通过相同的方式使用你的代码,只测试" +"公有接口而且每个测试都有可能会测试多个模块。" + +#: src/ch08-02-test-organization.md:5 +msgid "" +"Writing both kinds of tests is important to ensure that the pieces of your " +"library are doing what you expect them to, separately and together." +msgstr "" +"为了保证你的库能够按照你的预期运行,从独立和整体的角度编写这两类测试都是非常" +"重要的。" + +#: src/ch08-02-test-organization.md:7 +msgid "## Unit Tests" +msgstr "## 单元测试" + +#: src/ch08-02-test-organization.md:9 +msgid "" +"The purpose of unit tests is to test each unit of code in isolation from the " +"rest of the code to quickly pinpoint where code is and isn’t working as " +"expected. You’ll put unit tests in the `src` directory in each file with the " +"code that they’re testing." +msgstr "" +"单元测试的目的是在与其他部分隔离的环境中测试每一个单元的代码,以便于快速而准" +"确地验证某个单元的代码功能是否符合预期。单元测试与他们要测试的代码共同存放在" +"位于 src 目录下相同的文件中。" + +#: src/ch08-02-test-organization.md:11 +msgid "" +"The convention is to create a module named tests in each file to contain the " +"test functions and to annotate the module with `cfg(test)`." +msgstr "" +"规范是在每个文件中创建包含测试函数的 tests 模块,并使用 `cfg(test)` 标注模" +"块。" + +#: src/ch08-02-test-organization.md:13 +msgid "### The Tests Module and `#[cfg(test)]`" +msgstr "### 测试模块和`#[cfg(test)]`" + +#: src/ch08-02-test-organization.md:15 +msgid "" +"The `#[cfg(test)]` annotation on the tests module tells Cairo to compile and " +"run the test code only when you run `cairo-test`, not when you run `cairo-" +"run`. This saves compile time when you only want to build the library and " +"saves space in the resulting compiled artifact because the tests are not " +"included. You’ll see that because integration tests go in a different " +"directory, they don’t need the `#[cfg(test)]` annotation. However, because " +"unit tests go in the same files as the code, you’ll use `#[cfg(test)]` to " +"specify that they shouldn’t be included in the compiled result." +msgstr "" +"测试模块的 `#[cfg(test)]`注解告诉 Cairo 只在执行`cairo-test` 时才编译和运行测" +"试代码,而在运行 `cairo-run` 时不这么做。这在只希望构建库的时候可以节省编译时" +"间,并且因为它们并没有包含测试,所以能减少编译产生的文件的大小。与之对应的集" +"成测试因为位于另一个文件夹,所以它们并不需要 `#[cfg(test)]`注解。然而单元测试" +"位于与源码相同的文件中,所以你需要使用 `#[cfg(test)]` 来指定他们不应该被包含" +"进编译结果中。" + +#: src/ch08-02-test-organization.md:17 +msgid "" +"Recall that when we created the new `adder` project in the first section of " +"this chapter, we wrote this first test:" +msgstr "回顾一下,当我们在本章第一节创建新的`adder'项目时,我们写了这个测试:" + +#: src/ch08-02-test-organization.md:32 +msgid "" +"The attribute `cfg` stands for configuration and tells Cairo that the " +"following item should only be included given a certain configuration option. " +"In this case, the configuration option is `test`, which is provided by Cairo " +"for compiling and running tests. By using the `cfg` attribute, Cairo " +"compiles our test code only if we actively run the tests with `cairo-test`. " +"This includes any helper functions that might be within this module, in " +"addition to the functions annotated with `#[test]`." +msgstr "" +"属性`cfg`代表配置,告诉Cairo只有在给定的配置选项的情况下才应该包含下面的项" +"目。在本例中,配置选项是`test`,它由Cairo提供,用于编译和运行测试。通过使用" +"`cfg`属性,Cairo只有在我们用`cairo-test`主动运行测试时才会编译我们的测试代" +"码。这包括任何可能在这个模块中的辅助函数,以及用`#[test]`标注的函数。" + +#: src/ch08-02-test-organization.md:34 +msgid "## Integration Tests" +msgstr "## 集成测试" + +#: src/ch08-02-test-organization.md:36 +msgid "" +"Integration tests use your library in the same way any other code would. " +"Their purpose is to test whether many parts of your library work together " +"correctly. Units of code that work correctly on their own could have " +"problems when integrated, so test coverage of the integrated code is " +"important as well. To create integration tests, you first need a `tests` " +"directory." +msgstr "" +"集成测试对于你需要测试的库来说完全是外部的。同其他使用库的代码一样使用库文" +"件,也就是说它们只能调用一部分库中的公有 API。集成测试的目的是测试库的多个部" +"分能否一起正常工作。一些单独能正确运行的代码单元集成在一起也可能会出现问题," +"所以集成测试的覆盖率也是很重要的。为了创建集成测试,你需要先创建一个 `tests` " +"目录。" + +#: src/ch08-02-test-organization.md:38 +msgid "### The `tests` Directory" +msgstr "### `tests`目录" + +#: src/ch08-02-test-organization.md:40 +msgid "" +"```shell\n" +"adder\n" +"├── cairo_project.toml\n" +"├── src\n" +" ├── lib.cairo\n" +"│ └── main.cairo\n" +"└── tests\n" +" ├── lib.cairo\n" +" └── integration_test.cairo\n" +"```" +msgstr "" +"```shell\n" +"adder\n" +"├── cairo_project.toml\n" +"├── src\n" +" ├── lib.cairo\n" +"│ └── main.cairo\n" +"└── tests\n" +" ├── lib.cairo\n" +" └── integration_test.cairo\n" +"```" + +#: src/ch08-02-test-organization.md:53 +msgid "" +"> To successfully run your tests with `cairo-test` you will need to update " +"your `cairo_project.toml` file to add the declaration of your `tests` " +"crate.\n" +">\n" +"> ```rust\n" +"> [crate_roots]\n" +"> adder = \"src\"\n" +"> tests = \"tests\"\n" +"> ```" +msgstr "" +"> 为了成功地用`cairo-test`运行你的测试,你需要更新你的`cairo_project.toml`文" +"件,添加你的`tests`crate的声明。\n" +">\n" +"> ```rust\n" +"> [crate_roots]\n" +"> adder = “src”\n" +"> tests = “tests”\n" +"> ```" + +#: src/ch08-02-test-organization.md:61 +msgid "" +"Each test file is compiled as its own separate crate, that's why whenever " +"you add a new test file you must add it to your _tests/lib.cairo_." +msgstr "" +"每个测试文件都被编译为它自己独立的crate,这就是为什么每当你添加一个新的测试文" +"件,你必须把它添加到你的 _tests/lib.cairo_ 文件中。" + +#: src/ch08-02-test-organization.md:63 +msgid "Filename: tests/lib.cairo" +msgstr "文件名:test/lib.cairo" + +#: src/ch08-02-test-organization.md:65 +msgid "" +"```rust\n" +"#[cfg(tests)]\n" +"mod integration_tests;\n" +"```" +msgstr "" +"```rust\n" +"#[cfg(tests)]\n" +"mod integration_tests;\n" +"```" + +#: src/ch08-02-test-organization.md:70 +msgid "" +"Enter the code in Listing 11-13 into the _tests/integration_test.cairo_ file:" +msgstr "将清单11-13中的代码输入到 _tests/integration_test.cairo_ 文件:" + +#: src/ch08-02-test-organization.md:72 +msgid "Filename: tests/integration_test.cairo" +msgstr "文件名:test/integration_test.cairo" + +#: src/ch08-02-test-organization.md:74 +msgid "" +"```rust\n" +"use adder::main;\n" +"\n" +"#[test]\n" +"fn internal() {\n" +" assert(main::internal_adder(2_u32, 2_u32) == 4_u32, 'internal_adder " +"failed');\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use adder::main;\n" +"\n" +"#[test]\n" +"fn internal() {\n" +" assert(main::internal_adder(2_u32, 2_u32) == 4_u32, 'internal_adder " +"failed');\n" +"}\n" +"```" + +#: src/ch08-02-test-organization.md:83 +msgid "" +"Each file in the tests directory is a separate crate, so we need to bring " +"our library into each test crate’s scope. For that reason we add `use adder::" +"main` at the top of the code, which we didn’t need in the unit tests." +msgstr "" +"测试目录中的每个文件都是一个独立的crate,所以我们需要将我们的库引入每个测试" +"crate的范围。出于这个原因,我们在代码的顶部添加了`use adder::main`,在单元测" +"试中我们不需要这个。" + +#: src/ch08-02-test-organization.md:85 +msgid "" +"```shell\n" +"$ cairo-test tests/\n" +"running 1 tests\n" +"test tests::tests_integration::it_adds_two ... ok\n" +"test result: ok. 1 passed; 0 failed; 0 ignored; 0 filtered out;\n" +"```" +msgstr "" +"```shell\n" +"$ cairo-test tests/\n" +"running 1 tests\n" +"test tests::tests_integration::it_adds_two ... ok\n" +"test result: ok. 1 passed; 0 failed; 0 ignored; 0 filtered out;\n" +"```" + +#: src/ch08-02-test-organization.md:92 +msgid "" +"The result of the tests is the same as what we've been seeing: one line for " +"each test." +msgstr "测试的结果与我们之前看到的相同:每个测试一行。" + +#: src/ch09-00-error-handling.md:1 +msgid "# Error handling" +msgstr "# 错误处理" + +#: src/ch09-00-error-handling.md:3 +msgid "" +"In this chapter, we will explore various error handling techniques provided " +"by Cairo, which not only allow you to address potential issues in your code, " +"but also make it easier to create programs that are adaptable and " +"maintainable. By examining different approaches to managing errors, such as " +"pattern matching with the Result enum, using the ? operator for more " +"ergonomic error propagation, and employing the unwrap or expect methods for " +"handling recoverable errors, you'll gain a deeper understanding of Cairo's " +"error handling features. These concepts are crucial for building robust " +"applications that can effectively handle unexpected situations, ensuring " +"your code is ready for production." +msgstr "" +"在本章中,我们将探讨Cairo提供的各种错误处理技术,这些技术不仅能让你解决代码中" +"的潜在问题,还能让你更容易创建易适应和易维护的程序。通过研究管理错误的不同方" +"法,如用Result枚举进行模式匹配,使用 ? 操作符进行更人性化的错误传播,以及采" +"用unwrap或expect方法来处理可恢复的错误,你将对Cairo的错误处理功能有更深入的了" +"解。这些概念对于构建强大的应用程序至关重要,它可以有效地处理意外情况,确保你" +"的代码可以用于生产环境。" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:1 +msgid "# Unrecoverable Errors with panic" +msgstr "# 无法恢复的错误与恐慌(panic)" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:3 +msgid "" +"In Cairo, unexpected issues may arise during program execution, resulting in " +"runtime errors. While the panic function from the core library doesn't " +"provide a resolution for these errors, it does acknowledge their occurrence " +"and terminates the program. There are two primary ways that a panic can be " +"triggered in Cairo: inadvertently, through actions causing the code to panic " +"(e.g., accessing an array beyond its bounds), or deliberately, by invoking " +"the panic function." +msgstr "" +"在Cairo中,程序执行过程中可能会出现意外问题,导致运行时错误。虽然核心库中的" +"panic函数并没有为这些错误提供解决方案,但它确实承认这些错误的发生并终止程序。" +"在Cairo中,有两种主要的方式可以触发panic:无意地通过导致代码panic的行为(例" +"如,访问一个超出其界限的数组),或故意地,通过调用panic函数。" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:5 +msgid "" +"When a panic occurs, it leads to an abrupt termination of the program. The " +"`panic` function take an array as argument, which can be used to provide an " +"error message and performs an unwind process where all variables are dropped " +"and dictionaries squashed to ensure the soundness of the program to safely " +"terminate the execution." +msgstr "" +"当panic发生时,它会导致程序的突然终止。`panic` 函数接受一个数组作为参数,可以" +"用来提供一个错误信息,并执行一个展开(unwind)过程--所有的变量被丢弃,字典被" +"squash,以确保程序的合理地,安全地终止执行。" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:7 +msgid "" +"Here is how we can `panic` from inside a program and return the error code " +"`2`:" +msgstr "下面是我们如何在一个程序中`panic`并返回错误代码`2`:" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:11 +msgid "" +"```rust,does_not_compile\n" +"use array::ArrayTrait;\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" let mut data = ArrayTrait::new();\n" +" data.append(2);\n" +" panic(data);\n" +" 'This line isn't reached'.print();\n" +"}\n" +"```" +msgstr "" +"```rust,does_not_compile\n" +"use array::ArrayTrait;\n" +"use debug::PrintTrait;\n" +"\n" +"fn main() {\n" +" let mut data = ArrayTrait::new();\n" +" data.append(2);\n" +" panic(data);\n" +" 'This line isn't reached'.print();\n" +"}\n" +"```" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:23 +msgid "Running the program will produce the following output:" +msgstr "运行该程序将产生以下输出:" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:25 +msgid "" +"```console\n" +"$ cairo-run test.cairo\n" +"Run panicked with err values: [2]\n" +"```" +msgstr "" +"```console\n" +"$ cairo-run test.cairo\n" +"Run panicked with err values: [2]\n" +"```" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:30 +msgid "" +"As you can notice in the output, the print statement is never reached, as " +"the program terminates after encountering the `panic` statement." +msgstr "" +"正如你在输出中所注意到的,打印语句没有被执行,因为程序在遇到`panic'语句后就终" +"止了。" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:32 +msgid "" +"An alternative and more idiomatic approach to panic in Cairo would be to use " +"the `panic_with_felt252` function. This function serves as an abstraction of " +"the array-defining process and is often preferred due to its clearer and " +"more concise expression of intent. By using `panic_with_felt252`, developers " +"can panic in a one-liner by providing a felt252 error message as argument, " +"making the code more readable and maintainable." +msgstr "" +"在Cairo中,另一种更常见的方法是使用`panic_with_felt252`函数来处理恐慌。这个函" +"数是对数组定义过程的抽象,由于它更清晰、更简洁地表达了意图,所以实际运用中经" +"常使用该函数。通过使用`panic_with_felt252`,开发者可以通过提供felt252错误信息" +"作为参数,在一个单行代码中进行panic,使代码更易读和可维护。" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:34 +msgid "Let's consider an example:" +msgstr "让我们来考察一个例子:" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:36 +msgid "" +"```rust\n" +"fn main() {\n" +" panic_with_felt252(2);\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"fn main() {\n" +" panic_with_felt252(2);\n" +"}\n" +"```" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:42 +msgid "" +"Executing this program will yield the same error message as before. In that " +"case, if there is no need for an array and multiple values to be returned " +"within the error, so `panic_with_felt252` is a more succinct alternative." +msgstr "" +"执行这个程序会产生和之前一样的错误信息。在这种情况下,如果在返回错误是不需要" +"一个数组和多个值,那么`panic_with_felt252`是一个更简洁的选择。" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:44 +msgid "## nopanic notation" +msgstr "## nopanic记号" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:46 +msgid "" +"You can use the `nopanic` notation to indicate that a function will never " +"panic. Only `nopanic` functions can be called in a function annotated as " +"`nopanic`." +msgstr "" +"你可以使用`nopanic`记号来表示一个函数永远不会恐慌。只有 `nopanic`函数可以在标" +"注为 `nopanic`的函数中被调用。" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:48 +#: src/ch09-01-unrecoverable-errors-with-panic.md:83 +#: src/appendix-03-derivable-traits.md:17 +#: src/appendix-03-derivable-traits.md:42 +#: src/appendix-03-derivable-traits.md:63 +#: src/appendix-03-derivable-traits.md:85 +#: src/appendix-03-derivable-traits.md:118 +msgid "Example:" +msgstr "例子:" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:50 +msgid "" +"```rust\n" +"fn function_never_panic() -> felt252 nopanic {\n" +" 42\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"fn function_never_panic() -> felt252 nopanic {\n" +" 42\n" +"}\n" +"```" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:56 +msgid "Wrong example:" +msgstr "错误的例子:" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:58 +msgid "" +"```rust\n" +"fn function_never_panic() nopanic {\n" +" assert(1 == 1, 'what');\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"fn function_never_panic() nopanic {\n" +" assert(1 == 1, 'what');\n" +"}\n" +"```" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:64 +msgid "" +"If you write the following function that includes a function that may panic " +"you will get the following error:" +msgstr "如果你写了以下函数,其中包括一个可能会panic的函数,你会得到以下错误:" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:66 +msgid "" +"```bash\n" +"error: Function is declared as nopanic but calls a function that may panic.\n" +" --> test.cairo:2:12\n" +" assert(1 == 1, 'what');\n" +" ^****^\n" +"Function is declared as nopanic but calls a function that may panic.\n" +" --> test.cairo:2:5\n" +" assert(1 == 1, 'what');\n" +" ^********************^\n" +"```" +msgstr "" +"```bash\n" +"error: Function is declared as nopanic but calls a function that may panic.\n" +" --> test.cairo:2:12\n" +" assert(1 == 1, 'what');\n" +" ^****^\n" +"Function is declared as nopanic but calls a function that may panic.\n" +" --> test.cairo:2:5\n" +" assert(1 == 1, 'what');\n" +" ^********************^\n" +"```" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:77 +msgid "" +"Note that there are two functions that may panic here, assert and equality." +msgstr "请注意,有两个函数可能会在这里发生panic,即断言和相等比较。" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:79 +msgid "## panic_with macro" +msgstr "## panic_with 宏" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:81 +msgid "" +"You can use the `panic_with` macro to mark a function that returns an " +"`Option` or `Result`. This macro takes two arguments, which are the data " +"that is passed as the panic reason as well as the name for a wrapping " +"function. It will create a wrapper for your annotated function which will " +"panic if the function returns `None` or `Err`, the panic function will be " +"called with the given data." +msgstr "" +"你可以使用`panic_with`宏来标记一个返回`Option`或`Result`的函数。这个宏需要两" +"个参数,即作为panic原因传递的数据以及包装函数的名称。它将为你注释的函数创建一" +"个包装器,如果该函数返回`None` 或`Err`,该panic函数将被调用,并给出数据。" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:85 +msgid "" +"```rust\n" +"use option::OptionTrait;\n" +"\n" +"#[panic_with('value is 0', wrap_not_zero)]\n" +"fn wrap_if_not_zero(value: u128) -> Option {\n" +" if value == 0 {\n" +" Option::None(())\n" +" } else {\n" +" Option::Some(value)\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" wrap_if_not_zero(0); // this returns None\n" +" wrap_not_zero(0); // this panic with 'value is 0'\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use option::OptionTrait;\n" +"\n" +"#[panic_with('value is 0', wrap_not_zero)]\n" +"fn wrap_if_not_zero(value: u128) -> Option {\n" +" if value == 0 {\n" +" Option::None(())\n" +" } else {\n" +" Option::Some(value)\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" wrap_if_not_zero(0); // this returns None\n" +" wrap_not_zero(0); // this panic with 'value is 0'\n" +"}\n" +"```" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:103 +msgid "## Using assert" +msgstr "## 使用断言(assert)" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:105 +msgid "" +"The assert function from the Cairo core library is actually a utility " +"function based on panics. It asserts that a boolean expression is true at " +"runtime, and if it is not, it calls the panic function with an error value. " +"The assert function takes two arguments: the boolean expression to verify, " +"and the error value. The error value is specified as a felt252, so any " +"string passed must be able to fit inside a felt252." +msgstr "" +"Cairo核心库中的assert函数实际上是一个基于panic的实用函数。它断言一个布尔表达" +"式在运行时是真的,如果不是,它就会调用带有错误值的panic函数。assert函数需要两" +"个参数:要验证的布尔表达式,以及错误值。错误值被指定为felt252,所以任何传递的" +"字符串都必须能够容纳在felt252中。" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:107 +msgid "Here is an example of its usage:" +msgstr "下面是它的一个使用例子:" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:109 +msgid "" +"```rust\n" +"fn main() {\n" +" let my_number: u8 = 0;\n" +"\n" +" assert(my_number != 0, 'number is zero');\n" +"\n" +" 100 / my_number;\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"fn main() {\n" +" let my_number: u8 = 0;\n" +"\n" +" assert(my_number != 0, 'number is zero');\n" +"\n" +" 100 / my_number;\n" +"}\n" +"```" + +#: src/ch09-01-unrecoverable-errors-with-panic.md:119 +msgid "" +"We are asserting in main that `my_number` is not zero to ensure that we're " +"not performing a division by 0.\n" +"In this example, `my_number` is zero so the assertion will fail, and the " +"program will panic\n" +"with the string 'number is zero' (as a felt252) and the division will not be " +"reached." +msgstr "" +"我们在main中断言`my_number`不是0,以确保我们没有进行除以0的操作。\n" +"在这个例子中,`my_number`是零,所以断言会失败,程序会panic,\n" +"并给出 'number is zero'的字符串(保存在felt252中),除法将不会被执行。" + +#: src/ch09-02-error-handling.md:1 +msgid "# Recoverable Errors with `Result`" +msgstr "# 可恢复的错误与 `Result`" + +#: src/ch09-02-error-handling.md:3 src/ch09-02-error-handling.md:56 +msgid "
" +msgstr "
" + +#: src/ch09-02-error-handling.md:5 +msgid "" +"Most errors aren’t serious enough to require the program to stop entirely. " +"Sometimes, when a function fails, it’s for a reason that you can easily " +"interpret and respond to. For example, if you try to add two large integers " +"and the operation overflows because the sum exceeds the maximum " +"representable value, you might want to return an error or a wrapped result " +"instead of causing undefined behavior or terminating the process." +msgstr "" +"大多数错误并没有严重到需要程序完全停止的程度。有时,当一个函数失败时,它的原" +"因是你可以很容易地解释和应对的。例如,如果你试图将两个大的整数相加,而操作溢" +"出,因为总和超过了最大的可表示值,你可能想返回一个错误或一个包装好的结果,而" +"不是引起未定义行为或终止程序。" + +#: src/ch09-02-error-handling.md:7 +msgid "## The `Result` enum" +msgstr "## `Result`枚举" + +#: src/ch09-02-error-handling.md:9 +msgid "" +"Recall from [“Generic data types”](ch07-01-generic-data-types.md#enums) in " +"Chapter 7 that the `Result` enum is defined as having two variants, `Ok` and " +"`Err`, as follows:" +msgstr "" +"回顾第七章中的[\"通用数据类型\"](ch07-01-generic-data-types.md#enums)," +"`Result`枚举被定义为有两个变体,`Ok`和`Err`,如下所示:" + +#: src/ch09-02-error-handling.md:20 +msgid "## The `ResultTrait`" +msgstr "## `ResultTrait`" + +#: src/ch09-02-error-handling.md:22 +msgid "" +"The `ResultTrait` trait provides methods for working with the `Result` " +"enum, such as unwrapping values, checking whether the `Result` is `Ok` or " +"`Err`, and panicking with a custom message. The `ResultTraitImpl` " +"implementation defines the logic of these methods." +msgstr "" +"`ResultTrait`特征提供了处理`Result`枚举的方法,例如解包值,检查`Result`" +"是`Ok`还是`Err`,以及用自定义的消息进行panic。`ResultTraitImpl`实现定义了这些" +"方法的逻辑。" + +#: src/ch09-02-error-handling.md:24 +msgid "" +"```rust\n" +"trait ResultTrait {\n" +" fn expect>(self: Result, err: felt252) -> T;\n" +"\n" +" fn unwrap>(self: Result) -> T;\n" +"\n" +" fn expect_err>(self: Result, err: felt252) -> " +"E;\n" +"\n" +" fn unwrap_err>(self: Result) -> E;\n" +"\n" +" fn is_ok(self: @Result) -> bool;\n" +"\n" +" fn is_err(self: @Result) -> bool;\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"trait ResultTrait {\n" +" fn expect>(self: Result, err: felt252) -> T;\n" +"\n" +" fn unwrap>(self: Result) -> T;\n" +"\n" +" fn expect_err>(self: Result, err: felt252) -> " +"E;\n" +"\n" +" fn unwrap_err>(self: Result) -> E;\n" +"\n" +" fn is_ok(self: @Result) -> bool;\n" +"\n" +" fn is_err(self: @Result) -> bool;\n" +"}\n" +"```" + +#: src/ch09-02-error-handling.md:40 +msgid "" +"The `expect` and `unwrap` methods are similar in that they both attempt to " +"extract the value of type `T` from a `Result` when it is in the `Ok` " +"variant. If the `Result` is `Ok(x)`, both methods return the value `x`. " +"However, the key difference between the two methods lies in their behavior " +"when the `Result` is in the `Err` variant. The `expect` method allows you to " +"provide a custom error message (as a `felt252` value) that will be used when " +"panicking, giving you more control and context over the panic. On the other " +"hand, the `unwrap` method panics with a default error message, providing " +"less information about the cause of the panic." +msgstr "" +"`expect`和`unwrap`方法类似,它们都试图从`Result`中提取`T`类型的值,当它" +"处于`Ok`变体时。如果`Result`是 `Ok(x)`,两个方法都返回值 \"x\"。然而,这两个" +"方法的关键区别在于当`Result`是`Err`变量时的行为。`expect`方法允许你提供一个自" +"定义的错误信息(作为`felt252`值)在panic时使用,从而让你获取更多对panic相关的" +"控制和上下文。另一方面,`unwrap`方法用一个默认的错误信息进行panic,提供的关于" +"panic原因的信息较少。" + +#: src/ch09-02-error-handling.md:42 +msgid "" +"The `expect_err` and `unwrap_err` have the exact opposite behavior. If the " +"`Result` is `Err(x)`, both methods return the value `x`. However, the key " +"difference between the two methods is in case of `Result::Ok()`. The " +"`expect_err` method allows you to provide a custom error message (as a " +"`felt252` value) that will be used when panicking, giving you more control " +"and context over the panic. On the other hand, the `unwrap_err` method " +"panics with a default error message, providing less information about the " +"cause of the panic." +msgstr "" +"`expect_err`和`unwrap_err`的行为完全相反。如果`Result`是`Err(x)`,两个方法都" +"返回值`x`。然而,这两个方法的关键区别是在`Result::Ok()`的情况下。`expect_err`" +"方法允许你提供一个自定义的错误信息(作为`felt252`值),在panic时使用,从而让" +"你获取更多对panic相关的控制和上下文。另一方面,`unwrap_err`方法用一个默认的错" +"误信息进行panic,提供的关于panic原因的信息较少。" + +#: src/ch09-02-error-handling.md:44 +msgid "" +"A careful reader may have noticed the `>` and `>` in the first four methods signatures. This syntax " +"represents generic type constraints in the Cairo language. These constraints " +"indicate that the associated functions require an implementation of the " +"`Drop` trait for the generic types `T` and `E`, respectively." +msgstr "" +"细心的读者可能已经注意到前四个方法签名中的`>` and `>`。这种语法代表了Cairo语言中的通用类型约束。这些约束表示相关的" +"函数需要分别对通用类型`T`和`E`的`Drop`特性进行实现。" + +#: src/ch09-02-error-handling.md:46 +msgid "" +"Finally, the `is_ok` and `is_err` methods are utility functions provided by " +"the `ResultTrait` trait to check the variant of a `Result` enum value." +msgstr "" +"最后,`is_ok`和`is_err`方法是`ResultTrait`特征提供的实用函数,用于检查" +"`Result`枚举值的成员。" + +#: src/ch09-02-error-handling.md:48 +msgid "" +"`is_ok` takes a snapshot of a `Result` value and returns `true` if the " +"`Result` is the `Ok` variant, meaning the operation was successful. If the " +"`Result` is the `Err` variant, it returns `false`." +msgstr "" +"`is_ok`获取一个`Result`值的快照,如果`Result`是`Ok`成员,则返回`true`," +"意味着操作成功。如果`Result`是`Err`成员,则返回`false`。" + +#: src/ch09-02-error-handling.md:50 +msgid "" +"`is_err` takes a reference to a `Result` value and returns `true` if " +"the `Result` is the `Err` variant, meaning the operation encountered an " +"error. If the `Result` is the `Ok` variant, it returns `false`." +msgstr "" +"`is_err`接收一个对`Result`值的引用,如果`Result`是`Err`成员,意味着操作" +"遇到了错误,则返回`true`。如果 `Result`是 `Ok`成员,则返回 `false`。" + +#: src/ch09-02-error-handling.md:52 +msgid "" +"These methods are helpful when you want to check the success or failure of " +"an operation without consuming the Result value, allowing you to perform " +"additional operations or make decisions based on the variant without " +"unwrapping it." +msgstr "" +"当你想在不消耗结果值的情况下检查一个操作的成功或失败时,这些方法很有帮助,允" +"许你执行额外的操作或根据枚举成员做出决定,而不用解开(unwrap)它。" + +#: src/ch09-02-error-handling.md:54 +msgid "" +"You can find the implementation ot the `ResultTrait` [here](https://github." +"com/starkware-libs/cairo/blob/main/corelib/src/result.cairo#L20)." +msgstr "" +"你可以在[这里](https://github.com/starkware-libs/cairo/blob/main/corelib/src/" +"result.cairo#L20)找到`ResultTrait`的实现。" + +#: src/ch09-02-error-handling.md:58 +msgid "It is always easier to understand with examples." +msgstr "有例子总是更容易理解。" + +#: src/ch09-02-error-handling.md:60 +msgid "Have a look at this function signature:" +msgstr "请看一下这个函数签名:" + +#: src/ch09-02-error-handling.md:62 +msgid "" +"```rust\n" +"fn u128_overflowing_add(a: u128, b: u128) -> Result;\n" +"```" +msgstr "" +"```rust\n" +"fn u128_overflowing_add(a: u128, b: u128) -> Result;\n" +"```" + +#: src/ch09-02-error-handling.md:66 +msgid "" +"It takes two u128 integers, a and b, and returns a `Result` " +"where the `Ok` variant holds the sum if the addition does not overflow, and " +"the `Err` variant holds the overflowed value if the addition does overflow." +msgstr "" +"它接收两个u128整数,a和b,并返回一个`Result`,如果加法没有溢出," +"`Ok`成员存储加法的和,如果加法溢出,`Err’成员存储溢出的值。" + +#: src/ch09-02-error-handling.md:68 +msgid "Now, we can use this function elsewhere. For instance:" +msgstr "现在,我们可以在其他地方使用这个函数。比如说:" + +#: src/ch09-02-error-handling.md:70 +msgid "" +"```rust\n" +"fn u128_checked_add(a: u128, b: u128) -> Option {\n" +" match u128_overflowing_add(a, b) {\n" +" Result::Ok(r) => Option::Some(r),\n" +" Result::Err(r) => Option::None(()),\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"fn u128_checked_add(a: u128, b: u128) -> Option {\n" +" match u128_overflowing_add(a, b) {\n" +" Result::Ok(r) => Option::Some(r),\n" +" Result::Err(r) => Option::None(()),\n" +" }\n" +"}\n" +"```" + +#: src/ch09-02-error-handling.md:79 +msgid "" +"Here, it accepts two u128 integers, a and b, and returns an `Option`. " +"It uses the `Result` returned by `u128_overflowing_add` to determine the " +"success or failure of the addition operation. The match expression checks " +"the `Result` from `u128_overflowing_add`. If the result is `Ok(r)`, it " +"returns `Option::Some(r)` containing the sum. If the result is `Err(r)`, it " +"returns `Option::None(())` to indicate that the operation has failed due to " +"overflow. The function does not panic in case of an overflow." +msgstr "" +"这里,它接受两个u128整数,a和b,并返回一个`Option`。它使用" +"`u128_overflowing_add`返回的`Result`来确定加法操作的成功或失败。匹配表达式检" +"查来自`u128_overflowing_add`的`Result` 。如果结果是`Ok(r)`,则返回`Option::" +"Some(r)`,其中包含和。如果结果是`Err(r)`,则返回`Option::None(())`,表示由于" +"溢出导致操作失败。在溢出的情况下,该函数不会panic。" + +#: src/ch09-02-error-handling.md:81 +msgid "" +"Let's take another example demonstrating the use of `unwrap`.\n" +"First we import the necessary modules:" +msgstr "" +"让我们再举一个例子,演示一下`unwrap`的使用。\n" +"首先我们导入必要的模块:" + +#: src/ch09-02-error-handling.md:84 +msgid "" +"```rust\n" +"use core::traits::Into;\n" +"use traits::TryInto;\n" +"use option::OptionTrait;\n" +"use result::ResultTrait;\n" +"use result::ResultTraitImpl;\n" +"```" +msgstr "" +"```rust\n" +"use core::traits::Into;\n" +"use traits::TryInto;\n" +"use option::OptionTrait;\n" +"use result::ResultTrait;\n" +"use result::ResultTraitImpl;\n" +"```" + +#: src/ch09-02-error-handling.md:92 +msgid "" +"In this example, the `parse_u8` function takes a `felt252` integer and tries " +"to convert it into a `u8` integer using the `try_into` method. If " +"successful, it returns `Result::Ok(value)`, otherwise it returns `Result::" +"Err('Invalid integer')`." +msgstr "" +"在这个例子中,`parse_u8'函数接收一个`felt252`的整数,并尝试用`try_into`方法将" +"其转换为`u8'的整数。如果成功,它返回`Result::Ok(value)`,否则它返回`Result::" +"Err('Invalid integer')`。" + +#: src/ch09-02-error-handling.md:94 +msgid "" +"```rust\n" +"fn parse_u8(s: felt252) -> Result {\n" +" match s.try_into() {\n" +" Option::Some(value) => Result::Ok(value),\n" +" Option::None(_) => Result::Err('Invalid integer'),\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"fn parse_u8(s: felt252) -> Result {\n" +" match s.try_into() {\n" +" Option::Some(value) => Result::Ok(value),\n" +" Option::None(_) => Result::Err(‘Invalid integer’),\n" +" }\n" +"}\n" +"```" + +#: src/ch09-02-error-handling.md:103 +msgid "Our two test cases are:" +msgstr "我们的两个测试案例是:" + +#: src/ch09-02-error-handling.md:105 +msgid "" +"```rust\n" +"#[test]\n" +"fn test_felt252_to_u8() {\n" +" let number: felt252 = 5_felt252;\n" +" // should not panic\n" +" let res = parse_u8(number).unwrap();\n" +"}\n" +"\n" +"#[test]\n" +"fn test_felt252_to_u8_panic() {\n" +" let number: felt252 = 256_felt252;\n" +" // should panic\n" +" let res = parse_u8(number).unwrap();\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[test]\n" +"fn test_felt252_to_u8() {\n" +" let number: felt252 = 5_felt252;\n" +" // should not panic\n" +" let res = parse_u8(number).unwrap();\n" +"}\n" +"\n" +"#[test]\n" +"fn test_felt252_to_u8_panic() {\n" +" let number: felt252 = 256_felt252;\n" +" // should panic\n" +" let res = parse_u8(number).unwrap();\n" +"}\n" +"```" + +#: src/ch09-02-error-handling.md:121 +msgid "" +"The first one tests a valid conversion from `felt252` to `u8`, expecting the " +"`unwrap` method not to panic. The second test function attempts to convert a " +"value that is out of the `u8` range, expecting the `unwrap` method to panic " +"with the error message 'Invalid integer'." +msgstr "" +"第一个测试函数是测试从`felt252`到`u8`的有效转换,期望`unwrap`方法不要panic。" +"第二个测试函数试图转换一个超出`u8'范围的值,期望`unwrap'方法panic,错误信息" +"是 ‘Invalid integer’。" + +#: src/ch09-02-error-handling.md:123 +msgid "> We could have also used the #[should_panic] attribute here." +msgstr "> 我们也可以在这里使用#[should_panic]属性。" + +#: src/ch09-02-error-handling.md:125 +msgid "### The `?` operator ?" +msgstr "### `?`运算符?" + +#: src/ch09-02-error-handling.md:127 +msgid "" +"The last operator we will talk about is the `?` operator. The `?` operator " +"is used for more idiomatic and concise error handling. When you use the `?` " +"operator on a `Result` or `Option` type, it will do the following:" +msgstr "" +"我们要谈的最后一个操作符是`?`操作符。`?`运算符用于更成文和简明的错误处理。当" +"你在 `Result`或 `Option`类型上使用`?`运算符时,它将做以下事情:" + +#: src/ch09-02-error-handling.md:129 +msgid "" +"- If the value is `Result::Ok(x)` or `Option::Some(x)`, it will return the " +"inner value `x` directly.\n" +"- If the value is `Result::Err(e)` or `Option::None`, it will propagate the " +"error or `None` by immediately returning from the function." +msgstr "" +"- 如果值是`Result::Ok(x)`或`Option::Some(x)`,它将直接返回内部值`x`。\n" +"- 如果值是`Result::Err(e)`或`Option::None`,它将通过立即从函数返回来传播错误" +"或`None`。" + +#: src/ch09-02-error-handling.md:132 +msgid "" +"The `?` operator is useful when you want to handle errors implicitly and let " +"the calling function deal with them." +msgstr "当你想隐式处理错误并让调用函数处理它们时,`?`操作符很有用。" + +#: src/ch09-02-error-handling.md:134 +msgid "Here is an example." +msgstr "下面是一个例子。" + +#: src/ch09-02-error-handling.md:136 +msgid "" +"```rust\n" +"fn do_something_with_parse_u8(input: felt252) -> Result {\n" +" let input_to_u8: u8 = parse_u8(input)?;\n" +" // DO SOMETHING\n" +" let res = input_to_u8 - 1;\n" +" Result::Ok(res)\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"fn do_something_with_parse_u8(input: felt252) -> Result {\n" +" let input_to_u8: u8 = parse_u8(input)?;\n" +" // DO SOMETHING\n" +" let res = input_to_u8 - 1;\n" +" Result::Ok(res)\n" +"}\n" +"```" + +#: src/ch09-02-error-handling.md:145 +msgid "" +"`do_something_with_parse_u8` function takes a `felt252` value as input and " +"calls `parse_u8`. The `?` operator is used to propagate the error, if any, " +"or unwrap the successful value." +msgstr "" +"`do_something_with_parse_u8`函数接收一个`felt252`值作为输入并调用`parse_u8`。" +"`?`操作符用来传播错误,如果有的话,或者unwrap成功的值。" + +#: src/ch09-02-error-handling.md:147 +msgid "And with a little test case:" +msgstr "这里还有一个小的测试案例:" + +#: src/ch09-02-error-handling.md:149 +msgid "" +"```rust\n" +"#[test]\n" +"fn test_function_2() {\n" +" let number: felt252 = 258_felt252;\n" +" match do_something_with_parse_u8(number) {\n" +" Result::Ok(value) => value.print(),\n" +" Result::Err(e) => e.print()\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[test]\n" +"fn test_function_2() {\n" +" let number: felt252 = 258_felt252;\n" +" match do_something_with_parse_u8(number) {\n" +" Result::Ok(value) => value.print(),\n" +" Result::Err(e) => e.print()\n" +" }\n" +"}\n" +"```" + +#: src/ch09-02-error-handling.md:160 +msgid "The console will print the error \"Invalid Integer\"." +msgstr "控制台将打印错误 “Invalid Integer”。" + +#: src/ch09-02-error-handling.md:162 +msgid "
" +msgstr "
" + +#: src/ch09-02-error-handling.md:164 +msgid "### Summary" +msgstr "### 总结" + +#: src/ch09-02-error-handling.md:166 +msgid "" +"We saw that recoverable errors can be handled in Cairo using the Result " +"enum, which has two variants: `Ok` and `Err`. The `Result` enum is " +"generic, with types `T` and `E` representing the successful and error " +"values, respectively. The `ResultTrait` provides methods for working with " +"`Result`, such as unwrapping values, checking if the result is `Ok` or " +"`Err`, and panicking with custom messages." +msgstr "" +"我们看到,可恢复的错误可以在Cairo中使用结果枚举来处理,它有两个变体:`Ok`和" +"`Err`。`Result`枚举是通用的,其类型`T`和`E`分别代表成功和错误值。" +"`ResultTrait`提供了处理`Result`的方法,例如解包值,检查结果是`Ok'还是" +"`Err`,以及用自定义消息进行panic。" + +#: src/ch09-02-error-handling.md:168 +msgid "" +"To handle recoverable errors, a function can return a `Result` type and use " +"pattern matching to handle the success or failure of an operation. The `?` " +"operator can be used to implicitly handle errors by propagating the error or " +"unwrapping the successful value. This allows for more concise and clear " +"error handling, where the caller is responsible for managing errors raised " +"by the called function." +msgstr "" +"为了处理可恢复的错误,一个函数可以返回一个`Result`类型,并使用模式匹配来处理" +"操作的成功或失败。`?`操作符可用于通过传播错误或解包成功的值来隐含地处理错误。" +"这使得错误处理更加简洁明了,调用者负责管理由被调用函数引发的错误。" + +#: src/ch99-00-starknet-smart-contracts.md:1 +msgid "# Starknet Smart Contracts" +msgstr "# Starknet智能合约" + +#: src/ch99-00-starknet-smart-contracts.md:3 +msgid "" +"All through the previous sections, you've mostly written programs with a " +"`main` entrypoint. In the coming sections, you will learn to write and " +"deploy Starknet contracts." +msgstr "" +"在前面的章节中,你主要是用`main`入口来编写程序。在接下来的章节中,你将学习如" +"何编写和部署Starknet合约。" + +#: src/ch99-00-starknet-smart-contracts.md:5 +msgid "" +"Starknet contracts, in simple words, are programs that can run on the " +"Starknet VM. Since they run on the VM, they have access to Starknet’s " +"persistent state, can alter or modify variables in Starknet’s states, " +"communicate with other contracts, and interact seamlessly with the " +"underlying L1." +msgstr "" +"Starknet合约,简单地说,就是可以在Starknet虚拟机上运行的程序。由于它们在虚拟" +"机上运行,它们可以访问Starknet的持久性状态,可以改变或修改Starknet状态中的变" +"量,与其他合约沟通,并与底层的L1无缝交互。" + +#: src/ch99-00-starknet-smart-contracts.md:7 +msgid "" +"Starknet contracts are denoted by the `#[contract]` attribute. We'll dive " +"deeper into this in the next sections." +msgstr "" +"Starknet合约是由`#[contract]`属性表示的。我们将在接下来的章节中更深入地探讨这" +"个问题。" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:1 +msgid "# Introduction to smart-contracts" +msgstr "# 智能合约简介" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:3 +msgid "" +"This chapter will give you a high level introduction to what smart-contracts " +"are, what are they used for and why would blockchain developers use Cairo " +"and Starknet.\n" +"If you are already familiar with blockchain programming, feel free to skip " +"this chapter. The last part might still be intersting though." +msgstr "" +"本章是一个关于什么是智能合约,它们有什么用途,以及为什么区块链开发者会使用" +"Cairo和Starknet的高度简介。\n" +"如果你已经熟悉了区块链编程,可以跳过这一章。不过最后一部分应该还是有点意思" +"的。" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:6 +msgid "## Smart-contracts" +msgstr "## 智能合约" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:8 +msgid "" +"Smart contracts gained popularity and became more widespread with the birth " +"of Ethereum. Smart contracts are essentially programs deployed on a " +"blockchain. The term \"smart contract\" is somewhat misleading, as they are " +"neither \"smart\" nor \"contracts\" but rather code and instructions that " +"are executed based on specific inputs. They primarily consist of two " +"components: storage and functions. Once deployed, users can interact with " +"smart contracts by initiating blockchain transactions containing execution " +"data (which function to call and with what input). Smart contracts can " +"modify and read the storage of the underlying blockchain. A smart contract " +"has its own address and is considered a blockchain account, meaning it can " +"hold tokens." +msgstr "" +"随着以太坊的诞生,智能合约得到了普及并变得更加广泛。智能合约本质上是部署在区" +"块链上的程序。术语 \"智能合约 \"有些误导,因为它们既不 \"智能 \"也不是 \"合约" +"\",而只是根据特定输入执行的代码和指令。它们主要由两部分组成:存储和函数。部" +"署后,用户可以通过启动包含执行数据的区块链交易(调用哪个函数,输入什么参数)" +"与智能合约互动。智能合约可以修改和读取底层区块链的存储。智能合约有自己的地" +"址,因此它是一个区块链账户,意味着它可以持有代币。" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:10 +msgid "" +"The programming language used to write smart contracts varies depending on " +"the blockchain. For example, on Ethereum and the [EVM-compatible ecosystem]" +"(https://ethereum.org/en/developers/docs/evm/) ecosystem, the most commonly " +"used language is Solidity, while on Starknet, it is Cairo. The way the code " +"is compiled also differs based on the blockchain. On Ethereum, Solidity is " +"compiled into bytecode. On Starknet, Cairo is compiled into Sierra and then " +"into Cairo Assembly (casm)." +msgstr "" +"用于编写智能合约的编程语言因区块链的不同而不同。例如,在以太坊和[EVM兼容的生" +"态系统](https://ethereum.org/en/developers/docs/evm/)生态系统上,最常用的语言" +"是Solidity,而在Starknet上,是Cairo。代码的编译方式也根据区块链的不同而不同。" +"在Ethereum上,Solidity被编译成字节码。在Starknet上,Cairo被编译成Sierra,然后" +"再编译成Cairo Assembly(casm)。" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:12 +msgid "" +"Smart contracts possess several unique characteristics. They are " +"**permissionless**, meaning anyone can deploy a smart contract on the " +"network (within the context of a decentralized blockchain, of course). Smart " +"contracts are also **transparent**; the data stored by the smart contract is " +"accessible to anyone. The code that composes the contract can also be " +"transparent, enabling **composability**. This allows developers to write " +"smart contracts that use other smart contracts. Smart contracts can only " +"access and interact with data from the blockchain they are deployed on. They " +"require third-party softwares (called `oracles`) to access external data " +"(the price of a token for instance)." +msgstr "" +"智能合约拥有几个独特的特点。它们是**无权限的**,意味着任何人都可以在网络上部" +"署智能合约(当然该网络必须是去中心化区块链)。智能合约也是**透明的**;任何人" +"都可以访问智能合约所存储的数据。构成合约的代码也可以是透明的,实现了**可组合" +"性**。这使得开发者可以编写使用其他智能合约的智能合约。智能合约只能访问它们所" +"部署的区块链上的数据并与之互动。他们需要第三方工具或软件(称为 \"oracles\")" +"来访问外部数据(例如,代币的价格)。" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:14 +msgid "" +"For developers to build smart contracts that can interact with each others, " +"it is required to know what the other contracts look like. Hence, Ethereum " +"developers started to build standards for smart contract developement, the " +"`ERCxx`. The two most used and famous standards are the `ERC20`, used to " +"build tokens like `USDC`, `DAI` or `STARK`, and the `ERC721`, for NFTs (Non-" +"fungible tokens) like `CryptoPunks` or `Everai`." +msgstr "" +"对于开发者来说,要想建立能够相互互动的智能合约,就必须知道其他合约的是什么" +"样。因此,以太坊开发者建立了一些智能合约开发的标准,即 \"ERCxx\"。两个最常用" +"和最著名的标准是 \"ERC20\",用于建立 \"USDC\"、\"DAI \"或 \"STARK \"等代币," +"以及 \"ERC721\",用于 \"CryptoPunks \"或 \"Everai \"等NFTs(Non-fungible " +"tokens)。" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:16 +msgid "## Use cases" +msgstr "## 使用案例" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:18 +msgid "" +"There are many possible use cases for smart-contracts. The only limits are " +"the technical constraints of the blockchain and the creativity of developers." +msgstr "" +"智能合约有许多可能的用例。唯一的限制是区块链的技术限制和开发者的创造力。" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:20 +msgid "#### DeFi" +msgstr "#### DeFi" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:22 +msgid "" +"Right now, the principal use case for smart contracts is similar to that of " +"Ethereum or Bitcoin, which is essentially handling money. In the context of " +"the alternative payment system promised by Bitcoin, smart contracts on " +"Ethereum enable the creation of decentralized financial applications that no " +"longer rely on traditional financial intermediaries. This is what we call " +"DeFi (decentralized finance). DeFi consists of various projects such as " +"lending/borrowing apps, decentralized exchanges (DEX), on-chain derivatives, " +"stablecoins, decentralized hedge funds, insurance, and many more." +msgstr "" +"眼下,智能合约的主要用例与以太坊或比特币的用例类似,基本上是处理金钱。在比特" +"币承诺的替代支付系统的背景下,我们在以太坊上可以使用智能合约创建去中心化的金" +"融应用,不需要再依赖传统的金融中介机构。这就是我们所说的DeFi(去中心化金" +"融)。DeFi由各种项目组成,如借贷应用、去中心化交易所(DEX)、链上衍生品、稳定" +"币、去中心化对冲基金、保险等等。" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:24 +msgid "#### Tokenization" +msgstr "#### 代币化" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:26 +msgid "" +"Smart contracts can facilitate the tokenization of real-world assets, such " +"as real estate, art, or precious metals. Tokenization divides an asset into " +"digital tokens, which can be easily traded and managed on blockchain " +"platforms. This can increase liquidity, enable fractional ownership, and " +"simplify the buying and selling process." +msgstr "" +"智能合约可以促进现实世界资产的代币化,如房地产、艺术品或贵金属。代币化将资产" +"划分为数字代币,可以在区块链平台上轻松交易和管理。这可以增加流动性,实现部分" +"所有权,并简化购买和销售过程。" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:28 +msgid "#### Voting" +msgstr "#### 投票" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:30 +msgid "" +"Smart contracts can be used to create secure and transparent voting systems. " +"Votes can be recorded on the blockchain, ensuring immutability and " +"transparency. The smart contract can then automatically tally the votes and " +"declare the results, minimizing the potential for fraud or manipulation." +msgstr "" +"智能合约可用于创建安全和透明的投票系统。投票可以记录在区块链上,确保不可更改" +"性和透明度。然后,智能合约可以自动统计票数并宣布结果,将欺诈或操纵的可能性降" +"到最低。" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:32 +msgid "#### Royalties" +msgstr "#### 特许权使用费(版税)" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:34 +msgid "" +"Smart contracts can automate royalty payments for artists, musicians, and " +"other content creators. When a piece of content is consumed or sold, the " +"smart contract can automatically calculate and distribute the royalties to " +"the rightful owners, ensuring fair compensation and reducing the need for " +"intermediaries." +msgstr "" +"智能合约可以为艺术家、音乐家和其他内容创作者自动支付版税。当一段内容被消费或" +"出售时,智能合约可以自动计算并将版税分配给合法的所有者,确保公平的补偿并减少" +"对中间人的需求。" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:36 +msgid "#### Decentralized identities DIDs" +msgstr "#### 去中心化身份 DIDs" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:38 +msgid "" +"Smart contracts can be used to create and manage digital identities, " +"allowing individuals to control their personal information and share it with " +"third parties securely. The smart contract could verify the authenticity of " +"a user's identity and automatically grant or revoke access to specific " +"services based on the user's credentials." +msgstr "" +"智能合约可用于创建和管理数字身份,允许个人控制其个人信息,并与第三方安全地分" +"享。智能合约可以验证用户身份的真实性,并根据用户的凭证自动授予或撤销对特定服" +"务的访问。" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:40 +msgid "" +"
\n" +"
\n" +"As Ethereum continues to mature, we can expect the use cases and " +"applications of smart contracts to expand further, bringing about exciting " +"new opportunities and reshaping traditional systems for the better." +msgstr "" +"
\n" +"
\n" +"随着以太坊的不断成熟,我们可以预期智能合约的用例和应用将进一步扩大,带来令人" +"兴奋的新机会,并会更好地重塑传统系统。" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:44 +msgid "## The rise of Starknet and Cairo" +msgstr "## Starknet和Cairo语言的崛起" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:46 +msgid "" +"Ethereum, being the most widely used and resilient smart-contract platform, " +"became a victim of its own success. With the rapid adoption of some " +"previously mentioned use cases, mainly DeFi, the cost of performing " +"transactions became extremely high, rendering the network almost unusable. " +"Engineers and researchers in the ecosystem began working on solutions to " +"address this scalability issue. A famous theorem in the blockchain space " +"states that it is impossible to achieve a high level of scalability, " +"decentralization, and security simultaneously; trade-offs must be made. " +"Ethereum is at the intersection of decentralization and security. " +"Eventually, it was decided that Ethereum's purpose would be to serve as a " +"secure settlement layer, while complex computations would be offloaded to " +"other networks built on top of Ethereum. These are called Layer 2s (L2s). " +"The two primary types of L2s are optimistic rollups and validity rollups. " +"Both approaches involve compressing and batching numerous transactions " +"together, computing the new state, and settling the result on Ethereum (L1). " +"The difference lies in the way the result is settled on L1. For optimistic " +"rollups, the new state is considered valid by default, but there is a 7-day " +"window for nodes to identify malicious transactions. In contrast, validity " +"rollups, such as Starknet, use cryptography to prove that the new state has " +"been correctly computed. This is the purpose of STARKs, this cryptographic " +"technology could permit validity rollups to scale significantly more than " +"optimistic rollups. You can learn more about STARKs from Starkware's Medium " +"[article](https://medium.com/starkware/starks-starkex-and-" +"starknet-9a426680745a), which serves as a good primer." +msgstr "" +"以太坊作为使用最广泛、弹性最大的智能合约平台,成为了其自身成功的受害者。随着" +"前面提到的一些用例的快速采用,主要是DeFi,执行交易的成本变得非常高,使网络几" +"乎无法使用。生态系统中的工程师和研究人员开始研究解决这一可扩展性问题的方案。" +"区块链领域的一个著名定理指出,不可能同时实现高水平的可扩展性、去中心化和安全" +"性;必须做出权衡。以太坊正处于去中心化和安全的交叉点。最终,人们决定,以太坊" +"的目的是作为一个安全的结算层,而复杂的计算将被卸载到建立在以太坊之上的其他网" +"络。这些被称为第二层(L2)。L2的两种主要类型是optimistic-rollups和validity-" +"rollups。这两种方法都涉及到将众多交易压缩和批量化,计算新的状态,并将结果在以" +"太坊(L1)上结算。区别在于结果在L1上结算的方式。对于optimistic-rollups,新的" +"状态默认被认为是有效的,但有一个7天的窗口供节点识别恶意交易。相比之下," +"validity-rollups,如Starknet,使用密码学来证明新的状态已经被正确计算出来。这" +"是STARKs的目的,这种加密技术可以允许validity-rollups的规模大大超过optimistic-" +"rollups。你可以从Starkware的Medium[文章](https://medium.com/starkware/starks-" +"starkex-and-starknet-9a426680745a)中了解更多关于STARKs的信息,这可以作为一个" +"很好的入门。" + +#: src/ch99-01-01-introduction-to-smart-contracts.md:48 +msgid "" +"Remember Cairo? It is, in fact, a language developed specifically to work " +"with STARKs and make them general-purpose. With Cairo, we can write " +"**provable code**. In the context of Starknet, this allows proving the " +"correctness of computations from one state to another. Unlike most (if not " +"all) of Starknet's competitors that chose to use the EVM (either as-is or " +"adapted) as a base layer, Starknet employs its own VM. This frees developers " +"from the constraints of the EVM, opening up a broader range of " +"possibilities. Coupled with decreased transaction costs, the combination of " +"Starknet and Cairo creates an exiting playground for developers. Native " +"account abstraction enables more complex logic for accounts and transaction " +"flows. Emerging use cases include **transparent AI** and artificial " +"intelligence and machine learning applications. Finally, **blockchain " +"games** can be developed entirely **on-chain**. Starknet has been " +"specifically designed to maximize the capabilities of STARK proofs for " +"optimal scalability." +msgstr "" +"还记得Cairo吗?事实上,它是一种专门开发的语言,用于和STARKs一起工作并使其通用" +"化。通过Cairo,我们可以编写**可证明的代码**。在Starknet中,这允许证明从一个状" +"态到另一个状态的计算的正确性。与大多数(如果不是全部)Starknet的竞争对手不" +"同,他们选择使用EVM(无论是原样还是改编)作为基础层,Starknet采用了自己的VM。" +"这使开发者摆脱了EVM的限制,开辟了更广泛的可能性。再加上交易成本的降低," +"Starknet和Cairo的结合为开发者创造了一个令人兴奋的游乐场。原生的账户抽象使账户" +"和交易流的逻辑更加复杂。新兴的用例包括**透明的AI**和人工智能及机器学习应用。" +"最后,**区块链游戏**可以完全**在链上开发**。总之,Starknet是被专门来设计最大" +"化STARK证明能力,以实现最佳的可扩展性。" + +#: src/ch99-01-02-writing-starknet-contracts.md:1 +msgid "# Writing Starknet Contracts" +msgstr "# 撰写Starknet合约" + +#: src/ch99-01-02-writing-starknet-contracts.md:3 +msgid "" +"This chapter will guide you on how to create smart contracts in Cairo, and " +"will clarify the distinction between Cairo programs and Starknet contracts." +msgstr "" +"本章将指导你如何在Cairo中创建智能合约,并将阐明Cairo程序和Starknet合约之间的" +"区别。" + +#: src/ch99-01-02-writing-starknet-contracts.md:5 +msgid "## Cairo programs and Starknet contracts" +msgstr "## Cairo程序和Starknet合约" + +#: src/ch99-01-02-writing-starknet-contracts.md:7 +msgid "" +"Starknet contracts are a special subset of Cairo programs, so the concepts " +"previously learned in this book are still applicable to write Starknet " +"contracts.\n" +"As you may have already noticed, a Cairo program must always have a function " +"`main` that serves as the entry point for this program:" +msgstr "" +"Starknet合约是Cairo程序的一个特殊子集,所以之前在本书中学到的概念仍然适用于编" +"写Starknet合约。\n" +"你可能已经注意到,一个Cairo程序必须始终有一个函数`main`,作为这个程序的入口:" + +#: src/ch99-01-02-writing-starknet-contracts.md:10 +msgid "" +"```rust\n" +"fn main() {}\n" +"```" +msgstr "" +"```rust\n" +"fn main() {}\n" +"```" + +#: src/ch99-01-02-writing-starknet-contracts.md:14 +msgid "" +"Starknet contracts are essentially programs that can run on the Starknet OS, " +"and as such, have access to Starknet's state. For a module to be handled as " +"a contract by the compiler, it must be annotated with the `#[contract]` " +"attribute:" +msgstr "" +"Starknet合约本质上是可以在Starknet操作系统上运行的程序,因此可以访问Starknet" +"的状态。为了让编译器将一个module当作合约来处理,必须用`#[contract]`属性来标" +"注:" + +#: src/ch99-01-02-writing-starknet-contracts.md:16 +msgid "" +"```rust\n" +"#[contract]\n" +"mod Example{\n" +" use starknet::get_caller_address;\n" +" use starknet::ContractAddress;\n" +"\n" +" struct Storage{\n" +" names: LegacyMap::,\n" +" }\n" +"\n" +" #[event]\n" +" fn StoredName(caller: ContractAddress, name:felt252){}\n" +"\n" +" #[constructor]\n" +" fn constructor(_name: felt252, _address: ContractAddress){\n" +" names::write(_address, _name);\n" +" }\n" +"\n" +" #[external]\n" +" fn store_name(_name: felt252){\n" +" let caller = get_caller_address();\n" +" names::write(caller, _name);\n" +" StoredName(caller,_name);\n" +" }\n" +"\n" +" #[view]\n" +" fn get_name(_address:ContractAddress) -> felt252{\n" +" let name = names::read(_address);\n" +" return name;\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[contract]\n" +"mod Example{\n" +" use starknet::get_caller_address;\n" +" use starknet::ContractAddress;\n" +"\n" +" struct Storage{\n" +" names: LegacyMap::,\n" +" }\n" +"\n" +" #[event]\n" +" fn StoredName(caller: ContractAddress, name:felt252){}\n" +"\n" +" #[constructor]\n" +" fn constructor(_name: felt252, _address: ContractAddress){\n" +" names::write(_address, _name);\n" +" }\n" +"\n" +" #[external]\n" +" fn store_name(_name: felt252){\n" +" let caller = get_caller_address();\n" +" names::write(caller, _name);\n" +" StoredName(caller,_name);\n" +" }\n" +"\n" +" #[view]\n" +" fn get_name(_address:ContractAddress) -> felt252{\n" +" let name = names::read(_address);\n" +" return name;\n" +" }\n" +"}\n" +"```" + +#: src/ch99-01-02-writing-starknet-contracts.md:49 +msgid "" +"Listing 9-1: A simple naming service contract" +msgstr "清单9-1:一个简单的命名服务合约" + +#: src/ch99-01-02-writing-starknet-contracts.md:51 +msgid "" +"> NB: Starknet contracts are defined within [modules](./ch06-02-defining-" +"modules-to-control-scope.md)." +msgstr "" +"> 注意:Starknet合约是在[modules](./ch06-02-defining-modules-to-control-" +"scope.md)中定义的。" + +#: src/ch99-01-02-writing-starknet-contracts.md:53 +msgid "## Starknet Contract Attributes" +msgstr "## Starknet合约的属性" + +#: src/ch99-01-02-writing-starknet-contracts.md:55 +msgid "" +"Attributes are special annotations that modify the behavior of certain " +"functions or methods. They are placed preceding a function and are denoted " +"by the `#[]` symbol." +msgstr "" +"属性是修改某些函数或方法的行为的特殊标注。它们被放在一个函数的前面,用`#[]`符" +"号来表示。" + +#: src/ch99-01-02-writing-starknet-contracts.md:57 +msgid "" +msgstr "" + +#: src/ch99-01-02-writing-starknet-contracts.md:59 +msgid "Here are a list of common attributes used in Starknet contracts:" +msgstr "以下是Starknet合约中使用的常见属性列表:" + +#: src/ch99-01-02-writing-starknet-contracts.md:61 +msgid "" +"1. `#[contract]`: This attribute is used to annotate a module to be compiled " +"as a Starknet contract.\n" +" The compiler recognizes this attribute and prepares the module with " +"necessary contract elements,\n" +" such as the logic to handle external contract calls or how to access " +"storage variables.\n" +"\n" +"2. `#[constructor]`: This attribute marks a function as a constructor. The " +"constructor function is called only once upon deploying a contract, setting " +"the initial state of the contract.\n" +"\n" +"3. `#[external]`: This attribute marks a function as an external function. " +"External functions can be called by other contracts or externally and can " +"modify the contract's state.\n" +"\n" +"4. `#[view]`: This attribute marks a function as a view function. View " +"functions are read-only functions that allow you to access data from the " +"contract, but prevent you from modifying the state of the blockchain.\n" +"\n" +"5. `#[event]`: This is used to define events that can be emitted by the " +"contract.\n" +"\n" +"6. `#[l1_handler]`: This attribute is used to mark functions which can " +"receive messages from L1s." +msgstr "" +"1. `#[contract]`:这个属性用来标注一个要被编译为Starknet合约的模块。\n" +" 编译器会识别这个属性并为模块准备必要的合同元素、\n" +" 例如,处理外部合同调用的逻辑或如何访问存储变量。\n" +"\n" +"2. `#[constructor]`:这个属性标志着一个函数是一个构造函数。构造函数在部署合约" +"时只被调用一次,设置合约的初始状态。\n" +"\n" +"3. `#[external]`:这个属性标志着一个函数是一个外部函数。外部函数可以被其他合" +"约或外部调用,可以修改合约的状态。\n" +"\n" +"4. `#[view]`:这个属性标志着一个函数是一个视图函数。视图函数是只读函数,允许" +"你访问合约中的数据,但阻止你修改区块链的状态。\n" +"\n" +"5. `#[event]`:这是用来定义可由合约发出的事件。\n" +"\n" +"6. `#[l1_handler]`:这个属性用来标记可以接收L1消息的函数。" + +#: src/ch99-01-02-writing-starknet-contracts.md:75 +msgid "## Storage Variables" +msgstr "## 存储用变量" + +#: src/ch99-01-02-writing-starknet-contracts.md:77 +msgid "" +"Storage variables allow you to store data that will be stored on the " +"blockchain in the contract's storage. These data are persistent and can be " +"accessed and modified anytime once the contract is deployed." +msgstr "" +"存储用变量允许你存储数据,这些数据将存储在合约的存储区块链上。这些数据是持久" +"性的,一旦合约被部署,可以随时访问和修改。" + +#: src/ch99-01-02-writing-starknet-contracts.md:79 +msgid "" +"Storage variables in Starknet contracts are stored in a special struct " +"called `Storage`:" +msgstr "Starknet合同中的存储用变量被存储在一个特殊的结构中,称为`Storage`:" + +#: src/ch99-01-02-writing-starknet-contracts.md:81 +msgid "" +"```rust\n" +"struct Storage{\n" +" id: u8,\n" +" names: LegacyMap::,\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"struct Storage{\n" +" id: u8,\n" +" names: LegacyMap::,\n" +"}\n" +"```" + +#: src/ch99-01-02-writing-starknet-contracts.md:88 +msgid "Listing 9-2: A Storage Struct" +msgstr "清单9-2:存储用结构体" + +#: src/ch99-01-02-writing-starknet-contracts.md:90 +msgid "" +"The storage struct is a [struct](./ch04-00-using-structs-to-structure-" +"related-data.md) like any other,\n" +"except that it allows you to define mappings using the `LegacyMap` type." +msgstr "" +"存储用结构体是一个[struct](./ch04-00-using-structs-to-structure-related-data." +"md) ,基本与其他结构一样、\n" +"但是它允许你使用 `LegacyMap`类型来定义映射。" + +#: src/ch99-01-02-writing-starknet-contracts.md:93 +msgid "### Storage Mappings" +msgstr "### 存储用映射" + +#: src/ch99-01-02-writing-starknet-contracts.md:95 +msgid "" +"Mappings are a key-value data structure that you can use to store data " +"within a smart contract. They are essentially hash tables that allow you to " +"associate a unique key with a corresponding value. Mappings are also useful " +"to store sets of data, as it's impossible to store arrays in storage." +msgstr "" +"映射是一种键值数据结构,你可以用它来存储智能合约中的数据。它们本质上是哈希" +"表,允许你将一个唯一的键与一个相应的值联系起来。映射对于存储数据集也很有用," +"因为在存储中不可能存储数组。" + +#: src/ch99-01-02-writing-starknet-contracts.md:97 +msgid "" +"A mapping is a variable of type LegacyMap, in which the key and value types " +"are specified within angular brackets <>.\n" +"It is important to note that the `LegacyMap` type can only be used inside " +"the `Storage` struct, and can't be used to define mappings in user-defined " +"structs.\n" +"The syntax for declaring a mapping is as follows in Listing 9-2." +msgstr "" +"映射是一个LegacyMap类型的变量,其中键和值的类型在角括号<>内指定。\n" +"需要注意的是,\"LegacyMap \"类型只能在 \"Storage \"结构中使用,而不能用于在用" +"户定义的结构中定义映射。\n" +"声明映射的语法如清单9-2所示。" + +#: src/ch99-01-02-writing-starknet-contracts.md:101 +msgid "" +"You can also create more complex mappings than that found in Listing 9-2 " +"like the popular `allowances` storage variable in the ERC20 Standard which " +"maps the `owner` and `spender` to the `allowance` using tuples:" +msgstr "" +"你也可以创建比清单9-2中更复杂的映射,比如ERC20标准中流行的`allowances`存储变" +"量,它使用元组将 `owner`和 `spender`映射到`allowance` 上:" + +#: src/ch99-01-02-writing-starknet-contracts.md:103 +msgid "" +"```rust\n" +"struct Storage{\n" +" allowances: LegacyMap::<(ContractAddress, ContractAddress), u256>\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"struct Storage{\n" +" allowances: LegacyMap::<(ContractAddress, ContractAddress), u256>\n" +"}\n" +"```" + +#: src/ch99-01-02-writing-starknet-contracts.md:109 +msgid "" +"In mappings, the address of the value at key `k_1,...,k_n` is `h(..." +"h(h(sn_keccak(variable_name),k_1),k_2),...,k_n)` where ℎ\n" +"is the Pedersen hash and the final value is taken `mod2251−256`. You can " +"learn more about the contract storage layout in the [Starknet Documentation]" +"(https://docs.starknet.io/documentation/architecture_and_concepts/Contracts/" +"contract-storage/#storage_variables)" +msgstr "" +"在映射中,键`k_1,...,k_n`的值的地址是`h(...h(h(sn_keccak(variable_name),k_1)," +"k_2),...,k_n)`,其中ℎ\n" +"是Pedersen哈希值,最终值取为 \"mod2251-256\"。你可以在[Starknet文档](https://" +"docs.starknet.io/documentation/architecture_and_concepts/Contracts/contract-" +"storage/#storage_variables)中了解更多关于合约存储布局的信息。" + +#: src/ch99-01-02-writing-starknet-contracts.md:112 +msgid "### Reading from Storage" +msgstr "### 从存储中读取" + +#: src/ch99-01-02-writing-starknet-contracts.md:114 +msgid "" +"To read the value of the storage variable `names`, we call the `read` " +"function on the `names` storage variable, passing in the key `_address` as a " +"parameter." +msgstr "" +"为了读取存储变量`names`的值,我们在`names`的存储变量上调用`read`函数,将键" +"`_address`作为参数传入。" + +#: src/ch99-01-02-writing-starknet-contracts.md:116 +msgid "" +"```rust\n" +"let name = names::read(_address);\n" +"```" +msgstr "" +"```rust\n" +"let name = names::read(_address);\n" +"```" + +#: src/ch99-01-02-writing-starknet-contracts.md:120 +msgid "" +"Listing 9-3: Calling the `read` function on the " +"`names` variable" +msgstr "清单9-3:在`names`变量上调用`read`函数" + +#: src/ch99-01-02-writing-starknet-contracts.md:122 +msgid "" +"> Note: When the storage variable does not store a mapping, its value is " +"accessed without passing any parameters to the read method" +msgstr "" +"> 注意:当存储变量不存储映射时,使用读取方法访问其值不需要传递任何参数。" + +#: src/ch99-01-02-writing-starknet-contracts.md:124 +msgid "### Writing to Storage" +msgstr "### 写入存储" + +#: src/ch99-01-02-writing-starknet-contracts.md:126 +msgid "" +"To write a value to the storage variable `names`, we call the `write` " +"function on the `names` storage variable, passing in the key and values as " +"arguments." +msgstr "" +"为了给存储变量`names`写一个值,我们在`names`存储变量上调用`write`函数,将键和" +"值作为参数传入。" + +#: src/ch99-01-02-writing-starknet-contracts.md:128 +msgid "" +"```rust\n" +"names::write(_address, _name);\n" +"```" +msgstr "" +"```rust\n" +"names::write(_address, _name);\n" +"```" + +#: src/ch99-01-02-writing-starknet-contracts.md:132 +msgid "" +"Listing 9-4: Writing to the `names` variable" +msgstr "清单9-4:向 \"names \"变量写入内容" + +#: src/ch99-01-02-writing-starknet-contracts.md:136 +msgid "" +"In this section, we are going to be looking at some popular function types " +"you'd encounter with most contracts:" +msgstr "在这一节中,我们会看到一些大多数合同中会遇到的常用的函数类型:" + +#: src/ch99-01-02-writing-starknet-contracts.md:138 +msgid "### 1. Constructors" +msgstr "### 1.构造器(Constructors)" + +#: src/ch99-01-02-writing-starknet-contracts.md:140 +msgid "" +"Constructors are a special type of function that runs only once when " +"deploying a contract, and can be used to initialize the state of the " +"contract." +msgstr "" +"构造器是一种特殊的函数,在部署合约时只运行一次,可以用来初始化合约的状态。" + +#: src/ch99-01-02-writing-starknet-contracts.md:142 +msgid "" +"```rust\n" +"#[constructor]\n" +"fn constructor(_name: felt252, _address: ContractAddress){\n" +" names::write(_address, _name);\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[constructor]\n" +"fn constructor(_name: felt252, _address: ContractAddress){\n" +" names::write(_address, _name);\n" +"}\n" +"```" + +#: src/ch99-01-02-writing-starknet-contracts.md:149 +msgid "Some important rules to note:" +msgstr "一些需要注意的重要规则:" + +#: src/ch99-01-02-writing-starknet-contracts.md:151 +msgid "" +"1. Your contract can't have more than one constructor.\n" +"2. Your constructor function must be named `constructor`.\n" +"3. Lastly, it must be annotated with the `#[constructor]` attribute." +msgstr "" +"1.你的合同不能有一个以上的构造函数。\n" +"\n" +"2.你的构造函数必须被命名为`constructor`。\n" +"\n" +"3.最后,它必须用 `#[constructor]`属性来标注" + +#: src/ch99-01-02-writing-starknet-contracts.md:155 +msgid "### 2. External functions" +msgstr "### 2.外部函数" + +#: src/ch99-01-02-writing-starknet-contracts.md:157 +msgid "" +"External functions are functions that can modify the state of a contract. " +"They are public and can be called by any other contract or externally.\n" +"You can define external functions by annotating them with the `#[external]` " +"attribute:" +msgstr "" +"外部函数是可以修改合同状态的函数。它们是公共的,可以被任何其他合约或外部调" +"用。\n" +"你可以用 `#[external]`属性标注来定义外部函数:" + +#: src/ch99-01-02-writing-starknet-contracts.md:160 +msgid "" +"```rust\n" +"#[external]\n" +"fn store_name(_name: felt252){\n" +" let caller = get_caller_address();\n" +" names::write(caller, _name);\n" +" StoredName(caller,_name);\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[external]\n" +"fn store_name(_name: felt252){\n" +" let caller = get_caller_address();\n" +" names::write(caller, _name);\n" +" StoredName(caller,_name);\n" +"}\n" +"```" + +#: src/ch99-01-02-writing-starknet-contracts.md:169 +msgid "### 3. View functions" +msgstr "### 3.视图函数" + +#: src/ch99-01-02-writing-starknet-contracts.md:171 +msgid "" +"View functions are read-only functions allowing you to access data from the " +"contract while ensuring that the state of the contract is not modified. They " +"can be called by other contracts or externally.\n" +"You can define view functions by annotating them with the `#[view]` " +"attribute:" +msgstr "" +"视图函数是只读函数,允许你从合同中访问数据,同时确保合同的状态不被修改。它们" +"可以被其他合约或外部调用。\n" +"你可以通过用 `#[view]` 属性标注它们来定义视图函数:" + +#: src/ch99-01-02-writing-starknet-contracts.md:174 +msgid "" +"```rust\n" +"#[view]\n" +"fn get_name(_address:ContractAddress) -> felt252{\n" +" let name = names::read(_address);\n" +" return name;\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[view]\n" +"fn get_name(_address:ContractAddress) -> felt252{\n" +" let name = names::read(_address);\n" +" return name;\n" +"}\n" +"```" + +#: src/ch99-01-02-writing-starknet-contracts.md:182 +msgid "" +"> **NB:** It's important to note that, both external and view functions are " +"public. To create an internal function in a contract, you simply don't " +"annotate it with any attribute." +msgstr "" +"> **NB:** 需要注意的是,外部函数和视图函数都是公开的。要在合同中创建一个内部" +"函数,你只需不给它注解任何属性。" + +#: src/ch99-01-02-writing-starknet-contracts.md:184 +msgid "## Events" +msgstr "## 事件" + +#: src/ch99-01-02-writing-starknet-contracts.md:186 +msgid "" +"Events are custom data structures that are emitted by smart contracts during " +"execution.\n" +"They provide a way for smart contracts to communicate with the external " +"world by logging information\n" +"about specific occurences in a contract." +msgstr "" +"事件是定制的数据结构,由智能合约在执行期间发出。\n" +"它们为智能合约提供了一种与外部世界沟通的方式,即记录合约中特定事件的信息。" + +#: src/ch99-01-02-writing-starknet-contracts.md:190 +msgid "" +"Events play a crucial role in the creation of smart contracts. Take, for " +"instance, the Non-Fungible Tokens (NFTs) minted on Starknet. All of these " +"are indexed and stored in a database, then displayed to users through the " +"use of these events. Neglecting to include an event within your NFT contract " +"could lead to a bad user experience. This is because users may not see their " +"NFTs appear in their wallets (wallets use these indexers to display a user's " +"NFTs)." +msgstr "" +"事件在智能合约的创建中起着至关重要的作用。以Starknet上铸造的Non-Fungible " +"Tokens(NFTs)为例。所有这些都被索引并存储在数据库中,然后通过使用这些事件显" +"示给用户。忘记在你的NFT合约中编写一个事件可能会导致糟糕的用户体验。这是因为用" +"户可能看不到他们的NFT出现在他们的钱包里(钱包使用这些索引器来显示用户的" +"NFT)。" + +#: src/ch99-01-02-writing-starknet-contracts.md:192 +msgid "### Defining events" +msgstr "### 界定事件" + +#: src/ch99-01-02-writing-starknet-contracts.md:194 +msgid "" +"An event is defined as an empty function annotated with the `#[event]` " +"attribute. The parameters of this function\n" +"are the data that will be emitted by the event." +msgstr "" +"一个事件被定义为一个用`#[event]`属性注释的空函数。这个函数的参数\n" +"的参数是将由该事件发出的数据。" + +#: src/ch99-01-02-writing-starknet-contracts.md:197 +msgid "" +"In Listing 9-1, `StoredName` is an event that emits information when names " +"are stored in the contract:" +msgstr "" +"在清单9-1中,`StoredName`是一个当名字被存储在合约中时,会被触发并发出信息的事" +"件:" + +#: src/ch99-01-02-writing-starknet-contracts.md:199 +msgid "" +"```rust\n" +"#[event]\n" +"fn StoredName(caller: ContractAddress, name:felt252){}\n" +"```" +msgstr "" +"```rust\n" +"#[event]\n" +"fn StoredName(caller: ContractAddress, name:felt252){}\n" +"```" + +#: src/ch99-01-02-writing-starknet-contracts.md:204 +msgid "" +"We pass in the emitted data types as parameters within the parentheses. In " +"this example, our event will emit the contract address of the caller and the " +"name stored within the contract." +msgstr "" +"我们在括号内传入作为把发射的数据类型参数传入。在这个例子中,我们的事件将发出" +"调用者的合同地址和存储在合同中的名字的信息。" + +#: src/ch99-01-02-writing-starknet-contracts.md:206 +msgid "### Emitting events" +msgstr "### 发射事件" + +#: src/ch99-01-02-writing-starknet-contracts.md:208 +msgid "" +"After defining events, we can emit them by simply calling the event name " +"like we'll call functions,\n" +"passing in the values to be emitted as parameters:" +msgstr "" +"定义完事件后,我们可以像调用函数一样简单地调用事件名称来发射它们、\n" +"作为参数传入要发射的值:" + +#: src/ch99-01-02-writing-starknet-contracts.md:211 +msgid "" +"```rust\n" +"StoredName(caller,_name);\n" +"```" +msgstr "" +"```rust\n" +"StoredName(caller,_name);\n" +"```" + +#: src/ch99-02-00-abis-and-cross-contract-interactions.md:1 +msgid "# Starknet contracts: ABIs and cross-contract interactions" +msgstr "# Starknet合约:ABI和跨合约交互" + +#: src/ch99-02-00-abis-and-cross-contract-interactions.md:3 +msgid "" +"The ability of contracts to interact with other smart contracts on the " +"blockchain is a common pattern found in smart contract development." +msgstr "合约与区块链上其他智能合约的互动能力是智能合约开发中的一个常见模式。" + +#: src/ch99-02-00-abis-and-cross-contract-interactions.md:5 +msgid "" +"This chapter covers how cross-contract interactions between Starknet " +"contracts can be achieved. Specifically, you'll learn about ABIs, contract " +"interfaces, the contract and library dispatchers and their low-level system " +"call equivalents!" +msgstr "" +"这一章涵盖了如何实现Starknet合约之间的跨合约交互。具体来说,你会了解到ABI、合" +"约接口、合约和库调度器以及它们的底层系统调用存在形式!" + +#: src/ch99-02-01-abis-and-interfaces.md:1 +msgid "# ABIs and Contract Interfaces" +msgstr "# ABI和合约接口" + +#: src/ch99-02-01-abis-and-interfaces.md:3 +msgid "" +"Cross-contract interactions between smart contracts on a blockchain is a " +"common practice which enables us to build flexible contracts that can speak " +"with each other." +msgstr "" +"区块链上的智能合约之间的跨合约互动是一种常见的做法,它使我们能够建立灵活的合" +"约,相互对话。" + +#: src/ch99-02-01-abis-and-interfaces.md:5 +msgid "Achieving this on Starknet requires something we call an interface." +msgstr "在Starknet上实现这一点需要我们称之为接口的东西。" + +#: src/ch99-02-01-abis-and-interfaces.md:7 +msgid "## Interface" +msgstr "## 接口" + +#: src/ch99-02-01-abis-and-interfaces.md:9 +msgid "" +"An interface is a list of a contract's function definitions without " +"implementations. In other words, an interface specifies the function " +"declarations (name, parameters, visibility and return value) contained in a " +"smart contract without including the function body." +msgstr "" +"一个接口是一个合约的函数定义的列表,没有实现。换句话说,一个接口指定了智能合" +"约中包含的函数声明(名称、参数、可见性和返回值),而不包括函数主体。" + +#: src/ch99-02-01-abis-and-interfaces.md:11 +msgid "" +"Interfaces in Cairo are traits with the `#[abi]` attribute. If you are new " +"to traits, check out the dedicated chapter on [traits](./ch07-02-traits-in-" +"cairo.md)." +msgstr "" +"Cairo中的接口是带有`#[abi]`属性的traits。如果你是traits的新手,请查看关于" +"[traits](./ch07-02-traits-in-cairo.md)的专门章节。" + +#: src/ch99-02-01-abis-and-interfaces.md:13 +msgid "" +"For your Cairo code to qualify as an interface, it must meet the following " +"requirements:" +msgstr "要使你的Cairo代码有资格成为一个接口,它必须满足以下要求:" + +#: src/ch99-02-01-abis-and-interfaces.md:15 +msgid "" +"1. Must be appended with the `#[abi]` attribute.\n" +"2. Your interface functions should have no implementations.\n" +"3. You must explicitly declare the function's decorator.\n" +"4. Your interface should not declare a constructor.\n" +"5. Your interface should not declare state variables." +msgstr "" +"1. 必须附加 `#[abi]` 属性。\n" +"2. 你的接口函数不应该有任何实现。\n" +"3. 你必须明确地声明该函数的装饰器。\n" +"4. 你的接口不应该声明一个构造函数。\n" +"5. 你的接口不应该声明状态变量。" + +#: src/ch99-02-01-abis-and-interfaces.md:21 +msgid "Here's a sample interface for an ERC20 token contract:" +msgstr "下面是一个ERC20代币合约的接口样本:" + +#: src/ch99-02-01-abis-and-interfaces.md:23 +msgid "" +"```rust\n" +"use starknet::ContractAddress;\n" +"\n" +"#[abi]\n" +"trait IERC20 {\n" +" #[view]\n" +" fn name() -> felt252;\n" +"\n" +" #[view]\n" +" fn symbol() -> felt252;\n" +"\n" +" #[view]\n" +" fn decimals() -> u8;\n" +"\n" +" #[view]\n" +" fn total_supply() -> u256;\n" +"\n" +" #[view]\n" +" fn balance_of(account: ContractAddress) -> u256;\n" +"\n" +" #[view]\n" +" fn allowance(owner: ContractAddress, spender: ContractAddress) -> u256;\n" +"\n" +" #[external]\n" +" fn transfer(recipient: ContractAddress, amount: u256) -> bool;\n" +"\n" +" #[external]\n" +" fn transfer_from(sender: ContractAddress, recipient: ContractAddress, " +"amount: u256) -> bool;\n" +"\n" +" #[external]\n" +" fn approve(spender: ContractAddress, amount: u256) -> bool;\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"use starknet::ContractAddress;\n" +"\n" +"#[abi]\n" +"trait IERC20 {\n" +" #[view]\n" +" fn name() -> felt252;\n" +"\n" +" #[view]\n" +" fn symbol() -> felt252;\n" +"\n" +" #[view]\n" +" fn decimals() -> u8;\n" +"\n" +" #[view]\n" +" fn total_supply() -> u256;\n" +"\n" +" #[view]\n" +" fn balance_of(account: ContractAddress) -> u256;\n" +"\n" +" #[view]\n" +" fn allowance(owner: ContractAddress, spender: ContractAddress) -> u256;\n" +"\n" +" #[external]\n" +" fn transfer(recipient: ContractAddress, amount: u256) -> bool;\n" +"\n" +" #[external]\n" +" fn transfer_from(sender: ContractAddress, recipient: ContractAddress, " +"amount: u256) -> bool;\n" +"\n" +" #[external]\n" +" fn approve(spender: ContractAddress, amount: u256) -> bool;\n" +"}\n" +"```" + +#: src/ch99-02-01-abis-and-interfaces.md:57 +msgid "Listing 9-1: A simple ERC20 Interface" +msgstr "清单9-1:一个简单的ERC20接口" + +#: src/ch99-02-01-abis-and-interfaces.md:59 +msgid "## ABIs" +msgstr "## ABI" + +#: src/ch99-02-01-abis-and-interfaces.md:61 +msgid "" +"ABI stands for Application Binary Interface. ABIs gives a smart contract the " +"ability to communicate and interact with external applications or other " +"smart contracts. ABIs can be likened to APIs in traditional web development, " +"which helps data flow between applications and servers." +msgstr "" +"ABI是指应用二进制接口。ABI使智能合约有能力与外部应用程序或其他智能合约进行沟" +"通和互动。ABI可以比喻为传统网络开发中的API,它帮助数据在应用程序和服务器之间" +"流动。" + +#: src/ch99-02-01-abis-and-interfaces.md:63 +msgid "" +"While we write our smart contract logics in high-level Cairo, they are " +"stored on the VM as executable bytecodes which are in binary formats. Since " +"this bytecode is not human readable, it requires interpretation to be " +"understood. This is where ABIs come into play, defining specific methods " +"which can be called to a smart contract for execution." +msgstr "" +"虽然我们用高级语言Cairo编写智能合约逻辑,但它们被存储在虚拟机上的可执行字节码" +"是二进制格式的。由于这种字节码不是人类可读的,它需要解释才能理解。这就是ABI发" +"挥作用的地方,它定义了可以调用智能合约执行的特定方法。" + +#: src/ch99-02-01-abis-and-interfaces.md:65 +msgid "" +"Every contract on Starknet has an Application Binary Interface (ABI) that " +"defines how to encode and decode data when calling its methods." +msgstr "" +"Starknet上的每个合约都有一个应用二进制接口(ABI),它定义了在调用其方法时如何" +"对数据进行编码和解码。" + +#: src/ch99-02-01-abis-and-interfaces.md:67 +msgid "" +"In the next chapter, we are going to be looking into how we can call other " +"smart contracts using a `Contract Dispatcher`, `Library Dispatcher`, and " +"`System calls`." +msgstr "" +"在下一章,我们将研究如何使用 \"合约调度器\"、\"库调度器 \"和 \"系统调用 \"来" +"调用其他智能合约。" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:1 +msgid "# Contract Dispatcher, Library Dispatcher and System calls" +msgstr "# 合约调度器、库调度器和系统调用" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:3 +msgid "" +"Each time a contract interface is created on Starknet, two dispatchers are " +"automatically created and exported:" +msgstr "每次在Starknet上创建一个合同接口时,都会自动创建并输出两个调度器:" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:5 +msgid "" +"1. The Contract Dispatcher\n" +"2. The Library Dispatcher" +msgstr "" +"1. 合约调度器\n" +"2. 库调度器" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:8 +msgid "" +"In this chapter, we are going to extensively discuss how these dispatchers " +"work and their usage." +msgstr "在本章中,我们将广泛讨论这些调度器的工作方式和使用方法。" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:10 +msgid "" +"To effectively break down the concepts in this chapter, we are going to be " +"using the IERC20 interface from the previous chapter (refer to Listing 9-1):" +msgstr "" +"为了有效地分解本章的概念,我们将使用前一章的IERC20接口(参考清单9-1):" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:12 +msgid "## Contract Dispatcher" +msgstr "## 合约调度器" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:14 +msgid "" +"Traits annotated with the `#[abi]` attribute are programmed to automatically " +"generate and export the relevant dispatcher logic on compilation. The " +"compiler also generates a new trait, two new structs (one for contract " +"calls, and the other for library calls) and their implementation of this " +"trait. Our interface is expanded into something like this:" +msgstr "" +"用`#[abi]`属性注释的trait会在编译时自动生成并导出相关的调度器。编译器也会生成" +"一个新的trait、两个新的结构体(一个用于合约调用,另一个用于库调用)以及它们对" +"这个trait的实现。我们的接口被扩展为如下:" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:16 +msgid "" +"```rust\n" +"trait IERC20DispatcherTrait {\n" +" fn get_name(self: T) -> felt252;\n" +" fn transfer(self: T, recipient: ContractAddress, amount: u256);\n" +"}\n" +"\n" +"#[derive(Copy, Drop)]\n" +"struct IERC20Dispatcher {\n" +" contract_address: starknet::ContractAddress,\n" +"}\n" +"\n" +"impl IERC20DispatcherImpl of IERC20DispatcherTrait:: {\n" +" fn get_name(self: IERC20Dispatcher) -> felt252 {\n" +" // starknet::call_contract_syscall is called in here\n" +" }\n" +" fn transfer(self: IERC20Dispatcher, recipient: ContractAddress, amount: " +"u256) {\n" +" // starknet::call_contract_syscall is called in here\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"trait IERC20DispatcherTrait {\n" +" fn get_name(self: T) -> felt252;\n" +" fn transfer(self: T, recipient: ContractAddress, amount: u256);\n" +"}\n" +"\n" +"#[derive(Copy, Drop)]\n" +"struct IERC20Dispatcher {\n" +" contract_address: starknet::ContractAddress,\n" +"}\n" +"\n" +"impl IERC20DispatcherImpl of IERC20DispatcherTrait:: {\n" +" fn get_name(self: IERC20Dispatcher) -> felt252 {\n" +" // starknet::call_contract_syscall is called in here\n" +" }\n" +" fn transfer(self: IERC20Dispatcher, recipient: ContractAddress, amount: " +"u256) {\n" +" // starknet::call_contract_syscall is called in here\n" +" }\n" +"}\n" +"```" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:37 +msgid "" +"Listing 9-2: An expanded form of the IERC20 trait" +msgstr "清单9-2:IERC20trait的扩展" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:39 +msgid "" +"**NB:** The expanded code for our IERC20 interface is a lot more robust, but " +"to keep this chapter concise and straight to the point, we focused on one " +"view function `get_name`, and one external function `transfer`." +msgstr "" +"**NB:** 真实的IERC20接口的扩展代码要全面得多,但为了保持本章的简洁和直奔主" +"题,我们把重点放在一个视图函数`get_name`和一个外部函数`transfer`。" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:41 +msgid "" +"It's also worthy of note that all these is abstracted behind the scenes " +"thanks to the power of Cairo plugins." +msgstr "并且值得注意的是,由于Cairo插件的力量,所有这些都在幕后被抽象化了。" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:43 +msgid "### Calling Contracts using the Contract Dispatcher" +msgstr "### 使用合约调度器调用合约" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:45 +msgid "" +"This is an example of a contract named `Dispatcher` using the Contract " +"interface dispatcher to call an ERC-20 contract in the ERC-20 contract's " +"context and, in the case of `transfer_token`, altering the state of the " +"ERC-20 contract:" +msgstr "" +"这是一个名为`Dispatcher`的合同的例子,使用合约接口调度器在ERC-20合约的上下文" +"中调用ERC-20合约,并在`transfer_token`的中,改变了ERC-20合同的状态:" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:47 +msgid "" +"```rust\n" +"//**** Specify interface here ****//\n" +"\n" +"#[contract]\n" +"mod Dispatcher {\n" +" use super::IERC20DispatcherTrait;\n" +" use super::IERC20Dispatcher;\n" +" use starknet::ContractAddress;\n" +"\n" +" #[view]\n" +" fn token_name(\n" +" _contract_address: ContractAddress\n" +" ) -> felt252 {\n" +" IERC20Dispatcher {contract_address: _contract_address }.name()\n" +" }\n" +"\n" +" #[external]\n" +" fn transfer_token(\n" +" _contract_address: ContractAddress, recipient: ContractAddress, " +"amount: u256\n" +" ) -> bool {\n" +" IERC20Dispatcher {contract_address: _contract_address }." +"transfer(recipient, amount)\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"//**** Specify interface here ****//\n" +"\n" +"#[contract]\n" +"mod Dispatcher {\n" +" use super::IERC20DispatcherTrait;\n" +" use super::IERC20Dispatcher;\n" +" use starknet::ContractAddress;\n" +"\n" +" #[view]\n" +" fn token_name(\n" +" _contract_address: ContractAddress\n" +" ) -> felt252 {\n" +" IERC20Dispatcher {contract_address: _contract_address }.name()\n" +" }\n" +"\n" +" #[external]\n" +" fn transfer_token(\n" +" _contract_address: ContractAddress, recipient: ContractAddress, " +"amount: u256\n" +" ) -> bool {\n" +" IERC20Dispatcher {contract_address: _contract_address }." +"transfer(recipient, amount)\n" +" }\n" +"}\n" +"```" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:72 +msgid "" +"Listing 9-3: A sample contract which uses the " +"Contract Dispatcher" +msgstr "清单9-3:一个使用合约调度器的样本合约" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:74 +msgid "" +"As you can see, we had to first import the `IERC20DispatcherTrait` and " +"`IERC20Dispatcher` which was generated and exported on compiling our " +"interface, then we make calls to the methods implemented for the " +"`IERC20Dispatcher` struct (`name`, `transfer`, etc), passing in the " +"`contract_address` parameter which represents the address of the contract we " +"want to call." +msgstr "" +"正如你所看到的,我们必须首先导入`IERC20DispatcherTrait`和`IERC20Dispatcher`," +"这是在编译我们的接口时生成和导出的,然后我们调用为`IERC20Dispatcher`结构实现" +"的方法(`name`、`transfer`等),传入`contract_address`参数,表示我们要调用的" +"合同地址。" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:76 +msgid "## Library Dispatcher" +msgstr "## 库调度器" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:78 +msgid "" +"The key difference between the contract dispatcher and the library " +"dispatcher is that while the contract dispatcher calls an external " +"contract's logic in the external contract's context, the library dispatcher " +"calls the target contract's classhash, whilst executing the call in the " +"calling contract's context.\n" +"So unlike the contract dispatcher, calls made using the library dispatcher " +"have no possibility of tampering with the target contract's state." +msgstr "" +"合约调度器和库调度器的关键区别在于,合约调度器是在外部合约的上下文中调用外部" +"合约的逻辑,而库调度器则是在调用合约的上下文中执行调用,调用目标契约的" +"classhash。\n" +"因此,与合约调度器不同,使用库调度器进行的调用不可能篡改目标合约的状态。" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:81 +msgid "" +"As stated in the previous chapter, contracts annotated with the `#[abi]` " +"macro on compilation generates a new trait, two new structs (one for " +"contract calls, and the other for library calls) and their implementation of " +"this trait. The expanded form of the library traits looks like:" +msgstr "" +"如前一章所述,在编译时用`#[abi]`宏标注的合约会生成一个新的trait、两个新的结构" +"体(一个用于契约调用,另一个用于库调用)以及它们对该trait的实现。库特征的扩展" +"形式看起来像:" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:83 +msgid "" +"```rust\n" +"trait IERC20DispatcherTrait {\n" +" fn get_name(self: T) -> felt252;\n" +" fn transfer(self: T, recipient: ContractAddress, amount: u256);\n" +"}\n" +"\n" +"#[derive(Copy, Drop)]\n" +"struct IERC20LibraryDispatcher {\n" +" class_hash: starknet::ClassHash,\n" +"}\n" +"\n" +"impl IERC20LibraryDispatcherImpl of IERC20DispatcherTrait::" +" {\n" +" fn get_name(self: IERC20LibraryDispatcher) -> felt252 {\n" +" // starknet::syscalls::library_call_syscall is called in here\n" +" }\n" +" fn transfer(self: IERC20LibraryDispatcher, recipient: ContractAddress, " +"amount: u256) {\n" +" // starknet::syscalls::library_call_syscall is called in here\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"trait IERC20DispatcherTrait {\n" +" fn get_name(self: T) -> felt252;\n" +" fn transfer(self: T, recipient: ContractAddress, amount: u256);\n" +"}\n" +"\n" +"#[derive(Copy, Drop)]\n" +"struct IERC20LibraryDispatcher {\n" +" class_hash: starknet::ClassHash,\n" +"}\n" +"\n" +"impl IERC20LibraryDispatcherImpl of IERC20DispatcherTrait::" +" {\n" +" fn get_name(self: IERC20LibraryDispatcher) -> felt252 {\n" +" // starknet::syscalls::library_call_syscall is called in here\n" +" }\n" +" fn transfer(self: IERC20LibraryDispatcher, recipient: ContractAddress, " +"amount: u256) {\n" +" // starknet::syscalls::library_call_syscall is called in here\n" +" }\n" +"}\n" +"```" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:104 +msgid "" +"Listing 9-4: An expanded form of the IERC20 trait" +msgstr "清单9-4:IERC20trait的扩展形式" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:106 +msgid "### Calling Contracts using the Library Dispatcher" +msgstr "### 使用库调度器调用合约" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:108 +msgid "" +"Below's a sample code on calling contracts using the Library Dispatcher:" +msgstr "下面是一个关于使用库调度器调用合约的示例代码:" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:110 +msgid "" +"```rust\n" +"//**** Specify interface here ****//\n" +"\n" +"use super::IERC20DispatcherTrait;\n" +"use super::IERC20LibraryDispatcher;\n" +"use starknet::ContractAddress;\n" +"\n" +"#[view]\n" +"fn token_name() -> felt252 {\n" +" IERC20LibraryDispatcher { class_hash: starknet::class_hash_const::" +"<0x1234>() }.name()\n" +"}\n" +"\n" +"#[external]\n" +"fn transfer_token(\n" +" recipient: ContractAddress, amount: u256\n" +") -> bool {\n" +" IERC20LibraryDispatcher { class_hash: starknet::class_hash_const::" +"<0x1234>() }.transfer(recipient, amount)\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"//**** Specify interface here ****//\n" +"\n" +"use super::IERC20DispatcherTrait;\n" +"use super::IERC20LibraryDispatcher;\n" +"use starknet::ContractAddress;\n" +"\n" +"#[view]\n" +"fn token_name() -> felt252 {\n" +" IERC20LibraryDispatcher { class_hash: starknet::class_hash_const::" +"<0x1234>() }.name()\n" +"}\n" +"\n" +"#[external]\n" +"fn transfer_token(\n" +" recipient: ContractAddress, amount: u256\n" +") -> bool {\n" +" IERC20LibraryDispatcher { class_hash: starknet::class_hash_const::" +"<0x1234>() }.transfer(recipient, amount)\n" +"}\n" +"```" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:130 +msgid "" +"Listing 9-4: A sample contract using the Library " +"Dispatcher" +msgstr "清单9-4:一个使用库调度器的样本合约" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:132 +msgid "" +"As you can see, we had to first import the `IERC20DispatcherTrait` and " +"`IERC20LibraryDispatcher` which was generated and exported on compiling our " +"interface, then we make calls to the methods implemented for the " +"`IERC20LibraryDispatcher` struct (`name`, `transfer`, etc), passing in the " +"`class_hash` parameter which represents the class of the contract we want to " +"call." +msgstr "" +"正如你所看到的,我们必须首先导入`IERC20DispatcherTrait`和" +"`IERC20LibraryDispatcher`,这是在编译我们的接口时生成和导出的,然后我们对" +"`IERC20LibraryDispatcher`结构实现的方法进行调用(`name`、`transfer`等),传入" +"`class_hash`参数,代表我们要调用的合约的类别。" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:134 +msgid "## Calling Contracts using low-level System calls" +msgstr "## 使用底层系统调用来调用合约" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:136 +msgid "" +"Another way to call other contracts is to use the `starknet::" +"call_contract_syscall` system call. The Dispatchers we described in the " +"previous sections are high-level syntaxes for this low-level system call." +msgstr "" +"另一种调用其他合约的方法是使用`starknet::call_contract_syscall`系统调用。我们" +"在前几节描述的调度器是这种底层系统调用的高级语法。" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:138 +msgid "" +"Using the system call `starknet::call_contract_syscall` can be handy for " +"customized error handling or possessing more control over the serialization/" +"deserialization of the call data and the returned data. Here's an example " +"demonstrating a low-level `transfer` call:" +msgstr "" +"使用系统调用`starknet::call_contract_syscall`可以方便地进行自定义错误处理,或" +"者对调用数据和返回数据的序列化/反序列化进行更多的控制。下面是一个演示底层的" +"`transfer'调用的例子:" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:140 +msgid "" +"```rust\n" +"#[external]\n" +"fn transfer_token(\n" +" address: starknet::ContractAddress, selector: felt252, calldata: " +"Array\n" +") -> Span:: {\n" +" starknet::call_contract_syscall(address, selector, calldata.span())." +"unwrap_syscall()\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"#[external]\n" +"fn transfer_token(\n" +" address: starknet::ContractAddress, selector: felt252, calldata: " +"Array\n" +") -> Span:: {\n" +" starknet::call_contract_syscall(address, selector, calldata.span())." +"unwrap_syscall()\n" +"}\n" +"```" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:149 +msgid "" +"Listing 9-5: A sample contract implementing system " +"calls" +msgstr "清单9-5:一个实现系统调用的样本合约" + +#: src/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls.md:151 +msgid "" +"As you can see, rather than pass our function arguments directly, we passed " +"in the contract address, function selector (which is a keccak hash of the " +"function name), and the calldata (function arguments). At the end, we get " +"returned a serialized value which we'll need to deserialize ourselves!" +msgstr "" +"正如你所看到的,我们没有直接传递我们的函数参数,而是传递了合同地址、函数选择" +"器(这是一个函数名称的keccak哈希值)和calldata(函数参数)。最后,我们得到了" +"一个序列化的值,我们需要自己反序列化它。" + +#: src/appendix-00.md:1 +msgid "# Appendix" +msgstr "# 附录" + +#: src/appendix-00.md:3 +msgid "" +"The following sections contain reference material you may find useful in " +"your\n" +"Cairo journey." +msgstr "以下章节包含的参考资料可能对您的Cairo之旅有所帮助。" + +#: src/appendix-02-operators-and-symbols.md:1 +msgid "# Appendix B: Operators and Symbols" +msgstr "# 附录B:运算符和符号" + +#: src/appendix-02-operators-and-symbols.md:3 +msgid "This appendix includes a glossary of Cairo's syntax." +msgstr "本附录包含了Cairo语法的词汇表。" + +#: src/appendix-02-operators-and-symbols.md:5 +msgid "## Operators" +msgstr "## 运算符" + +#: src/appendix-02-operators-and-symbols.md:7 +msgid "" +"Table B-1 contains the operators in Cairo, an example of how the operator " +"would appear in context, a short explanation, and whether that operator is " +"overloadable. If an operator is overloadable, the relevant trait to use to " +"overload that operator is listed." +msgstr "" +"表B-1包含了开罗的运算符,运算符在上下文中出现的例子和简短的解释,以及该运算符" +"是否可以重载。如果一个运算符是可重载的,则列出了用于重载该运算符的相关特性。" + +#: src/appendix-02-operators-and-symbols.md:9 +msgid "Table B-1: Operators" +msgstr "表B-1:运算符" + +#: src/appendix-02-operators-and-symbols.md:11 +msgid "" +"| Operator | Example | Explanation | Overloadable? |\n" +"|----------|---------|-------------|---------------|\n" +"| `!` | `!expr` | Bitwise or logical complement | `Not` |\n" +"| `!=` | `expr != expr` | Non-equality comparison | `PartialEq` |\n" +"| `%` | `expr % expr` | Arithmetic remainder | `Rem` |\n" +"| `%=` | `var %= expr` | Arithmetic remainder and assignment | `RemEq` |\n" +"| `&` | `expr & expr` | Bitwise AND | `BitAnd` |\n" +"| `*` | `expr * expr` | Arithmetic multiplication | `Mul` |\n" +"| `*=` | `var *= expr` | Arithmetic multiplication and assignment | `MulEq` " +"|\n" +"| `@` | `@var` | Snapshot | |\n" +"| `*` | `*var` | Desnap | |\n" +"| `+` | `expr + expr` | Arithmetic addition | `Add` |\n" +"| `+=` | `var += expr` | Arithmetic addition and assignment | `AddEq` |\n" +"| `,` | `expr, expr` | Argument and element separator | |\n" +"| `-` | `-expr` | Arithmetic negation | `Neg` |\n" +"| `-` | `expr - expr` | Arithmetic subtraction | `Sub` |\n" +"| `-=` | `var -= expr` | Arithmetic subtraction and assignment | `SubEq` |\n" +"| `->` | `fn(...) -> type`, |...| -> type | Function " +"and closure return type | |\n" +"| `.` | `expr.ident` | Member access | |\n" +"| `/` | `expr / expr` | Arithmetic division | `Div` |\n" +"| `/=` | `var /= expr` | Arithmetic division and assignment | `DivEq` |\n" +"| `:` | `pat: type`, `ident: type` | Constraints | |\n" +"| `:` | `ident: expr` | Struct field initializer | |\n" +"| `;` | `expr;` | Statement and item terminator | |\n" +"| `<` | `expr < expr` | Less than comparison | `PartialOrd` |\n" +"| `<=` | `expr <= expr` | Less than or equal to comparison | `PartialOrd` |\n" +"| `=` | `var = expr` | Assignment | |\n" +"| `==` | `expr == expr` | Equality comparison | `PartialEq` |\n" +"| `=>` | `pat => expr` | Part of match arm syntax | |\n" +"| `>` | `expr > expr` | Greater than comparison | `PartialOrd` |\n" +"| `>=` | `expr >= expr` | Greater than or equal to comparison | `PartialOrd` " +"|\n" +"| `^` | `expr ^ expr` | Bitwise exclusive OR | `BitXor` |\n" +"| | | expr | expr | Bitwise OR | `BitOr` " +"|" +msgstr "" +"| 运算符 | 例子 | 解释 | 可重载?|\n" +"|----------|---------|-------------|---------------|\n" +"| `!` `!expr` | 位数或逻辑补码 | `Not` !\n" +"| `!=` | `expr != expr` | 非等价比较 | `PartialEq` !\n" +"| `%` | `expr% expr` | 算术余数 | `Rem` !\n" +"| `%=` | `var %= expr` | 算术余数和赋值 | `RemEq` !\n" +"| `&` | `expr & expr` | Bitwise AND | `BitAnd` |\n" +"| `*` | `expr * expr` | 算术乘法 | `Mul` !\n" +"| `*=` | `var *= expr` | 算术乘法和赋值 | `MulEq` !\n" +"| `@` | `@var` | 快照| |\n" +"| `*` | `*var` | 灭活 | | 灭活\n" +"| `+` | `expr + expr` | 算术加法 | `Add` |\n" +"| `+=` | `var += expr` | 算术加法和赋值 | `AddEq` !\n" +"| `,` | `expr, expr` | 参数和元素分隔器 | |\n" +"| `-` | `-expr` | 算术否定法 | `Neg` !\n" +"| `-` | `expr - expr` | 算术减法 | `Sub` !\n" +"| `-=` | `var -= expr` | 算术减法和赋值 | `SubEq` !\n" +"| `->` | `fn(...) -> type`, |...| -> type | 函数和闭包" +"的返回类型 | |\n" +"| `.` | `expr.ident` | 成员访问 |\n" +"| `/` | `expr / expr` | 算术除法 | `Div` !\n" +"| `/=` | `var /= expr` | 算术除法和赋值 | `DivEq` !\n" +"| `:` | `pat: type`, `ident: type` | 限制条件 | !\n" +"| `:` | `ident: expr` | 结构字段初始化器 | | `:` | `ident: expr` !\n" +"| `;` | `expr;` | 语句和项目的终止符 | | `;`;。\n" +"| `<` | `expr < expr` | 小于比较 | `PartialOrd` !\n" +"| `<=` | `expr <= expr` | Less than or equal to comparison | `PartialOrd` |\n" +"| `=` | `var = expr` | Assignment | |\n" +"| `==` | `expr == expr` | Equality comparison | `PartialEq` |\n" +"| `=>` | `pat => expr` | 部分匹配臂语法 | |\n" +"| `>` | `expr > expr` | 大于比较 | `PartialOrd` !\n" +"| `>=` | `expr >= expr` | 大于或等于比较 | `PartialOrd` !\n" +"| `^` | `expr ^ expr` | 位数排他性OR | `BitXor` !\n" +"| | | expr | expr | Bitwise OR | `BitOr` " +"|" + +#: src/appendix-02-operators-and-symbols.md:45 +msgid "## Non Operator Symbols" +msgstr "## 非运算符符号" + +#: src/appendix-02-operators-and-symbols.md:47 +msgid "" +"The following list contains all symbols that are not used as operators; that " +"is, they do not have the same behavior as a function or method call." +msgstr "" +"下面的列表包含了所有不作为运算符使用的符号;也就是说,他们并不像函数调用或方" +"法调用一样表现。" + +#: src/appendix-02-operators-and-symbols.md:49 +msgid "" +"Table B-2 shows symbols that appear on their own and are valid in a variety " +"of locations." +msgstr "表B-2 展示了以其自身出现以及出现在合法其他各个地方的符号。" + +#: src/appendix-02-operators-and-symbols.md:51 +msgid "Table B-2: Stand-Alone Syntax" +msgstr "表B-2:独立语法" + +#: src/appendix-02-operators-and-symbols.md:53 +msgid "" +"| Symbol | Explanation |\n" +"|--------|-------------|\n" +"| `..._u8`, `..._usize`, etc. | Numeric literal of specific type |\n" +"| `'...'` | Short string |\n" +"| `_` | “Ignored” pattern binding; also used to make integer literals " +"readable |" +msgstr "" +"| 符号 | 解释 |\n" +"|--------|-------------|\n" +"| `..._u8`, `..._usize`, 等等。| 指定类型的数值常量 |\n" +"| `'...'` | 短字符串 |\n" +"| `_` | \"“忽略” 模式绑定;也用于增强整型字面值的可读性 |" + +#: src/appendix-02-operators-and-symbols.md:59 +msgid "" +"Table B-3 shows symbols that are used within the context of a module " +"hierarchy path to access an item." +msgstr "表B-3 展示了出现在从模块结构到项的路径上下文中的符号。" + +#: src/appendix-02-operators-and-symbols.md:61 +msgid "Table B-3: Path-Related Syntax" +msgstr "表B-3:路径相关语法" + +#: src/appendix-02-operators-and-symbols.md:63 +msgid "" +"| Symbol | Explanation |\n" +"|--------|-------------|\n" +"| `ident::ident` | Namespace path |\n" +"| `super::path` | Path relative to the parent of the current module |\n" +"| `trait::method(...)` | Disambiguating a method call by naming the trait " +"that defines it |" +msgstr "" +"| 符号 | 解释 |\n" +"|--------|-------------|\n" +"| `ident::ident` | 命名空间路径 |\n" +"| `super::path` | 相对于当前模块的父级路径。\n" +"| `trait::method(...)` | 通过命名定义该方法的trait来消除方法调用的二义性。" + +#: src/appendix-02-operators-and-symbols.md:69 +msgid "" +"Table B-4 shows symbols that appear in the context of using generic type " +"parameters." +msgstr "表B-4 展示了出现在泛型类型参数上下文中的符号。" + +#: src/appendix-02-operators-and-symbols.md:71 +msgid "Table B-4: Generics" +msgstr "表 B-4:泛型" + +#: src/appendix-02-operators-and-symbols.md:73 +msgid "" +"| Symbol | Explanation |\n" +"|--------|-------------|\n" +"| `path<...>` | Specifies parameters to generic type in a type (e.g., " +"`Vec`) |\n" +"| `path::<...>`, `method::<...>` | Specifies parameters to generic type, " +"function, or method in an expression; often referred to as turbofish |\n" +"| `fn ident<...> ...` | Define generic function |\n" +"| `struct ident<...> ...` | Define generic structure |\n" +"| `enum ident<...> ...` | Define generic enumeration |\n" +"| `impl<...> ...` | Define generic implementation |" +msgstr "" +"| 符号 | 解释 |\n" +"|--------|-------------|\n" +"| `path<...>` | 为一个类型中的泛型指定具体参数(例如,`Vec`) |\n" +"| `path::<...>`, `method::<...>` | 为一个泛型、函数或表达式中的方法指定具体参" +"数; 通常被称为Turbofish。\n" +"| `fn ident<...>...` | 泛型函数定义\n" +"| `struct ident<...>...` | 泛型结构体定义\n" +"| `enum ident<...>...` | 泛型枚举定义\n" +"| `impl<...>...` | 定义泛型实现 |" + +#: src/appendix-02-operators-and-symbols.md:82 +msgid "" +"Table B-5 shows symbols that appear in the context of calling or defining " +"macros and specifying attributes on an item." +msgstr "表B-5展示了在调用或定义宏以及在其上指定属性时的上下文中出现的符号。" + +#: src/appendix-02-operators-and-symbols.md:84 +msgid "Table B-5: Macros and Attributes" +msgstr "表B-5:宏和属性" + +#: src/appendix-02-operators-and-symbols.md:86 +msgid "" +"| Symbol | Explanation |\n" +"|--------|-------------|\n" +"| `#[meta]` | Outer attribute |" +msgstr "" +"| 符号 | 解释 |\n" +"|--------|-------------|\n" +"| `#[meta]` | 外部属性 |" + +#: src/appendix-02-operators-and-symbols.md:90 +msgid "Table B-6 shows symbols that create comments." +msgstr "表B-6 展示了创建注释的符号。" + +#: src/appendix-02-operators-and-symbols.md:92 +msgid "Table B-6: Comments" +msgstr "表B-6:注释" + +#: src/appendix-02-operators-and-symbols.md:94 +msgid "" +"| Symbol | Explanation |\n" +"|--------|-------------|\n" +"| `//` | Line comment |" +msgstr "" +"| 符号 | 解释 |\n" +"|--------|-------------|\n" +"| `//` | 行注释 |" + +#: src/appendix-02-operators-and-symbols.md:98 +msgid "Table B-7 shows symbols that appear in the context of using tuples." +msgstr "表B-7 展示了出现在使用元组时上下文中的符号。" + +#: src/appendix-02-operators-and-symbols.md:100 +msgid "Table B-7: Tuples" +msgstr "表B-7:元组" + +#: src/appendix-02-operators-and-symbols.md:103 +msgid "" +"| Symbol | Explanation |\n" +"|--------|-------------|\n" +"| `()` | Empty tuple (aka unit), both literal and type |\n" +"| `(expr)` | Parenthesized expression |\n" +"| `(expr,)` | Single-element tuple expression |\n" +"| `(type,)` | Single-element tuple type |\n" +"| `(expr, ...)` | Tuple expression |\n" +"| `(type, ...)` | Tuple type |\n" +"| `expr(expr, ...)` | Function call expression; also used to initialize " +"tuple `struct`s and tuple `enum` variants |" +msgstr "" +"| 符号 | 解释 |\n" +"|--------|-------------|\n" +"| `()` | 空元组(又称单元),空元组(亦称单元),即是字面值也是类型 |\n" +"| `(expr)` | 括号表达式 |\n" +"| `(expr,)` | 单元素元组表达式 |\n" +"| `(type,)` | 单元素元组类型 |\n" +"| `(expr, ...)` | 元组表达式\n" +"| `(type, ...)` | 元组类型 |\n" +"| `expr(expr, ...)` | 函数调用表达式;也用于初始化元组`struct`和元组`enum`变" +"体" + +#: src/appendix-02-operators-and-symbols.md:113 +msgid "Table B-8 shows the contexts in which curly braces are used." +msgstr "表B-8展示了使用大括号的上下文。" + +#: src/appendix-02-operators-and-symbols.md:115 +msgid "Table B-8: Curly Brackets" +msgstr "表B-8:大括号" + +#: src/appendix-02-operators-and-symbols.md:117 +msgid "" +"| Context | Explanation |\n" +"|---------|-------------|\n" +"| `{...}` | Block expression |\n" +"| `Type {...}` | `struct` literal |" +msgstr "" +"| 上下文 | 解释 |\n" +"|---------|-------------|\n" +"| `{...}` | 块表达式 |\n" +"| `Type {...}` | `struct`字面值 |" + +#: src/appendix-03-derivable-traits.md:1 +msgid "# Appendix C: Derivable Traits" +msgstr "# 附录C: 可派生的 Trait" + +#: src/appendix-03-derivable-traits.md:3 +msgid "" +"In various places in the book, we’ve discussed the `derive` attribute, which " +"you can apply to a struct or enum definition. The `derive` attribute " +"generates code to implement a default trait on the type you’ve annotated " +"with the `derive` syntax." +msgstr "" +"在本书的各个部分中,我们讨论了可应用于结构体和枚举定义的 `derive` 属性。" +"`derive` 属性会在使用 `derive` 语法标记的类型上生成对应 trait 的默认实现的代" +"码。" + +#: src/appendix-03-derivable-traits.md:5 +msgid "" +"In this appendix, we provide a comprehensive reference detailing all the " +"traits in the standard library compatible with the `derive` attribute." +msgstr "" +"在这个附录中,我们提供了一个全面的参考,详细介绍了标准库中所有与`derive`属性" +"兼容的trait。" + +#: src/appendix-03-derivable-traits.md:7 +msgid "" +"These traits listed here are the only ones defined by the core library that " +"can be implemented on your types using `derive`. Other traits defined in the " +"standard library don’t have sensible default behavior, so it’s up to you to " +"implement them in the way that makes sense for what you’re trying to " +"accomplish." +msgstr "" +"这里列出的 trait 是仅有的在标准库中定义且能通过 `derive` 在类型上实现。标准库" +"中定义的其它 trait 不能通过 `derive` 在类型上实现。这些 trait 不存在有意义的" +"默认行为,所以由你负责以合理的方式实现它们。" + +#: src/appendix-03-derivable-traits.md:9 +msgid "" +"The list of derivable traits provided in this appendix does not encompass " +"all possibilities: external libraries can implement `derive` for their own " +"traits, expanding the list of traits compatible with `derive`." +msgstr "" +"本附录所提供的可派生 trait 列表并不全面:库可以为其自己的 trait 实现 " +"`derive`,可以使用 `derive` 的 trait 列表事实上是无限的。" + +#: src/appendix-03-derivable-traits.md:11 +msgid "## PartialEq for equality comparison" +msgstr "## 等值比较的 PartialEq 和 Eq" + +#: src/appendix-03-derivable-traits.md:13 +msgid "" +"The `PartialEq` trait allows for comparison between instances of a type for " +"equality, thereby enabling the == and != operators." +msgstr "" +"`PartialEq` trait允许在一个类型的实例之间进行等值比较,从而实现 == 和 != 运算" +"符。" + +#: src/appendix-03-derivable-traits.md:15 +msgid "" +"When `PartialEq` is derived on structs, two instances are equal only if all " +"fields are equal, and the instances are not equal if any fields are not " +"equal. When derived on enums, each variant is equal to itself and not equal " +"to the other variants." +msgstr "" +"当`PartialEq`在结构上派生时,只有当所有字段都相等时,两个实例才相等,如果任何" +"字段不相等,实例就不相等。当在枚举上派生时,每一个成员都和其自身相等,且和其" +"他成员都不相等。" + +#: src/appendix-03-derivable-traits.md:19 +msgid "" +"```Rust\n" +"#[derive(PartialEq, Drop)]\n" +"struct A {\n" +" item: felt252\n" +"}\n" +"\n" +"fn main() {\n" +" let first_struct = A {\n" +" item: 2\n" +" };\n" +" let second_struct = A {\n" +" item: 2\n" +" };\n" +" assert(first_struct == second_struct, 'Structs are different');\n" +"}\n" +"```" +msgstr "" +"```Rust\n" +"#[derive(PartialEq, Drop)]\n" +"struct A {\n" +" item: felt252\n" +"}\n" +"\n" +"fn main() {\n" +" let first_struct = A {\n" +" item: 2\n" +" };\n" +" let second_struct = A {\n" +" item: 2\n" +" };\n" +" assert(first_struct == second_struct, 'Structs are different');\n" +"}\n" +"```" + +#: src/appendix-03-derivable-traits.md:36 +msgid "## Clone and Copy for Duplicating Values" +msgstr "## 复制值的 Clone 和 Copy" + +#: src/appendix-03-derivable-traits.md:38 +msgid "" +"The `Clone` trait provides the functionality to explicitly create a deep " +"copy of a value." +msgstr "`Clone` trait 提供了明确创建一个值的深度拷贝的功能。" + +#: src/appendix-03-derivable-traits.md:40 +msgid "" +"Deriving `Clone` implements the `clone` method, which, in turn, calls clone " +"on each of the type's components. This means all the fields or values in the " +"type must also implement `Clone` to derive `Clone`." +msgstr "" +"派生 `Clone` 实现了 `clone` 方法,其为整个的类型实现时,在类型的每一部分上调" +"用了`clone` 方法。这意味着类型中所有字段或值也必须实现了 `Clone`,这样才能够" +"派生 `Clone`。" + +#: src/appendix-03-derivable-traits.md:44 +msgid "" +"```Rust\n" +"use clone::Clone;\n" +"\n" +"#[derive(Clone, Drop)]\n" +"struct A {\n" +" item: felt252\n" +"}\n" +"\n" +"fn main() {\n" +" let first_struct = A {\n" +" item: 2\n" +" };\n" +" let second_struct = first_struct.clone();\n" +" assert(second_struct.item == 2, 'Not equal');\n" +"}\n" +"```" +msgstr "" +"```Rust\n" +"use clone::Clone;\n" +"\n" +"#[derive(Clone, Drop)]\n" +"struct A {\n" +" item: felt252\n" +"}\n" +"\n" +"fn main() {\n" +" let first_struct = A {\n" +" item: 2\n" +" };\n" +" let second_struct = first_struct.clone();\n" +" assert(second_struct.item == 2, 'Not equal');\n" +"}\n" +"```" + +#: src/appendix-03-derivable-traits.md:61 +msgid "" +"The `Copy` trait allows for the duplication of values. You can derive `Copy` " +"on any type whose parts all implement `Copy`." +msgstr "" +"`Copy` trait 允许你复制值而不需要额外的代码。你可以在任何部分都实现了`Copy'的" +"类型上派生`Copy'。" + +#: src/appendix-03-derivable-traits.md:65 +msgid "" +"```Rust\n" +"#[derive(Copy, Drop)]\n" +"struct A {\n" +" item: felt252\n" +"}\n" +"\n" +"fn main() {\n" +" let first_struct = A {\n" +" item: 2\n" +" };\n" +" let second_struct = first_struct;\n" +" assert(second_struct.item == 2, 'Not equal');\n" +" assert(first_struct.item == 2, 'Not Equal'); // Copy Trait prevents " +"firs_struct from moving into second_struct\n" +"}\n" +"```" +msgstr "" +"```Rust\n" +"#[derive(Copy, Drop)]\n" +"struct A {\n" +" item: felt252\n" +"}\n" +"\n" +"fn main() {\n" +" let first_struct = A {\n" +" item: 2\n" +" };\n" +" let second_struct = first_struct;\n" +" assert(second_struct.item == 2, 'Not equal');\n" +" assert(first_struct.item == 2, 'Not Equal'); // Copy Trait prevents " +"firs_struct from moving into second_struct\n" +"}\n" +"```" + +#: src/appendix-03-derivable-traits.md:81 +msgid "## Serializing with Serde" +msgstr "## 用Serde进行序列化" + +#: src/appendix-03-derivable-traits.md:83 +msgid "" +"`Serde` provides trait implementations for `serialize` and `deserialize` " +"functions for data structures defined in your crate. It allows you to " +"transform your structure into an array (or the opposite)." +msgstr "" +"`Serde`为你的crate中定义的数据结构提供`serialize`和`deserialize`函数的trait实" +"现。它允许你将你的结构体转化为数组(或相反)。" + +#: src/appendix-03-derivable-traits.md:87 +msgid "" +"```Rust\n" +"use serde::Serde;\n" +"use array::ArrayTrait;\n" +"\n" +"#[derive(Serde, Drop)]\n" +"struct A {\n" +" item_one: felt252,\n" +" item_two: felt252,\n" +"}\n" +"\n" +"fn main() {\n" +" let first_struct = A {\n" +" item_one: 2,\n" +" item_two: 99,\n" +" };\n" +" let mut output_array = ArrayTrait::new();\n" +" let serialized = first_struct.serialize(ref output_array);\n" +" panic(output_array);\n" +"}\n" +"```" +msgstr "" +"```Rust\n" +"use serde::Serde;\n" +"use array::ArrayTrait;\n" +"\n" +"#[derive(Serde, Drop)]\n" +"struct A {\n" +" item_one: felt252,\n" +" item_two: felt252,\n" +"}\n" +"\n" +"fn main() {\n" +" let first_struct = A {\n" +" item_one: 2,\n" +" item_two: 99,\n" +" };\n" +" let mut output_array = ArrayTrait::new();\n" +" let serialized = first_struct.serialize(ref output_array);\n" +" panic(output_array);\n" +"}\n" +"```" + +#: src/appendix-03-derivable-traits.md:108 +msgid "Output:" +msgstr "输出:" + +#: src/appendix-03-derivable-traits.md:110 +msgid "" +"```Bash\n" +"Run panicked with [2 (''), 99 ('c'), ].\n" +"```" +msgstr "" +"```Bash\n" +"Run panicked with [2 (''), 99 ('c'), ].\n" +"```" + +#: src/appendix-03-derivable-traits.md:114 +msgid "" +"We can see here that our struct A has been serialized into the output array." +msgstr "我们在这里可以看到,我们的结构体A已经被序列化到输出数组中。" + +#: src/appendix-03-derivable-traits.md:116 +msgid "" +"Also, we can use `deserialize` function to convert the serialized array back " +"into our A struct." +msgstr "另外,我们可以使用`deserialize`函数将序列化的数组转换回我们的结构体A。" + +#: src/appendix-03-derivable-traits.md:120 +msgid "" +"```Rust\n" +"use serde::Serde;\n" +"use array::ArrayTrait;\n" +"use option::OptionTrait;\n" +"\n" +"#[derive(Serde, Drop)]\n" +"struct A {\n" +" item_one: felt252,\n" +" item_two: felt252,\n" +"}\n" +"\n" +"fn main() {\n" +" let first_struct = A {\n" +" item_one: 2,\n" +" item_two: 99,\n" +" };\n" +" let mut output_array = ArrayTrait::new();\n" +" let mut serialized = first_struct.serialize(ref output_array);\n" +" let mut span_array = output_array.span();\n" +" let deserialized_struct: A = Serde::::deserialize(ref span_array)." +"unwrap();\n" +"}\n" +"```" +msgstr "" +"```Rust\n" +"use serde::Serde;\n" +"use array::ArrayTrait;\n" +"use option::OptionTrait;\n" +"\n" +"#[derive(Serde, Drop)]\n" +"struct A {\n" +" item_one: felt252,\n" +" item_two: felt252,\n" +"}\n" +"\n" +"fn main() {\n" +" let first_struct = A {\n" +" item_one: 2,\n" +" item_two: 99,\n" +" };\n" +" let mut output_array = ArrayTrait::new();\n" +" let mut serialized = first_struct.serialize(ref output_array);\n" +" let mut span_array = output_array.span();\n" +" let deserialized_struct: A = Serde::::deserialize(ref span_array)." +"unwrap();\n" +"}\n" +"```" + +#: src/appendix-03-derivable-traits.md:143 +msgid "" +"Here we are converting a serialized array span back to the struct A. " +"`deserialize` returns an `Option` so we need to unwrap it. When using " +"deserialize we also need to specify the type we want to deserialize into." +msgstr "" +"这里我们要把一个序列化的数组span转换回结构体A。`deserialize`返回一个" +"`Option`,所以我们需要把它解包。当使用deserialize时,我们还需要指定我们想要反" +"序列化的类型。" + +#: src/appendix-03-derivable-traits.md:145 +msgid "## Drop and Destruct" +msgstr "## Drop 和 Destruct" + +#: src/appendix-03-derivable-traits.md:147 +msgid "" +"When moving out of scope, variables need to be moved first. This is where " +"the `Drop` trait intervenes. You can find more details about its usage [here]" +"(ch03-01-what-is-ownership.md#the-drop-trait)." +msgstr "" +"当离开作用域时,需要先移动变量。这就是 `Drop` trait起作用的地方。你可以在[这" +"里](ch03-01-what-is-ownership.md#the-drop-trait)找到更多关于它的用法的细节。" + +#: src/appendix-03-derivable-traits.md:149 +msgid "" +"Moreover Dictionary need to be squashed before going out of scope. Calling " +"manually the `squash` method on each of them can be quickly redundant. " +"`Destruct` trait allows Dictionaries to be automatically squashed when they " +"get out of scope. You can also find more information about `Destruct` [here]" +"(ch03-01-what-is-ownership.md#the-destruct-trait)." +msgstr "" +"此外,字典在离开作用域之前需要被squash(压缩)。在每个字典上手动调用`squash`" +"方法很快就不再是必须操作。`Destruct` 特性允许字典在超出范围时被自动压缩。你也" +"可以在[这里](ch03-01-what-is-ownership.md#the-destruct-trait) 找到更多关于" +"`Destruct`的信息。" + +#: src/appendix-03-derivable-traits.md:151 +msgid "## PartialOrd and Ord for Ordering Comparisons" +msgstr "## 用于排序比较的PartialOrd和Ord" + +#: src/appendix-03-derivable-traits.md:153 +msgid "TODO (Not derivable yet ?)" +msgstr "TODO (还不能派生?)" + +#: src/appendix-04-useful-development-tools.md:1 +msgid "## Appendix D - Useful Development Tools" +msgstr "## 附录D - 实用开发工具" + +#: src/appendix-04-useful-development-tools.md:3 +msgid "" +"In this appendix, we talk about some useful development tools that the " +"Cairo\n" +"project provides. We’ll look at automatic formatting, quick ways to apply\n" +"warning fixes, a linter, and integrating with IDEs." +msgstr "" +"在本附录中,我们将提到由Cairo项目提供的一些有用的开发工具。\n" +"我们将看看自动格式化、快速应用警告修正,linter,以及与IDE的整合。" + +#: src/appendix-04-useful-development-tools.md:7 +msgid "### Automatic Formatting with `cairo-format`" +msgstr "### 用`cairo-format’自动格式化" + +#: src/appendix-04-useful-development-tools.md:9 +msgid "" +"The `cairo-format` tool reformats your code according to the community code " +"style.\n" +"Many collaborative projects use `cairo-format` to prevent arguments about " +"which\n" +"style to use when writing Cairo: everyone formats their code using the tool." +msgstr "" +"`cairo-format`工具根据社区的代码风格重新格式化你的代码。\n" +"在很多合作项目里,每个成员都会使用`cairo-format`以防止在编写Cairo时争论使用哪" +"种风格。" + +#: src/appendix-04-useful-development-tools.md:13 +msgid "To format any Cairo project, enter the following:" +msgstr "要格式化任何Cairo项目,请输入以下命令:" + +#: src/appendix-04-useful-development-tools.md:15 +msgid "" +"```console\n" +"cairo-format -r\n" +"```" +msgstr "" +"```console\n" +"cairo-format -r\n" +"```" + +#: src/appendix-04-useful-development-tools.md:19 +msgid "" +"Running this command reformats all the Cairo code in the current directory, " +"recursively. This\n" +"should only change the code style, not the code semantics." +msgstr "" +"运行这条命令可以递归式的重新格式化当前目录下的所有Cairo代码。这条命令\n" +"只会改变代码的风格,而不会改变代码的语义。" + +#: src/appendix-04-useful-development-tools.md:22 +msgid "### IDE Integration Using `cairo-language-server`" +msgstr "### 使用`cairo-language-server`的IDE集成" + +#: src/appendix-04-useful-development-tools.md:24 +msgid "" +"To help IDE integration, the Cairo community recommends using the\n" +"[`cairo-language-server`][cairo-language-server]. This tool " +"is a set of\n" +"compiler-centric utilities that speaks the [Language Server Protocol]" +"[lsp], which is a specification for IDEs and programming languages to\n" +"communicate with each other. Different clients can use `cairo-language-" +"server`, such as\n" +"[the Cairo extension for Visual Studio Code][vscode-cairo]." +msgstr "" +"为了帮助IDE整合,Cairo社区建议使用\n" +"[`cairo-language-server`][cairo-language-server]。这个工具是一" +"套\n" +"[Language Server Protocol][lsp]的一套以编译器为中心的实用工" +"具。\n" +"它是IDE和编程语言的规范,用于\n" +"互相通信的规范。不同的客户端都可以使用`cairo-language-server`,例如\n" +"[Visual Studio Code的Cairo扩展][vscode-cairo]。" + +#: src/appendix-04-useful-development-tools.md:34 +msgid "" +"Visit the `vscode-cairo` [page][vscode-cairo]\n" +"for installation instructions, You will gain abilities such as " +"autocompletion, jump to\n" +"definition, and inline errors." +msgstr "" +"请访问 `vscode-cairo` [页面][vscode-cairo] \n" +"获取安装说明,你将得到自动完成、跳转到定义,以及内联错误等功能。" From 7872300961a42dcb7edf4a5de7e9451970053f12 Mon Sep 17 00:00:00 2001 From: cryptonerdcn Date: Tue, 30 May 2023 14:54:41 +0900 Subject: [PATCH 02/14] =?UTF-8?q?Fix:=20Some=20typos.=20=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E4=B8=80=E4=BA=9B=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- po/zh-cn.po | 1464 +++++++++++++++++++++++++-------------------------- 1 file changed, 725 insertions(+), 739 deletions(-) diff --git a/po/zh-cn.po b/po/zh-cn.po index a5f393a8c..7b8967bce 100644 --- a/po/zh-cn.po +++ b/po/zh-cn.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: The Cairo Programming Language\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2023-05-30 09:32+0900\n" +"PO-Revision-Date: 2023-05-30 13:59+0900\n" "Last-Translator: cryptonerdcn \n" "Language-Team: Language zh-cn\n" "Language: zh_CN\n" @@ -78,7 +78,7 @@ msgstr "什么是所有权?" #: src/SUMMARY.md:29 msgid "References and Snapshots" -msgstr "参考资料和快照" +msgstr "引用和快照" #: src/SUMMARY.md:31 msgid "Using Structs to Structure Related Data" @@ -106,7 +106,7 @@ msgstr "枚举的定义" #: src/SUMMARY.md:42 msgid "The Match Control Flow Construct" -msgstr "匹配控制流结构" +msgstr "Match控制流结构" #: src/SUMMARY.md:44 msgid "Managing Cairo Projects with Packages, Crates and Modules" @@ -219,9 +219,10 @@ msgid "" "through [OnlyDust](https://www.onlydust.xyz/), and [Voyager](https://voyager." "online/) for supporting the creation of this book." msgstr "" -"由Cairo社区和它的[贡献者](https://github.com/cairo-book/cairo-book.github." -"io)。特别感谢[Starkware](https://starkware.co/)通过[OnlyDust](https://www." -"onlydust.xyz/)和[Voyager](https://voyager.online/)支持这本书的创作。" +"由Cairo社区和它的[贡献者们](https://github.com/cairo-book/cairo-book.github." +"io)创作。特别感谢[Starkware](https://starkware.co/)通过[OnlyDust](https://" +"www.onlydust.xyz/)和[Voyager](https://voyager.online/)支持这本书的创作。\n" +"中文版由[StarknetAstro](https://starknet-astro.super.site/)翻译。" #: src/title-page.md:5 msgid "" @@ -303,11 +304,11 @@ msgstr "" #: src/ch00-01-foreword.md:13 msgid "— The Cairo community" -msgstr "- Cairo社区" +msgstr "— Cairo社区" #: src/ch00-00-introduction.md:1 msgid "# Introduction" -msgstr "# #介绍" +msgstr "# 介绍" #: src/ch00-00-introduction.md:3 msgid "## What is Cairo?" @@ -327,17 +328,17 @@ msgid "" "subset of CASM. The point of Sierra is to ensure your CASM will always be " "provable, even when the computation fails." msgstr "" -"Cairo是一种为同名的虚拟CPU设计的编程语言。这种处理器的独特之处在于,它不是为" -"我们世界的物理限制而创造的,而是为加密限制而创造的,这使得它能够有效地证明在" -"其上运行的任何程序的执行。这意味着你可以在一台你不信任的机器上进行耗时的操" +"Cairo是一种为同名的虚拟CPU设计的编程语言。这种虚拟处理器的独特之处在于,它不" +"是为我们世界的物理法则而创造的,而是为密码学法则而创造的,这使得它能够有效地" +"证明在其上运行的任何程序。这意味着你可以在一台你不信任的机器上进行耗时的操" "作,而在一台更便宜的机器上非常迅速地检查结果。\n" -"虽然Cairo 0曾经直接编译成CASM,即Cairo CPU汇编,但Cairo 1是一种更高水平的语" -"言。它首先编译到Sierra,这是Cairo的一个中间表示,以后会编译成CASM的一个安全子" -"集。Sierra的意义在于确保你的CASM总是可以证明的,即使计算失败。" +"虽然Cairo 0曾经直接编译成CASM,即Cairo CPU汇编,但Cairo 1是一种更高级的语言。" +"它首先编译到Cairo的一个中间表示,Sierra,接着会编译成CASM的一个安全子集。" +"Sierra的意义在于确保你的CASM总是可以证明的,即使计算失败。" #: src/ch00-00-introduction.md:8 msgid "## What can you do with it?" -msgstr "∮∮你能用它做什么?" +msgstr "## 你能用它做什么?" #: src/ch00-00-introduction.md:10 msgid "" @@ -364,7 +365,7 @@ msgstr "" #: src/ch00-00-introduction.md:12 msgid "## What are the differences with other programming languages?" -msgstr "##与其他编程语言有什么区别?" +msgstr "## 与其他编程语言有什么区别?" #: src/ch00-00-introduction.md:14 msgid "" @@ -372,8 +373,8 @@ msgid "" "when it comes to overhead costs and its primary advantages. Your program can " "be executed in two different ways:" msgstr "" -"Cairo与传统的编程语言有很大不同,特别是在开销成本和主要优势方面。你的程序可以" -"通过两种不同的方式执行:" +"Cairo与传统的编程语言,尤其是在额外的性能开销和语言的主要优势方面,有很大不" +"同。你的程序可以通过两种不同的方式执行:" #: src/ch00-00-introduction.md:16 msgid "" @@ -395,17 +396,19 @@ msgid "" "verifier doesn't sort the array, it just checks that it is sorted, which is " "cheaper." msgstr "" -"- 当被验证者执行时,它与任何其他语言相似。因为Cairo是虚拟化的,而且操作并不是" -"专门为最大效率而设计的,这可能会导致一些性能开销,但这并不是最需要优化的相关" -"部分。\n" +"- 当被证明器(prover)执行时,它与任何其他语言相似。因为Cairo是虚拟化的,而且" +"其操作并未设计为效率最大化,因此可能会导致一些额外性能开销,但这并不是最需要" +"优化的相关部分。\n" "\n" -"- 当生成的证明被验证者验证时,情况就有点不同了。这必须是尽可能便宜的,因为它" -"有可能在许多非常小的机器上进行验证。幸运的是,验证比计算更快,而且开罗有一些" -"独特的优势,可以进一步改善它。一个值得注意的是非确定性。这是一个你将在本书后" -"面详细介绍的话题,但其想法是,理论上你可以使用不同的算法来验证,而不是计算。" -"目前,开发人员不支持编写自定义的非确定性代码,但标准库利用非确定性来提高性" -"能。例如,在开罗对一个数组进行排序的成本与复制它的成本相同。因为验证器不对数" -"组进行排序,它只是检查它是否被排序,这就更便宜了。" +"- 当生成的证明被验证器验证时,情况就有点不同了。这必须是尽可能少消耗计算资源" +"的的,因为它有可能需要在许多非常慢的机器上进行验证。幸运的是,验证比计算更" +"快,而且Cairo有一些独特的优势,可以进一步提高验证速度。一个值得注意的是非确定" +"性,这是一个将在本书后面详细介绍的话题。其设计理念是,理论上你无需在计算时和" +"验证时使用同一种算法(译注:即在验证时你可以使用比生成证明时更快的算法来减少" +"时间消耗)。目前开发者还不能编写自定义的非确定性代码,但标准库利用非确定性来" +"提高性能。例如,在Cairo中对一个数组进行排序的成本与复制它的成本相同,这是因为" +"验证器只是检查它是否被排序而不是真的对数组进行排序,所以可以减少计算资源消" +"耗。" #: src/ch00-00-introduction.md:20 msgid "" @@ -433,7 +436,7 @@ msgid "" "- State of non determinism: " msgstr "" -"- CairoCPU架构:\n" +"- Cairo CPU架构:\n" "- Cairo, Sierra and Casm:\n" "- 非确定性的状态:> ~/.bashrc\n" -" echo 'command -v cairo-compile >/dev/null || export PATH=\"$CAIRO_ROOT/" -"target/release:$PATH\">> ~/.bashrc\n" +" ```bash\n" +" echo ‘export CAIRO_ROOT=“$HOME/.cairo”’ >> ~/.bashrc\n" +" echo ‘command -v cairo-compile >/dev/null || export PATH=“$CAIRO_ROOT/" +"target/release:$PATH”’ >> ~/.bashrc\n" " ```\n" "\n" " 然后,如果你有 `~/.profile`、`~/.bash_profile`或`~/.bash_login`,也将这些命" "令添加到它们所对应的文件中。如果没有这些文件,则添加到 `~/.profile`中。\n" "\n" -" - 来添加到 `~/.profile` 中:\n" +" - 添加到 `~/.profile` 中:\n" "\n" -" ``bash\n" -" echo 'export CAIRO_ROOT=\"$HOME/.cairo\"' >> ~/.profile\n" -" echo 'command -v cairo-compile >/dev/null || export PATH=\"$CAIRO_ROOT/" -"target/release:$PATH\"'>> ~/.profile\n" +" ```bash\n" +" echo ‘export CAIRO_ROOT=“$HOME/.cairo”’ >> ~/.profile\n" +" echo ‘command -v cairo-compile >/dev/null || export PATH=“$CAIRO_ROOT/" +"target/release:$PATH”’ >> ~/.profile\n" " ```\n" "\n" -" - 来添加到`~/.bash_profile`:\n" -" ``bash\n" -" echo 'export CAIRO_ROOT=\"$HOME/.cairo\"' >> ~/.bash_profile\n" -" echo 'command -v cairo-compile >/dev/null || export PATH=\"$CAIRO_ROOT/" -"target/release:$PATH\">> ~/.bash_profile\n" +" - 添加到`~/.bash_profile`:\n" +" ```bash\n" +" echo ‘export CAIRO_ROOT=“$HOME/.cairo”’ >> ~/.bash_profile\n" +" echo ‘command -v cairo-compile >/dev/null || export PATH=“$CAIRO_ROOT/" +"target/release:$PATH”’ >> ~/.bash_profile\n" " ```\n" "\n" "- 对于**Zsh**:\n" "\n" -" ``zsh\n" +" ```zsh\n" " echo 'export CAIRO_ROOT=\"$HOME/.cairo\"' >> ~/.zshrc\n" " echo 'command -v cairo-compile >/dev/null || export PATH=\"$CAIRO_ROOT/" -"target/release:$PATH\"' 。>> ~/.zshrc\n" +"target/release:$PATH\"' >> ~/.zshrc\n" " ```\n" "\n" " 如果你希望在非交互式登录shell中也能得到Cairo,也可以将这些命令添加到`~/." @@ -730,7 +735,7 @@ msgstr "" "\n" " 否则,执行下面的片段:\n" "\n" -" ``fish\n" +" ```fish\n" " set -Ux CAIRO_ROOT $HOME/.cairo\n" " set -U fish_user_paths $CAIRO_ROOT/target/release $fish_user_paths\n" " ```" @@ -747,7 +752,8 @@ msgstr "" "替\n" "代性的 shell 补全功能,并在终端窗口有一个类似于 IDE 的弹出式界面。(注意,他" "们\n" -"的完成方式与Cairo的代码库无关,所以他们可能在最新界面更改方面略微不同步)。" +"的命令补全功能与Cairo的代码库无关,所以他们有可能有点跟不上Cairo命令行界面的" +"更新)。" #: src/ch01-01-installation.md:127 msgid "### Restart your shell" @@ -755,7 +761,7 @@ msgstr "### 重新启动你的shell" #: src/ch01-01-installation.md:129 msgid "for the `PATH` changes to take effect." -msgstr "以使 \"PATH \"的改变生效。" +msgstr "以使 `PATH`的改变生效。" #: src/ch01-01-installation.md:131 msgid "" @@ -764,7 +770,7 @@ msgid "" "```" msgstr "" "```sh\n" -"exec \"$SHELL\"\n" +"exec “$SHELL”\n" "```" #: src/ch01-01-installation.md:135 @@ -772,12 +778,12 @@ msgid "" "## Installing Cairo Manually ([Guide](https://github.com/auditless/cairo-" "template) by [Abdel](https://github.com/abdelhamidbakhta))" msgstr "" -"##手动安装Cairo([指南](https://github.com/auditless/cairo-template)由[Abdel]" +"## 手动安装Cairo([指南](https://github.com/auditless/cairo-template)由[Abdel]" "(https://github.com/abdelhamidbakhta)提供)" #: src/ch01-01-installation.md:137 msgid "### Step 1: Install Cairo 1.0" -msgstr "###第1步:安装Cairo 1.0" +msgstr "### 第1步:安装Cairo 1.0" #: src/ch01-01-installation.md:139 msgid "" @@ -789,7 +795,7 @@ msgstr "" #: src/ch01-01-installation.md:141 msgid "For everyone else, we recommend compiling Cairo from source as follows:" -msgstr "对于其他人,我们建议从源码编译 Cairo,如下所示:" +msgstr "对于其他用户,我们建议从源码编译 Cairo,如下所示:" #: src/ch01-01-installation.md:143 msgid "" @@ -817,25 +823,26 @@ msgid "" "```" msgstr "" "```bash\n" -"# 开始定义环境变量CAIRO_ROOT\n" -"export CAIRO_ROOT=\"${HOME}/.cairo\"\n" +"# Start by defining environment variable CAIRO_ROOT\n" +"export CAIRO_ROOT=“${HOME}/.cairo”\n" "\n" -"# 创建.cairo文件夹,如果它还不存在的话\n" +"# Create .cairo folder if it doesn’t exist yet\n" "mkdir $CAIRO_ROOT\n" "\n" -"# 在$CAIRO_ROOT中克隆Cairo编译器(默认根目录)\n" +"# Clone the Cairo compiler in $CAIRO_ROOT (default root)\n" "cd $CAIRO_ROOT && git clone git@github.com:starkware-libs/cairo.git .\n" "\n" -"# OPTIONAL/RECOMMENDED: 如果你想安装一个特定版本的编译器\n" -"# 获取所有标签(版本)\n" -"git fetch --all --tags\n" -"# 查看标签(你也可以在 cairo 编译器仓库中这样做)\n" -"git describe --tags `git rev-list --tags`。\n" -"# 检查你想要的版本\n" +"# OPTIONAL/RECOMMENDED: If you want to install a specific version of the " +"compiler\n" +"# Fetch all tags (versions)\n" +"git fetch —all —tags\n" +"# View tags (you can also do this in the cairo compiler repository)\n" +"git describe —tags `git rev-list —tags`\n" +"# Checkout the version you want\n" "git checkout tags/v1.0.0\n" "\n" -"# 生成发布版二进制文件\n" -"cargo build --all --release\n" +"# Generate release binaries\n" +"cargo build —all —release\n" "```" #: src/ch01-01-installation.md:165 @@ -853,7 +860,7 @@ msgid "" "is pull the latest changes and rebuild as follows:" msgstr "" "现在你的Cairo编译器已经在一个克隆的仓库里了,你所需要做的是拉取最新的修改,\n" -"并按如下方式重建:" +"并按如下方式重新编译:" #: src/ch01-01-installation.md:172 msgid "" @@ -861,13 +868,13 @@ msgid "" "cd $CAIRO_ROOT && git fetch && git pull && cargo build --all --release\n" "```" msgstr "" -"``bash\n" -"cd $CAIRO_ROOT && git fetch && git pull && cargo build --all --release\n" +"```bash\n" +"cd $CAIRO_ROOT && git fetch && git pull && cargo build —all —release\n" "```" #: src/ch01-01-installation.md:176 msgid "### Step 2: Add Cairo 1.0 executables to your path" -msgstr "###第二步:将Cairo 1.0的可执行文件添加到你的路径中" +msgstr "### 第二步:将Cairo 1.0的可执行文件添加到你的路径中" #: src/ch01-01-installation.md:178 msgid "" @@ -875,15 +882,15 @@ msgid "" "export PATH=\"$CAIRO_ROOT/target/release:$PATH\"\n" "```" msgstr "" -"``bash\n" -"export PATH=\"$CAIRO_ROOT/target/release:$PATH\"\n" +"```bash\n" +"export PATH=“$CAIRO_ROOT/target/release:$PATH”\n" "```" #: src/ch01-01-installation.md:182 msgid "" "**NOTE: If installing from a Linux binary, adapt the destination path " "accordingly.**" -msgstr "**注意:如果从Linux二进制文件安装,请相应调整目标路径**" +msgstr "**注意:如果你是在Linux编译的二进制文件,请相应调整目标路径**" #: src/ch01-01-installation.md:184 msgid "### Step 3: Setup Language Server" @@ -916,8 +923,8 @@ msgid "" "server` binary should be built and executing this command will copy its path " "into your clipboard." msgstr "" -"从[Step 1](#step-1-install-cairo-10-guide-by-abdel),`cairo-language-" -"server'二进制文件应该已经建立,执行这个命令将复制其路径到你的剪贴板。" +"在[Step 1](#step-1-install-cairo-10-guide-by-abdel) 中,`cairo-language-" +"server'二进制文件应该已经编译完成,执行这个命令将复制其路径到你的剪贴板。" #: src/ch01-01-installation.md:196 msgid "" @@ -933,7 +940,7 @@ msgstr "" msgid "" "Update the `languageServerPath` of the Cairo 1.0 extension by pasting the " "path." -msgstr "通过粘贴路径更新Cairo 1.0扩展的`languageServerPath`。" +msgstr "将上面复制的路径更新到Cairo 1.0扩展的`languageServerPath`中。" #: src/ch01-02-hello-world.md:1 msgid "## Hello, World" @@ -966,13 +973,12 @@ msgid "" "> the language server and code highlighting. See [Appendix A][devtools]\n" "> for more details." msgstr "" -"> 注意:本书假定对命令行有基本的熟悉。Cairo对\n" +"> 注意:本书假定对你命令行有基本的熟悉。Cairo对\n" "> 对你的编辑或工具或你的代码所处的位置没有特别要求,所以\n" "> 如果你喜欢使用集成开发环境(IDE)而不是\n" "> 命令行,请随意使用你喜欢的IDE。Cairo团队已经开发了\n" "> Cairo语言的VSCode扩展,你可以用它来获得来自\n" -"> 语言服务器和代码高亮。参见[附录A][devtools]。\n" -"> 了解更多细节。" +"> 语言服务器和代码高亮。参见[附录D][devtools]来了解更多细节。" #: src/ch01-02-hello-world.md:15 msgid "### Creating a Project Directory" @@ -990,10 +996,8 @@ msgid "" msgstr "" "你首先要做一个目录来存储你的Cairo代码。对于Cairo来说,你的代码放在哪里并不重" "要。\n" -"但对于本书中的练习和项目来说,我们建议在你的主目录下建立一个_cairo_projects_" -"目录,并保存所有的代码、\n" -"我们建议在你的主目录下建立一个_cairo_projects_目录,并将所有的\n" -"你的项目都放在那里。" +"但对于本书中的练习和项目来说,我们建议在你的主目录下建立一个 " +"_cairo_projects_ 目录,并将你的所有项目存放在这里。" #: src/ch01-02-hello-world.md:22 msgid "" @@ -1002,12 +1006,12 @@ msgid "" "and a directory for the “Hello, world!” project within the _cairo_projects_ " "directory." msgstr "" -"打开一个终端,输入以下命令,建立一个_cairo_projects_目录\n" -"并在_cairo_projects_目录下为 \"Hello, world!\"项目建立一个目录。" +"打开一个终端,输入以下命令,建立一个 _cairo_projects_ 目录\n" +"并在 _cairo_projects_ 目录下为 \"Hello, world!\"项目建立一个目录。" #: src/ch01-02-hello-world.md:25 msgid "For Linux, macOS, and PowerShell on Windows, enter this:" -msgstr "对于Linux、macOS和Windows上的PowerShell,输入这个:" +msgstr "对于Linux、macOS和Windows上的PowerShell,输入:" #: src/ch01-02-hello-world.md:27 msgid "" @@ -1039,8 +1043,8 @@ msgid "" "```" msgstr "" "```cmd\n" -"> mkdir \"%USERPROFILE%\\projects\"\n" -"> cd /d \"%USERPROFILE%/projects\"\n" +"> mkdir “%USERPROFILE%\\projects”\n" +"> cd /d “%USERPROFILE%\\projects”\n" "> mkdir hello_world\n" "> cd hello_world\n" "```" @@ -1058,17 +1062,16 @@ msgid "" "convention is to use an underscore to separate them. For example, use\n" "_hello_world.cairo_ rather than _helloworld.cairo_." msgstr "" -"接下来,制作一个新的源代码文件,并将其称为_main.cairo_。Cairo文件总是以\n" -"扩展名为_.cairo_。如果你在文件名中使用一个以上的词,惯例是用下划线来分隔它" -"们。\n" -"惯例是用下划线来分隔它们。例如,使用\n" -"_hello_world.cairo_而不是_helloworld.cairo_。" +"接下来,制作一个新的源代码文件,并将命名为 _main.cairo_ 。Cairo文件的扩展名" +"为 _.cairo_ 。\n" +"如果你在文件名中使用一个以上的单词,惯例是用下划线来分隔它们。\n" +"例如,使用 _hello_world.cairo_ 而不是 _helloworld.cairo_ 。" #: src/ch01-02-hello-world.md:50 msgid "" "Now open the _main.cairo_ file you just created and enter the code in " "Listing 1-1." -msgstr "现在打开你刚刚创建的_main.cairo_文件,输入清单1-1中的代码。" +msgstr "现在打开你刚刚创建的 _main.cairo_ 文件,输入清单1-1中的代码。" #: src/ch01-02-hello-world.md:52 src/ch02-05-control-flow.md:9 #: src/ch02-05-control-flow.md:58 src/ch02-05-control-flow.md:90 @@ -1084,10 +1087,10 @@ msgid "" "}\n" "```" msgstr "" -"``rust,file=hello_world.cairo\n" -"use debug::PrintTrait;\n" +"```rust,file=hello_world.cairo\n" +"use debug::PrintTrait;\n" "fn main() {\n" -" 'Hello, world!'.print();\n" +" ‘Hello, world!’.print();\n" "}\n" "```" @@ -1105,7 +1108,7 @@ msgid "" "commands to compile and run the file:" msgstr "" "保存该文件,并回到你的终端窗口,在\n" -"_~/cairo_projects/hello_world_目录。输入以下\n" +" _~/cairo_projects/hello_world_ 目录。输入以下\n" "命令来编译和运行该文件:" #: src/ch01-02-hello-world.md:67 @@ -1125,7 +1128,7 @@ msgid "" "Regardless of your operating system, the string `Hello, world!` should print " "to\n" "the terminal." -msgstr "无论你的操作系统如何,字符串`Hello, world!`应该打印到终端。" +msgstr "无论你的操作系统如何,终端里都应该打印出字符串`Hello, world!`。" #: src/ch01-02-hello-world.md:75 msgid "" @@ -1133,8 +1136,9 @@ msgid "" "Cairo\n" "program. That makes you a Cairo programmer—welcome!" msgstr "" -"如果 \"Hello,world!\"确实打印出来了,那么恭喜你!你已经正式写出了Cairo!\n" -"你已经正式写了一个Cairo程序。这使你成为一名Cairo程序员--欢迎!" +"如果 \"Hello,world!\"打印出来了,那么恭喜你!你已经正式写了一个Cairo程" +"序!\n" +"你已经成为了一名Cairo程序员--欢迎!" #: src/ch01-02-hello-world.md:78 msgid "### Anatomy of a Cairo Program" @@ -1145,9 +1149,7 @@ msgid "" "Let’s review this “Hello, world!” program in detail. Here’s the first piece " "of\n" "the puzzle:" -msgstr "" -"让我们详细回顾一下这个 \"Hello,world!\"程序。这里有第一块\n" -"拼图的第一部分:" +msgstr "让我们详细回顾一下这个 \"Hello,world!\"程序。这里有拼图的第一部分:" #: src/ch01-02-hello-world.md:83 msgid "" @@ -1157,7 +1159,7 @@ msgid "" "}\n" "```" msgstr "" -"``rust\n" +"```rust\n" "fn main() {\n" "\n" "}\n" @@ -1173,11 +1175,10 @@ msgid "" "returns\n" "nothing. If there were parameters, they would go inside the parentheses `()`." msgstr "" -"这些行定义了一个名为 \"main \"的函数。`main'函数很特别:它总是每个可执行的" +"这些代码定义了一个名为 \"main \"的函数。`main'函数很特别:它总是每个可执行的" "Cairo程序中运行的第一个代码。\n" -"始终是每个可执行的Cairo程序中运行的第一段代码。这里,第一行\n" -"第一行声明了一个名为 \"main \"的函数,没有参数,也不返回\n" -"什么都没有。如果有参数,它们会被放在括号`()`里。" +"这里,第一行声明了一个名为 \"main \"的函数,没有参数,也不返回。如果有参数," +"它们会被放在括号`()`里。" #: src/ch01-02-hello-world.md:94 msgid "" @@ -1206,7 +1207,7 @@ msgstr "" "> 注意:如果你想在Cairo项目中坚持一个标准的风格,你可以\n" "> 使用自动格式化工具`cairo-format`来将你的代码格式化为\n" "> 特定的风格(更多关于`cairo-format'的信息见\n" -"> [附录A][devtools])。Cairo团队已经将这个工具\n" +"> [附录D][devtools])。Cairo团队已经将这个工具\n" "> 包含在标准的Cairo发行版中,就像`cairo-run`一样,所以它应该已经被\n" "> 已经安装在你的计算机上了!" @@ -1220,7 +1221,7 @@ msgid "" msgstr "" "在主函数声明之前,`use debug::PrintTrait;`一行负责导入另一个模块中定义的项" "目。在这个例子中,我们从Cairo核心库中导入了`PrintTrait`项目。通过这样做,我们" -"获得了在兼容打印的数据类型上使用`print()`方法的能力。" +"获得了在可以打印的数据类型上使用`print()`方法的能力。" #: src/ch01-02-hello-world.md:107 msgid "The body of the `main` function holds the following code:" @@ -1232,8 +1233,8 @@ msgid "" " 'Hello, world!'.print();\n" "```" msgstr "" -"``rust\n" -" 'Hello, world!'.print();\n" +"```rust\n" +" 'Hello, world!'.print();\n" "```" #: src/ch01-02-hello-world.md:113 @@ -1241,8 +1242,8 @@ msgid "" "This line does all the work in this little program: it prints text to the\n" "screen. There are four important details to notice here." msgstr "" -"这一行完成了这个小程序的所有工作:它将文本打印到\n" -"屏幕上。这里有四个重要的细节需要注意。" +"这一行完成了这个小程序的所有工作:将文本打印到屏幕上。这里有四个重要的细节需" +"要注意。" #: src/ch01-02-hello-world.md:116 msgid "First, Cairo style is to indent with four spaces, not a tab." @@ -1262,7 +1263,7 @@ msgstr "" "Cairo核心库中导入的,它定义了如何将不同数据类型的值打印到屏幕上。在我们的例子" "中,我们的文本被定义为 \"short string\",这是一个ASCII字符串,可以适合Cairo的" "基本数据类型,即`felt252`类型。通过调用`Hello, world!'.print()`,我们正在调用" -"`PrintTrait`特质的`felt252`实现的`print()`方法。" +"`PrintTrait`trait的`felt252`实现的`print()`方法。" #: src/ch01-02-hello-world.md:120 msgid "" @@ -1270,9 +1271,8 @@ msgid "" "as an argument\n" "to `print()`, and the short string is printed to the screen." msgstr "" -"第三,你看到了\"'Hello, world!'\"短字符串。我们把这个短字符串作为一个参数传" -"给\n" -"作为参数传递给`print()',短字符串被打印到屏幕上。" +"第三,看见了\"'Hello, world!'\"短字符串么。我们把这个短字符串作为一个参数传递" +"给`print()`,因此短字符串被打印到屏幕上。" #: src/ch01-02-hello-world.md:123 msgid "" @@ -1282,9 +1282,7 @@ msgid "" "end with a semicolon." msgstr "" "第四,我们用分号(`;`)来结束这一行,这表示这个表达式已经结束,下一个表达式准" -"备开始。\n" -"表达式已经结束,下一个表达式可以开始了。大多数Cairo的代码行\n" -"以分号结束。" +"备开始。大多数Cairo的代码行以分号结束。" #: src/ch01-02-hello-world.md:127 msgid "" @@ -1329,9 +1327,9 @@ msgid "" "programs, you’ll add dependencies, and if you start a project using Scarb, " "adding dependencies will be much easier to do." msgstr "" -"如果我们用Scarb来构建'Hello, world!'项目,只有Scarb处理构建代码的部分会被利" -"用,因为该程序不需要任何外部依赖。当你编写更复杂的Cairo程序时,你会增加依赖" -"性,如果你使用Scarb开始一个项目,增加依赖性将更容易做到。" +"如果我们用Scarb来构建 ‘Hello, world!’ 项目,我们只会用到Scarb处理构建代码的功" +"能,因为该程序不需要任何外部依赖。当你编写更复杂的Cairo程序时,你会增加外部依" +"赖,如果你使用Scarb开始一个项目,增加和管理外部依赖将更容易。" #: src/ch01-03-hello-scarb.md:9 msgid "Let's start by installing Scarb." @@ -1343,17 +1341,17 @@ msgstr "## 安装Scarb" #: src/ch01-03-hello-scarb.md:13 msgid "### Requirements" -msgstr "###要求" +msgstr "### 要求" #: src/ch01-03-hello-scarb.md:15 msgid "" "Scarb requires a Git executable to be available in the `PATH` environment " "variable." -msgstr "Scarb需要在`PATH`环境变量里有一个Git可执行文件。" +msgstr "Scarb需要`PATH`环境变量里有一个Git可执行文件。" #: src/ch01-03-hello-scarb.md:17 msgid "### Installation" -msgstr "###安装" +msgstr "### 安装" #: src/ch01-03-hello-scarb.md:19 msgid "As for now, Scarb needs manual installation with the following steps:" @@ -1399,15 +1397,15 @@ msgstr "" "- 在新的终端会话中运行以下命令来验证安装,它应该同时打印Scarb和Cairo语言版" "本,例如\n" "\n" -" ``bash\n" -" $ scarb --版本\n" +" ```bash\n" +" $ scarb —version\n" " scarb 0.1.0 (289137c24 2023-03-28)\n" " cairo: 1.0.0-alpha.6\n" " ```" #: src/ch01-03-hello-scarb.md:38 msgid "### Creating a Project with Scarb" -msgstr "###用Scarb创建一个项目" +msgstr "### 用Scarb创建一个项目" #: src/ch01-03-hello-scarb.md:40 msgid "" @@ -1421,7 +1419,7 @@ msgstr "" msgid "" "Navigate back to your projects directory (or wherever you decided to store " "your code). Then run the following:" -msgstr "导航到你的项目目录(或你决定存储代码的地方)。然后运行以下程序:" +msgstr "导航到你的项目目录(或你决定放代码的地方)。然后运行以下命令:" #: src/ch01-03-hello-scarb.md:44 msgid "" @@ -1440,7 +1438,7 @@ msgid "" "name." msgstr "" "它创建了一个新的目录和项目,名为hello_scarb。我们把我们的项目命名为" -"hello_scarb,Scarb在同名的目录下创建它的文件。" +"hello_scarb,因此Scarb会在同名的目录下创建它的文件。" #: src/ch01-03-hello-scarb.md:50 msgid "" @@ -1472,7 +1470,7 @@ msgid "" "Open _Scarb.toml_ in your text editor of choice. It should look similar to " "the code in Listing 1-2." msgstr "" -"在你选择的文本编辑器中打开_Scarb.toml_。它看起来应该与清单1-2中的代码相似。" +"在你选择的文本编辑器中打开 _Scarb.toml_ 。它看起来应该与清单1-2中的代码相似。" #: src/ch01-03-hello-scarb.md:59 msgid "Filename: Scarb.toml" @@ -1494,14 +1492,14 @@ msgid "" msgstr "" "```toml\n" "[package]\n" -"name = \"hello_scarb\"\n" -"version = \"0.1.0\"\n" +"name = “hello_scarb”\n" +"version = “0.1.0”\n" "\n" -"# 看到更多的键和它们的定义,https://docs.swmansion.com/scarb/docs/reference/" -"manifest\n" +"# See more keys and their definitions at https://docs.swmansion.com/scarb/" +"docs/reference/manifest\n" "\n" "[dependencies]\n" -"# foo = { path = \"vendor/foo\" }\n" +"# foo = { path = “vendor/foo” }\n" "```" #: src/ch01-03-hello-scarb.md:72 @@ -1517,7 +1515,7 @@ msgid "" "Language) format, which is Scarb’s configuration format." msgstr "" "这个文件是[TOML](https://toml.io/)(Tom's Obvious, Minimal Language)的格式," -"这是Scarb的配置格式。" +"是Scarb的配置文件格式。" #: src/ch01-03-hello-scarb.md:76 msgid "" @@ -1526,7 +1524,7 @@ msgid "" "to this file, we’ll add other sections." msgstr "" "第一行,`[package]`,是一个章节标题,表示下面的语句是在配置一个包。随着我们向" -"这个文件添加更多的信息,我们将添加其他部分。" +"这个文件添加更多的信息,我们将添加其他章节。" #: src/ch01-03-hello-scarb.md:78 msgid "" @@ -1542,16 +1540,16 @@ msgid "" "any of your project’s dependencies. In Cairo, packages of code are referred " "to as crates. We won’t need any other crates for this project." msgstr "" -"最后一行,`[dependencies]`,是一个部分的开始,供你列出你的项目的任何依赖性。" -"在Cairo中,代码包被称为crate。在这个项目中,我们不需要任何其他的crates。" +"最后一行,`[dependencies]`,是一个章节的开始,该章节供你列出你的项目的所有依" +"赖。在Cairo中,代码包被称为crate。在这个项目中,我们不需要任何其他的crate。" #: src/ch01-03-hello-scarb.md:82 msgid "" "The other file created by Scarb is `src/lib.cairo`, let's delete all the " "content and put in the following content, we will explain the reason later." msgstr "" -"Scarb创建的另一个文件是`src/lib.cairo`,让我们删除所有的内容,放入以下内容," -"我们将在后面解释原因。" +"Scarb创建的另一个文件是`src/lib.cairo`,让我们删除其中所有的内容,放入以下内" +"容,我们将在后面解释原因。" #: src/ch01-03-hello-scarb.md:84 msgid "" @@ -1559,8 +1557,8 @@ msgid "" "mod hello_scarb;\n" "```" msgstr "" -"``rust\n" -"mod hello_scarb;\n" +"```rust\n" +"mod hello_scarb;\n" "```" #: src/ch01-03-hello-scarb.md:88 @@ -1583,10 +1581,10 @@ msgid "" "}\n" "```" msgstr "" -"``rust,file=hello_scarb.cairo\n" -"use debug::PrintTrait;\n" +"```rust,file=hello_scarb.cairo\n" +"use debug::PrintTrait;\n" "fn main() {\n" -" 'Hello,Scarb!'.print();\n" +" ‘Hello, Scarb!’.print();\n" "}\n" "```" @@ -1615,7 +1613,7 @@ msgid "" msgstr "" "顶层项目目录是为README文件、许可证信息、配置文件和任何其他与代码无关的内容保" "留的。\n" -"Scarb确保所有项目组件都有一个指定的位置,维持一个结构化的组织。" +"Scarb确保所有项目组件都有一个指定的位置,维持一个结构化的组织架构。" #: src/ch01-03-hello-scarb.md:106 msgid "" @@ -1630,13 +1628,13 @@ msgstr "" #: src/ch01-03-hello-scarb.md:108 msgid "### Building a Scarb Project" -msgstr "###建立一个Scarb项目" +msgstr "### 编译Scarb项目" #: src/ch01-03-hello-scarb.md:110 msgid "" "From your hello_scarb directory, build your project by entering the " "following command:" -msgstr "从你的hello_scarb目录,通过输入以下命令建立你的项目:" +msgstr "在你的hello_scarb目录中,通过输入以下命令来编译你的项目:" #: src/ch01-03-hello-scarb.md:112 msgid "" @@ -1695,12 +1693,13 @@ msgid "" msgstr "" "> 注意:你会注意到这里我们没有使用Scarb的命令,而是直接使用了Cairo二进制文件" "的命令。\n" -"> 由于Scarb还没有执行Cairo代码的命令,我们必须直接使用`cairo-run`命令。\n" +"> 由于Scarb还没有执行Cairo代码的命令,我们必须直接使用`cairo-run`命令来执行代" +"码。\n" "> 在接下来的教程中我们将使用这个命令,但我们也将使用Scarb命令来初始化项目。" #: src/ch01-03-hello-scarb.md:133 msgid "### Defining Custom Scripts" -msgstr "###定义自定义脚本" +msgstr "### 定义自定义脚本" #: src/ch01-03-hello-scarb.md:135 msgid "" @@ -1776,18 +1775,18 @@ msgid "" "matter which operating system you’re working on. So, at this point, we’ll no " "longer provide specific instructions for Linux and macOS versus Windows." msgstr "" -"使用Scarb的另一个好处是,无论你在哪个操作系统上工作,命令都是一样的。所以,在" -"这一点上,我们将不再提供Linux和macOS与Windows的具体说明。" +"使用Scarb的另一个好处是,无论你在哪个操作系统上工作,命令都是一样的。所以我们" +"将不再提供Linux和macOS与Windows的具体说明。" #: src/ch01-03-hello-scarb.md:162 msgid "# Summary" -msgstr "# 摘要" +msgstr "# 总结" #: src/ch01-03-hello-scarb.md:164 msgid "" "You’re already off to a great start on your Cairo journey! In this chapter, " "you’ve learned how to:" -msgstr "你的Cairo之旅已经有了一个良好的开端!在本章中,你已经学会了如何:" +msgstr "你的Cairo之旅已经有了一个很好的开始!在本章中,你已经学会了如何:" #: src/ch01-03-hello-scarb.md:166 msgid "" @@ -1797,13 +1796,13 @@ msgid "" msgstr "" "- 安装最新的稳定版本的Cairo\n" "- 直接使用`cairo-run`编写并运行一个 \"Hello, world!\"程序\n" -"- 使用Scarb的惯例创建并运行一个新项目" +"- 使用Scarb创建并运行一个新项目" #: src/ch01-03-hello-scarb.md:170 msgid "" "This is a great time to build a more substantial program to get used to " "reading and writing Cairo code." -msgstr "这是一个建立更多实用程序的好时机,以习惯于阅读和编写Cairo代码。" +msgstr "是时候通过建立更多实用程序来熟悉阅读和编写Cairo代码了。" #: src/ch02-00-common-programming-concepts.md:1 msgid "# Common Programming Concepts" @@ -1828,7 +1827,7 @@ msgid "" "program, and learning them early will give you a strong core to start from." msgstr "" "具体来说,你将学习到变量、基本类型、函数、注释和控制流。这些基础将出现在每个" -"Cairo程序中,尽早学习它们将给你一个强大的核心开始。" +"Cairo程序中,尽早学习它们将给你一个强大的核心来开启旅程。" #: src/ch02-01-variables-and-mutability.md:1 msgid "## Variables and Mutability" @@ -1847,11 +1846,11 @@ msgid "" "and how\n" "you can make your variables mutable." msgstr "" -"Cairo使用一个不可改变的内存模型,这意味着一旦一个内存单元被写入就不能被覆\n" -"盖,只能被读出。为了反映这种不可变的内存模型,变量在Cairo中默认是不可变的。\n" -"然而,该语言对这种模式进行了抽象,让你可以选择让你的变量是可变的。让我们来\n" -"探讨一下Cairo是如何以及为什么要执行不可变性的变量,以及你如何使你的变量成为可" -"变的。" +"Cairo使用一个不可改变的内存模型,这意味着一旦一个内存单元被写入就不能被覆" +"盖,\n" +"只能被读出。为了反映这种不可变的内存模型,变量在Cairo中默认是不可变的。\n" +"然而,该语言对这种模式进行了抽象,让你可以选择变量是否可变。让我们来\n" +"探讨一下Cairo是如何以及为什么要强行规定变量不可变,以及如何使变量成为可变的。" #: src/ch02-01-variables-and-mutability.md:10 msgid "" @@ -1861,11 +1860,9 @@ msgid "" "in\n" "your _cairo_projects_ directory by using `scarb new variables`." msgstr "" -"当一个变量是不可变的,一旦一个值被绑定到一个名字上,你就不能改变\n" -"该值。为了说明这一点,在你的_cairo_projects_目录下生成一个名为_variables_的新" -"项目。\n" -"你的_cairo_projects_目录下,使用`scarb new variables`生成一个名为_variables的" -"新项目。" +"当一个变量是不可变的,一旦一个值被绑定到一个名字上,你就不能改变该值。\n" +"为了展示这一点,在你的 _cairo_projects_ 目录下,使用`scarb new variables`生成" +"一个名为 _variables_ 的新项目。" #: src/ch02-01-variables-and-mutability.md:14 msgid "" @@ -1873,8 +1870,8 @@ msgid "" "its\n" "code with the following code, which won’t compile just yet:" msgstr "" -"然后,在你新的_变量_目录下,打开_src/lib.cairo_并将其替换为\n" -"替换为下面的代码,这段代码还不会被编译:" +"然后,在你新的 _variables_ 目录下,打开 _src/lib.cairo_ 并将其替换为下面的代" +"码,这段代码还不会被编译:" #: src/ch02-01-variables-and-mutability.md:17 #: src/ch02-01-variables-and-mutability.md:76 @@ -1963,9 +1960,9 @@ msgid "" "not a good programmer! Experienced Caironautes still get compiler errors." msgstr "" "这个例子显示了编译器如何帮助你发现程序中的错误。\n" -"编译器错误可能令人沮丧,但实际上它们只意味着你的程序\n" +"编译错误可能令人沮丧,但实际上它们只意味着你的程序\n" "还没有安全地完成你想做的事情;它们并不意味着你不是一个好的程序员。\n" -"不是一个好的程序员!有经验的Caironautes仍然会出现编译器错误。" +"即使有经验的Caironautes仍然会遇到编译错误。" #: src/ch02-01-variables-and-mutability.md:46 msgid "" @@ -1993,12 +1990,13 @@ msgid "" "thus\n" "easier to reason through." msgstr "" -"在尝试改变预设为不可变的值时,产生编译时错误是很重要的,因为这种情况可能导\n" -"致 bug。如果一部分代码假设一个值永远也不会改变,而另一部分代码改变了这个\n" -"值,第一部分代码就有可能以不可预料的方式运行。不得不承认这种 bug 的起因难以\n" -"跟踪,尤其是第二部分代码只是 有时 会改变值。\n" -"Cairo 编译器保证,如果声明一个值不会变,它就真的不会变,所以你不必自己跟\n" -"踪它。这意味着你的代码更易于推导。" +"在尝试改变预设为不可变的值时,产生编译时错误是很重要的,因为这种情况可能导致 " +"bug。\n" +"如果一部分代码假设一个值永远也不会改变,而另一部分代码改变了这个值,\n" +"第一部分代码就有可能以不可预料的方式运行。不得不承认这种 bug 的起因难以跟踪," +"尤其是第二部分代码只是 _有时_ 会改变值。\n" +"Cairo 编译器保证,如果声明一个值不会变,它就真的不会变,所以你不必自己跟踪" +"它。这意味着你的代码更易于推导。" #: src/ch02-01-variables-and-mutability.md:60 msgid "" @@ -2011,8 +2009,8 @@ msgid "" "will be changing this variable’s value." msgstr "" "不过可变性也是非常有用的,可以用来更方便地编写代码。尽管变量默认是不可变的," -"你仍然可以在变量名前添加 `mut` 来使其可变。`mut` 也向读者表明了其他代码将会改" -"变这个变量值的意图。" +"你仍然可以在变量名前添加 `mut` 来使其可变。`mut` 也向阅读代码的人表明了其他代" +"码将会改变这个变量值的意图。" #: src/ch02-01-variables-and-mutability.md:66 msgid "" @@ -2030,17 +2028,17 @@ msgid "" "is that at the Cairo\n" "level, the variable is not redeclared so its type cannot change." msgstr "" -"然而,你可能想知道,当一个变量被声明为 `mut` 时,究竟会发生什么?\n" -"被声明为 `mut` 时会发生什么,因为我们之前提到Cairo的内存是不可改变的。\n" -"答案是,Cairo的内存是不可改变的,但变量指向的内存地址可以被改变。在检查了低\n" -"级别的Cairo汇编代码后,我们可以清楚地发现变量变化是以语法糖的形式实现的,它\n" -"将变异操作转化为一系列相当于变量变化的步骤。将变化操作转化为一系列的步\n" -"骤,等同于变量的隐藏。唯一的区别是,在Cairo,变量没有被重新声明,所以它\n" -"的类型不能改变。" +"然而,你可能想知道,当一个变量被声明为 `mut` 时,究竟会发生什么?因为我们之前" +"提到Cairo的内存是不可改变的。\n" +"答案是,Cairo的内存是不可改变的,但变量指向的内存地址可以被改变。在检查了低级" +"别的Cairo汇编代码后,\n" +"我们可以清楚地发现变量可变性是以语法糖的形式实现的,它将变量可变性操作转化为" +"一系列的步骤,等同于变量的隐藏(variable shadowing)。\n" +"唯一的区别是,在Cairo,变量没有被重新声明,所以它的类型不能改变。" #: src/ch02-01-variables-and-mutability.md:74 msgid "For example, let’s change _src/lib.cairo_ to the following:" -msgstr "例如,让我们把_src/lib.cairo_改为以下内容:" +msgstr "例如,让我们把 _src/lib.cairo_ 改为以下内容:" #: src/ch02-01-variables-and-mutability.md:78 msgid "" @@ -2097,8 +2095,7 @@ msgid "" "depends on what you think is clearest in that particular situation." msgstr "" "当使用 `mut` 时,我们将在`x`绑定的值从`5`改为 `6` 。\n" -"最终,决定是否使用可变性取决于你自己,并取决于你认为在特定情况下什么是最清楚" -"的。" +"最终,决定是否使用可变性取决于你自己以及你认为在特定情况下什么是最清楚的。" #: src/ch02-01-variables-and-mutability.md:103 msgid "### Constants" @@ -2112,8 +2109,8 @@ msgid "" "constants\n" "and variables." msgstr "" -"类似于不可变变量,常量 (constants) 是绑定到一个名称的不允许改变的值,不过常\n" -"量与变量还是有一些区别。" +"类似于不可变变量,常量 (constants) 是绑定到一个名称的不允许改变的值,不过常量" +"与变量还是有一些区别。" #: src/ch02-01-variables-and-mutability.md:109 msgid "" @@ -2127,18 +2124,18 @@ msgid "" "[“Data Types”][data-types], so don’t worry about the details\n" "right now. Just know that you must always annotate the type." msgstr "" -"首先,不允许对常量使用 `mut`。常量不光默认不可变,它总是不可变。声明常量使用 " -"`const` 关键字而不是 `let`,并且_必须_注明值的类型。在下一部分,[“数据类型”]" -"[data-types]中会介绍类型和类型注解,现在无需关心这些细节,记住总是标注类型即" -"可。" +"首先,不允许对常量使用 `mut`。常量不仅仅是默认不可变—它总是不可变。声明常量使" +"用 `const` 关键字而不是 `let`,并且 _必须_ 注明值的类型。在下一部分,[“数据类" +"型”][data-types]中会介绍类型和类型注解,现在无需关心这些细节,记住总是标注类" +"型即可。" #: src/ch02-01-variables-and-mutability.md:116 msgid "" "Constants can only be declared in the global scope, which makes\n" "them useful for values that many parts of code need to know about." msgstr "" -"常量可以在任何作用域中声明,包括全局作用域,这在一个值需要被很多部分的代码\n" -"用到时很有用。" +"常量可以在任何作用域中声明,包括全局作用域,这在一个值需要被很多部分的代码用" +"到时很有用。" #: src/ch02-01-variables-and-mutability.md:119 msgid "" @@ -2148,8 +2145,8 @@ msgid "" "literal constants\n" "are currently supported." msgstr "" -"最后一个区别是,常量只能被设置为常量表达式,而不可以是其他任何只能在运行时\n" -"计算出的值。目前只支持字面常量。" +"最后一个区别是,常量只能被设置为常量表达式,而不可以是其他任何只能在运行时计" +"算出的值。目前只支持字面常量。" #: src/ch02-01-variables-and-mutability.md:123 msgid "Here’s an example of a constant declaration:" @@ -2161,8 +2158,8 @@ msgid "" "const ONE_HOUR_IN_SECONDS: u32 = 3600_u32;\n" "```" msgstr "" -"``rust\n" -"const ONE_HOUR_IN_SECONDS: u32 = 3600_u32;\n" +"```rust\n" +"const ONE_HOUR_IN_SECONDS: u32 = 3600_u32;\n" "```" #: src/ch02-01-variables-and-mutability.md:129 @@ -2182,9 +2179,9 @@ msgid "" "to\n" "earn, or the speed of light." msgstr "" -"在声明它的作用域之中,常量在整个程序生命周期中都有效,此属性使得常量可以作\n" -"为多处代码使用的全局范围的值,例如一个游戏中所有玩家可以获取的最高分或者光\n" -"速。" +"在声明它的作用域之中,常量在整个程序生命周期中都有效,\n" +"此属性使得常量可以作为多处代码使用的全局范围的固定数值,例如一个游戏中玩家可" +"以获取的最高分,或者光速。" #: src/ch02-01-variables-and-mutability.md:138 msgid "" @@ -2195,8 +2192,9 @@ msgid "" "helps to have only one place in your code you would need to change if the\n" "hardcoded value needed to be updated in the future." msgstr "" -"将遍布于应用程序中的硬编码值声明为常量,能帮助后来的代码维护人员了解值的意\n" -"图。如果将来需要修改硬编码值,也只需修改汇聚于一处的硬编码值。" +"将遍布于应用程序中的硬编码值声明为常量,能帮助后来的代码维护人员了解值的意" +"图。\n" +"如果将来需要修改硬编码值,也只需修改汇此处的硬编码值。" #: src/ch02-01-variables-and-mutability.md:143 msgid "### Shadowing" @@ -2219,12 +2217,13 @@ msgid "" "use of the `let` keyword as follows:" msgstr "" "变量隐藏指的是声明一个与之前变量同名的新的变量。\n" -"Caironautes 说第一个变量被第二个变量所_隐藏_了,这意味着当您使用变量的名称" -"时,编译器将看到第二个变量\n" -"实际上,第二个变量“遮蔽”了第一个变量,此时任何使用该变量名的行为中都会视为\n" -"是在使用第二个变量,直到第二个变量自己也被隐藏或第二个变量的作用域结束。可\n" -"以用相同变量名称来隐藏一个变量,以及重复使用 `let` 关键字来多次隐藏,如下\n" -"所示:" +"当Caironautes 说第一个变量被第二个变量所 _隐藏_ 时,这意味着当您使用变量的名" +"称时,编译器看到的是第二个变量。\n" +"实际上,第二个变量“遮蔽”了第一个变量,此时任何使用该变量名的行为中都会视为是" +"在使用第二个变量,\n" +"直到第二个变量自己也被隐藏或第二个变量的作用域结束。\n" +"可以用相同变量名称来隐藏一个变量,以及重复使用 `let` 关键字来多次隐藏,如下所" +"示:" #: src/ch02-01-variables-and-mutability.md:156 msgid "" @@ -2250,10 +2249,10 @@ msgstr "" " let x = x + 1;\n" " {\n" " let x = x * 2;\n" -" 'Inner scope x value is:'.print();\n" +" ‘Inner scope x value is:’.print();\n" " x.print()\n" " }\n" -" 'Outer scope x value is:'.print();\n" +" ‘Outer scope x value is:’.print();\n" " x.print();\n" "}\n" "```" @@ -2326,8 +2325,8 @@ msgstr "" "隐藏与将变量标记为 `mut` 是有区别的。\n" "当不小心尝试对变量重新赋值时,如果没有使用 `let` 关键字,就会导致编译时错" "误。\n" -"通过使用 `let`,我们可以用这个值进行一些计算,不过计算完之后变量仍然是不可变" -"的。" +"通过使用 `let`,我们可以用这个新值进行一些计算,不过计算完之后变量仍然是不可" +"变的。" #: src/ch02-01-variables-and-mutability.md:199 msgid "" @@ -2347,10 +2346,8 @@ msgstr "" "`mut` 与隐藏的另一个区别是,当再次使用 `let` 时,实际上创建了一个新变量,我们" "可以改变值的类型,并且复用这个名字。\n" "如前所述,变量隐藏和可变量在较低层次上是等同的。\n" -"唯一的区别是,通过隐藏变量,编译器将不会检测到错误\n" -"如果你改变它的类型。例如,假设我们的程序在 `u64` 和 `u64` 之间进行了类型转" -"换。\n" -"`u64` 和 `felt252` 类型之间进行转换。" +"唯一的区别是,通过隐藏变量,即使你改变它的类型。编译器也不会检测到错误\n" +"例如,假设我们的程序在`u64` 和 `felt252` 类型之间进行转换。" #: src/ch02-01-variables-and-mutability.md:207 msgid "" @@ -2439,9 +2436,9 @@ msgid "" msgstr "" "```console\n" "❯ cairo-run src/lib.cairo\n" -"error: Unexpected argument type. Expected: \"core::integer::u64\", found: " -"\"core::felt252\".\n" -" --> lib.cairo:6:9\n" +"error: Unexpected argument type. Expected: “core::integer::u64”, found: " +"“core::felt252”.\n" +" —> lib.cairo:6:9\n" " x = x.into();\n" " ^******^\n" "\n" @@ -2453,7 +2450,8 @@ msgid "" "Now that we’ve explored how variables work, let’s look at more data types " "they\n" "can have." -msgstr "现在我们已经了解了变量如何工作,让我们看看变量可以拥有的更多数据类型。" +msgstr "" +"现在我们已经了解了变量如何工作,让我们看看变量可以被赋予的其他数据类型。" #: src/ch02-02-data-types.md:1 msgid "## Data Types" @@ -2481,8 +2479,7 @@ msgid "" msgstr "" "记住,Cairo 是静态类型(statically typed)语言,也就是说在编译时就必须知道所" "有变量的类型。根据值及其使用方式,编译器通常可以推断出我们想要用的类型。\n" -"\n" -"在可能存在多种类型的情况下,我们可以使用一种称为“转换方法”的方法,在其中指定" +"在可能存在多种类型的情况下,我们可以使用一种称为“类型转换”的方法,在其中指定" "所需的输出类型。" #: src/ch02-02-data-types.md:10 @@ -2521,7 +2518,7 @@ msgid "" "these from other programming languages. Let’s jump into how they work in " "Cairo." msgstr "" -"一个_标量_(scalar)类型表示一个单一的值。Cairo 有三种主要的标量类型:\n" +"一个 _标量_ (scalar)类型表示一个单一的值。Cairo 有三种主要的标量类型:\n" "felts、整数(integers)和布尔值(booleans)。你可能在其他语言中见过它们。\n" "让我们深入了解它们在 Cairo 中是如何工作的。" @@ -2544,9 +2541,9 @@ msgstr "" "在 Cairo 中,如果你没有指定一个变量或参数的类型,它的类型默认为一个字段元素," "由关键字 `felt252` 表示。在 Cairo 中,当我们说 \"一个字段元素 \"时,我们指的" "是范围为 `0 <= x < P` 的整数、\n" -"其中 `P` 是一个非常大的素数,目前等于 `P = 2^{251} + 17 * 2^{192}+1`。当加减" -"或乘法时,如果结果超出了质数的指定范围,就会发生溢出,然后再加上或减去 P 的适" -"当倍数,使结果回到范围内(也就是说,结果是以 P 为模数计算的)。" +"其中 `P` 是一个非常大的素数,目前为 `P = 2^{251} + 17 * 2^{192}+1`。当加减乘" +"时,如果结果超出了素数的指定范围,就会发生溢出,然后再加上或减去 P 的适当倍" +"数,使结果回到范围内(也就是说,结果是以 P 为模数计算的)。" #: src/ch02-02-data-types.md:32 msgid "" @@ -2561,7 +2558,7 @@ msgstr "" "整数和字段元素之间最重要的区别是除法:字段元素的除法(以及 Cairo 的除法)与普" "通 CPU 的除法不同,其中整数除法 `x / y` 被定义为`[x/y]`,\n" "其中商的整数部分被返回(所以你得到`7 / 3 = 2`),它可能满足或不满足方程式 " -"`(x / y) * y == x`,这取决于 `x` 是否能被 `y` 除以。" +"`(x / y) * y == x`,这取决于 `x` 是否能被 `y` 除。" #: src/ch02-02-data-types.md:36 msgid "" @@ -2602,12 +2599,12 @@ msgid "" "the type of an integer value." msgstr "" "felt252 类型是一个基本类型,是创建核心库中所有类型的基础。\n" -"然而,强烈建议程序员尽可能使用整数类型而不是 `felt252` 类型,因为 " -"`integer` \n" -"类型带有额外的安全功能,对代码中的潜在漏洞提供额外保护,如溢出检查。通过使用" -"这些整数类型,程序员可以确保他们的程序更加安全,不容易受到攻击或其他安全威" -"胁。一个_integer_是一个没有小数部分的数字。这个类型声明指出了程序员可以用来存" -"储整数的比特数。\n" +"然而,我们强烈建议程序员尽可能使用整数类型而不是 `felt252` 类型,因为 " +"`integer` 类型带有额外的安全功能,\n" +"对代码中的潜在漏洞提供额外保护,如溢出检查。通过使用这些整数类型,程序员可以" +"确保他们的程序更加安全,不容易受到攻击或其他安全威胁。\n" +"一个 _integer_ 是一个没有小数部分的数字。这个类型声明指出了该类型可以用来存储" +"整数的比特位。\n" "表3-1显示了Cairo中内建的整数类型。我们可以使用这些变体中的任何一种来声明一个" "整数值的类型。" @@ -2661,13 +2658,13 @@ msgid "" "}\n" "```" msgstr "" -"``rust\n" +"```rust\n" "fn sub_u8s(x: u8, y: u8) -> u8 {\n" " x - y\n" "}\n" "\n" "fn main() {\n" -" sub_u8s(1, 3);\n" +" sub_u8s(1, 3);\n" "}\n" "```" @@ -2680,7 +2677,7 @@ msgid "" msgstr "" "你可以用表 3-2 中的任何一种形式编写数字字面值。\n" "请注意可以是多种数字类型的数字字面值允许使用类型后缀,\n" -"例如 `57_u8` 来指定类型。" +"例如像 `57_u8` 这样指定类型。" #: src/ch02-02-data-types.md:78 msgid "Table 3-2: Integer Literals in Cairo" @@ -2709,9 +2706,9 @@ msgid "" "The primary situation in which you’d use `usize` is when indexing some sort " "of collection." msgstr "" -"那么,你如何知道要使用哪种类型的整数?试着估计你的 int 可以有的最大值,然后选" -"择合适的大小。\n" -"你使用 `usize` 的主要情况是在为某种集合做索引时。" +"那么,你如何知道要使用哪种类型的整数?试着估计你用的 int 的最大值,然后选择合" +"适的大小。\n" +" `usize` 的主要是用在为某种集合做索引时。" #: src/ch02-02-data-types.md:90 msgid "#### Numeric Operations" @@ -2779,8 +2776,8 @@ msgid "" "evaluates\n" "to a single value, which is then bound to a variable." msgstr "" -"这些语句中的每个表达式使用了一个数学运算符并计算出了一个值,\n" -"然后绑定给一个变量。" +"这些语句中的每个表达式使用了一个数学运算符并计算出了一个值,然后绑定给一个变" +"量。" #: src/ch02-02-data-types.md:120 msgid "" @@ -2788,8 +2785,9 @@ msgid "" "" msgstr "" -"<!-- TODO: 附录运算符 -->\n" -"<!-- [附录B][appendix_b] 忽略包含 Cairo 提供的所有操作符的列表。 -->" +"\n" +"" #: src/ch02-02-data-types.md:123 msgid "#### The Boolean Type" @@ -2832,7 +2830,7 @@ msgid "" "Flow”][control-flow] section." msgstr "" "使用布尔值的主要方式是通过条件语句,如 `if` 表达式。\n" -"我们将在[\"控制流\"][控制流]部分介绍 `if` 表达式在 Cairo 中的工作原理。" +"我们将在[\"控制流”][control-flow]部分介绍 `if` 表达式在 Cairo 中的工作原理。" #: src/ch02-02-data-types.md:143 msgid "#### The Short String Type" @@ -2850,7 +2848,7 @@ msgstr "" "Cairo 没有字符串(String)的原生类型,但你可以在 `felt252' 中存储短字符,形成" "我们所说的 \"短字符串\"。一个短字符串的最大长度为 31 个字符。这是为了确保它能" "装入一个 felt (一个 felt 是252位,一个 ASCII 字符是 8 位)。\n" -"下面是一些通过把值放在单引号之间来声明的例子:" +"可以通过把值放在单引号之间来声明短字符串,下面是一些例子:" #: src/ch02-02-data-types.md:148 msgid "" @@ -2859,9 +2857,9 @@ msgid "" "let my_first_string = 'Hello world';\n" "```" msgstr "" -"``rust\n" -"let my_first_char = 'C';\n" -"let my_first_string = 'Hello world';\n" +"```rust\n" +"let my_first_char = 'C';\n" +"let my_first_string = 'Hello world';\n" "```" #: src/ch02-02-data-types.md:153 @@ -2875,7 +2873,7 @@ msgid "" "traits, respectively." msgstr "" "在 Cairo 中,你可以使用 `TryInto' 和 `Into' 特性提供的 `try_into` 和 `into` " -"方法在普通标量类型和 `felt252` 之间转换数值。" +"方法在普通标量类型和 `felt252` 之间进行类型转换。" #: src/ch02-02-data-types.md:157 msgid "" @@ -2884,7 +2882,8 @@ msgid "" "`Option` type, which you'll need to unwrap to access the new value." msgstr "" "`try_into` 方法允许在目标类型可能不适合源值时进行安全的类型转换。请记住," -"`try_into` 返回一个 `Option` 类型,你需要解开这个类型来访问新的值。" +"`try_into` 会返回一个 `Option` 类型,你需要解开(unwrap)这个类型来访问新" +"的值。" #: src/ch02-02-data-types.md:159 msgid "" @@ -2892,7 +2891,7 @@ msgid "" "success is guaranteed, such as when the source type is smaller than the " "destination type." msgstr "" -"另一方面,当成功得到保证时,如源类型小于目的类型时,`into` 方法可用于类型转" +"另一方面,当转换必然成功时,如源类型小于目标类型时,`into` 方法可用于类型转" "换。" #: src/ch02-02-data-types.md:161 @@ -2958,7 +2957,7 @@ msgid "" "variety of types into one compound type. Tuples have a fixed length: once\n" "declared, they cannot grow or shrink in size." msgstr "" -"_元组_是一个将多个其他类型的值组合进一个复合类型的主要方式。\n" +"_元组_ 是一个将多个其他类型的值组合进一个复合类型的主要方式。\n" "元组长度固定:一旦声明,其长度不会增大或缩小。" #: src/ch02-02-data-types.md:188 @@ -2981,9 +2980,9 @@ msgid "" "}\n" "```" msgstr "" -"``rust\n" +"```rust\n" "fn main() {\n" -" let tup: (u32,u64,bool) = (10,20,true);\n" +" let tup: (u32,u64,bool) = (10,20,true);\n" "}\n" "```" @@ -3068,7 +3067,7 @@ msgstr "" #: src/ch02-02-data-types.md:231 msgid "### The unit type ()" -msgstr "###unit类型()" +msgstr "### unit类型 ()" #: src/ch02-02-data-types.md:233 msgid "" @@ -3077,9 +3076,9 @@ msgid "" "Its size is always zero, and it is guaranteed to not exist in the compiled " "code." msgstr "" -"一个_unit 类型_是一个只有一个值 `()` 的类型。\n" +"一个 _unit 类型_ 是一个只有一个值 `()` 的类型。\n" "它由一个没有元素的元组来表示。\n" -"它的大小总是为零,并且保证它在编译后的代码中不存在。" +"它的大小总是为零,并且它在编译后的代码中一定不存在。" #: src/ch02-03-functions.md:1 src/ch99-01-02-writing-starknet-contracts.md:134 msgid "## Functions" @@ -3105,7 +3104,7 @@ msgid "" "names, in which all letters are lowercase and underscores separate words.\n" "Here’s a program that contains an example function definition:" msgstr "" -"Cairo代码使用*蛇形大小写*作为函数和变量名称的常规样式。\n" +"Cairo代码使用 *蛇形命名法(snake case)* 作为函数和变量名称的常规样式。\n" "所有的字母都是小写的,并以下划线分隔单词。\n" "这里有一个程序,包含一个函数定义的例子:" @@ -3163,8 +3162,8 @@ msgid "" msgstr "" "可以使用函数名后跟圆括号来调用我们定义过的任意函数。\n" "因为程序中已定义 `another_function` 函数,所以可以在 `main` 函数中调用它。\n" -"注意,源码中 `another_function` 定义在 `main` 函数*之后*;也可以定义在之" -"前。\n" +"注意,源码中 `another_function` 定义在 `main` 函数 *之前* ;当然我们也可以定" +"义在之后。\n" "Cairo 不关心函数定义所在的位置,只要函数被调用时出现在调用之处可见的作用域内" "就行。" @@ -3176,8 +3175,8 @@ msgid "" "should see the following output:" msgstr "" "让我们用 Scarb 启动一个名为 *functions* 的新项目来进一步探索函数。\n" -"更进一步。把 `another_function` 的例子写入 *src/lib.cairo* 中并运行它。你\n" -"你应该看到以下输出:" +"更进一步。把 `another_function` 的例子写入 *src/lib.cairo* 中并运行它。你应该" +"看到以下输出:" #: src/ch02-03-functions.md:41 msgid "" @@ -3207,7 +3206,7 @@ msgstr "" #: src/ch02-03-functions.md:51 msgid "### Parameters" -msgstr "###参数" +msgstr "### 参数" #: src/ch02-03-functions.md:53 msgid "" @@ -3224,10 +3223,10 @@ msgid "" "function." msgstr "" "我们可以定义为拥有 *参数(parameters)* 的函数,参数是特殊变量,是函数签名的" -"一部分。当函数拥有参数(形参)时,可以为这些参数提供具体的值(实参)。技术上" -"讲,这些具体值被称为 *参数*(arguments),但是在日常交流中,人们倾向于不区分" -"使用 *parameter* 和 *argument* 来表示函数定义中的变量或调用函数时传入的具体" -"值。" +"一部分。当函数拥有参数(形参)时,可以为这些参数提供具体的值(实参)。\n" +"技术上讲,这些具体值被称为 *参数*(arguments),但是在日常交流中,人们倾向于" +"不区分使用 *parameter* 和 *argument* 来表示函数定义中的变量或调用函数时传入的" +"具体值。" #: src/ch02-03-functions.md:61 msgid "In this version of `another_function` we add a parameter:" @@ -3476,15 +3475,15 @@ msgid "" "}\n" "```" msgstr "" -"``rust,does_not_compile\n" +"```rust,does_not_compile\n" "fn main() {\n" -" let x = (let y = 6);\n" +" let x = (let y = 6);\n" "}\n" "```" #: src/ch02-03-functions.md:161 msgid "When you run this program, the error you’ll get looks like this:" -msgstr "当你运行这个程序时,你将得到的错误看起来像这样:" +msgstr "当你运行这个程序时,你将得到的错误看起来是这样:" #: src/ch02-03-functions.md:162 msgid "" @@ -3513,22 +3512,22 @@ msgstr "" "```console\n" "$ cairo-run src/lib.cairo\n" "error: Missing token TerminalRParen.\n" -" --> src/lib.cairo:2:14\n" +" —> src/lib.cairo:2:14\n" " let x = (let y = 6);\n" " ^\n" "\n" "error: Missing token TerminalSemicolon.\n" -" --> src/lib.cairo:2:14\n" +" —> src/lib.cairo:2:14\n" " let x = (let y = 6);\n" " ^\n" "\n" "error: Missing token TerminalSemicolon.\n" -" --> src/lib.cairo:2:14\n" +" —> src/lib.cairo:2:14\n" " let x = (let y = 6);\n" " ^\n" "\n" "error: Skipped tokens. Expected: statement.\n" -" --> src/lib.cairo:2:14\n" +" —> src/lib.cairo:2:14\n" " let x = (let y = 6);\n" "```" @@ -3546,8 +3545,9 @@ msgid "" msgstr "" "语句 `let y = 6` 没有返回一个值,所以没有任何东西让 `x` 与之绑定。这与其他语" "言\n" -"中的情况不同,比如说 C 和 Ruby,其中赋值会返回赋值的值。在这些语言中,你可\n" -"以写 `x = y = 6`,让 `x`和 `y` 都有值 `6`;但在 Cairo 中不是这样的。" +"中的情况不同,比如说 C 和 Ruby,其中赋值会返回赋值的值。\n" +"在这些语言中,你可以写 `x = y = 6`,让 `x`和 `y` 都有值 `6`;但在 Cairo 中不" +"是这样的。" #: src/ch02-03-functions.md:190 msgid "" @@ -3561,13 +3561,12 @@ msgid "" "expression. A new scope block created with\n" "curly brackets is an expression, for example:" msgstr "" -"表达式会计算出一个值,并且你将编写的大部分 Cairo 代码是由表达式组成的。考虑\n" -"一个数学运算,比如 `5 + 6` ,这是一个表达式并计算出值 `11`。表达式可以是语" -"句\n" -"的一部分:在示例 3-1 中,语句 `let y = 6;` 中的 `6` 是一个表达式,它计算出的" -"值\n" -"是 `6` 。函数调用是一个表达式。宏调用是一个表达式。用大括号创建的一个新的块\n" -"作用域也是一个表达式,例如:" +"表达式会计算出一个值,并且你编写的大部分 Cairo 代码将是由表达式组成的。\n" +"考虑一个数学运算,比如 `5 + 6` ,这是一个表达式并计算出值 `11`。\n" +"表达式可以是语句的一部分:在示例 3-1 中,语句 `let y = 6;` 中的 `6` 是一个表" +"达式,它计算出的值是 `6` 。\n" +"函数调用是一个表达式。宏调用也是一个表达式。用大括号创建的一个新的块作用域同" +"样也是一个表达式,例如:" #: src/ch02-03-functions.md:199 msgid "" @@ -3632,8 +3631,8 @@ msgstr "" "是一个代码块,它的值是 `4`。这个值作为 `let` 语句的一部分被绑定到 `y` 上。注" "意\n" " `x + 1` 这一行在结尾没有分号,与你见过的大部分代码行不同。表达式的结尾没有\n" -"分号。如果在表达式的结尾加上分号,它就变成了语句,而语句不会返回值。在接下\n" -"来探索具有返回值的函数和表达式时要谨记这一点。" +"分号。如果在表达式的结尾加上分号,它就变成了语句,而语句不会返回值。\n" +"在接下来学习具有返回值的函数和表达式时要谨记这一点。" #: src/ch02-03-functions.md:225 msgid "### Functions with Return Values" @@ -3654,8 +3653,9 @@ msgstr "" "函数可以向调用它的代码返回值。我们并不对返回值命名,但要在箭头(`->`)后声明" "它\n" "的类型。在 Cairo 中,函数的返回值等同于函数体最后一个表达式的值。使用 \n" -"`return` 关键字和指定值,可从函数中提前返回;但大部分函数隐式的返回最后的表\n" -"达式。这是一个有返回值的函数的例子:" +"`return` 关键字和指定值,可从函数中提前返回;但大部分函数隐式的返回最后的表达" +"式。\n" +"这是一个有返回值的函数的例子:" #: src/ch02-03-functions.md:234 msgid "" @@ -3836,11 +3836,10 @@ msgid "" "function\n" "definition and results in an error." msgstr "" -"主要的错误信息 `Unexpected return type` 揭示了该代码的核心问题。函数\n" -" `plus_one` 的定义说它将返回一个 `u32` 类型的值,但是语句并没有返回一个值,\n" -"这是由 `()`unit 类型表示的。因此,没有返回值,这与函数的定义相矛盾,导致了" -"错\n" -"误发生。" +"主要的错误信息 `Unexpected return type` 揭示了该代码的核心问题。\n" +"函数`plus_one` 的定义说它将返回一个 `u32` 类型的值,但是语句并不会返回一个" +"值,而是给出了一个 `()`unit 类型。\n" +"因此,没有返回值与函数的定义相矛盾,导致了错误发生。" #: src/ch02-04-comments.md:1 msgid "# Comments" @@ -3852,8 +3851,8 @@ msgid "" "comments. To create a comment, use the // syntax, after which any text on " "the same line will be ignored by the compiler." msgstr "" -"在 Cairo 程序中,你可以使用注释在代码中加入解释性的文本。要创建一个注释,请\n" -"使用 // 语法,之后同一行的任何文本都会被编译器忽略。" +"在 Cairo 程序中,你可以使用注释在代码中加入解释性的文本。\n" +"要创建一个注释,请使用 // 语法,之后同一行的任何文本都会被编译器忽略。" #: src/ch02-04-comments.md:5 msgid "" @@ -3864,10 +3863,10 @@ msgid "" "}\n" "```" msgstr "" -"````rust\n" +"```rust\n" "fn main() -> felt252 {\n" -" //函数的开始\n" -" 1 + 4 // 返回1和4的总和\n" +" // start of the function\n" +" 1 + 4 // return the sum of 1 and 4\n" "}\n" "```" @@ -4028,7 +4027,7 @@ msgstr "" #: src/ch02-05-control-flow.md:54 msgid "### Handling Multiple Conditions with `else if`" -msgstr "###用`else if`处理多个条件" +msgstr "### 用`else if`处理多个条件" #: src/ch02-05-control-flow.md:56 msgid "" @@ -4114,7 +4113,7 @@ msgstr "" #: src/ch02-05-control-flow.md:86 msgid "### Using `if` in a `let` statement" -msgstr "###在 `let` 语句中使用 `if`" +msgstr "### 在 `let` 语句中使用 `if`" #: src/ch02-05-control-flow.md:88 msgid "" @@ -4179,7 +4178,7 @@ msgstr "`number` 变量将会绑定到表示 `if` 表达式结果的值上。这 #: src/ch02-05-control-flow.md:116 msgid "### Repetition with Loops" -msgstr "###使用循环重复执行" +msgstr "### 使用循环重复执行" #: src/ch02-05-control-flow.md:118 msgid "" @@ -4438,7 +4437,7 @@ msgstr "" #: src/ch02-06-common-collections.md:1 msgid "## Common Collections" -msgstr "## ###常见的集合" +msgstr "## 常见集合" #: src/ch02-06-common-collections.md:3 msgid "" @@ -4453,7 +4452,7 @@ msgstr "" #: src/ch02-06-common-collections.md:5 msgid "### Array" -msgstr "### 阵列" +msgstr "### 数组" #: src/ch02-06-common-collections.md:7 msgid "" @@ -4501,14 +4500,14 @@ msgid "" "}\n" "```" msgstr "" -"``rust\n" -"使用array::ArrayTrait;\n" +"```rust\n" +"use array::ArrayTrait;\n" "\n" "fn main() {\n" -" let mut a = ArrayTrait::new();\n" -" a.append(0);\n" -" a.append(1);\n" -" a.append(2);\n" +" let mut a = ArrayTrait::new();\n" +" a.append(0);\n" +" a.append(1);\n" +" a.append(2);\n" "}\n" "```" @@ -4524,13 +4523,13 @@ msgid "" "let mut arr = ArrayTrait::::new();\n" "```" msgstr "" -"``rust、\n" -"let mut arr = ArrayTrait::::new();\n" +"```rust,\n" +"let mut arr = ArrayTrait::::new();\n" "```" #: src/ch02-06-common-collections.md:33 msgid "#### Updating an Array" -msgstr "#### 更新一个阵列" +msgstr "#### 更新一个数组" #: src/ch02-06-common-collections.md:35 msgid "##### Adding Elements" @@ -4550,11 +4549,11 @@ msgid "" " a.append(2);\n" "```" msgstr "" -"``rust\n" -" let mut a = ArrayTrait::new();\n" -" a.append(10);\n" -" a.append(1);\n" -" a.append(2);\n" +"```rust\n" +" let mut a = ArrayTrait::new();\n" +" a.append(10);\n" +" a.append(1);\n" +" a.append(2);\n" "```" #: src/ch02-06-common-collections.md:46 @@ -4589,19 +4588,19 @@ msgid "" "}\n" "```" msgstr "" -"``rust\n" -"use option::OptionTrait;\n" -"use array::ArrayTrait;\n" -"use debug::PrintTrait;\n" +"```rust\n" +"use option::OptionTrait;\n" +"use array::ArrayTrait;\n" +"use debug::PrintTrait;\n" "\n" "fn main() {\n" -" let mut a = ArrayTrait::new();\n" -" a.append(10);\n" -" a.append(1);\n" -" a.append(2);\n" +" let mut a = ArrayTrait::new();\n" +" a.append(10);\n" +" a.append(1);\n" +" a.append(2);\n" "\n" -" let first_value = a.pop_front().unwrap();\n" -" first_value.print(); // 打印 '10' 。\n" +" let first_value = a.pop_front().unwrap();\n" +" first_value.print(); // print '10'\n" "}\n" "```" @@ -4688,15 +4687,15 @@ msgid "" "}\n" "```" msgstr "" -"``rust\n" -"使用array::ArrayTrait;\n" +"```rust\n" +"use array::ArrayTrait;\n" "fn main() {\n" -" let mut a = ArrayTrait::new();\n" -" a.append(0);\n" -" a.append(1);\n" +" let mut a = ArrayTrait::new();\n" +" a.append(0);\n" +" a.append(1);\n" "\n" -" let first = *a.at(0_usize);\n" -" let second = *a.at(1_usize);\n" +" let first = *a.at(0_usize);\n" +" let second = *a.at(1_usize);\n" "}\n" "```" @@ -4743,25 +4742,25 @@ msgid "" "}\n" "```" msgstr "" -"``rust\n" -"use array::ArrayTrait;\n" -"使用box::BoxTrait;\n" -"fn main() -> u128 {\n" -" let mut arr = ArrayTrait::::new();\n" +"```rust\n" +"use array::ArrayTrait;\n" +"use box::BoxTrait;\n" +"fn main() -> u128 {\n" +" let mut arr = ArrayTrait::::new();\n" " arr.append(100_u128);\n" -" 让index_to_access =\n" -" 1_usize; // 改变这个值可以看到不同的结果,如果索引不存在会发生什" -"么?\n" +" let index_to_access =\n" +" 1_usize; // Change this value to see different results, what " +"would happen if the index doesn't exist ?\n" " match arr.get(index_to_access) {\n" -" Option::Some(x) => {\n" -" *x.unbox() // 暂时不用担心*,如果你好奇的话,请看3.2章 #desnap操" -"作符\n" -" // 基本上意味着 \"将get(idx)返回的东西转换成一个真实" -"的值\"\n" +" Option::Some(x) => {\n" +" *x.unbox() // Don't worry about * for now, if you are curious " +"see Chapter 3.2 #desnap operator\n" +" // It basically means \"transform what get(idx) " +"returned into a real value\"\n" " },\n" -" 选项::None(_) => {\n" -" let mut data = ArrayTrait::new();\n" -" data.append('out of bounds');\n" +" Option::None(_) => {\n" +" let mut data = ArrayTrait::new();\n" +" data.append('out of bounds');\n" " panic(data)\n" " }\n" " }\n" @@ -4770,7 +4769,7 @@ msgstr "" #: src/ch02-06-common-collections.md:121 msgid "#### Size related methods" -msgstr "#### 大小相关的方法" +msgstr "#### 数组体积相关的方法" #: src/ch02-06-common-collections.md:123 msgid "" @@ -4820,28 +4819,28 @@ msgid "" "}\n" "```" msgstr "" -"``rust\n" -"use array::ArrayTrait;\n" -"使用traits::Into;\n" +"```rust\n" +"use array::ArrayTrait;\n" +"use traits::Into;\n" "\n" "#[derive(Copy, Drop)]\n" "enum Data {\n" -" 整数: u128、\n" -" Felt: felt252、\n" -" Tuple: (u32, u32)、\n" +" Integer: u128,\n" +" Felt: felt252,\n" +" Tuple: (u32, u32),\n" "}\n" "\n" "fn main() {\n" -" let mut messages:Array = ArrayTrait::new();\n" -" messages.append(Data::Integer(100_u128));\n" -" messages.append(Data::Felt('hello world'));\n" -" messages.append(Data::Tuple((10_u32, 30_u32)) );\n" +" let mut messages: Array = ArrayTrait::new();\n" +" messages.append(Data::Integer(100_u128));\n" +" messages.append(Data::Felt('hello world'));\n" +" messages.append(Data::Tuple((10_u32, 30_u32)));\n" "}\n" "```" #: src/ch02-06-common-collections.md:150 msgid "#### Span" -msgstr "#### 跨度" +msgstr "#### Span" #: src/ch02-06-common-collections.md:152 msgid "" @@ -4852,25 +4851,24 @@ msgid "" "functions or when performing read-only operations (cf. [References and " "Snapshots](ch03-02-references-and-snapshots.md))" msgstr "" -"Span \"是一个结构,代表一个 \"数组 \"的快照。它被设计用来提供对数组元素的安全" -"和控制的访问,而不需要修改原始数组。Span对于确保数据的完整性和避免在函数间传" -"递数组或执行只读操作时的借用问题特别有用(参见[引用和快照](ch03-02-" -"references-and-snapshots.md))" +"`Span`是一个结构,代表一个 \"数组 \"的快照(snapshot)。它被设计用来提供对数" +"组元素的安全和控制的访问,而不需要修改原始数组。Span对于确保数据的完整性和避" +"免在函数间传递数组或执行只读操作时的借用问题特别有用(参见[引用和快照]" +"(ch03-02-references-and-snapshots.md))" #: src/ch02-06-common-collections.md:154 msgid "" "All methods provided by `Array` can also be used with `Span`, with the " "exception of the `append()` method." -msgstr "" -"除了 \"append() \"方法外,\"Array \"提供的所有方法也可以用于 \"Span\"。" +msgstr "除了 `append()`方法外,`Array`提供的其他所有方法都可以用于 `Span`。" #: src/ch02-06-common-collections.md:156 msgid "##### Turning an Array into span" -msgstr "##### 将一个数组变成跨度" +msgstr "##### 将一个数组变成span" #: src/ch02-06-common-collections.md:158 msgid "To create a `Span` of an `Array`, call the `span()` method:" -msgstr "要创建一个 \"数组 \"的 \"跨度\",请调用 \"span() \"方法:" +msgstr "要创建一个 `Array`的 `Span` ,请调用`span()`方法:" #: src/ch02-06-common-collections.md:160 msgid "" @@ -4878,14 +4876,14 @@ msgid "" "let span = array.span();\n" "```" msgstr "" -"``rust\n" -"let span = array.span();\n" +"```rust\n" +"let span = array.span();\n" "```" #: src/ch02-06-common-collections.md:164 src/ch04-03-method-syntax.md:286 #: src/ch06-05-separating-modules-into-different-files.md:98 msgid "## Summary" -msgstr "##摘要" +msgstr "## 总结" #: src/ch02-06-common-collections.md:166 msgid "" @@ -4904,8 +4902,8 @@ msgid "" "- Generate the _n_-th Fibonacci number.\n" "- Compute the factorial of a number _n_." msgstr "" -"- 产生第_n_个斐波那契数。\n" -"- 计算一个数字的阶乘_n_。" +"- 产生第 _n_ 个斐波那契数。\n" +"- 计算一个数字的阶乘 _n_ 。" #: src/ch02-06-common-collections.md:173 msgid "" @@ -4913,13 +4911,12 @@ msgid "" "with Rust and that _doesn’t_\n" "commonly exist in other programming languages: ownership." msgstr "" -"当你准备好继续前进时,我们将讨论一个Cairo与Rust共享的概念,而这个概念在其他编" -"程语言中并不常见。\n" -"在其他编程语言中通常不存在的概念:所有权。" +"当你准备好继续前进时,我们将讨论一个Cairo与Rust共有,而在其他编程语言中通常不" +"存在的概念:所有权。" #: src/ch03-00-understanding-ownership.md:1 msgid "# Understanding Cairo's Ownership system" -msgstr "# 了解开罗的所有权制度" +msgstr "# 了解Cairo的所有权制度" #: src/ch03-00-understanding-ownership.md:3 msgid "" @@ -4940,7 +4937,7 @@ msgstr "" "种错误的操作,如向一个内存单元写两次。\n" "这是通过实施一个所有权系统来实现的\n" "并在默认情况下禁止复制和丢弃数值。在本章中,我们将\n" -"讨论Cairo的所有权系统以及引用和快照。" +"讨论Cairo的所有权系统以及引用和快照(snapshot)。" #: src/ch03-01-what-is-ownership.md:1 msgid "## What Is Ownership?" @@ -4960,10 +4957,9 @@ msgid "" msgstr "" "Cairo实现了一个所有权系统以确保其编译代码的安全性和正确性。\n" "所有权机制是对线性类型系统的补充,该系统规定对象只能使用一次。\n" -"这有助于防止可能产生运行时错误的常见操作,如非法的内存地址\n" "这有助于防止可能产生运行时错误的常见操作,如非法的内存地址引用或对同一内存地" -"址的多次写入,并确保Cairo程序的正确性\n" -"通过在编译时检查所有的字典是否被压扁来确保Cairo程序的合理性。" +"址的多次写入,\n" +"并通过在编译时检查所有的字典是否被压缩(squash)来确保Cairo程序的正确性。" #: src/ch03-01-what-is-ownership.md:9 msgid "" @@ -4976,14 +4972,14 @@ msgid "" "bit more concise, letting us focus on the actual details rather than\n" "boilerplate code." msgstr "" -"现在我们已经过了Cairo的基本语法,我们不会在例子中包括所有的`fn main() {`的代" -"码。\n" -"所以如果你正在学习,请确保将下面的例子放在一个`main`函数中。因\n" -"此,我们的例子将更加简洁,让我们专注于实际的细节而不是样板代码。" +"既然我们已经掌握了Cairo基本语法,我们将不会在之后的例子中包含 `fn main() {` " +"代码,\n" +"所以如果你是一路跟过来的,必须手动将之后例子的代码放入一个 `main` 函数中。\n" +"这样,例子将显得更加简明,使我们可以关注实际细节而不是样板代码。" #: src/ch03-01-what-is-ownership.md:15 msgid "### Ownership Rules" -msgstr "###所有权规则" +msgstr "### 所有权规则" #: src/ch03-01-what-is-ownership.md:17 msgid "" @@ -4991,8 +4987,7 @@ msgid "" "we\n" "work through the examples that illustrate them:" msgstr "" -"首先,让我们看一下所有权规则。当我们通过说明这些规则的例子时,请牢记这\n" -"些规则,并通过例子来说明它们:" +"首先,让我们看一下所有权规则。请牢记这些规则,我们将通过例子来说明它们:" #: src/ch03-01-what-is-ownership.md:20 msgid "" @@ -5000,13 +4995,13 @@ msgid "" "- There can only be one owner at a time.\n" "- When the owner goes out of scope, the value will be _dropped_." msgstr "" -"- Cairo的每个值都有一个_所有者_。\n" +"- Cairo的每个值都有一个 _所有者_ 。\n" "- 在同一时间只能有一个所有者。\n" -"- 当所有者超出范围时,该值将被_丢弃_。" +"- 当所有者超出作用域(scope)时,该值将被 _丢弃_ 。" #: src/ch03-01-what-is-ownership.md:24 msgid "### Variable Scope" -msgstr "### 可变范围" +msgstr "### 变量作用域" #: src/ch03-01-what-is-ownership.md:26 msgid "" @@ -5015,8 +5010,8 @@ msgid "" "scope is the range within a program for which an item is valid. Take the\n" "following variable:" msgstr "" -"作为所有权的第一个例子,我们来看看一些变量的_范围。A范围是指程序中某一\n" -"项目有效的范围。考虑以下变量:" +"在所有权的第一个例子中,我们看看一些变量的 作用域( _scope_ )。作用域是一个" +"项(item)在程序中有效的范围。假设有这样一个变量:" #: src/ch03-01-what-is-ownership.md:30 msgid "" @@ -5024,8 +5019,8 @@ msgid "" "let s = 'hello';\n" "```" msgstr "" -"``rust\n" -"let s = 'hello';\n" +"```rust\n" +"let s = ‘hello’;\n" "```" #: src/ch03-01-what-is-ownership.md:34 @@ -5038,11 +5033,8 @@ msgid "" "program with comments annotating where the variable `s` would be valid." msgstr "" "变量`s`指的是一个短字符串,字符串的值被硬编码到我们的程序文本中。\n" -"硬编码到我们程序的文本中。这个变量从它被声明的那一刻起,一直到当前_scope_的结" -"束,都是有效的。\n" -"这个变量从它被声明的那一刻起一直到当前_scope_的结束都有效。清单3-1显示了一" -"个\n" -"程序,其中的注释说明了变量`s`的有效位置。" +"这个变量从它被声明的那一刻起,一直到当前 _scope_ 的结束,都是有效的。\n" +"清单3-1的程序中的注释标明了变量 `s` 在何处是有效的。" #: src/ch03-01-what-is-ownership.md:39 msgid "" @@ -5055,12 +5047,13 @@ msgid "" "valid\n" "```" msgstr "" -"``rust\n" -" { // s在这里是无效的,它还没有被声明。\n" -" let s = 'hello'; // s从现在开始是有效的\n" +"```rust\n" +" { // s is not valid here, it’s not yet declared\n" +" let s = ‘hello’; // s is valid from this point forward\n" "\n" -" // 对s做一些事情\n" -" } // 这个范围现在结束了,s不再有效了\n" +" // do stuff with s\n" +" } // this scope is now over, and s is no longer " +"valid\n" "```" #: src/ch03-01-what-is-ownership.md:47 @@ -5068,9 +5061,7 @@ msgid "" "Listing 3-1: A variable and the scope in which it " "is\n" "valid" -msgstr "" -"清单3-1:一个变量和它所处的范围\n" -"有效" +msgstr "清单3-1:一个变量和其有效的作用域" #: src/ch03-01-what-is-ownership.md:50 msgid "In other words, there are two important points in time here:" @@ -5081,8 +5072,8 @@ msgid "" "- When `s` comes _into_ scope, it is valid.\n" "- It remains valid until it goes _out of_ scope." msgstr "" -"- 当`s`进入_范围时,它是有效的。\n" -"- 它一直有效,直到它退出范围。" +"- 当`s`进入 _进入作用域_ 时,它就是有效的。\n" +"- 这一直持续到它 _离开_ 作用域 为止。" #: src/ch03-01-what-is-ownership.md:55 msgid "" @@ -5093,14 +5084,13 @@ msgid "" "understanding by using the `Array` type we introduced in the [previous " "chapter](ch02-06-common-collections.md)." msgstr "" -"在这一点上,作用域和变量有效时间之间的关系与其他编程语言类似。\n" -"与其他编程语言中的关系相似。现在我们将在这个基础上\n" -"的理解,使用我们在[前一章](ch02-06-common-collections.md)中介绍的`Array`类" -"型。" +"目前为止,变量是否有效与作用域的关系跟其他编程语言是类似的。\n" +"现在我们在此基础上通过在[前一章](ch02-06-common-collections.md)中介绍的" +"`Array`类型进一步理解。" #: src/ch03-01-what-is-ownership.md:59 msgid "### Ownership with the `Array` Type" -msgstr "### 拥有 `Array` 类型的所有权" +msgstr "### `Array` 类型的所有权" #: src/ch03-01-what-is-ownership.md:61 msgid "" @@ -5115,18 +5105,16 @@ msgid "" "`Array` type whose size\n" "is unknown at compile time and which can't be trivially copied ?" msgstr "" -"为了说明所有权的规则,我们需要一个更复杂的数据类型。\n" -"第二章[\"数据类型\"][data-types]部分中所涉及的类型\n" -"中所涉及的类型都是已知大小的,可以快速而琐碎地复制成\n" -"如果另一部分代码需要使用相同的类型,可以快速地复制一个新的、独立的实例。\n" -"如果另一部分代码需要在不同的范围内使用相同的值,就可以快速、简单地复制一个新" -"的、独立的实例。\n" -"当它们不再被使用时可以很容易地被丢弃。但是对于 `Array` 类型的行为是什么?\n" -"在编译时是未知的,并且不能被简单地复制?" +"为了演示所有权的规则,我们需要一个比第二章 [“Data Types”][data-types] 中讲到的都要复杂的数据类型。\n" +"前面介绍的类型都是已知大小的,如果代码的另一部分需要在不同的作用域中使用相同" +"的值,可以快速简单地复制它们来创建一个新的独立实例,并且当离开作用域时被丢" +"弃。\n" +"但当编译时大小未知且无法被简单复制的`Array`会怎么样?" #: src/ch03-01-what-is-ownership.md:69 msgid "Here is a short reminder of what an array looks like:" -msgstr "这里简单提醒一下数组的样子:" +msgstr "这里简单回忆一下数组的样子:" #: src/ch03-01-what-is-ownership.md:71 msgid "" @@ -5136,10 +5124,10 @@ msgid "" "arr.append(2);\n" "```" msgstr "" -"``rust\n" -"let mut arr = ArrayTrait::::new();\n" -"arr.append(1);\n" -"arr.append(2);\n" +"```rust\n" +"let mut arr = ArrayTrait::::new();\n" +"arr.append(1);\n" +"arr.append(2);\n" "```" #: src/ch03-01-what-is-ownership.md:77 @@ -5150,9 +5138,8 @@ msgid "" "array in two consecutive\n" "function calls:" msgstr "" -"那么,所有权系统如何确保每个单元格不会被写入超过一次?\n" -"考虑一下下面的代码,我们试图在两个连续的数组中传递同一个实例\n" -"函数调用中传递同一个数组实例:" +"那么,所有权系统如何确保每个内存单元不会被写入超过一次?\n" +"考虑一下下面的代码,我们试图在两个连续的函数调用中传递同一个数组实例:" #: src/ch03-01-what-is-ownership.md:81 msgid "" @@ -5203,14 +5190,13 @@ msgid "" "system thus prevents us from using the same instance of `arr` in `foo`." msgstr "" "在这种情况下,我们试图将同一个数组实例`arr`通过值传递给函数`foo`和`bar`,这意" -"味着两个函数调用的参数都是同一个数组实例。如果你在`foo`中向数组添加一个值,然" -"后在`bar`中向数组添加一个值\n" -"中向数组追加一个值,然后试图在`bar`中向同一个数组追加另一个值,会发生什么" +"味着两个函数调用的参数都是同一个数组实例。\n" +"如果你在`foo`中向数组添加一个值,然后再在`bar`中向数组添加一个值,会发生什么" "呢?\n" "你会试图向同一个内存单元写两次,这在Cairo中是不允许的。\n" -"为了防止这种情况,`arr`变量的所有权从`main`函数转移到`foo`函数。当试\n" -"图以`arr`为参数调用`bar`时,`arr`的所有权已经被转移到第一次调用时。所\n" -"有权系统因此阻止我们在`foo`中使用相同的`arr`实例。" +"为了防止这种情况,`arr`变量的所有权从`main`函数转移到`foo`函数。当试图以`arr`" +"为参数调用`bar`时,`arr`的所有权早已再第一次调用时被转移。\n" +"所有权系统阻止了我们在`foo`中使用相同的`arr`实例。" #: src/ch03-01-what-is-ownership.md:104 msgid "Running the code above will result in a compile-time error:" @@ -5236,7 +5222,7 @@ msgstr "" #: src/ch03-01-what-is-ownership.md:113 msgid "### The `Copy` Trait" -msgstr "### `Copy` 特性" +msgstr "### `Copy` Trait" #: src/ch03-01-what-is-ownership.md:115 msgid "" @@ -5250,10 +5236,10 @@ msgid "" "While Arrays and Dictionaries can't be copied, custom types that don't " "contain either of them can be." msgstr "" -"如果一个类型实现了`Copy'特性,把它传递给一个函数将不会把值的所有权转移给被调" +"如果一个类型实现了`Copy`Trait,把它传递给一个函数将不会把值的所有权转移给被调" "用的函数,而是传递一个值的副本。\n" -"你可以通过在你的类型定义中添加`#[derive(Copy)]`注解来实现`Copy`特性。然而,如" -"果一个类型本身或其任何组件没有实现Copy特性,Cairo将不允许该类型被注解为" +"你可以通过在你的类型定义中添加`#[derive(Copy)]`标注来实现`Copy` Trait。然而," +"如果一个类型本身或其任何组件没有实现Copy Trait,Cairo将不允许该类型被标注为" "Copy。\n" "虽然数组和字典不能被复制,但不包含它们的自定义类型可以被复制。" @@ -5330,9 +5316,9 @@ msgid "" "For example, the following code will not compile, because the struct `A` is " "not moved before it goes out of scope:" msgstr "" -"你可能已经注意到,前面例子中的`Point`类型也实现了`Drop`特性。在Cairo中,一个" -"值不能超出范围,除非它之前被移动过。\n" -"例如,下面的代码将无法编译,因为结构体`A`在超出范围之前没有被移动:" +"你可能已经注意到,前面例子中的`Point`类型也实现了`Drop` trait。在Cairo中,一" +"个值不能超出其作用域,除非它之前被移动过。\n" +"例如,下面的代码将无法编译,因为结构体`A`在超出作用域之前没有被移动:" #: src/ch03-01-what-is-ownership.md:147 msgid "" @@ -5371,10 +5357,10 @@ msgid "" msgstr "" "这是为了确保Cairo程序的健全性。健全性指的是,如果在程序执行过程中的一个语句是" "假的,任何作弊的验证者都不可能说服一个诚实的验证者相信它是真的。\n" -"在我们的案例中,我们要确保程序执行过程中连续的字典钥匙更新的一致性。\n" -"这只有在词典被`squashed'时才会进行检查--它将词典的所有权转移到了`squash`方" -"法,从而允许字典超出范围。未被压缩的字典是危险的,因为恶意的证明者可以证明不" -"一致的更新的正确性。" +"在我们的案例中,我们要确保程序执行过程中连续的字典key更新的一致性。\n" +"这只有在字典被压缩(`squashed`)时才会进行检查--它将字典的所有权转移到了" +"`squash`方法,从而允许字典超出范围。未被压缩的字典是危险的,因为恶意的证明者" +"可以证明不一致更新的正确性。" #: src/ch03-01-what-is-ownership.md:163 msgid "" @@ -5387,9 +5373,9 @@ msgid "" "meaning that it doesn't perform any actions other than allowing the value to " "go out of scope." msgstr "" -"然而,实现了`Drop`特性的类型被允许超出范围而不被明确移动。当一个实现了" -"`Drop'特性的类型的值超出范围时,`Drop'的实现会被调用,它将值移动到`drop'函数" -"中,允许它超出范围--这就是我们所说的 \"放弃 \"一个值。\n" +"然而,实现了`Drop` trait的类型被允许超出作用域而不被明确移动。当一个实现了" +"`Drop` trait的类型的值超出作用域时,`Drop`的实现会被调用,它将值移动到`drop`" +"函数中,允许它超出作用域--这就是我们所说的 \"丢弃 \"一个值。\n" "值得注意的是,drop的实现是一个 \"no-op\",也就是说,除了允许值离开作用域之" "外,它不执行任何其他操作。" @@ -5400,8 +5386,8 @@ msgid "" "types containing dictionaries.\n" "For example, the following code compiles:" msgstr "" -"`Drop`的实现可以为所有类型派生,允许它们在超出范围时被丢弃,除了字典" -"(`Felt252Dict`)和包含字典的类型。\n" +"除了字典(`Felt252Dict`)和包含字典的类型外,`Drop`的实现可以成为所有类型派" +"生,允许它们在超出作用域时被丢弃。\n" "例如,下面的代码可以编译:" #: src/ch03-01-what-is-ownership.md:169 @@ -5426,7 +5412,7 @@ msgstr "" #: src/ch03-01-what-is-ownership.md:178 msgid "### The `Destruct` Trait" -msgstr "### `Destruct`特性" +msgstr "### `Destruct` Trait" #: src/ch03-01-what-is-ownership.md:180 msgid "" @@ -5440,15 +5426,15 @@ msgid "" "`squash` method." msgstr "" "手动调用字典上的 `squash` 方法不是很方便,而且很容易忘记这样做。为了方便使用" -"字典,Cairo 提供了 `Destruct` 特质,它允许你指定一个类型超出范围时的行为。虽" -"然字典没有实现`Drop'特性,但它们确实实现了`Destruct'特性,这允许它们在超出范" -"围时自动被`squashed'。这意味着你可以使用字典而不需要手动调用`squash`方法。" +"字典,Cairo 提供了 `Destruct` trait,它允许你指定一个类型超出作用域时的行为。" +"虽然字典没有实现`Drop` trait,但它们实现了`Destruct`trait,这允许它们在超出作" +"用域时自动被`squashed`,因此你可以不需要手动调用`squash`方法。" #: src/ch03-01-what-is-ownership.md:182 msgid "" "Consider the following example, in which we define a custom type that " "contains a dictionary:" -msgstr "考虑下面的例子,在这个例子中,我们定义了一个包含字典的自定义类型:" +msgstr "下面的这个例子中,我们定义了一个包含字典的自定义类型:" #: src/ch03-01-what-is-ownership.md:184 msgid "" @@ -5511,9 +5497,9 @@ msgid "" "`Destruct` trait. To fix this, we can derive the `Destruct` trait " "implementation for the `A` type:" msgstr "" -"当A超出范围时,它不能被丢弃,因为它既没有实现`Drop`(因为它包含一个字典,不能" -"`derive(Drop)`)也没有实现`Destruct`特性。为了解决这个问题,我们可以为`A`类型" -"派生出`Destruct`特质的实现:" +"当A超出作用域时,它不能被丢弃,因为它既没有实现`Drop`(因为它包含一个字典,不" +"能派生`derive(Drop)`)也没有实现`Destruct` trait。为了解决这个问题,我们可以" +"为`A`类型派生出`Destruct` trait的实现:" #: src/ch03-01-what-is-ownership.md:209 msgid "" @@ -5551,11 +5537,12 @@ msgstr "" msgid "" "Now, when `A` goes out of scope, its dictionary will be automatically " "`squashed`, and the program will compile." -msgstr "现在,当`A`超出范围时,它的字典将被自动`squashed`,并且程序将被编译。" +msgstr "" +"现在,当`A`超出作用域时,它的字典将被自动`squashed`,并且程序将被编译。" #: src/ch03-01-what-is-ownership.md:226 msgid "### Copy Array data with Clone" -msgstr "###用克隆复制数组数据" +msgstr "### 用Clone复制数组数据" #: src/ch03-01-what-is-ownership.md:228 msgid "" @@ -5564,10 +5551,10 @@ msgid "" "methods are a common feature in many\n" "programming languages, you’ve probably seen them before." msgstr "" -"如果我们确实想深入复制一个 \"数组 \"的数据,我们可以使用一个叫做 \"克隆 \"的" -"普通方法。我们将在第5章中讨论方法的语法,但由于方法是许多编程语言中的一个共同" -"特征,你可能已经见过了。\n" -"但由于方法是许多编程语言的共同特征,你可能已经见过它们了。" +"如果我们确实想深入复制一个 \"数组 \"的数据,我们可以使用一个叫做 `clone`的通" +"用方法。\n" +"我们将在第5章中讨论方法的语法,但由于方法是许多编程语言的共同特征,你可能已经" +"见过它们了。" #: src/ch03-01-what-is-ownership.md:231 msgid "Here’s an example of the `clone` method in action." @@ -5579,8 +5566,8 @@ msgid "" "the corelib `clone` module, and its implementation for the array type from " "the `array` module." msgstr "" -"> 注意:在下面的例子中,我们需要从corelib的`clone`模块中导入`clone`特质,并从" -"`array`模块中导入其对数组类型的实现。" +"> 注意:在下面的例子中,我们需要从corelib的`clone`模块中导入`clone`trait,并" +"从`array`模块中导入其对数组类型的实现。" #: src/ch03-01-what-is-ownership.md:235 msgid "" @@ -5594,13 +5581,13 @@ msgid "" "\n" "```" msgstr "" -"``rust\n" -"use array::ArrayTrait;\n" -"use clone::Clone;\n" -"use array::ArrayTCloneImpl;\n" +"```rust\n" +"use array::ArrayTrait;\n" +"use clone::Clone;\n" +"use array::ArrayTCloneImpl;\n" "...\n" -"let arr1 = ArrayTrait::::new();\n" -"let arr2 = arr1.clone();\n" +"let arr1 = ArrayTrait::::new();\n" +"let arr2 = arr1.clone();\n" "\n" "```" @@ -5610,8 +5597,8 @@ msgid "" "option to run this example, because it uses a loop and must be ran with a " "gas limit." msgstr "" -"> 注意:你需要用`--可用气体=2000000`选项运行`cairo-run`来运行这个例子,因为它" -"使用了一个循环,必须用气体限制来运行。" +"> 注意:你需要用`--available-gas=2000000`选项运行`cairo-run`来运行这个例子," +"因为它使用了一个循环,运行时必须有gas限制。" #: src/ch03-01-what-is-ownership.md:247 msgid "" @@ -5620,13 +5607,13 @@ msgid "" "something\n" "different is going on." msgstr "" -"当你看到对`clone'的调用时,你知道一些任意的代码正在被执行。\n" -"执行,而这些代码可能是昂贵的。这是一个视觉指标,表明有一些\n" -"不同的事情正在发生。" +"当你看到对`clone`的调用时,你知道一些特定的代码被执行而且这些代码可能相当消耗" +"资源。\n" +"你很容易察觉到一些不寻常的事情正在发生。" #: src/ch03-01-what-is-ownership.md:251 msgid "### Ownership and Functions" -msgstr "###所有权与函数" +msgstr "### 所有权与函数" #: src/ch03-01-what-is-ownership.md:253 msgid "" @@ -5635,15 +5622,14 @@ msgid "" "ownership; let's see what happens with other types." msgstr "" "将一个变量传递给一个函数,要么移动它,要么复制它。正如在数组部分所看到的,将 " -"`Array` 作为一个函数参数传递给它的所有权;让我们看看其他类型会发生什么。" +"`Array` 作为一个函数参数传递同时会传递它的所有权;让我们看看其他类型会发生什" +"么。" #: src/ch03-01-what-is-ownership.md:255 msgid "" "Listing 3-3 has an example with some annotations\n" "showing where variables go into and out of scope." -msgstr "" -"清单3-3有一个带有一些注释的例子\n" -"显示了变量进入和离开范围的位置。" +msgstr "清单3-3使用注释展示变量何时进入和离开作用域。" #: src/ch03-01-what-is-ownership.md:258 src/ch03-01-what-is-ownership.md:300 #: src/ch03-01-what-is-ownership.md:353 @@ -5714,9 +5700,7 @@ msgstr "" msgid "" "Listing 3-3: Functions with ownership and scope\n" "annotated" -msgstr "" -"清单3-3:具有所有权与作用域的函数\n" -"有注释的" +msgstr "清单3-3:带有所有权和作用域注释的函数" #: src/ch03-01-what-is-ownership.md:289 msgid "" @@ -5728,10 +5712,11 @@ msgid "" "and where\n" "the ownership rules prevent you from doing so." msgstr "" -"如果我们试图在调用`takes_ownership'之后使用`my_struct',Cairo会抛出一个\n" -"编译时错误。这些静态检查可以保护我们不犯错误。试着在`main`中加入\n" -"在`main`中添加使用`my_struct`和`x`的代码,看看哪里可以使用它们,哪里\n" -"所有权规则将会阻止你这样做。" +"如果我们试图在调用`takes_ownership`之后使用`my_struct`,Cairo会抛出一个编译时" +"错误。\n" +"这些静态检查可以保护我们不犯错误。试着在`main`中添加使用`my_struct`和`x`的代" +"码,看看哪里可以使用它们,\n" +"哪里所有权规则将会阻止你这样做。" #: src/ch03-01-what-is-ownership.md:294 msgid "### Return Values and Scope" @@ -5857,15 +5842,14 @@ msgid "" "from the body of the function that we might want to return as well." msgstr "" "虽然这样是可以的,但是在每一个函数中都获取所有权并接着返回所有权有些啰嗦。\n" -"如果我们想要函数使用一个值但不获取所有权该怎么办呢?如果我们还要接着使\n" -"用它的话,每次都传进去再返回来就有点烦人了,除此之外,我们也可能想返回\n" -"函数体中产生的一些数据。" +"如果我们想要函数使用一个值但不获取所有权该怎么办呢?\n" +"除此之外,我们也可能想返回函数体中产生的一些数据。" #: src/ch03-01-what-is-ownership.md:351 msgid "" "Cairo does let us return multiple values using a tuple, as shown in Listing " "3-5." -msgstr "Cairo确实让我们可以使用一个元组返回多个值,如示例3-5所示。" +msgstr "Cairo的确让我们可以使用一个元组返回多个值,如示例3-5所示。" #: src/ch03-01-what-is-ownership.md:355 msgid "" @@ -5911,13 +5895,13 @@ msgid "" "common. Luckily for us, Cairo has two features for using a value without\n" "transferring ownership, called _references_ and _snapshots_." msgstr "" -"但是,对于一个应该是很普遍的概念来说,这样的仪式和工作太多。\n" -"寻常。幸运的是,Cairo有两个功能可以在不转移所有权的情况下使用一个值。\n" -"转移所有权,称为_references_和_snapshots_。" +"但是这未免有些形式主义,而且这种场景应该很常见。\n" +"幸运的是,Cairo提供了两个功能可以在不转移所有权的情况下使用一个值,\n" +"称为 引用( _references_ )和 快照( _snapshots_ )。" #: src/ch03-02-references-and-snapshots.md:1 msgid "## References and Snapshots" -msgstr "## 参考资料和快照" +msgstr "## 引用和快照" #: src/ch03-02-references-and-snapshots.md:3 msgid "" @@ -5926,15 +5910,14 @@ msgid "" "call to `calculate_length`, because the `Array` was moved into\n" "`calculate_length`." msgstr "" -"清单3-5中元组代码的问题是,我们必须返回\n" -"`Array`返回给调用的函数,这样我们在调用`calculate_length`后仍然可以使用" -"`Array`。\n" -"因为 \"Array \"被移到了`calculate_length`中.\n" -"`calculate_length`中。" +"清单3-5中元组代码的问题是,因为 `Array`的所有权被移到了`calculate_length`" +"中。\n" +"我们必须返回`Array`给调用的函数,这样我们在调用`calculate_length`后才仍然可以" +"使用`Array`。" #: src/ch03-02-references-and-snapshots.md:8 msgid "### Snapshots" -msgstr "###快照" +msgstr "### 快照(Snapshots)" #: src/ch03-02-references-and-snapshots.md:10 msgid "" @@ -5950,10 +5933,10 @@ msgid "" "we can retain ownership\n" "of the value in the calling function using snapshots." msgstr "" -"相反,我们可以提供一个`Array`值的_快照_。在Cairo,一个快照是一个在某个时\n" -"间点上的不可改变的值的视图。在上一章中,我们谈到了Cairo的所有权系统是\n" -"如何防止我们在移动一个值后使用它,从而防止我们在向数组添加值时不会潜在\n" -"地多次写入相同的内存单元。\n" +"不过,我们可以提供一个`Array`值的 _snapshot_ 。在Cairo,一个快照是一个在某个" +"时间点上的不可改变的值的视图。\n" +"在上一章中,我们谈到了Cairo的所有权系统是如何防止我们在移动一个值后使用它,从" +"而防止我们在向数组添加值时不会潜在地多次写入相同的内存单元。\n" "然而,这不是很方便。让我们看看如何使用快照在调用函数中保留值的所有权。" #: src/ch03-02-references-and-snapshots.md:17 @@ -5969,8 +5952,8 @@ msgid "" "the `calculate_length` function will not mutate the array, and ownership of " "the array is kept in the main function." msgstr "" -"下面是你如何定义和使用一个`计算长度`函数,它以一个快照作为参数,而不是获取底" -"层值的所有权。在这个例子中、\n" +"下面是你如何定义和使用一个`calculate_length` 函数,它以一个快照作为参数,而不" +"是获取底层值的所有权。在这个例子中、\n" "`calculate_length`函数返回作为参数的数组的长度。\n" "因为我们是以快照的形式传递的,这是一个不可改变的数组视图,我们可以确定\n" "`calculate_length`函数不会改变数组,数组的所有权被保留在主函数中。" @@ -6029,9 +6012,9 @@ msgid "" "compilation error. However, you can call methods expecting a snapshot on non-" "snapshot types." msgstr "" -"> 注意:只有在数组快照上才能调用 `len()` 方法,因为它在 `ArrayTrait` 特质中被" -"定义成这样。如果你试图在一个快照上调用一个没有为快照定义的方法,你会得到一个" -"编译错误。然而,你可以在非快照类型上调用期望有快照的方法。" +"> 注意:只有在数组快照上才能调用 `len()` 方法,因为它在 `ArrayTrait` trait中" +"被定义成这样。如果你试图在一个快照上调用一个没有为快照定义的方法,你会得到一" +"个编译错误。然而,你可以在非快照类型上调用快照的方法。" #: src/ch03-02-references-and-snapshots.md:46 msgid "The output of this program is:" @@ -6062,9 +6045,9 @@ msgid "" "that we pass `@arr1` into `calculate_length` and, in its definition, we take " "`@Array` rather than `Array`." msgstr "" -"首先,注意到变量声明和函数返回值中的所有元组代码都消失了。第二,注意\n" -"我们把`@arr1`传入`calculate_length`,在它的定义中,我们采用`@Array`,而" -"不是`Array`。" +"首先,注意到变量声明和函数返回值中的所有元组代码都消失了。\n" +"第二,注意看我们把`@arr1`传入`calculate_length`,因此在它的定义中,我们采用" +"`@Array`,而不是`Array`。" #: src/ch03-02-references-and-snapshots.md:59 msgid "Let’s take a closer look at the function call here:" @@ -6078,9 +6061,10 @@ msgid "" "of the array\n" "```" msgstr "" -"``rust\n" -"let mut arr1 = ArrayTrait::::new();\n" -"let second_length = calculate_length(@arr1); // 计算数组的当前长度\n" +"```rust\n" +"let mut arr1 = ArrayTrait::::new();\n" +"let second_length = calculate_length(@arr1); // Calculate the current length " +"of the array\n" "```" #: src/ch03-02-references-and-snapshots.md:66 @@ -6090,9 +6074,9 @@ msgid "" "modified through the snapshot, and the value it refers to will not be " "dropped once the snapshot stops being used." msgstr "" -"`@arr1`语法让我们为`arr1`中的值创建一个快照。因为快照是一个值的不可改变的视" -"图,它所指向的值不能通过快照被修改,而且一旦快照停止使用,它所指向的值也不会" -"被丢弃。" +"`@arr1`语法让我们为`arr1`中的值创建了一个快照。因为快照是一个值的不可改变的视" +"图,它所指向的值不能通过快照被修改,因此即使快照停止被使用,它所指向的值也不" +"会被丢弃。" #: src/ch03-02-references-and-snapshots.md:68 msgid "" @@ -6113,11 +6097,11 @@ msgid "" "contains, the original `arr` can still be used.\n" "```" msgstr "" -"``rust\n" +"```rust\n" "fn calculate_length(array_snapshot: @Array) -> usize { // " "array_snapshot是一个数组的快照。\n" " array_snapshot.len()\n" -"}// 这里,array_snapshot超出了范围,被丢弃了。\n" +"}// 这里,array_snapshot超出了范围被丢弃。\n" "// 但是,因为它只是原始数组`arr`所包含的视图,原始`arr`仍然可以被使用。\n" "```" @@ -6300,7 +6284,7 @@ msgstr "编译器阻止我们修改与快照相关的值。" #: src/ch03-02-references-and-snapshots.md:145 msgid "### Mutable References" -msgstr "### 可变的参考资料" +msgstr "### 可变引用" #: src/ch03-02-references-and-snapshots.md:147 msgid "" @@ -6313,11 +6297,11 @@ msgid "" "In Cairo, a parameter can be passed as _mutable reference_ using the `ref` " "modifier." msgstr "" -"在清单3-6中,我们可以通过使用_mutable reference_而不是快照来实现我们想要的行" -"为。可变引用实际上是传递给函数的可变值,在函数结束时被隐式返回,将所有权返回" -"给调用的上下文。通过这样做,它们允许你对传递的值进行改变,同时通过在执行结束" -"时自动返回来保持对它的所有权。\n" -"在Cairo中,一个参数可以使用`ref`修饰符作为_mutable reference_传递。" +"在清单3-6中,我们也可以通过使用 _mutable reference_ 而不是快照来实现我们想要" +"的行为。可变引用实际上是传递给函数的可变值,在函数结束时被隐式返回,将所有权" +"返回给调用的上下文。通过这样做,它们允许你对传递的值进行改变,同时通过在执行" +"结束时自动返回来保持对它的所有权。\n" +"在Cairo中,一个参数可以使用`ref`修饰符作为 _mutable reference_ 传递。" #: src/ch03-02-references-and-snapshots.md:150 msgid "" @@ -6429,7 +6413,7 @@ msgstr "正如预期的那样, `rec` 变量的 `height` 和 `width` 字段被 #: src/ch03-02-references-and-snapshots.md:191 msgid "### Small recap" -msgstr "###小结" +msgstr "### 小结" #: src/ch03-02-references-and-snapshots.md:193 msgid "" @@ -6469,10 +6453,10 @@ msgid "" "to build on what you already know and demonstrate when structs are a better " "way to group data." msgstr "" -"_struct_,或称_structure_,是一种自定义的数据类型,允许你包装和命名多个相关的" -"值,从而形成一个有意义的组合。如果你熟悉一门面向对象语言,struct 就像对象中的" -"数据属性。在本章中,我们会对元组和结构体进行比较和对比。在你已经知道的基础" -"上,以证明结构是一种更好的数据分组方式。" +"结构体( _struct_ ),或称 _structure_ ,是一种自定义的数据类型,允许你包装和" +"命名多个相关的值,从而形成一个有意义的组合。如果你熟悉一门面向对象语言," +"struct 就像对象中的数据属性。在本章中,我们会对元组和结构体进行比较和对比,并" +"演示什么时候结构体是一种更好的数据分组方式。" #: src/ch04-00-using-structs-to-structure-related-data.md:5 msgid "" @@ -6483,9 +6467,9 @@ msgid "" "creating new types in your program’s domain to take full advantage of " "Cairo's compile-time type checking." msgstr "" -"我们还将演示如何定义和实例化结构体,并讨论如何定义关联函数,特别是被称为 方" -"法 的那种关联函数,以指定与结构体类型相关的行为。你可以在程序中基于结构体和枚" -"举(enum)(将在下一章讨论)创建新类型,以充分利用 Cairo 的编译时类型检查。" +"我们还将演示如何定义和实例化结构体,并讨论如何定义关联函数,特别是被称为 _方" +"法_ 的关联函数,以指定与结构体类型相关的行为。你可以在程序中基于结构体和枚举" +"(enum)(将在下一章讨论)创建新类型,以充分利用 Cairo 的编译时类型检查。" #: src/ch04-01-defining-and-instantiating-structs.md:1 msgid "# Defining and Instantiating Structs" @@ -6501,10 +6485,10 @@ msgid "" "don’t have to rely on the order of the data to specify or access the values " "of an instance." msgstr "" -"结构与[数据类型](ch02-02-data-types.md)一节中讨论的元组类似,它们都包含多个相" -"关的值。和元组一样,结构体的每一部分可以是不同类型。但不同于元组,结构体需要" -"命名各部分数据以便能清楚的表明其值的意义。由于有了这些名字,结构体比元组更灵" -"活:不需要依赖顺序来指定或访问实例中的值。" +"结构体与[数据类型](ch02-02-data-types.md)一节中讨论的元组类似,它们都包含多个" +"相关的值。和元组一样,结构体的每一部分可以是不同类型。但不同于元组,结构体需" +"要命名各部分数据以便能清楚的表明其值的意义。由于有了这些名字,结构体比元组更" +"灵活:不需要依赖顺序来指定或访问实例中的值。" #: src/ch04-01-defining-and-instantiating-structs.md:5 msgid "" @@ -6619,7 +6603,7 @@ msgstr "" msgid "" "Listing 4-2: Creating an instance of the `User` " "struct" -msgstr "示例4-2:创建一个`用户`结构的实例" +msgstr "示例4-2:创建一个`User`结构的实例" #: src/ch04-01-defining-and-instantiating-structs.md:48 msgid "" @@ -6664,7 +6648,7 @@ msgid "" "Listing 4-3: Changing the value in the email field " "of a `User` instance" msgstr "" -"示例4-3:改变`用户`实例的电子邮件字段中的值" +"示例4-3:改变`User`实例的电子邮件字段中的值" #: src/ch04-01-defining-and-instantiating-structs.md:66 msgid "" @@ -6735,7 +6719,7 @@ msgstr "" #: src/ch04-01-defining-and-instantiating-structs.md:89 msgid "## Using the Field Init Shorthand" -msgstr "##使用字段初始化简写语法" +msgstr "## 使用字段初始化简写语法" #: src/ch04-01-defining-and-instantiating-structs.md:91 msgid "" @@ -6813,9 +6797,9 @@ msgid "" "of the rectangle. Listing 4-6 shows a short program with one way of doing " "exactly that in our project’s _src/lib.cairo_." msgstr "" -"让我们用Scarb做一个名为_rectangles_的新项目,它获取以像素为单位的长方形的宽度" -"和高度,并计算出长方形的面积。清单4-6显示了位于项目中的_src/lib.cairo_中的小" -"程序,它刚刚好实现此功能。" +"让我们用Scarb做一个名为 _rectangles_ 的新项目,它获取以像素为单位的长方形的宽" +"度和高度,并计算出长方形的面积。清单4-6显示了位于项目中的 _src/lib.cairo_ 中" +"的小程序,它刚刚好实现此功能。" #: src/ch04-02-an-example-program-using-structs.md:9 msgid "" @@ -6894,7 +6878,7 @@ msgid "" "fn area(width: u64, height: u64) -> u64 {\n" "```" msgstr "" -"``rust\n" +"```rust\n" "fn area(width: u64, height: u64) -> u64 {\n" "```" @@ -7065,7 +7049,7 @@ msgstr "" #: src/ch04-02-an-example-program-using-structs.md:102 msgid "## Adding Useful Functionality with Trait" -msgstr "##用Trait增加实用功能" +msgstr "## 用Trait增加实用功能" #: src/ch04-02-an-example-program-using-structs.md:104 msgid "" @@ -7155,8 +7139,8 @@ msgid "" "To learn more about traits, see [Traits in Cairo](ch07-02-traits-in-cairo." "md)." msgstr "" -"许多数据类型都实现了 `print` 特性,但 `Rectangle` 结构没有。我们可以通过在" -"`Rectangle`上实现`PrintTrait`trait来解决这个问题,如示例4-10所示。\n" +"许多数据类型都实现了 `print` trait,但 `Rectangle` 结构没有。我们可以通过在" +"`Rectangle`上实现`PrintTrait` trait来解决这个问题,如示例4-10所示。\n" "要了解更多关于traits的信息,请参阅[Traits in Cairo](ch07-02-traits-in-cairo." "md)。" @@ -7215,7 +7199,8 @@ msgid "" "Listing 4-10: Implementing the `PrintTrait` trait on " "`Rectangle`" msgstr "" -"示例4-10:在`Rectangle`上实现`PrintTrait`属性" +"示例4-10:在`Rectangle`上实现`PrintTrait` trait" #: src/ch04-02-an-example-program-using-structs.md:170 msgid "" @@ -7227,7 +7212,7 @@ msgstr "" #: src/ch04-03-method-syntax.md:1 msgid "## Method Syntax" -msgstr "##方法语法" +msgstr "## 方法语法(Method Syntax)" #: src/ch04-03-method-syntax.md:3 msgid "" @@ -7251,8 +7236,9 @@ msgstr "" "回值,同时包含在某处调用该方法时会执行的代码。不过方法与函数是不同的,因为它" "们在结构体的上下文中被定义,并且它们第一个参数总是 `self`,它代表调用该方法的" "结构体实例。\n" -"对于那些熟悉Rust的人来说,Cairo的方法可能会令人困惑,因为方法不能被直接定\n" -"义在类型上。相反,你必须定义一个trait和一个与该方法所在类型相关的实现。" +"对于那些熟悉Rust的人来说,Cairo的方法可能会令人困惑,因为方法不能被直接定义在" +"类型上。\n" +"相反,你必须定义一个trait和一个与该方法所在类型相关的实现。" #: src/ch04-03-method-syntax.md:12 msgid "### Defining Methods" @@ -7374,7 +7360,7 @@ msgstr "" "本例中是唯一的)参数改为`self`。在`main`中,我们调用`area`函数并传递`rect1`作" "为参数、\n" "\n" -"我们可以使用_method syntax_在我们的`Rectangle`实例上调用`area`方法。\n" +"我们可以使用 _method syntax_ 在我们的`Rectangle`实例上调用`area`方法。\n" "方法语法获取一个实例并加上一个点号,后跟方法名、圆括号以及任何参数。" #: src/ch04-03-method-syntax.md:64 @@ -7427,7 +7413,7 @@ msgid "" "field values are of type `@T`,\n" "requiring them to be desnapped in order to manipulate them." msgstr "" -"在访问结构体的成员时,请注意在区域方法中使用desnap操作符`*`。\n" +"在访问结构体的成员时,请注意在区域方法中使用 _desnap_ 操作符`*`。\n" "这是必要的,因为该结构是以快照形式传递的,其所有字段值都是`@T`类型、\n" "需要对它们进行解快照,以便对其进行操作。" @@ -7445,11 +7431,11 @@ msgid "" "another block." msgstr "" "使用方法而不是函数的主要原因是为了组织和代码的清晰性。我们把所有我们能对一个" -"类型的实例做的操作都放在一组`trait'和`impl'块的组合中,而不是让未来的用户在我" -"们提供的库中的不同地方搜索 `Rectangle`的功能。\n" -"然而,我们可以在不同的地方为同一类型定义多个`trait'和`impl'块的组合,这对更细" -"化的代码组织很有用。例如,你可以在一个`impl`块中为你的类型实现 `impl`trait ," -"在另一个块中实现 `Sub`trait 。" +"类型的实例做的操作都放在一组`trait`和`impl`块的组合中,而不是让未来的用户在我" +"们提供的库中的不同地方搜索 `Rectangle`的函数。\n" +"然而,我们可以在不同的地方为同一类型定义多个`trait`和`impl`块的组合,这对更细" +"化的代码组织很有用。例如,你可以在一个`impl`块中为你的类型实现 `impl` " +"trait ,在另一个块中实现 `Sub` trait 。" #: src/ch04-03-method-syntax.md:89 msgid "" @@ -7533,7 +7519,7 @@ msgstr "" #: src/ch04-03-method-syntax.md:126 msgid "### Methods with More Parameters" -msgstr "###带有更多参数的方法" +msgstr "### 带有更多参数的方法" #: src/ch04-03-method-syntax.md:128 msgid "" @@ -7601,8 +7587,7 @@ msgstr "" msgid "" "Listing 5-14: Using the as-yet-unwritten `can_hold`\n" "method" -msgstr "" -"列表5-14:使用尚未编写的 \"can_hold\"方法" +msgstr "列表5-14:使用尚未编写的`can_hold`方法" #: src/ch04-03-method-syntax.md:161 msgid "" @@ -7737,7 +7722,7 @@ msgstr "" #: src/ch04-03-method-syntax.md:219 msgid "### Accessing implementation functions" -msgstr "###访问执行功能" +msgstr "### 访问实现里的函数" #: src/ch04-03-method-syntax.md:221 msgid "" @@ -7757,7 +7742,7 @@ msgid "" "same\n" "value twice:" msgstr "" -"所有在`trait`和`impl` 块中定义的功能可以直接使用`::` 运算符在实现名称上进行访" +"所有在`trait`和`impl` 块中定义的函数可以直接使用`::` 运算符在实现名称上进行访" "问。\n" "在`trait`中的不是方法的函数通常用于构造函数,以返回一个结构体的新实例。\n" "这些函数通常被称为`new`,但`new`不是一个特殊的名称,也不是内置到语言中的。\n" @@ -7814,7 +7799,7 @@ msgstr "" #: src/ch04-03-method-syntax.md:252 msgid "### Multiple `impl` Blocks" -msgstr "###多个`impl`块" +msgstr "### 多个`impl`块" #: src/ch04-03-method-syntax.md:254 msgid "" @@ -7890,7 +7875,7 @@ msgid "" msgstr "" "这里没有理由把这些方法分成多个`trait`和`impl`块,\n" "但这是有效的语法。我们将在[第7章](ch07-00-generic-types-and-traits.md)中看\n" -"到一个多块的情况,在那里我们讨论泛型和traits。" +"到一个多块的情况,在那里我们讨论泛型和trait。" #: src/ch04-03-method-syntax.md:288 msgid "" @@ -7914,8 +7899,8 @@ msgid "" "But structs aren’t the only way you can create custom types: let’s turn to\n" "Cairo’s enum feature to add another tool to your toolbox." msgstr "" -"但结构体并不是创建自定义类型的唯一方法:让我们转向 Cairo 的枚举功能,为你的\n" -"工具箱再添一个工具。" +"但结构体并不是创建自定义类型的唯一方法:让我们转向 Cairo 的枚举功能,为你的工" +"具箱再添一个工具。" #: src/ch05-00-enums-and-pattern-matching.md:1 msgid "# Enums and Pattern Matching" @@ -7933,12 +7918,12 @@ msgid "" "distinct and has a specific meaning." msgstr "" "本章介绍 \"枚举\"(enumerations),也被称作 enums,是一种自定义数据类型的方" -"式,它由一组固定的命名值组成,称为_variants_。枚举对于表示相关值的集合非常有" -"用,其中每个值都是不同的,并且有特定的含义。" +"式,它由一组固定的命名值成员组成,称为 _variants_ 。枚举对于表示相关值的集合" +"非常有用,其中每个值都是不同的,并且有特定的含义。" #: src/ch05-01-enums.md:5 msgid "## Enum Variants and Values" -msgstr "## 枚举变量和值" +msgstr "## 枚举成员和值" #: src/ch05-01-enums.md:7 msgid "Here's a simple example of an enum:" @@ -7977,10 +7962,10 @@ msgid "" "type and is associated with a unit type `()`. One variant can be " "instantiated using this syntax:" msgstr "" -"与Rust等其他语言不同,每个变体都有一个类型。在这个例子中,我们定义了一个叫做 " +"与Rust等其他语言不同,每个成员都有一个类型。在这个例子中,我们定义了一个叫做 " "`Direction`的枚举,有四个变量:`North`, `East`, `South`, 和 `West`。命名惯例" -"是使用PascalCase来表示枚举变量。每个变量代表方向类型的一个不同的值,并与一个" -"unit类型`()`相关。一个变量可以使用这种语法进行实例化:" +"是使用PascalCase来表示枚举成员。每个成员代表方向类型的一个不同的值,并与一个" +"unit类型`()`相关。一个成员可以使用这种语法进行实例化:" #: src/ch05-01-enums.md:22 msgid "" @@ -7988,8 +7973,8 @@ msgid "" "let direction = Direction::North(());\n" "```" msgstr "" -"````rs\n" -"let direction = Direction::North(());\n" +"```rs\n" +"let direction = Direction::North(());\n" "```" #: src/ch05-01-enums.md:26 @@ -7999,9 +7984,9 @@ msgid "" "Direction. You can learn more about it on the [The Match Control Flow " "Construct page](ch05-02-the-match-control-flow-construct.md)." msgstr "" -"写代码很容易根据枚举实例的变量而采取不同的行动,在这个例子中,根据一个方向来" -"运行特定的代码。你可以在 [match 控制流结构](ch05-02-the-match-control-flow-" -"construct.md)页面上了解更多信息。" +"我们可以很轻易的写出根据枚举的成员运行不同的代码,在上面这个例子中,是根据方" +"向来运行特定的代码。你可以在 [match 控制流结构](ch05-02-the-match-control-" +"flow-construct.md)页面上了解更多信息。" #: src/ch05-01-enums.md:28 msgid "## Enums Combined with Custom Types" @@ -8011,7 +7996,7 @@ msgstr "## 枚举与自定义类型相结合" msgid "" "Enums can also be used to store more interesting data associated with each " "variant. For example:" -msgstr "枚举也可以用来存储与每个变体相关的更有趣的数据。比如说:" +msgstr "枚举也可以用来存储与每个成员相关的更有趣的数据。比如说:" #: src/ch05-01-enums.md:32 msgid "" @@ -8027,9 +8012,9 @@ msgstr "" "```rs\n" "#[derive(Drop)]\n" "enum Message {\n" -" Quit : ()、\n" -" Echo : felt252、\n" -" Move : (u128, u128)、\n" +" Quit : (),\n" +" Echo : felt252,\n" +" Move : (u128, u128),\n" "}\n" "```" @@ -8038,7 +8023,7 @@ msgid "" "In this example, the `Message` enum has three variants: `Quit`, `Echo` and " "`Move`, all with different types:" msgstr "" -"在这个例子中,`Message'枚举有三个变体:`Quit'、`Echo'和`Move',都有不同的类" +"在这个例子中,`Message'枚举有三个成员:`Quit'、`Echo'和`Move',都有不同的类" "型:" #: src/ch05-01-enums.md:43 @@ -8055,7 +8040,7 @@ msgstr "" msgid "" "You could even use a Struct or another Enum you defined inside one of your " "Enum variants." -msgstr "你甚至可以在你的一个枚举变量中使用一个结构体或另一个你定义的枚举。" +msgstr "你甚至可以在你的一个枚举成员中使用一个结构体或另一个你定义的枚举。" #: src/ch05-01-enums.md:49 msgid "## Trait Implementations for Enums" @@ -8068,7 +8053,7 @@ msgid "" "Here's an example of defining a trait and implementing it for the previous " "`Message` enum:" msgstr "" -"在Cairo中,你可以为你的自定义枚举定义traits并实现它们。这允许你定义与枚举相关" +"在Cairo中,你可以为你的自定义枚举定义trait并实现它们。这允许你定义与枚举相关" "的方法和行为。下面是一个定义trait并为之前的 `Message` 枚举实现的例子:" #: src/ch05-01-enums.md:53 @@ -8095,22 +8080,22 @@ msgid "" "}\n" "```" msgstr "" -"````rs\n" +"```rs\n" "trait Processing {\n" -" fn process(self: Message);\n" +" fn process(self: Message);\n" "}\n" "\n" "impl ProcessingImpl of Processing {\n" " fn process(self: Message) {\n" " match self {\n" " Message::Quit(()) => {\n" -" 'quitting'.print();\n" +" 'quitting'.print();\n" " },\n" " Message::Echo(value) => {\n" -" value.print();\n" +" value.print();\n" " },\n" " Message::Move((x, y)) => {\n" -" 'moving'.print();\n" +" 'moving'.print();\n" " },\n" " }\n" " }\n" @@ -8143,7 +8128,7 @@ msgstr "运行这段代码会打印出 `quitting`。" #: src/ch05-01-enums.md:84 msgid "## The Option Enum and Its Advantages" -msgstr "## 选项枚举及其优势" +msgstr "## Option枚举及其优势" #: src/ch05-01-enums.md:86 msgid "" @@ -8152,8 +8137,8 @@ msgid "" "indicates that there's a value of type `T`, while `None` represents the " "absence of a value." msgstr "" -"Option枚举是一个标准的Cairo枚举,表示一个可选值的概念。它有两个变量:`Some:" -"T \"和 \"None: ()\"。`Some:T`表示有一个`T`类型的值,而`None`表示没有一个值。" +"Option枚举是一个标准的Cairo枚举,表示一个可选值的概念。它有两个变量:`Some: " +"T` 和 `None: ()`。`Some:T`表示有一个`T`类型的值,而`None`表示没有值。" #: src/ch05-01-enums.md:88 msgid "" @@ -8178,8 +8163,8 @@ msgid "" "and easier to reason about. Using `Option` can also help prevent bugs caused " "by using uninitialized or unexpected `null` values." msgstr "" -"`Option` 枚举很有帮助,因为它允许你明确地表示一个值不存在的可能性,使你的代码" -"更具表现力,更容易推理。使用 `Option` 也可以帮助防止因使用未初始化的或意外的 " +"`Option` 枚举很有用,因为它允许你明确地表示一个值不存在的可能性,使你的代码更" +"具表现力,更容易推理。使用 `Option` 也可以帮助防止因使用未初始化的或意外的 " "`null` 值而引起的错误。" #: src/ch05-01-enums.md:97 @@ -8200,8 +8185,8 @@ msgid "" "- Recursive Approach `find_value_recursive`\n" "- Iterative Approach `find_value_iterative`" msgstr "" -"- 递归法 `find_value_recursive`。\n" -"- 迭代法 `find_value_iterative`。" +"- 递归法 `find_value_recursive`\n" +"- 迭代法 `find_value_iterative`" #: src/ch05-01-enums.md:104 msgid "" @@ -8387,7 +8372,9 @@ msgstr "# match控制流结构" msgid "" "" -msgstr "<!-- TODO:更新以下段落中提到的第18章(关于模式和模式匹配章节)-->" +msgstr "" +"" #: src/ch05-02-the-match-control-flow-construct.md:5 msgid "" @@ -8398,10 +8385,10 @@ msgid "" "comes from the expressiveness of the patterns and the fact that the compiler " "confirms that all possible cases are handled." msgstr "" -"Cairo 有一个非常强大的控制流结构,叫做 `match`,它允许你将一个值与一系列的模" -"式进行比较,然后根据模式的匹配情况执行代码。模式可以由字面值、变量名、通配符" -"和许多其他东西组成。match 的力量来自于模式的表达性,以及编译器确认所有可能的" -"情况都得到了处理的事实。" +"Cairo 有一个叫做 `match` 的极为强大的控制流运算符,它允许我们将一个值与一系列" +"的模式相比较,并根据相匹配的模式执行相应代码。模式可由字面值、变量、通配符和" +"许多其他内容构成;第十八章会涉及到所有不同种类的模式以及它们的作用。`match` " +"的力量来源于模式的表现力以及编译器检查,它确保了所有可能的情况都得到处理。" #: src/ch05-02-the-match-control-flow-construct.md:7 msgid "" @@ -8412,9 +8399,9 @@ msgid "" "value “fits”, the value falls into the associated code block to be used " "during execution." msgstr "" -"可以把 match 表达式想象成一台硬币分类机:硬币沿着有各种大小的孔的轨道滑下,每" -"枚硬币都从它遇到的第一个适合它的孔中落下。以同样的方式,值穿过 match 中的每个" -"模式,在值 “fits” 的第一个模式中,值落入相关的代码块,在执行中使用。" +"可以把 `match` 表达式想象成某种硬币分类器:硬币滑入有着不同大小孔洞的轨道,每" +"一个硬币都会掉入符合它大小的孔洞。同样地,值也会通过 `match` 的每一个模式,并" +"且在遇到第一个 “符合” 的模式时,值会进入相关联的代码块并在执行中被使用。" #: src/ch05-02-the-match-control-flow-construct.md:9 msgid "" @@ -8423,9 +8410,9 @@ msgid "" "machine, determines which coin it is and returns its value in cents, as " "shown in Listing 5-3." msgstr "" -"说到硬币,让我们用它们作为一个例子,使用 match 我们可以写一个函数,接收一个未" -"知的美国硬币,并以类似于点钞机的方式,确定它是哪种硬币,并返回其价值(美" -"分),如清单5-3所示。" +"因为刚刚提到了硬币,让我们用它们来作为一个使用 `match` 的例子!我们可以编写一" +"个函数来获取一个未知的硬币,并以一种类似验钞机的方式,确定它是何种硬币,并返" +"回其价值(美分),如清单5-3所示。" #: src/ch05-02-the-match-control-flow-construct.md:11 msgid "" @@ -8447,29 +8434,29 @@ msgid "" "}\n" "```" msgstr "" -"``rust\n" +"```rust\n" "enum Coin {\n" -" Penny: ()、\n" -" Nickel: ()、\n" -" Dime: ()、\n" -" Quarter: ()、\n" +" Penny: (),\n" +" Nickel: (),\n" +" Dime: (),\n" +" Quarter: (),\n" "}\n" "\n" "fn value_in_cents(coin: Coin) -> felt252 {\n" " match coin {\n" -" Coin::Penny(_) => 1、\n" -" Coin::Nickel(_) => 5、\n" -" Coin::Dime(_) => 10、\n" -" Coin::Quarter(_) => 25、\n" +" Coin::Penny(_) => 1,\n" +" Coin::Nickel(_) => 5,\n" +" Coin::Dime(_) => 10,\n" +" Coin::Quarter(_) => 25,\n" " }\n" -"\n" +"}\n" "```" #: src/ch05-02-the-match-control-flow-construct.md:29 msgid "" "Listing 5-3: An enum and a match expression that has the variants of the " "enum as its patterns" -msgstr "清单5-3:一个枚举和一个将枚举的变量作为其模式的 match 表达式" +msgstr "清单5-3:一个枚举和一个将枚举成员作为其模式的 match 表达式" #: src/ch05-02-the-match-control-flow-construct.md:31 msgid "" @@ -8480,10 +8467,10 @@ msgid "" "to a Boolean value, but here it can be any type. The type of coin in this " "example is the `Coin` enum that we defined on the first line." msgstr "" -"让我们来分析一下 `value_in_cents' 函数中的 `match'。首先,我们列出了 `match' " -"关键字,后面是一个表达式,在本例中是 `coin' 值。这似乎与使用 if 的条件表达式" -"非常相似,但有一个很大的区别:在 if 中,条件需要求值为一个布尔值,但在这里它" -"可以是任何类型。本例中硬币的类型是我们在第一行定义的 `Coin` 枚举。" +"拆开 `value_in_cents` 函数中的 `match` 来看。首先,我们列出 `match` 关键字后" +"跟一个表达式,在这个例子中是 coin 的值。这看起来非常像 `if` 所使用的条件表达" +"式,不过这里有一个非常大的区别:对于 `if`,表达式必须返回一个布尔值,而这里它" +"可以是任何类型的。本例中硬币的类型是我们在第一行定义的 `Coin` 枚举。" #: src/ch05-02-the-match-control-flow-construct.md:33 msgid "" @@ -8495,7 +8482,7 @@ msgid "" msgstr "" "接下来是 `match` 分支。一个分支有两个部分:一个模式和一些代码。这里的第一个分" "支有一个模式,就是值 `Coin::Penny(_)`,然后是`=>`操作符,把模式和要运行的代码" -"分开。本例中的代码只是值 `1'。每个分支都用逗号与下一个分支隔开。" +"分开。本例中的代码只是值 `1`。每个分支都用逗号与下一个分支隔开。" #: src/ch05-02-the-match-control-flow-construct.md:35 msgid "" @@ -8508,8 +8495,8 @@ msgid "" msgstr "" "当 `match` 表达式执行时,它将结果值与每个分支的模式进行比较,依次进行。如果一" "个模式与值匹配,则执行与该模式相关的代码。如果该模式不匹配该值,则继续执行下" -"一个分支,就像硬币排序机一样。我们可以根据自己的需要有多少个分支:在上面的例" -"子中,我们的匹配有四个分支。" +"一个分支,就像验钞机一样。我们可以根据自己的需要有多少个分支:在上面的例子" +"中,我们的匹配有四个分支。" #: src/ch05-02-the-match-control-flow-construct.md:37 msgid "In Cairo, the order of the arms must follow the same order as the enum." @@ -8554,23 +8541,23 @@ msgid "" "}\n" "```" msgstr "" -"``rust\n" +"```rust\n" "fn value_in_cents(coin: Coin) -> felt252 {\n" " match coin {\n" " Coin::Penny(_) => {\n" -" ('Lucky penny!').print();\n" +" ('Lucky penny!').print();\n" " 1\n" " },\n" -" Coin::Nickel(_) => 5、\n" -" Coin::Dime(_) => 10、\n" -" Coin::Quarter(_)=> 25、\n" +" Coin::Nickel(_) => 5,\n" +" Coin::Dime(_) => 10,\n" +" Coin::Quarter(_)=> 25,\n" " }\n" -"\n" +"}\n" "```" #: src/ch05-02-the-match-control-flow-construct.md:57 msgid "## Patterns That Bind to Values" -msgstr "## 绑定价值的模式" +msgstr "## 绑定值的模式" #: src/ch05-02-the-match-control-flow-construct.md:59 msgid "" @@ -8578,8 +8565,8 @@ msgid "" "the values that match the pattern. This is how we can extract values out of " "enum variants." msgstr "" -"match分支的另一个有用的特点是它们可以绑定到值中与模式相匹配的部分。这就是我们" -"如何从枚举变量中提取数值的方法。" +"另一个match分支的有用的特点是它们可以绑定到值中与模式相匹配的部分。这就是如何" +"从枚举成员中提取数值的方法。" #: src/ch05-02-the-match-control-flow-construct.md:61 msgid "" @@ -8590,11 +8577,11 @@ msgid "" "to our `enum` by changing the `Quarter` variant to include a `UsState` value " "stored inside it, which we’ve done in Listing 5-4." msgstr "" -"作为一个例子,让我们改变我们的一个枚举变量,在它里面保存数据。从1999年到2008" -"年,美国铸造了25分硬币,其中一面为50个州的不同设计。其他硬币没有州的设计,所" -"以只有25分硬币有这个额外的价值。我们可以通过改变 `Quarter` 变量,使其包含一个" -"`UsState` 的值,从而将这个信息添加到我们的 `enum` 中,我们在清单5-4中已经这样" -"做了。" +"作为一个例子,让我们修改枚举的一个成员来存放数据。1999 年到 2008 年间,美国" +"在 25 美分的硬币的一侧为 50 个州的每一个都印刷了不同的设计。其他的硬币都没有" +"这种区分州的设计,所以只有这些 25 美分硬币有特殊的价值。我们可以通过改变 " +"`Quarter` 变量,使其包含一个`UsState` 的值,从而将这个信息添加到我们的 " +"`enum` 中,我们在清单5-4中已经这样做了。" #: src/ch05-02-the-match-control-flow-construct.md:63 msgid "" @@ -8614,19 +8601,19 @@ msgid "" "}\n" "```" msgstr "" -"``rust\n" +"```rust\n" "#[derive(Drop)]\n" "enum UsState {\n" -" Alabama: ()、\n" -" Alaska: ()、\n" +" Alabama: (),\n" +" Alaska: (),\n" "}\n" "\n" "#[derive(Drop)]\n" "enum Coin {\n" -" Penny: ()、\n" -" Nickel: ()、\n" -" Dime: ()、\n" -" Quarter: (UsState)、\n" +" Penny: (),\n" +" Nickel: (),\n" +" Dime: (),\n" +" Quarter: (UsState),\n" "}\n" "```" @@ -8634,8 +8621,7 @@ msgstr "" msgid "" "Listing 5-4: A `Coin` enum in which the `Quarter` variant also holds a " "`UsState` value" -msgstr "" -"列表5-4: 一个 `Coin` 枚举,其中 `Quarter` 变量也持有一个 `UsState` 值。" +msgstr "列表5-4: 一个 `Coin` 枚举,其中 `Quarter` 变量也持有一个 `UsState` 值" #: src/ch05-02-the-match-control-flow-construct.md:81 msgid "" @@ -8644,9 +8630,9 @@ msgid "" "the state associated with each quarter so that if it’s one our friend " "doesn’t have, they can add it to their collection." msgstr "" -"让我们想象一下,一个朋友正试图收集所有50个州的硬币。当我们按硬币类型对零钱进" -"行分类时,我们也会叫出与每个25分硬币相关的州名,这样如果是我们的朋友没有的," -"他们就可以把它加入他们的集合。" +"想象一下我们的一个朋友尝试收集所有 50 个州的 25 美分硬币。在根据硬币类型分类" +"零钱的同时,也可以报告出每个 25 美分硬币所对应的州名称,这样如果我们的朋友没" +"有的话,他可以将其加入收藏。" #: src/ch05-02-the-match-control-flow-construct.md:83 msgid "" @@ -8675,14 +8661,14 @@ msgid "" "}\n" "```" msgstr "" -"``rust\n" +"```rust\n" "fn value_in_cents(coin: Coin) -> felt252 {\n" " match coin {\n" -" Coin::Penny(_) => 1、\n" -" Coin::Nickel(_) => 5、\n" -" Coin::Dime(_) => 10、\n" +" Coin::Penny(_) => 1,\n" +" Coin::Nickel(_) => 5,\n" +" Coin::Dime(_) => 10,\n" " Coin::Quarter(state)=> {\n" -" state.print();\n" +" state.print();\n" " 25\n" " },\n" " }\n" @@ -8710,12 +8696,12 @@ msgid "" "}\n" "```" msgstr "" -"``rust\n" -"impl UsStatePrintImpl of PrintTrait:: {\n" +"```rust\n" +"impl UsStatePrintImpl of PrintTrait:: {\n" " fn print(self: UsState) {\n" " match self {\n" -" UsState::Alabama(_) => ('Alabama').print()、\n" -" UsState::Alaska(_) => ('Alaska').print()、\n" +" UsState::Alabama(_) => ('Alabama').print(),\n" +" UsState::Alaska(_) => ('Alaska').print(),\n" " }\n" " }\n" "}\n" @@ -8733,12 +8719,12 @@ msgstr "" "如果我们调用 `value_in_cents(Coin::quarter(UsState::Alaska(())))`,`coin` 将" "是 `Coin::quarter(UsState::Alaska())`。当我们将该值与每个匹配臂进行比较时,没" "有一个匹配,直到我们到达 `Coin::Quarter(state)`。在这一点上,state 的绑定将" -"是 `UsState::Alaska()` 的值。然后我们可以在 `PrintTrait' 中使用该绑定,从而" -"从 `Coin' 枚举变量中获得 `Quarter' 的内部状态值。" +"是 `UsState::Alaska()` 的值。然后我们可以在 `PrintTrait` 中使用该绑定,从而" +"从 `Coin` 枚举变量中获得 `Quarter` 的内部状态值。" #: src/ch05-02-the-match-control-flow-construct.md:114 msgid "## Matching with Options" -msgstr "##用选项进行匹配" +msgstr "## 匹配 Option" #: src/ch05-02-the-match-control-flow-construct.md:116 msgid "" @@ -8750,9 +8736,9 @@ msgid "" "OptionTrait` trait." msgstr "" "在上一节中,我们想在使用 `Option` 时从 `Some` 情况下得到内部的 `T` 值;我" -"们也可以使用`match` 来处理 `Option`,就像我们对 `Coin` 枚举所做的那样!我们" -"不比较代币,而是比较 `Option` 的变量,但 `match` 表达式的工作方式保持不" -"变。你可以通过导入 `option::OptionTrait` trait来使用Option。" +"们也可以使用`match` 来处理 `Option`,就像我们对 `Coin` 枚举所做的那样! 只" +"不过这回比较的不再是硬币,而是比较 `Option` 的成员,但 `match` 表达式的工" +"作方式保持不变。你可以通过导入 `option::OptionTrait` trait来使用Option。" #: src/ch05-02-the-match-control-flow-construct.md:118 msgid "" @@ -8793,36 +8779,36 @@ msgid "" "}\n" "```" msgstr "" -"``rust\n" -"use option::OptionTrait;\n" -"use debug::PrintTrait;\n" +"```rust\n" +"use option::OptionTrait;\n" +"use debug::PrintTrait;\n" "\n" -"fn plus_one(x: Option) -> Option {\n" +"fn plus_one(x: Option) -> Option {\n" " match x {\n" -" Option::Some(val) => Option::Some(val + 1_u8)、\n" -" Option::None(_) => Option::None(())、\n" +" Option::Some(val) => Option::Some(val + 1_u8),\n" +" Option::None(_) => Option::None(()),\n" " }\n" "}\n" "\n" "fn main() {\n" -" let five:Option = Option::Some(5_u8);\n" -" let six:Option = plus_one(five);\n" -" six.unwrap().print();\n" -" let none = plus_one(Option::None(()));\n" -" none.unwrap().print();\n" +" let five: Option = Option::Some(5_u8);\n" +" let six: Option = plus_one(five);\n" +" six.unwrap().print();\n" +" let none = plus_one(Option::None(()));\n" +" none.unwrap().print();\n" "}\n" "```" #: src/ch05-02-the-match-control-flow-construct.md:142 msgid "Listing 5-5: A function that uses a match expression on an `Option`" -msgstr "清单5-5:一个在 \"选项\"上使用匹配表达式的函数。" +msgstr "清单5-5:一个在`Option`上使用匹配表达式的函数" #: src/ch05-02-the-match-control-flow-construct.md:144 msgid "" "Note that your arms must respect the same order as the enum defined in the " "`OptionTrait` of the core Cairo lib." msgstr "" -"注意,你的分支必须尊重与核心Cairo库的`OptionTrait`中定义的枚举相同的顺序。" +"注意,你的分支顺序与核心Cairo库的`OptionTrait`中定义的枚举顺序必须相同。" #: src/ch05-02-the-match-control-flow-construct.md:146 msgid "" @@ -8833,10 +8819,10 @@ msgid "" " }\n" "```" msgstr "" -"``rust\n" +"```rust\n" " enum Option {\n" " Some: T,\n" -" None: ()、\n" +" None: (),\n" " }\n" "```" @@ -8857,8 +8843,8 @@ msgid "" " Option::Some(val) => Option::Some(val + 1_u8),\n" "```" msgstr "" -"``rust\n" -" Option::Some(val) => Option::Some(val + 1_u8)、\n" +"```rust\n" +" Option::Some(val) => Option::Some(val + 1_u8),\n" "```" #: src/ch05-02-the-match-control-flow-construct.md:159 @@ -8870,11 +8856,11 @@ msgid "" "`Option::Some` value with our total `6_u8` inside. Because the first arm " "matched, no other arms are compared." msgstr "" -"`Option::Some(5_u8)` 值是否符合`Option::Some(val)`的模式?是的!我们有相同的变" -"量。`val` 与 `Option::Some` 中包含的值绑定,所以 `val` 取值为 `5_u8` 。然后执" -"行匹配分支中的代码,所以我们在 `val` 的值上加上 `1_u8`,并创建一个新的 " -"`Option::Some` 值,里面有我们的总数 `6_u8` 。因为第一个分支的匹配,没有其他分" -"支被比较。" +"`Option::Some(5_u8)` 和`Option::Some(val)`匹配吗?当然匹配!它们是相同的成" +"员。`val` 与 `Option::Some` 中包含的值绑定,所以 `val` 取值为 `5_u8` 。接着匹" +"配分支的代码被执行,所以我们在 `val` 的值上加上 `1_u8`,并创建一个新的 " +"`Option::Some` 值,里面有我们的和 `6_u8` 。因为第一个分支就匹配到了,其他的分" +"支将不再比较。" #: src/ch05-02-the-match-control-flow-construct.md:161 msgid "" @@ -8889,8 +8875,7 @@ msgid "" "The `Option::Some(val)` value doesn’t match the pattern `Option::None`, so " "we continue to the next arm:" msgstr "" -"`Option::Some(val)` 的值不符合 `Option::None` 的模式,所以我们继续到下一个分" -"支:" +"`Option::Some(val)` 的值不匹配 `Option::None` ,所以我们继续到下一个分支:" #: src/ch05-02-the-match-control-flow-construct.md:169 msgid "" @@ -8898,8 +8883,8 @@ msgid "" " Option::None(_) => Option::None(()),\n" "```" msgstr "" -"``rust\n" -" Option::None(_) => Option::None(() )、\n" +"```rust\n" +" Option::None(_) => Option::None(()),\n" "```" #: src/ch05-02-the-match-control-flow-construct.md:173 @@ -8918,10 +8903,10 @@ msgid "" "but once you get used to it, you’ll wish you had it in all languages. It’s " "consistently a user favorite." msgstr "" -"结合 `match` 和枚举在很多情况下都很有用。你会在 Cairo 的代码中经常看到这种模" -"式:`match` 针对一个枚举,将一个变量与里面的数据绑定,然后根据它来执行代码。" -"一开始有点棘手,但一旦你习惯了,你会希望所有语言都有这种模式。它一直是用户的" -"最爱。" +"将 `match` 与枚举相结合在很多场景中都是有用的。你会在 Cairo 代码中看到很多这" +"样的模式:`match` 一个枚举,绑定其中的值到一个变量,接着根据其值执行代码。这" +"在一开始有点复杂,不过一旦习惯了,你会希望所有语言都拥有它!这一直是用户的最" +"爱。" #: src/ch05-02-the-match-control-flow-construct.md:177 msgid "## Matches Are Exhaustive" @@ -8933,8 +8918,8 @@ msgid "" "must cover all possibilities. Consider this version of our `plus_one` " "function, which has a bug and won’t compile:" msgstr "" -"我们还需要讨论匹配的另一个方面:武器的模式必须涵盖所有的可能性。考虑一下这个" -"版本的`plus_one`函数,它有一个错误,无法编译:" +"还有另一方面需要讨论:这些分支必须覆盖了所有的可能性。考虑一下 `plus_one` 函" +"数的这个版本,它有一个 bug 并不能编译:" #: src/ch05-02-the-match-control-flow-construct.md:181 msgid "" @@ -8970,11 +8955,10 @@ msgid "" "might have null, thus making the billion-dollar mistake discussed earlier " "impossible." msgstr "" -"Cairo 知道我们没有涵盖所有可能的情况,甚至知道我们忘记了哪种模式!Cairo 中的" -"匹配是穷举性的:我们必须穷举每一种最后的可能性,这样代码才是有效的。特别是在 " -"`Option` 的情况下,当 Cairo 防止我们忘记明确处理 `None` 的情况时,它保护我" -"们不会在可能有 null 的情况下假设我们有一个值,从而使前面讨论的十亿美元的错误" -"成为可能。" +"Rust 知道我们没有覆盖所有可能的情况甚至知道哪些模式被忘记了!Cairo 中的匹配" +"是 穷尽的(exhaustive):必须穷举到最后的可能性来使代码有效。特别的在这个 " +"`Option` 的例子中,Cairo 防止我们忘记明确的处理 None 的情况,这让我们免于" +"假设拥有一个实际上为空的值,从而使之前提到的价值亿万的错误不可能发生。" #: src/ch05-02-the-match-control-flow-construct.md:193 msgid "## Match 0 and the \\_ Placeholder" @@ -9011,11 +8995,11 @@ msgid "" "}\n" "```" msgstr "" -"````rust\n" +"```rust\n" "fn did_i_win(nb: felt252) {\n" " match nb {\n" -" 0 => ('You won!').print()、\n" -" _ => ('You lost...').print()、\n" +" 0 => ('You won!').print(),\n" +" _ => ('You lost...').print(),\n" " }\n" "}\n" "```" @@ -9043,7 +9027,9 @@ msgstr "" msgid "" "" -msgstr "<!-- TODO:可能需要将本章的结尾与模式和匹配章节联系起来-->" +msgstr "" +"" #: src/ch06-00-managing-cairo-projects-with-packages-crates-and-modules.md:1 msgid "# Managing Cairo Projects with Packages, Crates and Modules" From e56ca7530ebd7e620679f79b59119480a66b3059 Mon Sep 17 00:00:00 2001 From: cryptonerdcn Date: Tue, 30 May 2023 23:36:11 +0900 Subject: [PATCH 03/14] Update: Modified the index.hbs file and LANGUAGES file in order to show the zh-cn item in the language-list. --- LANGUAGES | 2 +- po/zh-cn.po | 3 ++- theme/index.hbs | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/LANGUAGES b/LANGUAGES index 11f4c613e..a4aeec6a0 100644 --- a/LANGUAGES +++ b/LANGUAGES @@ -1 +1 @@ -es fr +es fr zh-cn diff --git a/po/zh-cn.po b/po/zh-cn.po index 7b8967bce..691c57f6f 100644 --- a/po/zh-cn.po +++ b/po/zh-cn.po @@ -14548,12 +14548,13 @@ msgid "# Introduction to smart-contracts" msgstr "# 智能合约简介" #: src/ch99-01-01-introduction-to-smart-contracts.md:3 +#, fuzzy msgid "" "This chapter will give you a high level introduction to what smart-contracts " "are, what are they used for and why would blockchain developers use Cairo " "and Starknet.\n" "If you are already familiar with blockchain programming, feel free to skip " -"this chapter. The last part might still be intersting though." +"this chapter. The last part might still be interesting though." msgstr "" "本章是一个关于什么是智能合约,它们有什么用途,以及为什么区块链开发者会使用" "Cairo和Starknet的高度简介。\n" diff --git a/theme/index.hbs b/theme/index.hbs index ca6ae2140..f9bb7c7bb 100644 --- a/theme/index.hbs +++ b/theme/index.hbs @@ -156,6 +156,9 @@
  • +