2014-11-01 2 views
0

Контекст: Я пытаюсь параметризовать функцию другой функцией и получить ее статически. С первого взгляда привязка к Fn, похоже, соответствует моей потребности.UFCS: Разрешение метода T ::

То, что я ожидал, чтобы быть «обертка» кажется хорошо (до сих пор), я бы плохо застрял на просто обозначая метод, который я хотел бы передать:

fn binop<T,Op:Fn<(T,T),T>>(op: Op, a:T, b:T) -> T { 
    // [...] 
    op.call((a,b)) 
} 

fn addx(a: f64, b: f64) -> f64 { 
    binop(f64::add, a, b) 
    // ^~~~~~~~ error: unresolved name `f64::add`. 
} 

fn main() { 
    addx(1.0, 2.0); 
} 

Я искал подсказки в RFC UFCS, и «случайно» попробовал кучу вариантов обозначения (вплоть до ссылки std::ops::Add::add и прыгания на какой-то магический вывод, чтобы выполнить эту работу), но с признательностью не может понять это правильно. Любая помощь о (/ указателях) механизма разрешения будет очень полезна.

Спасибо!

ответ

1

Fn является новыми Unboxed укупорочных вещей. Там также просто прямой fn(…) -> …, простой тип функции. Такого рода вещи (имея в виду, что add берет свои аргументы по ссылке, а не по значению):

fn binop<T>(op: fn(&T, &T) -> T, a: &T, b: &T) -> T { 
    // [...] 
    op(a, b) 
} 

fn addx(a: f64, b: f64) -> f64 { 
    binop(Add::add, &a, &b) 
} 

fn main() { 
    addx(1.0, 2.0); 
} 

Выполнить это через rustc и вы получите это:

error: internal compiler error: unexpected failure 
note: the compiler hit an unexpected failure path. this is a bug. 
note: we would appreciate a bug report: http://doc.rust-lang.org/complement-bugreport.html 
note: run with `RUST_BACKTRACE=1` for a backtrace 
task 'rustc' failed at 'assertion failed: `(left == right) && (right == left)` (left: `3`, right: `0`)', /home/chris/rust/src/librustc/middle/trans/callee.rs:528 

... хм, может быть, не так хорошо в этом конкретном случае. Вероятно, это связано с выводами типа признаков, но я не мог сказать, что.

+0

ICE сообщила (я думаю) аналогичную проблему https://github.com/rust-lang/rust/issues/18501 – pao

+0

Исправлено в [# 18061] (https://github.com/rust-lang/rust/ проблемы/18061), ваш пример просто работает сейчас. Благодарю. – pao

1

Fn* черты - это незакрытые черты замыкания, а незакрытые затворы находятся в активной разработке прямо сейчас. Некоторые удобства, такие как автоматическое преобразование из функций в их экземпляры, пока не работают, хотя я считаю, что закрытые блокировки будут заменены текущими коробочными, что-то вроде этого будет работать в будущем.

Однако есть еще одна проблема. UFCS is not implemented, и я думаю, что они не будут реализованы в 1.0, поэтому теперь вы не можете определять методы признаков. Вы должны использовать явную конструкцию закрытия, например:

#![feature(unboxed_closures, unboxed_closure_sugar, overloaded_calls)] 

fn binop<T, Op: Fn(T, T) -> T>(op: Op, a: T, b: T) -> T { 
    // [...] 
    op(a, b) 
} 

fn addx(a: f64, b: f64) -> f64 { 
    binop(|&: a: f64, b: f64| a + b, a, b) 
} 

fn main() { 
    println!("{}", addx(1.0, 2.0)); 
} 

(попробуйте here)

+0

Спасибо за информацию. Несколько коммитов приземлились, но RFC в целом действительно не завершен, мне следовало бы более внимательно рассмотреть вопрос, связанный с github. Извините за это. – pao

Смежные вопросы