I am trying to write a print function for a binary tree and here is what I have so far:
impl TreeNode {
fn print(&self) {
self.print(0);
}
fn print(&self, level: u8) {
for _i in range(0,level) {
print!("\t");
}
match self.data {
Some(x) => println!("{}",x),
None => ()
};
match self.left {
Some(ref x) => x.print(level+1),
None => ()
};
match self.right {
Some(ref x) => x.print(level+1),
None => ()
};
}
}
I am getting the error: duplicate definition of value print
. So I was wondering if there is a way to create functions with the same name but different arguments. Alternatively optional parameters would solve this problem, but I don't think that is possible at the moment (at least I couldn't find it via a Google search).
So, what is the best way to do this? Renaming the second print function works but looks ugly and requires you to remember more than one function name if I want to (for this example) print starting from the middle of the tree.
If you come to Rust from languages like Javascript which have support for optional arguments in functions, you might find it inconvenient that there is no way to omit arguments in Rust.
Rust does not support traditional overloading where the same method is defined with multiple signatures. But traits provide much of the benefit of overloading: if a method is defined generically over a trait, it can be called with any type implementing that trait.
Rust does not have overloading, so it is impossible to have two functions or methods with the same name and with different sets of parameters.
However, it is sometimes possible to emulate overload with traits. This approach is likely inappropriate for your use case, but you can see how it is done in the standard library, where Path::new()
constructor can be called with something resembling a vector of bytes:
Path::new("/a/b/c/d") // argument is &str
Path::new(b"/a/b/c/d") // argument is &[u8]
Path::new(Path::new("/a/b/c/d")) // argument is another Path
This is done via BytesContainer
trait, and new()
method is defined like this:
fn new<T: BytesContainer>(bytes: T) -> Path { ... }
Then this trait is implemented for all the types you want:
impl<'a> BytesContainer for &'a str { ... }
impl<'a> BytesContainer for &'a [u8] { ... }
impl BytesContainer for Path { ... }
// and more
This resembles overloading precisely because new()
does exactly the same thing regardless of what kind of input it is provided; it is just a convenience thing which makes Path
constructor more flexible. In the end new()
just converts its argument to a byte slice. However, this does not allow you to have completely different functions with the same name.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With