슬라이스 (Slice)
슬라이스(slice)는 한 컬렉션 중 연속적인 일부를 표현하는 것으로 레퍼런스로 리턴한다.
Range 범위
슬라이스는 부분을 표현하기 위해 Range (범위) 문법을 사용하는데, 괄호 안에 [시작위치..마지막위치] 와 같이 표현한다. 예를 들어, 어떤 컬렉션 a의 2번째 요소부터 4번째 요소까지를 표현하고 싶으면, a[1..4]와 같이 표현한다. 컬렉션의 인덱스를 0부터 시작하므로, 2번째 요소의 인덱스는 1이 되고, 4번째 요소의 인덱스는 3이 된다. Range 문법에서 마지막위치는 마지막 요소 인덱스보다 1이 더 많게 적기 때문에서 3+1=4가 된다.
아래 예제는 정수 배열을 가진 변수 a의 일부 (혹은 전체)를 Range 범위로 잘라내는 예들을 표현한 것이다. Range에서 시작위치가 생략되면 0 을 의미하고, 마지막 위치가 생략되면 마지막 요소까지를 가리킨다.
fn main() { let a: [i32; 5] = [1,2,3,4,5]; println!("{:?}", &a[0..2]); // [1, 2] 출력 println!("{:?}", &a[1..4]); // [2, 3, 4] 출력 println!("{:?}", &a[..4]); // [1, 2, 3, 4] 출력 println!("{:?}", &a[1..]); // [2, 3, 4, 5] 출력 println!("{:?}", &a[..]); // [1, 2, 3, 4, 5] 출력 }
슬라이스
슬라이스는 레퍼런스로서 소유권(Ownership)을 갖지 않는다. 즉, 어떤 컬렉션에 대해 슬라이스를 만들면, 컬렉션 변수의 소유권이 이전되지 않는다.
아래 예제는 정수 배열을 가진 변수 numbers를 슬라이스로 get_first_two() 함수로 전달하고, 배열의 처음 2개의 요소를 다시 슬라이스(&[i32])로 리턴하는 예이다.
fn main() { let numbers: [i32; 5] = [1,2,3,4,5]; let first2 = get_first_two(&numbers); println!("{:?}", first2); } fn get_first_two(data: &[i32]) -> &[i32] { if data.len() < 2 { panic!("invalid data"); } &data[0..2] }
문자열 슬라이스: &str
슬라이스 중에 가장 많이 사용되는 것 중의 하나는 문자열 슬라이스(string slice)이다. 문자열 슬라이스는 String 타입의 문자열의 일부를 취하는 슬라이스로서 &str 타입으로 표현한다.
아래 예제에서 변수 s는 String 타입인데, 이 변수에 Range를 지정하여 문자열 슬라이스 &str 타입의 변수 s1과 s2를 만들었다. 이때의 변수 s1과 s2는 레퍼런스 타입으로 변수 s의 소유권을 이전받지 않는다. 따라서, 소유권 이전 없이 여러 개의 문자열 슬라이스를 만들 수 있다.
fn main() { let s: String = String::from("hello"); let s1: &str = &s[1..4]; // "ell" let s2: &str = &s[2..]; // "llo" println!("{:?},{:?}", s1, s2); }
문자열 슬라이스를 그림으로 표현하면 다음과 같다. 위 예제의 변수 s에 대해 s[1..4]이 슬라이스 s1이라고 했을 때, s1은 &str 타입으로 시작위치를 가리키는 포인터와 슬라이스의 길이를 가리키는 Len 데이타를 갖게 된다.
아래 예제는 문자열 슬라이스를 함수의 파라미터로 전달하고, 다시 문자열 슬라이스를 리턴받는 예이다. 문자열 리터럴은 (전체 문자열을 갖는) 슬라이스이고 &str 타입이다. 함수 get_first_two()의 파라미터로 문자열 슬라이스 s를 전달하고, 함수 내에 처음 2개의 문자를 발췌하여 이를 다시 ' 문자열 슬라이스 &str 타입으로 리턴하고 있다.
fn main() { let s = "hello world"; let first2: &str = get_first_two(s); println!("{}", first2); } fn get_first_two(data: &str) -> &str { if data.len() < 2 { panic!("invalid data"); } &data[0..2] }