Chain methods in Vec?

Like digest::Update::chain.

trait VecChain<T> {
    fn chain_push(self, value: T) -> Self;
    fn chain_extend<I: IntoIterator<Item = T>>(self, iter: I) -> Self;
}

impl<T> VecChain<T> for Vec<T> {
    fn chain_push(mut self, value: T) -> Self {
        self.push(value);
        self
    }

    fn chain_extend<I: IntoIterator<Item = T>>(mut self, iter: I) -> Self {
        self.extend(iter);
        self
    }
}

#[derive(Clone, Copy, Debug)]
struct Item;

fn main() {
    let v = Vec::new()
        .chain_push(Item)
        .chain_extend([Item; 3]);
    dbg!(v);
}

playground

1 Like

The same concept for String:

trait StringChain {
    fn chain_push(self, ch: char) -> Self;
    fn chain_push_str(self, string: &str) -> Self;
}

impl StringChain for String {
    fn chain_push(mut self, ch: char) -> Self {
        self.push(ch);
        self
    }

    fn chain_push_str(mut self, string: &str) -> Self {
        self.push_str(string);
        self
    }
}

fn main() {
    let s = String::new()
        .chain_push('a')
        .chain_push_str("bcd");
    dbg!(s);
}

playground

Vec::chain_append for Vec::append can also be considered.

That seems quite specific. Since it's already implementable with an extension trait or applied in a more general fashion with the tap crate I don't see much benefit of having it in std.

7 Likes

This changes the API, but the goal is to have a nicer syntax. There are plenty of other types that could want fluent API too. This could be addressed more directly with a pipeline operator (|> in some languages).

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.