Discussion: Better Method Chaining in Rust

A Real-World Example


                    let result = Command::new("foo")
                        .arg("--bar")
                        .arg("--baz")
                        .arg("quux")
                        .status()
                        .unwrap();
                    

                    let command = Command::new("foo")
                        .arg("--bar");

                    if set_baz {
                        command.arg("--baz");
                    }

                    let result = command
                        .arg("quux")
                        .status()
                        .unwrap();
                    

                    error[E0716]: temporary value dropped while borrowed
                     --> src/main.rs:6:19
                      |
                    6 |     let command = Command::new("foo").arg("--bar");
                      |                   ^^^^^^^^^^^^^^^^^^^             - temporary value is freed at the end of this statement
                      |                   |
                      |                   creates a temporary which is freed while still in use
                    ...
                    9 |         command.arg("--baz");
                      |         ------- borrow later used here
                      |
                      = note: consider using a `let` binding to create a longer lived value
                    

                    let mut command = Command::new("foo");
                    command.arg("--bar");

                    if set_baz {
                        command.arg("--baz");
                    }

                    let result = command
                        .arg("quux")
                        .status()
                        .unwrap();
                    

Method Chaining Today


                    pub fn arg<S>(&mut self, arg: S) -> &mut Command {
                        // Add the argument...
                        self
                    }
                    

                    pub fn chain_ref(&mut self) -> &mut Self {
                        // Do some work...
                        self
                    }

                    pub fn chain_move(mut self) -> Self {
                        // Do some work...
                        self
                    }
                    

A Digression


                    someValue
                        ..foo()
                        ..bar()
                        ..baz();
                    

                    foo() |> bar() |> baz()
                    

Some Existing Alternatives

cascade


                    let cascaded_list = cascade! {
                        Vec::new();
                        ..push("Cascades");
                        ..push("reduce");
                        ..push("boilerplate");
                    };
                    

pipeline


                    let result = pipe_res!(
                        "http://rust-lang.org"
                        => download
                        => parse
                        => get_links
                    );
                    

Discuss!