PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Wednesday, July 6, 2022

[FIXED] How does this recursive join work in Rust

 July 06, 2022     pass-by-reference, recursion, reference, rust     No comments   

Issue

So I wrote this recursive string join function in Rust which seems to work, but I'm a bit confused why it works.

fn join(separator: &str, strs: &[&str]) -> String {
    match strs.len() {
        l if l > 1    => return strs[0].to_string() + separator + &join(separator, &strs[1..]),
        l if l == 1   => return strs[0].to_string(),
        _             => return "".to_string(),
    }
}

So I have an array of 3 Strings that I would like to join and a String separator. The function takes in the reference to a str &str for its first argument and then a reference to an array of Strings &[&str] for the second argument.

let j1 = ["one", "two", "three"];
println!("{}", join(", ", &j1));
  1. Why does the recursive join have to be defined as &join(separator, &strs[1..])?
  2. why does &strs[1..] have to be dereferenced again?

Solution

  1. std::ops::Add<&'_ str> is implemented for String (scroll to the very bottom of the page). std::ops::Add<String> is not. Hence, you can only add &'_ strs to Strings, and only on the right hand side. You have to reference your call to join because that uses deref coercion to turn the String into a &str.

  2. This one is a bit more convoluted to provide exact evidence for, but in simplest terms, slicing (using a range in the index position) a slice or array will produce a slice, IE, [T]. Since you can't pass around bare [T]s around, you need to take a reference to it.
    The more exact reason as to why is:

    • Index<i> is impl-ed for [T] where I: SliceIndex<[T]>.
    • The output is I's output as a SliceIndex.
    • 1.. is a [std::ops::RangeFrom](https://doc.rust-lang.org/beta/std/ops/struct.RangeFrom.html).
    • SliceIndex<[T]> is impl-ed for all [T] on RangeFrom<usize>.
    • The output is [T] and not &[T].

Additionally, this isn't the most idiomatic way of writing this function:

pub fn join(separator: &str, strs: &[&str]) -> String {
    match strs {
        [last]               => last.to_string(),
        [current, rest @ ..] => current.to_string() + separator + &join(separator, &rest),
        []                   => "".to_string(),
    }
}

Pattern matching works on slices.



Answered By - Optimistic Peach
Answer Checked By - Clifford M. (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing