호출 구문에 과부하를 실험하려는 시도에서 값 비싼 계산 결과를 캐시 할 수있는 간단한 캐시를 도입했습니다. 구문의 일부를 사용하는 것에 대해 약간 혼란 스럽습니다. 질문 앞에 단계별 코드를 소개하겠습니다.`FnOnce`의 의미없는 정의를 피할 수 있습니까?
이 캐시는 다음과 같이 사용하기위한 것입니다 :
fn fib(x: i32) -> i32 {
if x < 2 { x } else { fib(x-1) + fib(x-2) }
}
fn main() {
let mut cfib = Cache::new(fib);
// Loop that repeats computation and extracts it from the cache
// the second time.
for x in 1..200 {
let val = 5 * x % 40;
println!("fibc({}) = {}", val, cfib(val));
}
}
우리가 먼저 안정에 아직있는 기능을 사용하려면 프리앰블이 있습니다
#![feature(fn_traits, unboxed_closures)]
use std::collections::HashMap;
use std::hash::Hash;
우리는 구조로 캐시를 소개합니다
HashMap
및 새 값을 계산하는 함수가 있습니다. 캐시가 변경 가능해야하므로
struct Cache<T, R> {
cache: HashMap<T, R>,
func: fn(T) -> R,
}
impl<T, R> Cache<T, R>
where T: Eq + Hash + Copy,
R: Copy
{
fn new(func: fn(T) -> R) -> Cache<T, R> {
Cache { cache: HashMap::new(), func: func }
}
fn compute(&mut self, x: T) -> R {
let func = self.func;
let do_insert = || (func)(x);
*self.cache.entry(x).or_insert_with(do_insert)
}
}
은 내가 FnMut
특성의 구현을 작성합니다.
impl<T, R> FnMut<(T,)> for Cache<T, R>
where T: Eq + Hash + Copy,
R: Copy
{
extern "rust-call" fn call_mut(&mut self, args: (T,))
-> Self::Output
{
let (arg,) = args;
self.compute(arg)
}
}
내가 구문을 찾을 수 있지만 FnMut<(T,)>
아주 이상한,이 미세하고 안전하고 매우 명확한 의도를 전달한다. 나는 함수의 반환 유형을 정의 할 필요가 있기 때문에, 나는으로 시작 작성하려합니다 :
impl<T, R> FnMut<(T,), Output=R> for Cache<T, R>
where T: Eq + Hash + Copy,
R: Copy
{}
을하지만 그 오류와 함께 실패합니다
error[E0229]: associated type bindings are not allowed here
--> src/main.rs:55:24
|
55 | impl<T, R> FnMut<(T,), Output=R> for Cache<T, R>
| ^^^^^^^^ associate type not allowed here
이 같은 FnOnce
을 구현했다 : 가지 의미가 call_once
이후입니다
impl<T, R> FnOnce<(T,)> for Cache<T,R>
where T: Eq + Hash + Copy,
R: Copy
{
type Output = R;
extern "rust-call" fn call_once(self, _arg: (T,))
-> Self::Output
{
unimplemented!()
}
}
호출하지 않으며,이 가능해야한다처럼 Associated Types에서 보인다 않을 것이다. 그러나 관련 유형이 허용되지 않는 오류로 인해 실패합니다.
Rust Compiler Error Index은 Fn(T) -> R
이라는 문구를 언급하고 있으며, Fn<(T,), Output=U>
이 작동해야한다고 말하지만, 야간 녹 작성기를 사용하고 있어도 작동하지는 못합니다.
컴파일 타임에 가능한 한 많은 오류를 포착하는 것이 바람직하므로 FnOnce
에 "구현되지 않은"함수가 작성되는 것을 피하는 것이 좋습니다. 컴파일 시간이 아닌 런타임시 오류가 발생하기 때문입니다.
FnMut
만 구현하고 어떤 식 으로든 함수의 반환 형식을 제공 할 수 있습니까?
작동하는 것 같다 참조하십시오. 감사. –
'extern'rust-call은 여기서 엄격히 필요합니까? –
@MatthieuM. 네. 이 특성은 'extern'녹 호출 "함수를 정의하며 구현은 특성 정의와 일치해야합니다. 보다 광범위하게 'rust-call'은 컴파일러에게 'arg'가 실제로 함수에 대한 다중 인수이고 각 튜플 값이 별도의 인수가되도록 변환을 수행하는 것입니다. 아마도 함수에 전달 된 하나의 큰 튜플은 하드웨어 수준에서 많은 개별 값과 다르게 동작합니다. – Shepmaster