#rust
#Ржавчина
Вопрос:
возьмите это минимальное воспроизведение (игровая площадка), где я пытаюсь создать структуру с замыканием в виде поля и определить некоторые дополнительные фабричные методы, которые предоставляют пользовательскую логику в форме замыкания.
#![allow(non_snake_case)]
struct FunStruct<T>
where
T: Fn(i32) -> i32
{
pub p: T,
}
fn Create<T>() -> FunStruct<T>
where
T: Fn(i32) -> i32
{
let p : T = |val| -> i32 {
return val;
};
let a = FunStruct {
p,
};
return a;
}
fn main() {
let a = Create();
println!("{}", (a.p)(5));
}
приведенный выше фрагмент выдает следующую ошибку.
error[E0308]: mismatched types
--> src/main.rs:14:17
|
10 | fn Create<T>() -> FunStruct<T>
| - this type parameter
...
14 | let p : T = |val| -> i32 {
| _____________-___^
| | |
| | expected due to this
15 | | return val;
16 | | };
| |_____^ expected type parameter `T`, found closure
|
= note: expected type parameter `T`
found closure `[closure@src/main.rs:14:17: 16:6]`
error[E0282]: type annotations needed for `FunStruct<T>`
--> src/main.rs:26:13
|
26 | let a = Create();
| - ^^^^^^ cannot infer type for type parameter `T` declared on the function `Create`
| |
| consider giving `a` the explicit type `FunStruct<T>`, where the type parameter `T` is specified
|
= note: type must be known at this point
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0282, E0308.
For more information about an error, try `rustc --explain E0282`.
однако, похоже, это работает просто отлично
struct FunStruct<T>
where
T: Fn(i32) -> i32
{
pub p: T,
}
fn main() {
let p = |val| -> i32 {
return val;
};
let a = FunStruct {
p
};
println!("{}", (a.p)(5));
}
кажется, что один уровень абстракции разрушает его.
Комментарии:
1. Вы можете взглянуть на doc.rust-lang.org/book /. … Похоже, «Rust не знает, сколько места потребуется для хранения закрытия» (что немного странно, потому что у компилятора, похоже, много информации о закрытии), поэтому его нужно хранить в куче.
2. @ForceBru я не возвращаю closoure , хотя и предоставляю всю необходимую компилятору информацию о размерах. на самом деле, я даю больше информации в примере, который не компилируется, чем в примере, который компилируется.
Ответ №1:
Общий параметр означает, что он работает для любого типа — однако замыкание в Create
не работает для любого типа замыкания, оно создает замыкание с одним конкретным типом. Вы можете сделать это:
fn Create() -> FunStruct<impl Fn(i32) -> i32>{
let p/*: some anonymous, unique type */ = |val| -> i32 {
return val;
};
let a = FunStruct {
p,
};
return a;
}
Позиция impl Trait
in return означает «Я возвращаю некоторый тип, который реализует эту особенность, я не собираюсь рассказывать вам, что это на самом деле». В отличие от этого, ваша исходная функция говорит: «Учитывая любой тип, который является функцией, я могу его вернуть», что, очевидно, не имеет смысла.