【问题标题】:How to write a recursive generic type in Rust?如何在 Rust 中编写递归泛型类型?
【发布时间】:2022-03-19 04:27:41
【问题描述】:

我想定义一个HashMap,键类型为String,值类型是它本身。

我试着写这样的东西:

HashMap<String, HashMap<String, ...>>

我发现这需要递归,但我不知道如何在类型中编写递归。

看完Recursive generic types,我试过了:

type HashToHash = HashMap<String, HashToHash>

但是我得到了错误:

error[E0391]: cycle detected when processing `HashToHash`
 --> src/lib.rs:3:35
  |
3 | type HashToHash = HashMap<String, HashToHash>;
  |                                   ^^^^^^^^^^
  |
  = note: ...which again requires processing `HashToHash`, completing the cycle

有没有办法在 Rust 中定义这种类型?

【问题讨论】:

  • 试试struct HashToHash(HashMap&lt;String, HashToHash&gt;);
  • 副本是错误的。 HashTable 就像一个盒子,所以你可以有一个递归结构。
  • @trentcl 当然,它没有理由不起作用。 HashMap 的大小在编译时已知,它与键和值类型无关,因此在标记为重复的问题中提到的无限大小类型的问题在这里不会出现。仍然存在一个问题,这种类型有多有用,因为叶节点中不能有任何值,但我不能排除这种数据结构的用例。
  • @trentcl 够公平的。它actually does work。 :)

标签: generics recursion types rust


【解决方案1】:

编译器试图告诉你你将要定义一个无限类型。 您错误的原因是 C# 和 Java 中的泛型是 ∀-多态的,即所有参数都存在一个实现。 Rust 是 λ-多态的,即为每个参数创建(和优化)一个实现。 这就是通常所说的模板,您可能从 C++ 中知道它。 如果早期的 Rust 开发人员有更多的经验,Rust 中的许多概念就会以不同的名称而闻名。泛型只是其中之一。

摆脱无限循环的唯一方法是使用某种指向您在 RHS 上定义的类型的指针。

老实说,我发现这个问题是因为我想知道 Rust 是否可以预先声明一个模板并在不知道定义的情况下使用指向它的指针。 由于我没有找到有关该主题的任何文档,因此答案可能是否定的。

如果你真的需要这个,你可以在任何 λ 多态语言中使用无类型指针来中断递归。 这样做,您应该将所有数据访问封装在 API 后面。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-05
    相关资源
    最近更新 更多