learn

Expression-based 언어란 무엇인가

Expression-based 언어란 무엇인가

"Rust는 expression-based language다"라는 말을 자주 듣는다. 단순한 문법 차이처럼 보이지만, 사실은 언어가 코드를 어떻게 바라보는가에 대한 철학의 차이다.

두 가지 패러다임

언어를 크게 두 부류로 나눌 수 있다.

Statement-based (명령 중심)

  • 코드 = statement의 나열
  • statement는 "동작을 수행"하고, expression은 "값을 만든다"
  • 둘이 명확히 분리됨
  • 예: C, Java, Python (대부분)

Expression-based (값 중심)

  • 코드 = expression의 합성
  • 거의 모든 문법 요소가 값을 만든다
  • 제어 흐름조차 값을 가짐
  • 예: Lisp, ML, Haskell, Rust, Scala

차이가 드러나는 지점

핵심은 if, match, block 같은 제어 구조가 값을 가지느냐다.

// C: if는 statement. 값이 없음
int x;
if (cond) {
    x = 5;
} else {
    x = 10;
}

C에서는 if가 값을 만들지 않으니 변수에 직접 할당이 불가능하다. 그래서 삼항연산자 ?:라는 별도의 expression 버전을 따로 만들어 두었다.

// Rust: if는 expression. 값을 가짐
let x = if cond { 5 } else { 10 };

Rust는 if 자체가 expression이라 별도의 삼항연산자가 필요 없다. match, loop, block { ... }도 전부 같은 방식으로 동작한다.

핵심 통찰: 합성 가능성

Expression-based의 진짜 힘은 모든 게 합성 가능하다는 점이다. 값을 만드는 것끼리는 서로 끼워 넣을 수 있다.

let result = match status {
    Status::Ok => if data.is_empty() { 0 } else { data.len() },
    Status::Err => -1,
};

match 안에 if가 들어가고, 그게 다시 변수의 값이 된다. C였다면 임시 변수와 여러 줄의 statement로 풀어써야 하는 흐름을 하나의 식으로 표현할 수 있다.

C++ 비유로 말하자면, expression-based 언어는 모든 문법이 rvalue를 만든다. 그래서 어디든 끼워 넣을 수 있다.

스펙트럼으로 이해하기

흑백이 아니라 정도 차이다.

순수 statement-based ────────────────── 순수 expression-based

   Pascal      C/C++      Python      Rust    ML/Haskell    Lisp

                              ↑                              ↑
                    제어구조 일부 expression          모든 것이 expression
                    (lambda, 삼항)                  (괄호 자체가 함수 호출)
  • Lisp가 가장 극단적이다. (+ 1 2)처럼 괄호 친 모든 게 expression이고, 언어 자체가 expression 트리다.
  • Haskell도 거의 순수 expression-based.
  • Rust실용적인 expression-based. let 바인딩 같은 statement도 있지만, 제어 흐름은 모두 expression화했다.
  • **C/C++**은 assignment(=)나 comma operator(,) 같은 일부만 expression이고, 제어 구조는 statement.

왜 이게 중요한가

Expression-based 설계는 함수형 프로그래밍의 영향이다. "코드는 값을 변환하는 식의 조합이다"라는 시각이 깔려 있다. 이게 주는 장점은:

  1. 표현력: 임시 변수와 분기를 줄여 코드가 짧아진다
  2. 합성성: 작은 부품을 큰 부품으로 조립하기 쉽다
  3. 참조 투명성: expression은 그 값으로 치환 가능 — 추론과 최적화에 유리하다
  4. 불변성과 잘 맞음: 값을 만드는 식의 조합이라 mutation이 줄어든다

Rust는 시스템 언어인데도 이 철학을 받아들였다. 그래서 C++보다 함수형 스타일을 자연스럽게 쓸 수 있고, Option/Result 같은 타입과 match의 조합이 깔끔하게 동작한다.

이 철학이 문법 차원에서 어떻게 드러나는지는 statements-vs-expressions|Statements vs Expressions에서 더 구체적으로 볼 수 있다.


한 줄 요약

Expression-based 언어는 거의 모든 문법 요소가 값을 만들도록 설계되어, 식끼리의 합성을 통해 프로그램을 구성한다. Rust는 시스템 언어이면서도 이 철학을 받아들인 대표적인 사례다.