2015-06-09 2 views
0

Чтобы узнать о Rust, я начал реализовывать некоторые проблемы Project Euler. Теперь я хочу сделать следующий шаг и создать консольный пользовательский интерфейс, который имеет возможность запускать все или только конкретные проблемы. Другое требование состоит в том, что пользователь должен иметь возможность передавать необязательные параметры только по конкретной проблеме.Как объединить разные алгоритмы в одном исполняемом файле

Мое текущее решение должно иметь черту ProjectEulerProblem, которая объявляет, например, run(). С этими словами я могу сделать что-то вроде этого:

fn main() { 
    let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit()); 

    let problems: Vec<Box<problems::ProjectEulerProblem>> = vec![ 
     box problems::Problem1, 
     box problems::Problem2 
    ]; 

    match args.flag_problem { 
     Some(x) => println!("Result of problem: {} is {}", x, problems[x-1].run()), 
     None => println!("No problem number given.") 
    } 
} 

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

+0

Так что вы хотите только указать общее количество проблем, а не полные имена проблемы, или вы хорошо с помощью макроса, который требует вы должны указать все номера проблем, такие как '[1, 2]' в вашем случае –

+0

Я думаю, что макрос с использованием '[1, 2]' должен быть в порядке. – kunerd

+0

@kunerd: при написании этого, используя 'Vec >' не нужно, требуя выделения; он может быть определен полностью статически, '& 'static [&' static Problem]' –

ответ

2

Вы можете использовать macro with repetition, чтобы генерировать свой список, не набирая полный путь и имя каждый раз.

macro_rules! problem_vec(
    ($($prob:tt),*) => ({ 
     &[ 
      $(
       &concat_idents!(Proble, $prob), 
      )* 
     ] 
    }); 
); 
const PROBLEMS: &'static[&'static ProjectEulerProblem] = problem_vec!(m1, m2); 

Обратите внимание, вы не можете просто использовать индексы, поскольку concat_idents макрос требует идентификатора и номера не являются идентификаторами. concat_idents также доступен только по ночам. На стабильной вы должны дать полное имя структуры:

macro_rules! problem_vec(
    ($($prob:ident),*) => ({ 
     &[ 
      $(
       &problems::$prob, 
      )* 
     ] 
    }); 
); 

const PROBLEMS: &'static [&'static problems::ProjectEulerProblem] = problem_vec!(
    Problem1, Problem2 
); 

PlayPen