CodeBlanks Logo Icon CodeBlanks

Binding modes

Learn binding modes with ref and ref mut.

Binding modes

A pattern can bind a value in three ways: by moving (the default), by borrowing with ref, by mutable borrowing with ref mut. Today you mostly don't need to write these: when matching on a reference (match &x, match &mut x), the compiler picks the binding mode itself:

let mut cift = (String::from("a"), 1);
match &mut cift {
    (s, n) => {          // s: &mut String, n: &mut i32
        s.push('!');
        *n += 1;
    }
}
println!("{:?}", cift);   // ("a!", 2)

When is ref needed?

When matching on the value itself and you want to borrow one part while moving another, ref is still useful:

let kayit = (String::from("ece"), vec![1, 2]);
let (ref ad, puanlar) = kayit;   // ad borrowed, puanlar moved
println!("{ad} {:?}", puanlar);
// kayit.1 can no longer be used; kayit.0 can

Partial move and partial borrow together; this fine control lets you split large structures without needless copies.

Practice Change in place

Declare let mut cift = (String::from("a"), 1);. With match &mut cift, append '!' to the text and increment the number by 1; then print cift with {:?}.

Starter code

main.rs
fn main() {
    // buraya yaz
}

Sample solution

main.rs
fn main() {
    let mut cift = (String::from("a"), 1);
    match &mut cift {
        (s, n) => {
            s.push('!');
            *n += 1;
        }
    }
    println!("{:?}", cift);
}

Expected output

("a!", 2)

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Can <code>opt</code> be used after <code>match opt { Some(s) =&gt; .., None =&gt; .. }</code> (<code>opt: Option&lt;String&gt;</code>)?

  • Yes
  • Only if it's None
  • It doesn't compile
  • No; the String was moved into s. You need to match on &opt Correct answer

Explanation: With match &opt, s becomes a &String and opt keeps ownership; Some(ref s) is the older form.

2 Mutable matching

Question
match ____ cift {
    (s, n) => {
        s.push('!');
        *n += 1;
    }
}
Answer
match &mut cift {
    (s, n) => {
        s.push('!');
        *n += 1;
    }
}

Explanation: When matching on &mut, the bindings become &mut.

3 Matching and binding type

Term Meaning
match x { (s, _) } Move
match &x { (s, _) } &String
match &mut x { (s, _) } &mut String
let (ref a, b) = x; a borrowed, b moved

All lessons in Advanced