I want to "hide" a vector type using a trait Vector.
I also want this trait to provide a method to push values to implementers via a string reference.
Ideally, I'd like to use the FromStr trait to automatically implement the Vector trait. Here you have an example (it does not compile):
use std::str::FromStr;
trait Vector {
fn try_push(&mut self, val: &str) -> Result<(), ()>;
}
struct MyVec<T>(Vec<T>);
impl<T: FromStr> Vector for MyVec<T> {
fn try_push(&mut self, val: &str) -> Result<(), ()> {
match T::from_str(val) {
Ok(val) => {
self.0.push(val);
Ok(())
},
Err(_) => Err(()),
}
}
}
impl<T: !FromStr> Vector for MyVec<T> {
fn try_push(&mut self, val: &str) -> Result<(), ()> {
Err(())
}
}
The compiler complains because "negative bounds are not supported". I am aware that negative bounds are not currently supported by stable Rust, but cannot figure out how to implement what I want. Can anyone suggest me the most appropriate way to implement this pattern?
Related
I'm currently develloping my own library for vectors and matrices, and to simplify my life, I defined my Matrix to be a Vec of Vector, and defined the Deref trait as such:
pub struct Matrix(Vec<RowVector>);
impl Deref for Matrix {
type Target = [RowVector];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Matrix {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
This work like a charm, but it has one flaw: you can override one row to be a RowVector of a different size of the rest, which is obviously VERY BAD.
Am I doomed? is there a solution to disallow the overwrite but allow to mutate the Vector ?
You could implement Index and IndexMut over a pair (usize, usize):
use std::ops::{IndexMut, Index};
pub struct Matrix(Vec<Vec<usize>>);
impl Index<(usize, usize)> for Matrix {
type Output = usize;
fn index(&self, index: (usize, usize)) -> &Self::Output {
self.0.get(index.0).unwrap().get(index.1).unwrap()
}
}
impl IndexMut<(usize, usize)> for Matrix {
fn index_mut(&mut self, index: (usize, usize)) -> &mut Self::Output {
self.0.get_mut(index.0).unwrap().get_mut(index.1).unwrap()
}
}
Playground
Disclaimer: Please take into account that using unwrap is not clean here. Either assert lengths, deal with options or at least use expect depending on your needs.
This is literally the same question as this C++ question, but in Rust.
Suppose I have a "sparse vector" type that stores filled entries in a map of some kind. Unfilled entries are some kind of default value, like 0.
use std::ops::{Index, IndexMut};
use std::collections::BTreeMap;
use num_traits::Float;
struct SparseVector<T: Float, const N: usize>(BTreeMap<usize, T>);
// Returning a ref is easy when a value is present.
impl<T: Float, const N: usize> IndexMut<usize> for SparseVector<T, N> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.0.entry(index).or_insert(T::zero())
}
}
// What to return when we hit the default?
impl<T: Float, const N: usize> Index<usize> for SparseVector<T, N> {
type Output = T;
fn index(&self, index: usize) -> &T {
match self.0.get(&index) {
Some(value) => t,
None => ???
}
}
}
To implement Index on this type, I need to return a &T. For filled entries, that's just a reference to the value. How do I return a ref to the default?
I obviously can't return a &0 for lifetime reasons.
I can't necessarily store the default in a const field of the struct impl. It might not come from a const function.
I'm trying to avoid storing the default value on every instance of the type. It's literally the same value, why must it be allocated on every instance, etc.
The C++ answer is to return an instance of a wrapper type that dereferences to a &T. But in Rust, a Deref<Target = &T> cannot be substituted for &T, as far as I know.
How can I implement Index (override the [] operator) on this type?
You cannot.
There were some discussions around extending the Index and Deref traits to support situations similar to that (https://github.com/rust-lang/rfcs/issues/997), but today you cannot.
This particular case is even more problematic because it requires GAT: the trait will have to be defined like:
pub trait IndexGat<I> {
type Output<'a>: Deref
where
Self: 'a;
fn index(&self, index: I) -> Self::Output<'_>;
}
impl<I, T: Index> IndexGat<I> for T {
type Output<'a> = &'a <Self as Index>::Output
where
Self: 'a;
fn index(&self, index: I) -> Self::Output<'_> { <Self as Index>::index(self, index) }
}
So you can implement it:
impl<T, const N: usize> IndexGat<usize> for SparseVector<T, N> {
type Output<'a> = Wrapper<'a, T>;
where
Self: 'a;
fn index(&self, index: usize) -> Self::Output<'_> { ... }
}
pub enum Wrapper<'a, T> {
Default(T),
Ref(&'a T),
}
impl<T> Deref for Wrapper<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
match self {
Self::Default(v) => v,
Self::Ref(v) => *v,
}
}
}
So it cannot be done until GATs are stabilized.
The best thing you can do is just to use a regular method get() (or at(), or whatever).
First, I know I can use Box if I want to define a recursive structure. For example,
struct LinkNode {
next: Option<Box<LinkNode>>
}
impl LinkNode{
fn get_next(&self) -> Option<Box<LinkNode>>{
None
}
fn append_next(&mut self, next: LinkNode) -> Self{
self
}
}
But how can I make a trait on these structures via templates or trait object?
Due to the existence of fn append_next(...) -> Self, I cannot create a trait object directly like this:
pub trait Linkable {
fn get_next(&self) -> Option<Box<dyn Linkable>>;
fn append_next(&mut self, next: impl Linkable) -> Self;
}
And we cannot return Option<Box<impl Linkable>> or impl Linkable for fn get_next(&self).
Then I tried the following implementation via generic templates and it does not work.
Because I need to assign the type of T recursively when construct a new LinkNode.
pub trait Linkable<T:Linkable<T> + Clone> : Clone {
fn get_next(&self) -> Option<Box<T>>;
fn append_next(&mut self, next: T) -> Self;
}
I finally implement it in this way, by creating other traits for assistance. And it works well. Again...Is there other better ways?
pub trait Linkable: LinkClone{
fn get_next(&self) -> Option<Box<dyn Linkable>>;
}
pub trait LinkAppend {
fn append_next(&mut self, next: Box<dyn Linkable>) -> Box<dyn Linkable>;
}
pub trait LinkClone{
fn clone_box(&self) -> Box<dyn Linkable>;
}
impl<T> LinkClonefor T
where
T: 'static + Linkable+ LinkAppend + Clone,
{
fn clone_box(&self) -> Box<dyn Linkable> {
Box::new(self.clone())
}
}
impl Clone for Box<dyn Linkable> {
fn clone(&self) -> Box<dyn Linkable> {
self.clone_box()
}
}
BTW, I have some other questions during the exploration above: Why Rust forbids the impl Linkable sugar, like the Box<impl Linkale>? And why returning impl Linkable is forbidden in a trait?
Updated after Ibraheem's answer:
Except the associated type implementation from Ibraheem, it is also fine to work like this. The core idea is to avoid the recursive type declaration in the trait.
pub trait Linkable {
fn get_next<T:Linkable>(&self) -> Next<T>;
fn append_next<T:Linkable>(&mut self, next: Next<T>) -> Self;
}
struct Next<T: Linkable> {
node: T,
}
This is mentioned in another question: Can I define a trait with a type parameter of itself in Rust?
Linkable could have associated type called Next.
pub trait Linkable {
type Next: Linkable;
}
get_next now returns an instance of type Self::Next, and append_next takes Self::Next as a parameter:
pub trait Linkable {
type Next: Linkable;
fn get_next(&self) -> Option<Self::Next>;
fn append_next(&mut self, next: Self::Next) -> &Self;
}
Now you can implement Linkable for Linknode:
impl Linkable for LinkNode {
type Next = LinkNode;
fn get_next(&self) -> Option<Box<LinkNode>> {
None
}
fn append_next(&mut self, next: LinkNode) -> &Self {
self
}
}
Why Rust forbids the impl Linkable sugar, like the Box? And why returning impl Linkable is forbidden in a trait?
You can refer to Is it possible to use impl Trait as a function's return type in a trait definition? for the answer to this question.
I have a trait, MyGoodTrait, with the function label(&self) -> &str. I want every implementor of MyGoodTrait to also implement Display and FromStr. However, I do not necessarily need Display and FromStr to be supertraits of MyGoodTrait. I would rather somehow have a default implementation of Display and FromStr, which will internally use the label function from MyGoodTrait. That way, every implementor of MyGoodTrait will get Display and FromStr "for free", as if there was a default implementation for those traits.
Here is an example that is similar to what I want to do, but it does not compile:
use std::str::FromStr;
pub trait MyGoodTrait {
fn new() -> Self;
fn label(&self) -> &'static str;
}
impl FromStr for dyn MyGoodTrait {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::new())
}
}
pub struct A {}
impl MyGoodTrait for A {
fn new() -> Self {
A{}
}
fn label(&self) -> &'static str {
"A"
}
}
pub struct B {}
impl MyGoodTrait for B {
fn new() -> Self {
B{}
}
fn label(&self) -> &'static str {
"B"
}
}
// In this hypothetical, A and B now both have `fmt` and `from_str` functions
Is there a way to write this default implementation of Display and FromStr, such that I do not have to duplicate the code for each struct that implements MyGoodTrait?
Note: My actual use case is that I have a trait which has serde::se::Serialize and serde::de::Deserialize as supertraits. The implementors of my trait will be used as keys in a map, and I will serialize the map to JSON, so I need the implementors to be serialized to Strings. So this may be an example of the XY Problem
TL;DR: You can't.
You can't implement FromStr for dyn SomeTrait because it has a method that returns a Result<Self, _>, hence you can only implement it for types whose size are know at compile time, which is not the case of trait objects.
What you would really want is
impl<T: MyGoodTrait> FromStr for T
But now you might violate the orphan rule. As the compiler explains:
Implementing a foreign trait is only possible if at least one of the types for which is it implemented is local.
Only traits defined in the current crate can be implemented for a type parameter.
But you could do it if FromStr was a local trait instead:
/// Copy of `std::str::FromStr`
trait Foo: Sized {
type Err;
fn from_str(s: &str) -> Result<Self, Self::Err>;
}
impl<T: MyGoodTrait> Foo for T {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::new())
}
}
Or you could implement it for any specific local type:
impl FromStr for A {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::new())
}
}
I'm trying to write an extension trait that allows me to move any value of type T into any Box<B>, where Box<T> can be coerced into Box<B>. My first attempt is the following:
trait IntoBox<B: ?Sized> {
fn into_box(self) -> Box<B>;
}
impl<T, B: ?Sized> IntoBox<B> for T
where
Box<T>: Into<Box<B>>,
{
fn into_box(self) -> Box<B> {
Box::new(self).into()
}
}
fn main() {
// Ok
let _: Box<u32> = 42.into_box();
// Error: the trait bound `std::boxed::Box<std::fmt::Display>:
// std::convert::From<std::boxed::Box<&str>>` is not satisfied
let _: Box<std::fmt::Display> = "Hello World".into_box();
}
This code works for regular boxes, but not trait objects. I suspect Into is the wrong bound here. What should I use instead?
Edit: As explained in the answer to this question, this problem can be solved with respect to any number of concrete types T by providing a blanket impl for T: Unsize<U>. However this does not work in the generic case because the impls would be conflicting:
impl<T, B> IntoBox<B> for T
where
Box<T>: Into<Box<B>>,
{
fn into_box(self) -> Box<B> {
Box::new(self).into()
}
}
impl<T, B: ?Sized> IntoBox<B> for T
where
B: std::marker::Unsize<T>
{
fn into_box(self) -> Box<B> {
Box::new(self)
}
}