gpt4 book ai didi

generics - 如何在 Rust 中正确设置通用集合类型

转载 作者:行者123 更新时间:2023-12-02 22:15:38 26 4
gpt4 key购买 nike

我正在尝试测试 FreeBSD 12 下 Rust 1.39 中的一些语言功能,并将其与 Free Pascal 3.0.4 进行比较,以获取由字符串键寻址的 2D 点的简单通用点集合。不幸的是,泛型类型声明的代码不会在很早的状态下编译并停止:

error[E0106]: missing lifetime specifier
--> src/main.rs:11:31
|
11 | type TPointMap = BTreeMap<&TString, TPoint>;
|

我该如何重写 Rust 代码?

详细信息:

为了测试语言行为,我用 Rust 和 Pascal 编写了两个小程序,“在语法上”处理相同的上下文。 Pascal 程序是一个简单的声明:

  1. 一些普通类型、记录类型和通用 map 容器,
  2. 将用于定义一个点,将该点存储在新分配的 map 中,
  3. 通过按键查找点并将数据写入STDIO
  4. 终于释放了 map 。
program test;
uses fgl; { Use the free pascal generics library }
type
TDouble = Double; { Define a 64 bit float }
TString = String; { Define a string type }
TPoint = record { Define a point record }
X : TDouble; { Coordinate X }
Y : TDouble; { Coordinate Y }
end;
{ Define a map of points with strings as key }
TPointMap = specialize TFPGMap<TString, TPoint>;

{ Test program }
var
map : TPointMap; { Declare the map variable }
point : TPoint; { Declare a point variable }
found : TPoint; { Varaiable for a found point }
key : TString; { Variable to address the point in the map }
begin
map := TPointMap.create; { Allocate a new ma container }
with point do begin { Set the point variable }
x := 1.0; y := 2.0;
end;
key := '123'; { Set the key address to '123' }
map.add(key,point); { Store the point in the map }

{ Search the point an write the result in the rusty way }
case map.TryGetData(key, found) of
true : writeln('X: ',found.X:2;, ' Y:', found.Y:2:2);
false : writeln('Key ''',key,''' not found');
end;
map.free; { De-allocate the map }
{ Plain types are de-allocated by scope }
end.

程序编译并给出:

$ ./main 
X: 1.00 Y:2.00

这是我错误的 Rust 版本的代码:

use std::collections::BTreeMap; // Use a map from the collection 

type TDouble = f64; // Define the 64 bit float type
type TString = str; // Define the string type
struct TPoint { // Define the string type
x: TDouble, // Coordinate X
y: TDouble, // Coordinate Y
}

// Define a map of points with strings as key
type TPointMap = BTreeMap<&TString, TPoint>;

// Test program
fn main() {
let point = TPoint { x: 1.0, y: 2.0 }; // Declare and define the point variable
let mut map = TPointMap::new(); // Declare the map and allocate it
let key: TString = "123"; // Declare and define the address of point
map.insert(&key, point); // Add the point to the map
// search the point and print it
match map.get(&key) {
Some(found) => println!("X: {} Y: {}", found.X, found.y),
None => println!("Key '{}' not found", key),
}
// map is de-allocated by scope
}

备注:我知道由于借用和所有权概念,某些代码行不能在 Rust 代码中使用。该行

 match map.get(&key)...

就是其中之一。

最佳答案

为了大致相当于 freepascal 版本, TString 可能应该是 String 而不是 strfreepascal 字符串是 ( depending on some flags ) 一个指针、一个长度和一个堆分配的字符数组。这(几乎)正是 Stringstr 只是字符数组并且未调整大小,因此它始终必须位于某种(胖)指针后面。

完成更改后,只需执行一些其他操作即可修复代码。 TPointMap 需要一个生命周期参数,因为它使用引用类型。引用的生命周期必须来自某个地方,因此我们在该生命周期中将 TPointMap 设为通用。

type TPointMap<'a> = BTreeMap<&'a TString, TPoint>;

如果您的用例允许,您也可以考虑简单地使用 BTreeMap<TString, TPoint>

我们需要进行一些转换来声明 key: TString 。字符串文字的类型为 'static str ,但有一个简单的 to_string 方法可以将它们转换为 String

let key: TString = "123".to_string(); 

最后,found.X 中有一个拼写错误。

Some(found) => println!("X: {} Y: {}", found.x, found.y),

总而言之,我们有

use std::collections::BTreeMap; // Use a map from the collection

type TDouble = f64; // Define the 64 bit float type
type TString = String; // Define the string type
struct TPoint {
// Define the string type
x: TDouble, // Coordinate X
y: TDouble, // Coordinate Y
}

// Define a map of points with strings as key
type TPointMap<'a> = BTreeMap<&'a TString, TPoint>;

// Test program
fn main() {
let point = TPoint { x: 1.0, y: 2.0 }; // Declare and define the point variable
let mut map = TPointMap::new(); // Declare the map and allocate it
let key: TString = "123".to_string(); // Declare and define the address of point
map.insert(&key, point); // Add the point to the map
// search the point and print it
match map.get(&key) {
Some(found) => println!("X: {} Y: {}", found.x, found.y),
None => println!("Key '{}' not found", key),
}
// map is de-allocated by scope
}

(playground)

另请参阅 What are the differences between Rust's String and str ?

关于generics - 如何在 Rust 中正确设置通用集合类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59432258/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com