간단하지만 처음에 헷갈릴 수 있는 개념인 Expression, Statement의 차이에 대해서 알아보도록 하겠다.
Expression은 '표현식' 또는 '식'이라고도 부르며, Statement는 '구문', '문'이라고 부른다.
가장 큰 차이점은 반환값의 유무다.
Expression은 값을 반환하고, Statement는 반환하지 않는다.
// rust
1 + 2; // 3을 반환하므로 Expression
let a = 1; // 할당문은 값을 반환하지 않으므로 Statement
대표적인 Expression과 Statement를 예시 코드로 들었다.
가장 간단하게 Expression, Statement를 구분하는 방법은 변수에 할당해보는 것이다.
// rust
let v1 = 1 + 2; // Expression이므로 할당 가능
let v2 = let a = 1; // Statement이므로 할당 불가
위 코드를 에디터로 작성하면 컴파일러가 친절하게 다음과 같은 오류 메세지를 표시한다.
expected expression, found
letstatement only supported directly in conditions ofifandwhileexpressions
Expression이 올 것을 예상했으나, 실제로는 Statement이 할당되었다. 까지만 읽으면 된다.
혼동이 올 때는 직접 할당해보는 것으로 판단이 가능하다.
Expression에 대해서 좀 더 깊게 알아보겠다.
1;
1 + 1 + 1;
1 * 1 - 1;
위 연산의 결과값은 각각 1, 3, 0이다.
그리고 각 결과는 단 하나의 값으로 귀결된다.
몇 번을 연산해도 마찬가지다.
100번, 1000번, 100000000을 연산해도 결과는 단 하나의 값이 된다.
최종적으로 하나의 값이 된다는 것, Expression의 특성이다.
이를 인지한다면, 입문할 때, 모호한 부분을 해소하는데 도움이 된다.
// rust
fn add(a: i32, b: i32) -> i32 {
return a + b;
}
i32는 정수 타입이다.
간단한 덧셈을 해주는 함수가 있다.
이 함수는 2개의 값을 입력 받아서 1개의 값을 출력해준다.
// rust
add(1 + 1 + 1, 2 + 2 + 2);
그렇다면 1 + 1 + 1과 2 + 2 + 2는 add가 호출되기 전에 연산될까, add가 호출되고 연산될까.
너무 당연해보일 수도 있다.
애초에 인자가 2개이므로, 2개의 값이 할당되어야 한다는 점을 생각하면,
1 + 1 + 1, 2 + 2 + 2가 add보다 먼저 연산되어 3, 6이 인자로 주어진 뒤, add가 호출된다는 것을 쉽게 유추할 수 있었을 것이다.
그렇다면 다음 함수와 인자로 주어진 함수들의 호출 순서는 어떻게 될까.
// rust
exec(fve(xel(ne())), len(str));
Expression의 본질을 이해했다면 쉽게 호출 순서를 유추할 수 있을 것이다.
함수의 괄호 안에 들어가는 각 인자는 항상 Expression이다.
Expression은 '표현식', 또는 '식'이라고 부르지만 결국 하나의 '값'으로 평가, 귀결된다.
고로 모든 인자는 '값'이 되어야 한다.
그렇다면 인자로 Expression이 주어진 경우, 먼저 '값'으로 평가될 필요가 있다.
또한 함수도 하나의 '값'으로 평가되는 Expression이다.
고로 위 예제는 함수 ne가 가장 먼저 호출되어 평가된 '값'이 xel의 인자로 주어지고, xel의 결과가 fve의 인자로 주어져 fve(xel(ne()))는 최종적으로 하나의 값으로 평가된다.
이전에 덧셈, 곱셈 등의 연산을 몇 번 하던 하나의 값으로 평가되었던 것과 완전히 동일하다.
함수 호출도 결국 연산인 셈이다.
fve(xel(ne()))의 결과가 1이라고 가정하겠다.
중간 점검을 해보면 exec(1, len(str))인 상태다.
len(str)이 8이라면, exec(1, 8)이 된다.
인자로 주어진 모든 Expression이 각각 하나의 값으로 평가된 후에야 비로소 exec를 호출할 수 있게 된 것이다.