Hi,
I'm a C and Fortran programmer for high performance systems and want to dive into Rust. I read "The Rust Programming Language", but I learn new languages mostly by playing around with the compiler and trying out stuff. I would like to understand how polymorphism works in Rust.
My aim is to have something like this and the compiler working out the appropriate types:
let vector = Vector::new(5);
let matrix = Matrix::new(5,5);
let result = dotproduct(vector, matrix);
The dotproduct
function should result in a new vector. If I give it two vectors it should produce a new vector and if I give it two matrices it should return a matrix.
In Fortran I would implement the appropriate function for each type combination and create an interface and the compiler will figure out what actual function to call.
In C this is not really possible.
Here is what I got so far:
struct Vector {
len: usize,
data: Vec<f64>
}
impl Vector {
pub fn new(len: usize) -> Vector {
return Vector {
len: len,
data: vec![0.0; len]
}
}
pub fn print(&self) {
print!("Vector (len = {}):", self.len);
for idx in 0..self.len {
print!(" {:5.3}", self.data[idx]);
}
print!("\n");
}
}
struct Matrix {
nrows: usize,
ncols: usize,
data: Vec<f64>
}
impl Matrix {
pub fn new(nrows: usize, ncols: usize) -> Matrix {
return Matrix {
nrows: nrows,
ncols: ncols,
data: vec![0.0; nrows*ncols]
}
}
pub fn print(&self) {
print!("Matrix ({}X{}):\n", self.nrows, self.ncols);
for irow in 0..self.nrows {
let rowidx = irow*self.ncols;
for icol in 0..self.ncols {
let idx = rowidx + icol;
print!(" {:5.3}", self.data[idx]);
}
print!("\n");
}
}
}
// This is the part where I am unsure what to do exactly
// because I do not understand the trait and generics system fully
trait DotProduct {
fn dotproduct<A,B>(a: &A, b: &B) -> B;
}
impl DotProduct for Vector {
fn dotproduct<Matrix, Vector>(a: &Matrix, b: &Vector) -> Vector {
let mut result = Vector::new(a.nrows);
// Some calculation on `a` and `b` to be done!
return result;
}
}
fn main() {
let vector = Vector::new(5);
vector.print();
let matrix = Matrix::new(5,5);
matrix.print();
let result = dotproduct(matrix, vector);
}
I am defining structs to hold the data for a vector and a matrix, and define new
and print
methods for those.
Then my understanding of Rust is not enough to continue.
I understand that I need a trait lets call it DotProduct
where I specify which functionality needs to be implemented if a struct should adopt the trait. Since the function I define is not a method but an associated function with different types, I thought type parameters are the way to go.
In the trait implementation block I thought I should fill in the types I want to implement the function for.
If I try to compile it I get the following error messages:
$ cargo run
Compiling testcase v0.1.0 (/home/fuhl/software/Rust/testcase)
error[E0425]: cannot find function `dotproduct` in this scope
--> src/main.rs:69:18
|
69 | let result = dotproduct(matrix, vector);
| ^^^^^^^^^^ not found in this scope
error[E0599]: no function or associated item named `new` found for type parameter `Vector` in the current scope
--> src/main.rs:57:34
|
57 | let mut result = Vector::new(a.nrows);
| ^^^ function or associated item not found in `Vector`
error[E0609]: no field `nrows` on type `&Matrix`
--> src/main.rs:57:40
|
56 | fn dotproduct<Matrix, Vector>(a: &Matrix, b: &Vector) -> Vector {
| ------ type parameter 'Matrix' declared here
57 | let mut result = Vector::new(a.nrows);
| ^^^^^
Some errors have detailed explanations: E0425, E0599, E0609.
For more information about an error, try `rustc --explain E0425`.
error: could not compile `testcase` due to 3 previous errors
The first thing I do not understand is why new
is not found on line 57. I clearly implemented new
for the Vector struct.
Next I do not understand why the nrows
is apparently not a field in the Matrix
struct on line 57. I clearly defined it to be.
Those errors do not appear if I access the fields or methods outside of the impl
scope for the DotProduct trait.
If I take out the trait
related stuff, the code compiles and runs fine.
Could someone also explain to me how to achieve the kind of polymorphism I am aiming at here?
Thanks a lot in advance. Help is appreciated.