Тип функции против типа закрытия

#rust

#закрытие #Ржавчина

Вопрос:

Я хочу создать вектор функций

 let all_rerankers =  vec![ match_full
                         , match_partial
                         , match_regex
                         , match_camel_case
                         ];
  

Однако match_camel_case требуется на один параметр больше, чем для других функций, поэтому я подумал, что мог бы определить закрытие для match_camel_case

 // 3 is the extra parameter needed by match_camel_case
let close_camel_case = |str: amp;str, keyword: amp;str| {
    match_camel_case(str, keyword, 3) 
};
  

а затем укажите тип моего вектора:

 let all_rerankers: Vec<|str: amp;str, kwd: amp;str| -> MatchScore>
    = vec![ match_full
          , match_partial
          , match_regex
          , close_camel_case
          ];
  

Однако его компиляция показывает мне, что Rust относится к ним по-разному:

 mismatched types: expected `fn(amp;str, amp;str) -> MatchScore`, 
found `|amp;str, amp;str| -> MatchScore` 
(expected extern fn, found fn)

close_camel_case
^~~~~~~~~~~~~~~~
  

(и аналогичная ошибка типа в моем vec! макросе)

Также, похоже, проводится различие между Fn типом и типом закрытия. Я могу сделать эту компиляцию, обернув каждую match_* функцию в замыкание, но я уверен, что есть лучшее решение.

Вопрос:

  1. В чем здесь фактическое несоответствие? сообщение об ошибке, похоже, указывает Fn на тип закрытия vs, но тогда expected extern fn, found fn в сообщении об ошибке также есть
  2. Как я могу сопоставить тип? (а именно, преобразовать закрытие в fn тип, поскольку оно чистое)

моя версия rustc: rustc 0.12.0-pre-nightly (09cebc25a 2014-09-07 00:31:28 0000) (при необходимости можно обновить)

Ответ №1:

Это похоже на какую-то досадную проблему при выводе типов. Если вы сделаете это:

 let mut all_rerankers: Vec<|str: amp;str, kwd: amp;str| -> MatchScore> = Vec::new();
all_rerankers.push(match_full);
all_rerankers.push(match_partial);
all_rerankers.push(match_regex);
all_rerankers.push(close_camel_case);
  

Тогда все в порядке. Дублирование обширно, но вы можете легко написать макрос, вызов которого может выглядеть следующим образом:

 push_to!(all_rerankers;
    match_full,
    match_partial,
    match_regex,
    close_camel_case
)
  

Вероятно, это заслуживает создания проблемы в Rust bug tracker, но старые закрытия скоро устареют, поэтому я не уверен, стоит ли это исправлять.

Комментарии:

1. На самом деле это не проблема. Это все равно, что поместить 3 элемента некоторого типа X в вектор, а затем ожидать, что вектор изменится на более общий тип Y. Если тип не задан, выводимый тип является первым, добавленным в Vec. И это имеет место здесь.