IF
if/else
if 문은 어떤 조건을 만족하는 경우, 그에 해당하는 코드를 실행하도록 논리적 분기를 만드는 방법입니다. 만일 조건이 만족되지 않으면 해당 분기의 코드는 실행되지 않고 넘어갑니다. 보통 if 문은 첫 번째 조건을 검사하는 부분인 if 와, 그 다음 조건을 만족하는지를 검사하는 else if , 그리고 모두 해당되지 않는 경우에 실행되는 else 로 구성됩니다.
파이썬에서 if문을 구현하면 다음과 같습니다. 항상 if 문은 if 라는 키워드로 시작합니다. 여기서는 변수 x 가 y 보다 작은지를 검사하고 있는데, x 는 1.0이고 y가 10이기 때문에 조건이 만족됩니다. 조건이 만족되는 경우에는 아래에 있는 다른 조건들은 검사하지 않고 넘어가기 때문에 실행 결과는 "x is less than y" 가 출력됩니다.
x = 1.0
y = 10
if x < y:
print("x is less than y")
elif x == y:
print("x is equal to y")
else:
print("x is not less than y")
실행 결과
x is less than y
만일 x의 값을 10으로 수정하고 다시 실행한다면 이번에는 "x is equal to y"가 출력될 것입니다.
러스트에서 동일한 코드를 작성해 보겠습니다. 여기서 몇 가지 다른 점이 있는데, 첫 번째로 x와 y를 조건문에서 바로 비교할 수 없습니다. 왜냐하면 두 변수의 타입이 다르기 때문에 둘 중 하나를 나머지의 타입으로 변환해 주어야 하기 때문입니다. 여기서는 y를 f64로 타입 변환을 해서 두 값을 비교하고 있습니다. 두 번째로는 파이썬의 elif가 else if 로 바뀐 것입니다. 세 번째는 러스트는 스코프를 중괄호로 구분하고 있기 때문에, if문의 각 분기에 해당하는 코드를 중괄호로 묶어주고 있습니다.
fn main() {
let x = 1.0;
let y = 10;
if x < (y as f64) {
// casting
println!("x is less than y");
} else if x == (y as f64) {
println!("x is equal to y");
} else {
println!("x is not less than y");
}
}
실행 결과
x is less than y
실행 결과는 파이썬과 동일합니다.
let if
러스트에서는 if문의 각 분기를 변수에 바로 할당하는 것이 가능합니다. 방금 보았던 if문을 아래와 같이 바꿀 수 있습니다. 각 분기에서 문자열을 프린트했었는데, 프린트가 사라졌고 각 분기의 마지막에 붙어있던 세미콜론도 사라졌습니다. 그 다음 if문 전체를 result 라는 변수에다가 할당하고 있습니다.
fn main() {
let x = 1.0;
let y = 10;
let result = if x < (y as f64) {
"x is less than y"
} else if x == (y as f64) {
"x is equal to y"
} else {
"x is not less than y"
};
println!("{}", result);
}
실행 결과
x is less than y
실행 결과를 확인해보면 이전과 동일합니다. 그 이유는 if문의 각 분기에 해당하는 문자열들이 result 변수에 할당되기 때문인데, 위 코드에서는 첫 번째 조건인 x < (y as f64)가 만족되기 때문에, 결국 위 if문은 아래와 동일합니다.
let result = "x is less than y";
주의해야 하는 점은 위처럼 let if 문을 쓰려면 각 분기에서 할당하는 값들이 모두 동일한 타입이어야 한다는 것입니다.
만일 if를 함수에서 바로 리턴한다면, 다음과 같은 코드도 가능합니다.
fn check_password(password: i32) -> bool {
if password == 1234 {
true
} else {
false
}
}
fn main() {
let password = 1234;
let result = check_password(password);
println!("Result: {}", result);
}
FOR
for을 사용하면 값들의 모음(collection)에서 각 값들을 순서대로 꺼낼 수 있습니다. 이처럼 값들을 순서대로 꺼내는 것을 순회(loop over)한다고 말합니다.
6부터 9까지의 정수를 순서대로 프린트하는 코드를 작성해 보겠습니다. 먼저 파이썬에서는 range를 사용하면 됩니다. 이때 range는 마지막 값은 생략되므로 range(6, 10) 과 같이 입력해야 합니다. 이때 print 함수에 end=","를 넣어 줄바꿈 대신 콤마가 들어가도록 해서 결과가 한줄로 출력되도록 했습니다.
for i in range(6, 10):
print(i, end=",")
실행 결과
6,7,8,9,
러스트에서는 특정 범위의 정수를 a..b 와 같은 문법으로 간단하게 만들 수 있습니다. 마찬가지로 마지막 값은 생략되기 때문에 6..10과 같이 입력합니다. 결과를 한 줄로 프린트하기 위해서 println! 대신 print! 함수를 사용합니다.
fn main() {
for i in 6..10 {
print!("{},", i);
}
}
실행 결과
6,7,8,9,
파이썬에서 range를 변수에 할당했다가 나중에 for 로 반복할 수 있습니다.
num_range = range(6, 10)
for i in num_range:
print(i, end=",")
마찬가지로 러스트에서도 정수 범위를 변수에 할당해 두었다가 나중에 반복할 수 있습니다.
fn main() {
let num_range = 6..10;
for i in num_range {
print!("{},", i);
}
}
러스트에서는 정수 범위를 만들 때, 마지막 숫자를 포함할 수 있습니다.
fn main() {
let num_range = 6..=10;
for i in num_range {
print!("{},", i);
}
}
실행 결과
6,7,8,9,10,
while
while 문은 조건이 만족되는 동안 코드가 계속 반복해서 실행됩니다. 만일 조건이 만족되지 않으면 코드가 실행되지 않고 반복이 종료됩니다. 파이썬에서 while문을 사용해 0부터 4까지의 정수를 프린트하는 코드를 작성해 보겠습니다.
x = 0
while x < 5:
print(x, end=",")
x += 1
실행 결과
0,1,2,3,4,
동일한 코드를 러스트로 작성해 보겠습니다. 중괄호가 들어간 것 말고는 크게 다른 점이 없습니다. 참고로, 러스트는 파이썬과 마찬가지로 증감 연산자(++, --)가 없어 변수의 값을 직접 증가시키거나 감소시켜야 합니다.
fn main() {
let mut x = 0;
while x < 5 {
print!("{},", x);
x += 1; // no incremental operator: x++
}
}
실행 결과
0,1,2,3,4,
loop
이번에는 러스트의 특별하고 강력한 문법인 loop 를 알아보겠습니다. 먼저 loop 중 무한 루프의 경우는 파이썬에서 아래와 같이 구현 가능합니다. 중간에 x의 값이 5가 되면 break를 통해서 루프를 탈출할 수 있습니다.
x = 0
while True:
x += 1
if x == 5:
break
print(x, end=",")
실행 결과
0,1,2,3,4,
loop는 파이썬의 무한 루프와 동일한 역할을 합니다. 따라서 루프를 종료하는 break 에 해당하는 조건문이 있어야 루프를 종료하고 다음으로 진행할 수 있습니다.
fn main() {
let mut x = 0;
loop {
x += 1;
if x == 5 {
break;
}
print!("{},", x);
}
}
실행 결과
0,1,2,3,4,
loop는 조건이 만족되면 루프를 탈출하는데, 이때 특정 값을 리턴할 수 있습니다. break 뒤에 리턴할 값을 넣어주면 됩니다. x가 5가 됐을 때 x를 리턴하도록 코드를 고치면 다음과 같습니다.
fn main() {
let mut x = 0;
let y = loop {
x += 1;
if x == 5 {
break x;
}
print!("{},", x);
};
println!("{}", y);
}
실행 결과
1,2,3,4,5
루프 안에서 1부터 4까지가 출력되고, 그 뒤에 y의 값 5가 출력됩니다.
match
다음은 다른 언어에서는 switch ... case 로 많이 사용되는 match 입니다. 파이썬에는 동일한 문법이 없으므로 if ... else 문으로 구현해 보겠습니다.
파이썬에서는 최신 버전인 3.10 이후부터 match ... case가 추가되었습니다.
아래 코드는 name 변수에 값에 따라서 서로 다른 결과를 출력하는 코드입니다. 현재 name 변수의 값이 "John" 이므로 "Hello, John!"가 출력됩니다.
name = "John"
if name == "John":
print("Hello, John!")
elif name == "Mary":
print("Hello, Mary!")
else:
print("Hello, stranger!")
실행 결과
Hello, John!
이렇게 특정 변수의 값에 따라서 다른 행동을 하도록 하는 것이 match 문의 핵심입니다. match 뒤에 값을 비교할 변수를 입력하고, 중괄호 안에서 콤마로 각 경우를 구분해서 표기합니다. name 변수가 "John"인 경우, "Mary"인 경우, 그리고 나머지 모든 경우의 세 가지 경우의 수가 있습니다. 나머지 경우를 나타내기 위해서 매칭할 값을 생략하는 _을 사용합니다. 여기서 name 변수의 값이 "John"이기 때문에 "Hello, John!"이 출력됩니다.
fn main() {
let name = "John";
match name {
"John" => println!("Hello, John!"),
"Mary" => println!("Hello, Mary!"),
_ => println!("Hello, stranger!"),
}
}
실행 결과
Hello, John!
loop와 마찬가지로 match 문도 값을 리턴할 수 있습니다. let <변수명> = match ...와 같이 선언하면 됩니다. 이때 컴파일러가 match문의 리턴값으로부터 변수 greet의 타입을 추론합니다. 또한, 각 조건마다 리턴하는 값들의 타입이 반드시 동일해야 합니다.
fn main() {
let name = "John";
let greet = match name {
"John" => "Hello, John!",
"Mary" => "Hello, Mary!",
_ => "Hello, stranger!",
};
println!("{}", greet);
}
실행 결과
Hello, John!
'Rust' 카테고리의 다른 글
Rust 데이터 구조와 이터레이터 (77) | 2023.04.22 |
---|---|
Rust 소유권 (89) | 2023.04.21 |
Rust 함수 (90) | 2023.04.19 |
Rust 변수 (94) | 2023.04.18 |
개발자들이 가장 사랑하는 언어 Rust 소개 (158) | 2023.04.17 |