I am writing a program for sorting a &mut [T]
to help me learn generics. I have already had a working version of the simple sorting function (optimised bubble sort) when I decided that the swapping part could be its own function. I am now stuck trying to get the swap function to compile.
I think a first step to trying to fix it would be to understand how exactly a Vec<T>
works with other owned, heap-allocated data types. Would I be correct to say that a Vec<String>
consists of the pointer, capacity and length in a heap-allocated array and the String
's chars is stored in some other random place in the heap? So that a Vec<String>
containing "Hello"
and ", world!"
would look like this:
(assume 0xabffff00 is on the heap and the value in the Vec<T>
's pointer)
0xabffff00 => ptr = 0xabffffa0
0xabffff04 => cap >= 5
0xabffff08 => len = 5
0xabffff0c => ptr = 0xabffffd4
0xabffff10 => cap = >=8
0xabffff14 => len = 8
...
0xabffffa0 => 'h'
0xabffffa1 => 'e'
0xabffffa2 => 'l'
0xabffffa3 => 'l'
0xabffffa4 => 'o'
...
0xabffffd4 => ','
0xabffffd5 => ' '
0xabffffd6 => 'w'
0xabffffd7 => 'o'
0xabffffd8 => 'r'
0xabffffd9 => 'l'
0xabffffda => 'd'
0xabffffd4 => '!'
In this case, I want to swap the ptr, cap and len of the first and second String
s, but keep the heap allocations just as they are. But I also want the swap()
function to be generic, so it should work with any data type, e.g. with i32
.
Here is the swap()
function:
fn swap<T>(a: &mut T, b: &mut T) {
let temp = a;
a = b;
b = temp;
}
It doesn't compile yet, but this should make clearer what I am trying to do.
Here is the full program:
use std::fmt::Display;
fn sort<T: PartialOrd>(list: &mut [T]) {
for i in (0..list.len()).rev() {
let mut swapped = false;
for j in 0..i {
if list[j] > list[j+1] {
swap(&mut list[j], &mut list[j+1]);
swapped = true;
}
}
if !swapped {
break;
}
}
}
fn swap<T>(a: &mut T, b: &mut T) {
let temp = a;
a = b;
b = temp;
}
fn print<T: Display>(list: &[T]) {
for (i, item) in list.iter().enumerate() {
print!("{}", item);
print!("{}", if i < list.len()-1 { ", " } else { "\n\n" });
}
}
fn main() {
let mut number_list = vec![40, 31, 98, 25, 67, 59, 72, 14];
print(&number_list);
sort(&mut number_list);
print(&number_list);
let mut string_list = vec!["Johan", "Louis", "Louis", "Clarice", "JP",
"Hannes", "Thys", "Bernard", "Mariandri"];
print(&string_list);
sort(&mut string_list);
print(&string_list);
let mut char_list = vec!['b', 'e', 'z', 'l', 'y', 'a', 'r', 'o', 'n', 'k', 'q', 'c', 'v',
'm', 'x', 'd', 'h', 'f', 'g', 's', 'w', 't', 'p', 'i', 'u', 'j'];
print(&char_list);
sort(&mut char_list);
print(&char_list);
}
- Am I correct in my hypothesis about how
String
s are stored in aVec
? - Can I somehow do what I want and write a generic swap function that swaps two instances of the same type efficiently?
Thanks in advance for your consideration!