title: How to pass &mut str and change the original mut str without a return?
body: <p>I'm learning Rust from the Book and I was tackling the exercises at the end of chapter 8, but I'm hitting a wall with the one about converting words into Pig Latin. I wanted to see specifically if I could pass a <code>&amp;mut String</code> to a function that takes a <code>&amp;mut str</code> (to also accept slices) and modify the referenced string inside it so the changes are reflected back outside without the need of a <code>return</code>, like in C with a <code>char **</code>.</p>
  <p>I'm not quite sure if I'm just messing up the syntax or if it's more complicated than it sounds due to Rust's strict rules, which I have yet to fully grasp. For the lifetime errors inside <code>to_pig_latin()</code> I remember reading something that explained how to properly handle the situation but right now I can't find it, so if you could also point it out for me it would be very appreciated.</p>
  <p>Also what do you think of the way I handled the chars and indexing inside strings?</p>
  <pre><code>use std::io::{self, Write};
  
  fn main() {
      let v = vec![
          String::from(&quot;kaka&quot;),
          String::from(&quot;Apple&quot;),
          String::from(&quot;everett&quot;),
          String::from(&quot;Robin&quot;),
      ];
  
      for s in &amp;v {
          // cannot borrow `s` as mutable, as it is not declared as mutable
          // cannot borrow data in a `&amp;` reference as mutable
          to_pig_latin(&amp;mut s);
      }
  
      for (i, s) in v.iter().enumerate() {
          print!(&quot;{}&quot;, s);
  
          if i &lt; v.len() - 1 {
              print!(&quot;, &quot;);
          }
      }
  
      io::stdout().flush().unwrap();
  }
  
  fn to_pig_latin(mut s: &amp;mut str) {
      let first = s.chars().nth(0).unwrap();
      let mut pig;
  
      if &quot;aeiouAEIOU&quot;.contains(first) {
          pig = format!(&quot;{}-{}&quot;, s, &quot;hay&quot;);
          s = &amp;mut pig[..]; // `pig` does not live long enough
      } else {
          let mut word = String::new();
  
          for (i, c) in s.char_indices() {
              if i != 0 {
                  word.push(c);
              }
          }
  
          pig = format!(&quot;{}-{}{}&quot;, word, first.to_lowercase(), &quot;ay&quot;);
          s = &amp;mut pig[..]; // `pig` does not live long enough
      }
  }
  </code></pre>
  <p><strong>Edit: here's the fixed code with the suggestions from below.</strong></p>
  <pre><code>fn main() {
      // added mut
      let mut v = vec![
          String::from(&quot;kaka&quot;),
          String::from(&quot;Apple&quot;),
          String::from(&quot;everett&quot;),
          String::from(&quot;Robin&quot;),
      ];
  
      // added mut
      for mut s in &amp;mut v {
          to_pig_latin(&amp;mut s);
      }
  
      for (i, s) in v.iter().enumerate() {
          print!(&quot;{}&quot;, s);
  
          if i &lt; v.len() - 1 {
              print!(&quot;, &quot;);
          }
      }
  
      println!();
  }
  
  // converted into &amp;mut String
  fn to_pig_latin(s: &amp;mut String) {
      let first = s.chars().nth(0).unwrap();
  
      if &quot;aeiouAEIOU&quot;.contains(first) {
          s.push_str(&quot;-hay&quot;);
      } else {
          // added code to make the new first letter uppercase
          let second = s.chars().nth(1).unwrap();
  
          *s = format!(
              &quot;{}{}-{}ay&quot;,
              second.to_uppercase(),
              // the slice starts at the third char of the string, as if &amp;s[2..]
              &amp;s[first.len_utf8() * 2..],
              first.to_lowercase()
          );
      }
  }
  </code></pre>