mutability : 변경가능여부
기본적으로 immutable (변수 선언 시 기본적으로 변경 불가능)
fn main(){
let my_number = 10;
my_number = 9;
}
>>> ERROR
my_number 는 immutable 이기 때문에 에러 발생
이 경우 mut 키워드를 사용해서 변경가능할 수 있게 해줘야함
fn main(){
let mut my_number = 10;
my_number = 9;
}
mut 키워드를 사용하고나서 변경되지 않았다면, 컴파일러가 이를 알려주고, mut 키워드 삭제 가능
shadowing : 같은 이름을 다시 쓰는 것
fn main(){
let my_variable = 10;
let my_variable = "My Variable";
}
// -> my_variable 은 마지막에 작성된 "My Variable"만 값으로 생각함.
왜 사용?
코딩을 하면서 필요한 값은 최종 결과인데, 이를 위한 여러 변수들이 불필요하게 선언될 필요 없음
fn double(input: i32) -> i32 {
input * 2
}
fn triple(input: i32) -> i32 {
input * 3
}
fn main(){
let x_origin = 9;
let x_double = double(x_origin);
let x_final = triple(x_double);
println!("{}", x_final);
}
// -> 결과적으로 필요한 값은 xFinal 인데, xOrigin, xDouble 같은 변수가 선언됨
//-----------Shadowing 으로 다음과같이 사용할 수 있음-----------
fn main(){
let x = 9;
let x = double(x);
let x = triple(x);
println!("{}", x);
}
CodeBlock 을 이용해서 Shadowing을 다양하게 활용할 수 있음
fn main(){
let my_var = 9;
{
let my_var = "Some String";
println!("{}", my_var); // Some String 출력
}
println!("{}", my_var); // 9 출력
}
먼저 들어온 Task가 다음에 들어온 Task가 종료될때까지 기다리는 메모리 구조.
Task가 종료되면 할당받은 Memory 는 반환
창고같은 곳에서 "어디로 가면 어떤 물건이 있어요" 같이 동작하는 메모리 구조. 비교적 속도가 느리지만 많은 용량을 저장할 수 있음.
아래와 같이 어떤 내용이 어디에 있는지 알려주는 역할
Chapter
Chapter 1: My life, Page : 1
Chapter 2: My life, Page : 15
Chapter 3: My life, Page : 23
Rust에서는 Pointer를 Reference 라고 부름.
reference 를 사용할 때에는 "&" 기호를 사용함.
fn main(){
let my_number = 15; // 값. i32
let single_reference = &my_number; // my_number 에 대한 싱글 레퍼런스. &i32
let double_reference = &single_reference; // my_number 에 대한 레퍼런스에 대한 레퍼런스. &&i32
let five_references = &&&&&my_number; // 이것도 사용 가능.
}
싱글레퍼런스, 더블레퍼런스, 모두 다른 타입이기 때문에 상호 비교가 불가능!!
Fancy Printing : print!() 사용
아래 두 줄의 문장은 같은 동작을 함
println!(message);
print!("{}\n",message);
예를들면
fn main(){
//#1
println!("This");
println!("is");
println!("a");
println!("message");
//#2
print!("This\n");
print!("is\n");
print!("a\n");
print!("message\n");
//#3
print!("This\nis\na\nmessage\n");
}
위의 1, 2, 3번 코두 동일한 동작을 함
Output :
This
is
a
message
\n 이라는 기호를 출력하고 싶다면? -> \\n 사용
fn main(){
print!("This \\n is a message"); // Output : This \n is a message
}
그런데 \를 너무 많이 써야하는 상황이라면?
예를들어 다음 디렉토리를 표시하려면
c:\drive_a\new_drive\path_name
코드는 다음과 같이 안예뻐질 것
fn main(){
print!("c:\\drive_a\\new_drive\\path_name");
}
이럴때 사용하는것이 "Raw Text"
다음과 같이 사용할 수 있다.
fn main(){
print!(r#"c:\drive_a\new_drive\path_name"#);
}
줄바꿈을 다음과같이 사용할 수도 있는데
fn main(){
println!("Let me tell you
some story
about
rust");
}
출력이 다음과 같다.
Let met tell you
some story
about
rust
앞에 인덴트가 있기 때문에 그런것! 주의하여 사용할 것
전에 Debug Print 에 대해 잠시 다뤘는데
println!("{:?}", var_name);
으로 사용했다.
왜 물음표로 사용하냐면 어떤 타입이든 출력을 하기 때문.
특정 data type을 출력하기 위해선 다음과 같은 format을 사용한다
fn main(){
let my_number = 9000;
println!("{:p}", &my_number); // reference(pointer) 출력
println!("{:X}", my_number); // Hex값 출력
println!("{:b}", my_number); // Bytes값 출력
println!("{:p}", my_number); // 는 오류 : p는 포인터 data type을 출력한다고 하는데, my_number 는 값이기 때문에
}
이 포맷을 조금 더 다양하게 활용이 가능하다.
fn main() {
let title = "TODAY'S NEWS";
println!("{:-^30}", title); // no variable name, pad with -, put in centre, 30 characters long
let bar = "|";
println!("{: <15}{: >15}", bar, bar); // no variable name, pad with space, 15 characters each, one to the left, one to the right
let a = "SEOUL";
let b = "TOKYO";
println!("{city1:-<15}{city2:->15}", city1 = a, city2 = b); // variable names city1 and city2, pad with -, one to the left, one to the right
}
Output:
---------TODAY'S NEWS---------
| |
SEOUL--------------------TOKYO
더 많은 내용은 아래 링크 참고
https://doc.rust-lang.org/stable/std/fmt/
Strings
String / &str 을 주로 사용
fn main(){
let my_name = "David"; // &str
let other_name = String::from("David2");
/*
let my_other_name = "David3"; // &str
my_other_name.push("!"); // 여기서 에러 발생! &str 에는 .push 가 없기 때문
*/
// 다음과 같이 하면 오류 발생 안함
let my_other_name = "David3".to_string(); // String
my_other_name.push("!");
println!("{}", my_other_name);
}
String type 은 Sized type
str = dynamic type -> 길이를 컴파일러가 알 수 없음 => &str을 사용
&str 보다 String 이 사용하기 더 쉬운 이유!
method 사용이 용이함
.push : 한 글자 추가
.push_str : &str 추가
.capacity : 바이트 크기
.pop :
with_capacity : 바이트 크기 명시하여 String 선언
let mut my_name = "David".to_string();
my_name.push('!');
println!("My name is {}", my_name);
let mut my_name = String::with_capacity(26);
println!("Length is {} and capacity is {}", my_name.len(), my_name.capacity());
my_name.push_str("David!");
println!("Length is {} and capacity is {}", my_name.len(), my_name.capacity());
my_name.push_str("And I live in Seoul");
println!("Length is {} and capacity is {}", my_name.len(), my_name.capacity());
my_name.push('a');
println!("Length is {} and capacity is {}", my_name.len(), my_name.capacity());
/* Output :
Length is 0 and capacity is 26
Length is 6 and capacity is 26
Length is 25 and capacity is 26
Length is 26 and capacity is 26
*/
const / static
fn main(){
let x = 8; // 'let' binding 이라고 함
}
const는 Global 변수를 선언함
const NUMBER: i32 = 20; // const 선언 변수명은 대문자로(소문자로 쓰면 warning), 타입 지정은 필수!
fn main(){
let x = 8; // 'let' binding 이라고 함
}
static도 const와 비슷
const NUMBER: i32 = 20; // const 선언 변수명은 대문자로(소문자로 쓰면 warning), 타입 지정은 필수!
static LOW_SCORE: i32 = 0;
/*
static 은 mut 를 통해 unsafe 를 사용할 수는 있으나 거~~의 안씀!!
static mut LOW_SCORE: i32 = 0;
*/
fn main(){
let x = 8; // 'let' binding 이라고 함
}
OWNERSHIP
fn main(){
let country = String::from("대한민국");
let ref_one = &country;
let ref_two = &country;
println!("Country is: {}", ref_one);
}
fn return_it() -> &String {
let country = String::from("대한민국");
&country // ref 반환
}
fn main(){
let my_country = return_it(); // >> 오류!!
}
mutable references
& -> immutable reference / shared reference
&mut -> mutable reference / unique reference
fn main(){
let mut my_number = 9;
let num_ref = &mut my_number;
/* 이렇게 코딩하면 오류남!!
num_ref = 10;
*/
*num_ref = 10; // &의 반대개념 *
// && 이면 ** 사용!
/*
let num_ref = &mut &mut my_number;
**num_ref = 10;
*/
}
references and shadowing
// 오류 반환됨!!
fn main(){
let mut number = 10;
let number_ref = &number;
let number_change = &met number;
*number_change += 10;
}
// 정상 작동됨
fn main(){
let mut number = 10;
let number_change = &met number;
*number_change += 10;
let number_ref = &number;
}
shadowing!
// 정상 작동됨
fn main(){
let country = "대한민국";
let country_ref = & country;
let country = 8; // shadowing
println!("{}, {}", country_ref, country);
// -> "대한민국" 이 없어지지 않았음을 확인할 수 있음!"
}
OWNERSHIP
fn print_country(country_name: String){
println!("My country is {}", country_name);
}
fn main(){
let country = "대한민국".to_string();
print_country(country); // 여기서 country 의 소유권이 print_country 함수로 넘어감
print_country(country); // 여기서 에러 발생!!
}
fn print_country(country_name: &String){
println!("My country is {}", country_name);
}
fn main(){
let country = "대한민국".to_string();
print_country(&country); // 여기서 country 의 소유권은 넘어가지 않음!
print_country(&country); // 에러 발생 X!
}