当前位置:网站首页>[rust notes] 08 enumeration and mode
[rust notes] 08 enumeration and mode
2022-07-03 08:35:00 【phial03】
08 - Enumeration and mode
8.1 - enumeration
Definition of enumeration :
enum Ordering { Less, Equal, Greater }The value of an enumeration is called a variation , Or structural formula (constructor):
Ordering::Less;Ordering::Equal;Ordering::Greater.
This enumeration is defined in the standard library , It can be imported directly into the code :【 recommend 】
use std::cmp::Ordering;perhaps , Import all its constructors : Unless you can make the code better understand , Otherwise, do not directly import constructors .
use std::cmp::Ordering::*;
If you want to import the constructor of the enumeration declared in the current module , To use
selfParameters :enum Pet { Orca, Giraffe } use self::Pet::*;Rust Allows you to convert enumerated values to integers , But you can't directly convert an integer to an enumerated value .
Rust Ensure that the enumeration value must be in
enumAs defined in the declaration .Enumerations are the same as structs , Support use
#[derive]attribute , To mark common features .Enumerations are the same as structs , It can also be done through
implBlock definition method .
8.1.1 - Enumeration containing data
Enumeration contains what data , Just call it why variant :
#[derive(Copy, Clone, Debug, PartialEq)] enum RoughTime { InThePast(TimeUnit, u32), JustNow, InTheFuture(TimeUnit, u32) }InThePastandInTheFutureCalled tuple variant (tuple variant)- Enumeration values can also be structural variants
RoughTmeEach construct of takes 8 Bytes .
Rust There are three variants of enumeration :
Primitive like variants : Variants without data .
enum EnumName;Tuple variants :
enum EnumName (...);Structural variant :
enum EnumName { ... }An enumeration can contain these three variant data at the same time :
enum RelationshipStatus { Single, InARelationship, ItsComplicated(Option<String>), ItsExtremelyComplicated { car: DifferentialEquation, cdr: EarlyModernistPoem } }
All constructors and fields of public enumeration are automatically public .
8.1.2 - Enumeration of memory layout
- The integer label is Rust Fields used internally , Through it, you can know which constructor created the current value , And which fields the current value contains .
- Rust For some enumerations, label fields will be optimized directly . Such as generic enumeration .
8.1.3 - Rich data structure using enumeration
Enumerations can be used to quickly implement tree like data structures .
Rust Realization
Jsonenumeration :enum Json { Null, Boolean(bool), Number(f64), String(String), Array(Vec<Json>), Object(Box<HashMap<String, Json>>) }- JSON The standard stipulates that it can appear in JSON The different data types in the document are :null、 Boolean value 、 The number 、 character string 、JSON An array of values 、 Take string as key and JSON Objects with values .
- use
BoxpackingHashMapTo expressObject, Can make all JSON Value is more concise . - JSON The value of type accounts for 4 A machine word .
StringandVecValue of the 3 A machine wordBox<HashMap>Occupy 1 A machine word
8.1.4 - Generic enumeration
Common generic enumerations :
enum Option<T> { None, Some(T) } enum Result<T, E> { Ok(T), Err(E) }Examples of generic based data structures : Implement a binary tree
// establish T An ordered set of type values enum BinaryTree<T> { // BinaryTree The value of only accounts for 1 A machine word Empty, // Does not contain any data NonEmpty(Box<TreeNode<T>>) // Contains a Box, It points to the in heap memory TreeNode The pointer to } // BinaryTree The node of struct TreeNode<T> { element: T, // Actual element left: BinaryTree<T>, // The left subtree right: BinaryTree<T> // Right subtree }Create any specific node of this tree :
use self::BinaryTree::* let jupiter_tree = NonEmpty(Box::new(TreeNode { element: "Jupiter", left: Empty, right: Empty }));Larger trees can be created based on smaller trees
// take jupiter_node and mercury_node The ownership of the , Transfer to the new parent node by assignment mars_tree let mars_tree = NonEmpty(Box::new(TreeNode { element: "Mars", left: jupiter_tree, right: mercury_tree }));The root node is created in the same way :
let tree = NonEmpty(Box::new(TreeNode { element: "Saturn", left: mars_tree, right: uranus_tree }));Suppose this tree has one
addMethod , Then you can call the tree in this way :let mut tree = BinaryTree::Empty; for planet in planets { tree.add(planet); }
8.2 - Pattern
The only safe way to access enumerated data : Pattern matching .
Define a
RoughTmeEnumeration type :enum RoughTime { InThePast(TimeUnit, u32), JustNow, InTheFuture(TimeUnit, u32) }Use
matchExpressions access enumerated data :fn rough_time_to_english(rt: RoughTime) -> String { match rt { RoughTime::InThePast(units, count) => format!("{} {} ago", count, units.plural()), RoughTime::JustNow => format!("just now"), RoughTime::InTheFuture(units, count) => format!("{} {} from now", count, units.plural()) } }
enumeration 、 Structure or tuple when matching patterns , Each component of the heap mode will be stacked from left to right , Check whether the current value matches it in turn . If it doesn't match , Will enter the next mode .
The special type of pattern
Rust The pattern itself is a mini language :
Pattern type Example explain Literal 100
“name”Match the exact value ;const The name of the declaration can also Range 0 … 100
‘a’ … ‘k’Match any value in the range , Including the final value wildcard _ Match any value and ignore it Variable name
mut countsimilar _, But the matching value will be transferred or copied to the new local variablerefVariableref field
ref mut fieldDo not transfer or copy matching values , Instead, it borrows references to matching values Sub mode binding val @ 0 … 99
ref circle @Shape::Circle { .. }matching @ Mode on the right , Use the variable name on the left Enumeration mode Some(value)
NonePet::OrcaTuple mode (Key, value)
<r, g, b>Structure mode Color(r, g, b)
Point { x, y }
Card { suit: Clubs, rank: n }
Account { id, name, … }quote &value&(k, v)Only match reference values Multiple patterns 'a''A'Protector expression x if x * x <= r2Limited to match( Can't be in let Etc )
8.2.1 - Literal quantity in the pattern 、 Variables and wildcards
0、1 Equal integer values can be used as patterns :
match meadow.count_rabbits() { 0 => { }, 1 => println!("A rabbit is nosing around in the clover."), n => println!("There are {} rabbits hopping about in the meadow", n) }Other types of literals can also be used as patterns , Including Boolean 、 character , Even strings :
let calendar = match settings.get_string("calendar") { "gregorian" => Calendar::Gregorian, "chinese" => Calendar::Chinese, "ethiopian" => Calendar::Ethiopian, other => return parse_error("calendar", other) };You can use wildcards
_As a model , To match any value , But do not save the matching value :let caption = match photo.tagged_pet() { Pet::Tyrannosaur => "RRRAAAAAHHHHHH", Pet::Samoyed => "*dog thoughts*", _ => "I'm cute, love me" // General title , Applicable to any pet };Every
matchThere will be a wildcard at the end of the expression , Even if it is quite certain that nothing else will happen , At least one backup surprise branch must also be added :// There are many shapes (shape), But only for “ choice ” Some texts , // Or everything in a rectangular area , You cannot select ellipse or trapezoid . match document.selection() { Shape::TextSpan(start, end) => paint_text_selection(start, end), Shape::Rectangle(rect) => paint_rect_selection(rect), _ => panic!("unexpected selection type") }In order to avoid that the last branch cannot run to , Can combine
ifExpression implementation pattern :fn check_move(current_hex: Hex, click: Point) -> game::Result<Hex> { match point_to_hex(click) { None => Err("That's not a game space"), Some(hex) => if hex == current_hex { Err("You are already there! You must click somewhere else") } else { Ok(hex) } } }
8.2.2 - Tuples and structure patterns
Tuple patterns match tuples , Fit in a
matchMultiple data are matched in the expression at the same time :fn describe_point(x: i32, y: i32) -> &'static str { use std::cmp::Ordering::*; match (x.cmp(&0), y.cmp(&0)) { (Equal, Equal) => "at the orgin", (_, Equal) => "on the x axis", (Equal, _) => "on the y axis", (Greater, Greater) => "in the first quadrant", (Less, Greater) => "in the second quadrant", _ => "somewhere else" } }Struct mode uses curly braces , Similar to structure expression , Each of these fields is a sub pattern :
match balloon.location { Point { x: 0, y: height } => println!("straight up {} meters", height), Point { x: x, y: y } => println!("at ({}m, {}m)", x, y) }For complex structures , To keep the code simple , have access to
..Indicates that you don't care about other fields :match get_account(id) { ... Some(Account { name, language, .. }) => language.show_custom_greeting(name) }
8.2.3 - Pattern reference
For quotes ,Rust Two modes are supported :
refPattern : Borrow elements with matching values&Pattern : Match reference
In general , Matching non replicable values will transfer values :
match account { Account { name, language, .. } => { ui.greet(&name, &language); ui.show_settings(&account); // error : The transferred value is used account } }Use
refPattern , You can borrow matching values , Without transferring it :match account { Account { ref name, ref language, .. } => { ui.greet(name, language); ui.show_settings(&account); } }You can also use
ref mutTo borrowmutquote :match line_result { Err(ref err) => log_error(err), // err yes &Error( Shared ref) // Pattern Ok(ref mut line) Can match any successful result , And borrow the value stored in the result mut quote Ok(ref mut line) => { // line yes &mut String( Modifiable ref) trim_comments(line); // Modify the string in place handle(line); } }And
refThe mode corresponds to&Pattern . With&The pattern matching reference at the beginning :match sphere.center() { &Point3d { x, y, z} => ... }Matching references follow the rules of references :
- Life span ;
- Cannot take on shared references
mutoperation ; - Cannot quote from ( Include
mutquote ) Transfer out value .
8.2.4 - Multiple possibilities of matching
A vertical bar
|Can be used in amatchCombine multiple patterns in a branch :let at_end = match chars.peek() { Some(&'\r') | Some(&'\n') | None => true, _ => false };Use
...You can match values in a range . The range mode contains the start value and the end value , namely'0' ... '9'Match all ASCII Numbers :match next_char { '0' ... '9' => self.read_number(), 'a' ... 'z' | 'A' ... 'Z' => self.read_word(), ' ' | '\t' | '\n' => self.skip_whitespace(), _ => self.handle_punctuation() }Quanna (inclusive) Range
...: It is suitable for pattern matching .Mutually exclusive range
..: It is suitable for loops and fragments .
8.2.5 - Pattern protector
Use
ifKeywords can bematchAdd armor to the branch . Only when the protector is evaluated astrueTime matching is successful , If the value of the protective device isfalse, that Rust Will continue to match the next pattern .match robot.last_known_location() { Some(point) if self.distance_to(point) < 10 => short_distance_strategy(point), Some(point) => long_distance_strategy(point), None => searching_strategy() }
8.2.6-@ Pattern
x @ patternCan match a givenpattern, You can transfer or copy the whole matching value to a variablexin :Create the following pattern :
match self.get_selection() { Shape::Rect(top_left, bottom_right) => optimized_paint(&Shape::Rect(top_left, bottom_right)), other_shape => paint_outline(other_shape.get_outline()), }Shape::RectAfter the branch is disassembled to get the value , You can recreate the same value , So it can be used@Pattern rewriting :rect @ Shape::Rect(..) => Optimized_paint(&rect),@Patterns support matching range values :match chars.next() { Some(digit @ '0' ... '9') => read_number(digit, chars), ... }
8.2.7 - Use scenarios of patterns
The disassembly value can be realized through pattern matching , Instead of just storing the value in a variable :
Use in
matchExpressionUsed in place of identifiers
It is used to disassemble the structure into 3 A new local variable :
let Track { album, track_number, title, .. } = song;Used to disassemble tuples as function parameters :
fn distance_to((x, y): (f64, f64)) -> f64 { ... }For iteration
HashMapThe bond and the value of :for (id, document) in &cache_map { println!("Document #{}: {}", id, document.title); }Used to automatically dereference parameters passed to closures :
let sum = numbers.fold(0, |a, &num| a + num);
The above example , stay JavaScript It is called deconstruction (restructuring),Python It's called unpacking (unpacking).
Irrefutable mode (irrefutable pattern): Patterns that can always be matched . Can be used for :
letBack .- Function parameters .
forBack .- Closure parameters .
Refutable mode (refutable pattern): Patterns that may not match . Can be used for :
matchexpression .if letexpression .while letexpression .Only one specific enumeration variant is handled :
if let RoughTime::InTheFuture(_, _) = user.date_of_birth() { user.set_time_traveler(true); }Only run some code when the table lookup is successful :
if let Some(document) = cache_map.get(&id) { return send_cached_response(document); }If you don't succeed, do something repeatedly :
while let Err(err) = present_cheesy_anti_robot_task() { log_robot_attempt(err); }An iterator is handy by hand :
while let Some(_) = lines.peek() { read_paragraph(&mut lines); }
8.2.8 - Fill binary tree
Realization BinaryTree::add() Method , Used to direct to BinaryTree Add child nodes of the same type in :
enum BinaryTree<T> {
Empty,
NonEmpty(Box<TreeNode<T>>)
}
struct TreeNode<T> {
element: T,
left: BinaryTree<T>,
right: BinaryTree<T>
}
impl<T: Ord> BinaryTree<T> {
fn add(&mut self, value: T) {
match *self {
BinaryTree::Empty =>
*self = BinaryTree::NonEmpty(Box::new(TreeNode {
element: value,
left: BinaryTree::Empty,
right: BinaryTree::Empty
})),
BinaryTree::NonEmpty(ref mut node) =>
if value <= node.element {
node.left.add(value);
} else {
node.right.add(value);
}
}
}
}
When
*selfIt's empty , So runBinaryTree::EmptyPattern , holdEmptyChange the tree intoNonEmptyTrees .When
*selfNot empty , So runBinaryTree::NonEmpty(ref mut node)Pattern , You can access and modify the data in the tree node .Call this
addMethod :let mut tree = BinaryTree::Empty; tree.add("Mercury"); tree.add("Venus"); ...
8.3 - Pattern design
- Rust Enumeration , Also known as algebraic data types (algebraic data type). Closely related to the following characteristics :
- variant (variant)
- quote
- variability (mutability)
- Memory safety
- Functions need no variability to become languages .
- C Of
unionThe consortium also supports variants 、 The pointer ( quote ) And variability , But it is not memory safe . - Enumeration is a design tool for specific data forms :
- A value may be a value ;
- It may also be another value ;
- There may be nothing
- Enumeration does not support extended enumeration :
- If you want to add a new variant , Then you can only modify the declaration of enumeration
- Modified the declaration of enumeration , Each of the variants in the match must be rechecked
matchexpression , Because they need to add a new branch to deal with the new variant .
- Rust Is more flexible than enumeration .
See 《Rust Programming 》( Jim - Brandy 、 Jason, - By orendov , Translated by lisongfeng ) Chapter ten
Original address
边栏推荐
- ArrayList
- Go resolve ID card
- Unity learning notes
- 单调栈-42. 接雨水
- Conversion between string and int types in golang
- Golang 字符串分割,替换和截取
- Delete the last character of the string in golang
- Find the intersection of line segments
- Golang time format sorting
- Cloudcompare learning (1) - cloudcompare compilation and common plug-in implementation
猜你喜欢

數據庫應用技術課程設計之商城管理系統

Jupyter remote server configuration and server startup

matlab神经网络所有传递函数(激活函数)公式详解
![P1596 [USACO10OCT]Lake Counting S](/img/a7/07a84c93ee476788d9443c0add808b.png)
P1596 [USACO10OCT]Lake Counting S

100 GIS practical application cases (78) - Multi compliance database design and data warehousing

jupyter远程服务器配置以及服务器开机自启

Student educational administration management system of C # curriculum design

Solution détaillée de toutes les formules de fonction de transfert (fonction d'activation) du réseau neuronal MATLAB
![[MySQL] MySQL Performance Optimization Practice: introduction of database lock and index search principle](/img/b7/7bf2a4a9ab51364352aa5e0a196b6d.jpg)
[MySQL] MySQL Performance Optimization Practice: introduction of database lock and index search principle

matlab神經網絡所有傳遞函數(激活函數)公式詳解
随机推荐
Vscode, idea, VIM development tool shortcut keys
Location of package cache downloaded by unity packagemanager
Creation and content of mapnode -- osgearth rendering engine series (2)
Osgearth topographic shading map drawing
Unity Editor Extension - drag and drop
【K&R】中文第二版 个人题解 Chapter1
Message queue for interprocess communication
Unity editor expansion - controls, layouts
十六进制编码简介
Mall management system of database application technology course design
Why can void * be a general pointer
如何应对数仓资源不足导致的核心任务延迟
Message pack in C deserializes array objects
Easy touch plug-in
UE4 source code reading_ Bone model and animation system_ Animation compression
P1596 [USACO10OCT]Lake Counting S
[MySQL] MySQL Performance Optimization Practice: introduction of database lock and index search principle
Golang中删除字符串的最后一个字符
Find the intersection of line segments
Simply start with the essence and principle of SOM neural network