1. 러스트에서 item은 항상 둘중 하나의 access를 갖는다. 1. public 2.priave 2. 기본적으로 러스트에서는 private이 디폴트 값이다. private item은 현재 모듈과 그 자손들만 쓸 수 있다. 하지만 예외적으로 pub Trait과 pub enum안의 변수들은 public이다. 어떠한 item이 pub으로 선언될 때, 외부에서 접근할 수 있다. 또한 러스트는 기본으로 같은 모듈 안에서는 private item을 사용할 수 있다. 이는 모듈의 자손에 있는 함수나 기타 다른 상황에서도 똑같이 동작한다. 여기서 폴더의 경우, mod.rs에 내부 파일을 mod 선언하여 접근할 수 있다. 이때에도 mod.rs에서는 public item에만 접근할 수 있으며 private item에..
cargo run 명령어로 코드를 컴파일 한 다음 결과 바이너리 파일을 실행하는 것처럼, cargo test 명령어는 코드를 컴파일 한 후 테스트 결과를 바이너리 파일로 실행된다. cargo test 옵션을 확인하려면 cargo test --help, cargo test 옵션이 아닌 test 바이너리의 옵션을 확인하려면 cargo test -- --help명령어를 사용할 수 있다. 직/병렬 테스트 실행하기 기본적으로 각 테스트들은 병렬적으로 실행된다. 그래서 각각의 테스트가 독립적으로 실행되도록 주의해야 한다. 테스트들을 직렬로 실행하고 싶다면 --test-threads 플래그를 사용하고 뒤에 사용할 쓰레드 개수를 적어준다. $ cargo test -- --test-threads=1 기본적으로 테스트가 ..
이 장에서는 테스트 작성 시 사용할 수 있는 주석과 매크로, 테스트 실행에 제공되는 기본 동작과 옵션, 테스트를 유닛 테스트와 통합 테스트로 구성하는 방법에 대해 설명한다. 테스트 함수 해부 함수를 테스트 함수로 바꾸려면, fn전에 #{test}를 추가하면 된다. cargo test명령어를 사용하여 #{test}함수를 실행하여 통과/실패 결과를 보고한다. Cargo로 새로운 라이브러리를 생성하면 자동으로 테스트 모듈이 만들어진다. 실제 코드를 실행하는 대신에 생성된 템플릿 테스트 코드를 실행해보자. 새로운 라이브러리 프로젝트 adder를 생성한다. {프로젝트이름}/adder/src/lib.rs에 코드가 생성되어 있다. #[cfg(test)] mod tests { #[test] fn it_works() {..
라이프타임을 이용하여 댕글링 참조 막기 라이프타임(lifetime) 주된 목적은 dangling reference를 막는 것이다. { let r; { let x = 5; r = &x; } println!("r: {}", r); } 컴파일 에러가 나는데 이는 r이 참조하는 x가 범위를 벗어났을 때 r을 호출했기 때문이다. r이 x의 범위보다 더 넓기 때문에 러스트는 이를 "live longer"라고 표현한다. 그렇다면 러스트는 어떻게 이 코드가 유효하지 않다고 아는 걸까? Borrow Checker 러스트 컴파일러는 모든 빌린 값이 유효한지 확인하기 위해 스코프를 비교하는 borrow checker라는 것을 가지고 있다. { let r; // ---------+-- 'a // | { // | let x =..
특성(Trait) 예전부터 글에 자주 등장했던 특성(trait)이란 단어를 알아볼 시간이 왔다. 특성(트레잇)이란 타입들이 특정 타입이 갖고 있는 동작(기능)을 다른 타입들과 함께 공유할 수 있도록 공통적으로 갖는 동작에 대하여 추상화한 것을 말한다. 제네릭 타입이 어떤 행동을 하는 타입이 될 수 있도록 특정하는 것을 trait bounds라고 한다. traits은 인터페이스(interface)와 비슷하지만, 몇몇 차이점이 존재한다. Defining a trait 타입의 행동(behavior)은 그 타입이 호출할 수 있는 메소드들로 이루어져 있다. 이에 만약 같은 메소드를 가진다면 다른 타입이라도 같은 행동을 공유한다. 트레잇을 정의한다는 것은 어떤 목적을 달성하기 위해 필요한 행동(behavior)들을..
다양한 곳에서 제너릭(제네릭, generic)이 쓰이는데 이를 알아보자. Function Definitions 함수 선언할 때 파라미터의 데이터 타입과 리턴 타입을 적는 함수의 시그니처에서 제네릭을 쓸 수 있다. 제네릭을 파라미터로 받기 때문에 유연성이 높아진다. fn largest_i32(list: &[i32]) -> i32 { let mut largest = list[0]; for &item in list { if item > largest { largest = item; } } largest } fn largest_char(list: &[char]) -> char { let mut largest = list[0]; for &item in list { if item > largest { largest..
fn main() { let number_list = vec![34, 50, 25, 100, 65]; let mut largest = number_list[0]; for number in number_list { if number > largest { largest = number; } } println!("The largest number is {}", largest); let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8]; let mut largest = number_list[0]; for number in number_list { if number > largest { largest = number; } } println!("The largest num..
러스트는 에러를 크게 두 범주로 묶어서 본다. 하나는 복구 가능한 에러(recoverable), 다른 하나는 복구 불가능한 에러(unrecoverable)이다. 복구 가능한 에러는 보통 사용자에게 문제를 보고하고 연산을 재시도한다. 예시) 파일을 찾지 못하는 경우 복구 불가능한 에러는 항상 버그의 증상이 나타난다. 예시) 배열 끝을 넘은 위치의 값에 접근하려는 경우 러스트에는 예외 처리 기능(exception)이 없다! 이를 대신해서 panic! 매크로와 Result가 있다. panic! 매크로 panic! 매크로가 실행되는 상황은 보통 버그가 발견되었을 때, 프로그래머가 이 버그에 대한 처리를 명시하지 않은 경우이다. panic! 매크로가 실행되면 1. 프로그램이 실패 메시지를 출력하고 2. 스택을 거..
Hash Map HashMap 타입은 K타입의 키에 V타입의 값을 매핑한 것을 저장한다. 이 매핑은 hashing function을 통해 작동하는데, 이는 어디에 키와 값들이 메모리에 저장될지를 결정한다. 다른 언어에서는 해쉬, 맵, 오브젝트, 해쉬 테이블, 딕셔너리, associative array라고 불린다. 해쉬 맵은 키를 이용해 값을 찾을 때에 유용하게 쓰인다. 1. 해쉬 맵 만들기 use std::collections::HashMap; let mut scores = HashMap::new(); scores.insert(String::from("Blue"), 10); scores.insert(String::from("Yellow"), 50); insert와 new를 사용해서 해쉬 맵을 만들고 값을..
String 러스트는 핵심 언어 기능 내에서 단 한 가지 스트링 타입만 제공하는데, 이는 스트링 슬라이스인 str이다. 저번에 이야기했던 스트링 슬라이스는 사실 어딘가에 저장된 UTF-8로 인코딩 된 스트링 데이터의 참조자이다. 예를 들어, 스트링 리터럴은 프로그램의 바이너리 출력물 내에 저장되어 있는 스트링 슬라이스이다. String 타입은 핵심 언어 기능에 구현되어 있는 게 아니라 러스트의 표준 라이브러리에서 제공되는 스트링 타입이다. String 타입은 크기를 늘릴 수 있고, 변할 수 있고, 소유권이 있으며, UTF-8로 인코딩 되어있다. 대개 러스트에서 strings라고 하면 String과 string slice인 &str 타입을 의미한다. 1. 스트링 생성하기 let mut s = String:..