Reputation: 889
I tried to sketch a generic way of running “problems” represented according to the struct Problem
below. These structs include test input/output and a solver function. My goal is to run these problems either by interacting with standard I/O, or by some tester function that verifies the validity of the solver
against the given test_input
/test_output
. The sketch here only includes a tester function.
When I try to compile it, I get type mismatches:
problem.rs:43:22: 43:27 error: mismatched types:
expected `R`,
found `std::io::cursor::Cursor<&[u8]>`
(expected type parameter,
found struct `std::io::cursor::Cursor`) [E0308]
problem.rs:43 (problem.solver)(input, &mut output);
^~~~~
problem.rs:43:22: 43:27 help: run `rustc --explain E0308` to see a detailed explanation
problem.rs:43:29: 43:40 error: mismatched types:
expected `&mut W`,
found `&mut std::io::cursor::Cursor<collections::vec::Vec<u8>>`
(expected type parameter,
found struct `std::io::cursor::Cursor`) [E0308]
problem.rs:43 (problem.solver)(input, &mut output);
^~~~~~~~~~~
problem.rs:43:29: 43:40 help: run `rustc --explain E0308` to see a detailed explanation
error: aborting due to 2 previous errors
I was expecting the compiler to take Cursor<&[u8]>
as a BufRead
er, and Cursor<Vec<u8>>
as a Write
r, but it didn’t work. I don’t know what to make of the expectation for an R
or a W
.
I tried to run a similar tester function by calling directly the solver, without involving a Problem
at all, and it worked; so I suppose these errors might have something to do with the way I call (problem.solver)(input, &mut output)
. Other than this, I have no clue. Can somebody please give me a hint of what’s happening here?
use std::io::prelude::*;
use problems::Problem;
mod problems {
use std::io::prelude::*;
pub struct Problem<'a, R, W>
where R: BufRead, W: Write
{
test_input: &'a str,
test_output: &'a str,
solver: Box<fn(R, &mut W)>,
}
mod a_problem {
use std::io::prelude::*;
use super::Problem;
pub fn getProblem<'a, R, W>() -> Problem<'a, R, W>
where R: BufRead, W: Write
{
Problem {
test_input: unimplemented!(),
test_output: unimplemented!(),
solver: Box::new(solver),
}
}
fn solver<R, W>(input: R, output: &mut W)
where R: BufRead, W: Write
{
unimplemented!();
}
}
}
fn test_solver<R, W>(problem: Problem<R, W>)
where R: BufRead, W: Write
{
let input = std::io::Cursor::new(problem.test_input.as_bytes());
let mut output = std::io::Cursor::new(Vec::<u8>::new());
(problem.solver)(input, &mut output);
assert_eq!(problem.test_output.as_bytes(), &*output.into_inner());
}
fn main() {
let problem = problems::a_problem::getProblem();
test_solver(problem);
}
Upvotes: 1
Views: 471
Reputation: 65692
The way you defined the Problem
struct means that R
and W
are fixed at the time the Problem
is instantiated. In test_solver
, you allow the caller to specify any R
and any W
they want, but then you try to pass specific Cursor
types to (problem.solver)
instead.
You can fix this in two ways:
1) Don't define test_solver
as a generic function. Note that you wouldn't be to call (problem.solver)
multiple times with different types for R
and W
.
fn test_solver<'a>(problem: Problem<'a, std::io::Cursor<&'a [u8]>, std::io::Cursor<Vec<u8>>>)
{
let input = std::io::Cursor::new(problem.test_input.as_bytes());
let mut output = std::io::Cursor::new(Vec::<u8>::new());
(problem.solver)(input, &mut output);
assert_eq!(problem.test_output.as_bytes(), &*output.into_inner());
}
2) Don't define the solver
field as generic. Have the function take trait references instead.
use std::io::prelude::*;
use problems::Problem;
mod problems {
use std::io::prelude::*;
pub struct Problem<'a>
{
pub test_input: &'a str,
pub test_output: &'a str,
pub solver: Box<fn(&mut BufRead, &mut Write)>,
}
pub mod a_problem {
use std::io::prelude::*;
use super::Problem;
pub fn getProblem<'a>() -> Problem<'a>
{
Problem {
test_input: unimplemented!(),
test_output: unimplemented!(),
solver: Box::new(solver),
}
}
fn solver(input: &mut BufRead, output: &mut Write)
{
unimplemented!();
}
}
}
fn test_solver(problem: Problem)
{
let mut input = std::io::Cursor::new(problem.test_input.as_bytes());
let mut output = std::io::Cursor::new(Vec::<u8>::new());
(problem.solver)(&mut input, &mut output);
assert_eq!(problem.test_output.as_bytes(), &*output.into_inner());
}
fn main() {
let problem = problems::a_problem::getProblem();
test_solver(problem);
}
Upvotes: 4