Pattern question

Hello everyone

Sample working code, producing identical results:

fn main2() {
    let input_string1 = r#"He""l:lo/Wor*ld\\<GPT-3>?*""#.to_string();
    let input_string2 = input_string1.clone();

    // question re next 2 lines of code - which one to use and why?
    let s1 = input_string1.replace(&['/', '\\', '*', '\"', '?', '>', ':', '<'][..], "");
    let s2 = input_string2.replace(['/', '\\', '*', '\"', '?', '>', ':', '<'], "");


Please see the two patterns above - ref to two-dimensional array and ref to one-dim array.

I would like explanation of why the &ref to 2-dimensional array works what are the reasons for implementing it and advantages of using & [ ] [ . . ] versus a simple [ . . ] array ?
Is it about performance? or additional functionality? or both?

thank you

No, they're both one-dimensional. Could you explain why you think &[_][..] is two-dimensional?

I mean, the first one works because it's just a normal array reference, and that's a pretty basic thing to want to use. Without digging into the implementation, I'd hazard a guess that the second probably works for one or more of the following reasons:

a. It's slightly more convenient to type.
b. It's slightly more performant.
c. There's no compelling reason not to support it.

1 Like

The thing you call “ref to two-dimensional array” is actually producing a slice (reference). Searching by slice (reference), i.e. with &[char] was originally the only supported kind of “list of characters” pattern.

With the introduction of const generics, the standard library could then move on to support more alternatives, and has since added support for &[char; N] and [char; N], i.e. reference to array, and array by-value.

The’s a slight performance benefit for the array because the loop that searches the character can be special-cased to the specific length at hand (and thus more easily unrolled for short lists).

Another main motivation though was probably that previously, passing a reference to an array would have failed to compile. For methods where &[T] is supported, giving &[T; N] works, too, due to automatic coercion, but for generic methods like replace<'a, P: Pattern<'a>>(&'a self, from: P, …) that doesn’t work anymore.

As for the performance of using &[char; N] vs [char; N], I’m not entirely sure… of course for very long lists, there could be an advantage in avoiding to pass the array by-value.

For completeness, calling the replace method with a &[char; N] reference would look like .replace(&['/', '\\', '*', '\"', '?', '>', ':', '<'], ""). Generally, if arr is an array of type [T; N], then &arr is a &[T; N] and &arr[..] or arr.as_slice() is a &[T].

Also, your calls to replace won’t consume the string, so the initial .clone to a second input_string2 is entirely unnecessary.


My brain fade, I have not looked at Rust for almost a year....
I got confused because I saw 2 sets of brackets [ ] [ ] well, duhh... LOL
IE Like this code:

    let mut char_2d_array: [[char; 3]; 4] = [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'], ['j', 'k', 'l']];

    // Access and modify elements in the array
    char_2d_array[1][1] = 'X';

so in this line


it is a & ref to entire ( [ . . ] ) slice of a one-dimensional array of char

Thank you for the explanations in any case.

This all works nicely with Vec < char > too such as this:

    let mut illegals = ('\x00'..='\x1F').collect::<Vec<_>>();
    illegals.append(&mut vec!['/', '\\', ':', '*', '?', '"', '<', '>']);

    let mut filnm2 = r#"Hello, colon{:} Yuri; gt{>} lt{<} aster{*} question{?} back{\} forward{/} two+back{\\} single{'} double{"} World!"#

    filnm2 = filnm2.replace(&illegals[..][..], "");  //works

    filnm2 = filnm2.replace(&illegals[..], ""); // works 


Rust indeed rocks.

Happy 2024 to everyone, here is hoping my Rust skills will improve this year.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.