Functions

이 포스트는 Rust를 처음 공부하면서 정리한 내용입니다. 해당 포스트는 개인적으로 기억하기 위한 메모 성격에 가깝습니다. “러스트 프로그래밍 공식 가이드 (2018, 제이펍)” 서적을 참고하였으며, 러스트 공식 사이트 에서 책과 동일한 내용을 찾을 수 있습니다. 따라서 더 자세한 내용을 찾으시면 위의 링크를 참고하시면 좋습니다.

Basics

Rust에서 함수와 변수는 snake case naming convention을 사용합니다. snake case는 소문자와 함께 단어를 밑줄 기호로 구분하는 형식을 말합니다. 함수를 선언할 때는 fn 키워드를 사용합니다.

매개 변수 (Parameters)

함수의 매개 변수는 아래와 같이 저으이에 포함합니다. 이때 함수 시그니쳐에는 각 매개변수의 타입을 명시해야 합니다. 함수 정의에 타입 애노테이션을 포함하도록 하면 컴파일러가 각 매개변수가 코드 내에서 어떻게 사용되는지 추적하지 않아도 타입을 확인할 수 있습니다.

fn main() {
    some_function(5);
}

fn some_function(x: i32) {
    println!("Value: {}", x);
}

fn some_function_2(x: i32, y: i32) {
    println!("Value: {}, {}", x, y);
}

값을 리턴하는 함수

함수는 자신을 호출한 코드에 값을 리턴할 수 있습니다. 이때 함수는 리턴 타입을 지정해주어야 합니다.

fn five() -> i32 {
    5
}

Rust에서 함수의 리턴 값은 함수의 마지막 표현식의 값이 됩니다. 물론 함수 중간에서 실행이 완료되기 전에 return 구문을 사용하여 값을 리턴할 수도 있습니다. 하지만 대부분의 함수는 마지막에 표현식의 값을 리턴하게 됩니다. 위의 예제에서 5는 표현식이므로 세미 콜론(;)이 붙지 않습니다.

함수의 리턴 값은 표현식이므로 세미콜론이 붙지 않습니다.

함수를 호출한 쪽의 코드가 아래와 같다고 합시다.

fn main() {

    let x = five();
    // identical to let x = 5;
}

위의 호출부는 let x = 5;의 코드와 동일합니다.

또 다른 예시를 들어보겠습니다.

fn plus_one(x: i32) -> i32 {
    x + 1;
    // 올바른 형식은 x + 1
}

plus_one 함수의 경우 리턴하고자 하는 값 뒤에 세미콜론이 추가되었습니다. 따라서 x + 1 줄은 표현식이 아니라 구문이 되어버립니다. 따라서 이 코드를 실행하면 빈 튜플이 반환되며 지정한 리턴 타입이 일치하지 않는다는 오류를 만나게 됩니다.

함수 본문의 구문과 표현식 (Statements and Expressions)

함수 본문은 여러 개의 구문(Statement)을 가지고 있고, 표현식(Expression)으로 끝나기도 합니다. Rust는 표현식 기반 언어이기 때문에 구문과 표현식을 구분하는 것이 아주 중요합니다. 다른 언어에는 이러한 구분이 존재하지 않기 때문에 처음 접하는 경우 헷갈릴 수 있습니다.

구문은 어떠한 동작을 실행합니다. 반면 표현식은 최종 결과값으로 평가(Evaluate) 됩니다.

예제 1: 구문

다음 예시 코드는 하나의 구문으로 구성된 main 함수입니다. let 키워드를 이용하여 변수를 생성하고 값을 대입하는 행위는 구문입니다. let y = 6 은 하나의 구문이며 함수 선언 역시 구문에 속합니다.

fn main() {
    let y = 6;
}

구문은 값을 리턴하지 않습니다. 따라서 아래와 같은 코드는 허용되지 않습니다. ley y = 6는 값을 리턴하지 않으므로 컴파일 시 에러를 발생시킵니다. C나 기타 다른 언어에서 흔히 볼 수 있는 x = y = 6과 같은 구문은 Rust에서 작성할 수 없습니다.

fn main() {
    let x = (let y = 6);
}

예제 2: 표현식

표현식은 어떠한 값으로 평가됩니다. 예를 들어 5 + 6과 같은 산술 연산은 11이라는 값으로 평가될 수 있습니다. 따라서 이는 표현식입니다.

표현식은 구문의 일부가 될 수 있습니다. 위의 예제에서 let y = 6; 에서 6은 표현식이 됩니다. 따라서 함수의 호출 역시 표현식입니다. 마찬가지로 매크로의 호출도 표현식입니다. 그리고 새로운 범위를 선언하기 위한 코드 블록({}) 또한 표현식입니다.

fn main() {
    let x = 5;
    let y = {
        let x = 3; // Statement
        x + 1 // Expression
    }; // Statement

    println!("The value of y is: {}", y);
}

위의 예시에서 코드 블록은 표현식 입니다. 이 예제에서 코드 블록은 4로 평가되면서 let y = 4; 구문(Statement)로 인해 대입됩니다. 마찬가지로 세미 콜론이 붙어있지 않은 줄에서는 x + 1값을 리턴하기 위해 표현식으로 나타냅니다.

태그:

카테고리:

업데이트: