← Previous revisionRevision as of 05:38, 10 October 2026 Line 210: Line 210: In the above code, {{code|1=4..=10}} is a value of type {{code|std::range::Range}} which implements the {{code|std::iter::Iterator}} trait. The code within the curly braces is applied to each element returned by the iterator. In the above code, {{code|1=4..=10}} is a value of type {{code|std::range::Range}} which implements the {{code|std::iter::Iterator}} trait. The code within the curly braces is applied to each element returned by the iterator. Iterators can be combined with functions over iterators like {{code|map}}, {{code|filter}}, and {{code|sum}}. For example, the following adds up all numbers between 1 and 100 that are multiples of 3: Iterators can be combined with functions over iterators like {{code|map()}}, {{code|filter()}}, and {{code|sum()}}. For example, the following adds up all numbers between 1 and 100 that are multiples of 3: Line 327: Line 327: The function {{code|print_string}} takes ownership over the {{code|String}} value passed in; Alternatively, {{code|&}} can be used to indicate a [[Reference (computer science)|reference]] type (in {{code|&String}}) and to create a reference (in {{code|&s}}):{{sfn|Klabnik|Nichols|2023|pp=71–72}} The function {{code|print_string()}} takes ownership over the {{code|String}} value passed in; Alternatively, {{code|&}} can be used to indicate a [[Reference (computer science)|reference]] type (in {{code|&String}}) and to create a reference (in {{code|&s}}):{{sfn|Klabnik|Nichols|2023|pp=71–72}} Line 674: Line 674: Rust's type system supports a mechanism called traits, inspired by [[type class]]es in the [[Haskell]] language, to define shared behavior between different types. For example, the Add trait can be implemented for floats and integers, which can be added; and the std::fmt::Display or std::fmt::Debug traits can be implemented for any type that can be converted to a string. Traits can be used to provide a set of common behavior for different types without knowing the actual type. This facility is known as [[ad hoc polymorphism]]. Rust's type system supports a mechanism called traits, inspired by [[type class]]es in the [[Haskell]] language, to define shared behavior between different types. For example, the Add trait can be implemented for floats and integers, which can be added; and the std::fmt::Display or std::fmt::Debug traits can be implemented for any type that can be converted to a string. Traits can be used to provide a set of common behavior for different types without knowing the actual type. This facility is known as [[ad hoc polymorphism]]. Generic functions can constrain the generic type to implement a particular trait or traits; for example, an add_one function might require the type to implement std::ops::Add. This means that a generic function can be type-checked as soon as it is defined. The implementation of generics is similar to the typical implementation of C++ templates: a separate copy of the code is generated for each instantiation. This is called [[monomorphization]] and contrasts with the [[type erasure]] scheme typically used in Java and Haskell. Type erasure is also available via the keyword dyn (short for dynamic).{{sfn|Klabnik|Nichols|2019|pp=181,182}} Because monomorphization duplicates the code for each type used, it can result in more optimized code for specific-use cases, but compile time and size of the output binary are also increased.{{sfn|Gjengset|2021|p=25}} Generic functions can constrain the generic type to implement a particular trait or traits; for example, an add_one() function might require the type to implement std::ops::Add. This means that a generic function can be type-checked as soon as it is defined. The implementation of generics is similar to the typical implementation of C++ templates: a separate copy of the code is generated for each instantiation. This is called [[monomorphization]] and contrasts with the [[type erasure]] scheme typically used in Java and Haskell. Type erasure is also available via the keyword dyn (short for dynamic).{{sfn|Klabnik|Nichols|2019|pp=181,182}} Because monomorphization duplicates the code for each type used, it can result in more optimized code for specific-use cases, but compile time and size of the output binary are also increased.{{sfn|Gjengset|2021|p=25}} In addition to defining methods for a user-defined type, the impl keyword can be used to implement a trait for a type.{{sfn|Klabnik|Nichols|2019|pp=93}} Traits can provide additional derived methods when implemented.{{sfn|Klabnik|Nichols|2019|pp=182–184}} For example, the trait std::iter::Iterator requires that the next method be defined for the type. Once the next method is defined, the trait can provide common functional helper methods over the iterator, such as map or filter.{{sfn|Klabnik|Nichols|2019|pp=281–283}} In addition to defining methods for a user-defined type, the impl keyword can be used to implement a trait for a type.{{sfn|Klabnik|Nichols|2019|pp=93}} Traits can provide additional derived methods when implemented.{{sfn|Klabnik|Nichols|2019|pp=182–184}} For example, the trait std::iter::Iterator requires that the next() method be defined for the type. Once the next() method is defined, the trait can provide common functional helper methods over the iterator, such as map() or filter().{{sfn|Klabnik|Nichols|2019|pp=281–283}} === Trait objects === === Trait objects ===