Account: please sign in
AA

함수형 계산 이론과 함수형 프로그래밍 진영에서 거의 공통적으로 통용되는 특유의 용어와 표기 관례들이 있습니다.

함수의 적용과 환산

절차형 프로그래밍 진영에서는 주로 "인자를 주어 함수를 호출한다 (call a function with an argument)"라고 말하지만 함수형 프로그래밍 진영에서는 거의 언제나

  • "함수를 인자에 적용한다 (apply a function to an argument)"

라고 말합니다. 다시 강조하건대, 인자를 함수에 적용하는게 아니라 함수를 인자에 적용하는겁니다: 무엇이 목적어고 무엇이 보어인지 주의해서 기억하시기 바랍니다. (혼동하는 사람들을 개인적으로 많이 봤습니다.)

또한, 절차형 진영에서는 주로 "함수가 결과를 돌려준다 (a function returns a result)"라고 말하지만, 함수형 진영에서는 거의 언제나

  • "함수 적용이 값으로 환산된다 (a function application is reduced to a result)"

라고 말합니다.

예를 들어, f : NN라는 단항 함수가 있을 때 f(5) = 8이라면 이는 "f를 5에 적용한 결과는 8로 환산된다"라고 이야기합니다. ("f(5) is reduced to 8.")

사실은, 함수형 프로그래밍 진영 뿐만 아니라 일반적인 수학에서도 f(5)는 함수 호출(function call)이 아니라 함수 적용(function application)이라고 부릅니다. 결과에 대해서 일반적인 수학에서는 환산reduction이라는 표현보다는 대응mapping이라는 표현을 더 많이 쓰는 듯도 한데, (the function f maps 5 to 8), 이 점은 확실히 통계를 내보지는 않았으니 이렇게 표현하는 경우도 많다는 것만 알아두고 각자 확인해보기 바랍니다.

Juxtapositioning

절차형 프로그래밍 진영이나 일반적인 수학에서 f(5)라고 표기하는 함수 적용을 함수형 프로그래밍 진영에서는 거의 항상

  • f  5

라고 표기합니다. (함수와 인자 사이를 한 칸 띄우고, 이 자리에서는 결코 줄바꿈을 하지 않습니다.) 이러한 표기법을 juxtapositioning이라고 하며, 접두사 "juxta-"는 "바로 곁에 나란히" 정도의 뜻입니다.

Juxtapositioning을 굳이 억지로 번역하자면 "병치(竝置)"라고 할 수는 있겠지만, 제가 방금 영한사전에서 찾아본 낱말일 뿐 이 번역이 전산학계 사람들끼리 널리 쉽게 통할 수 있을지는 알 수 없으니 그냥 원어 그대로 쓰시는게 나을 듯 합니다. ;)

순서쌍 표기

이 소절에서는 앞으로 이 문서에서 사용할 규칙 한 가지를 (느슨하게나마) 정하고 안내해드립니다만, 그 규칙이 다른 곳에서도 일반적으로 널리 통용되는 확실한 관례라는 뜻은 아님을 미리 밝힙니다.

먼저, 각괄호angle brackets '〈', '〉'는 부등호inequality signs '<', '>'와는 글자 코드 상으로도 서로 다른 글자들이며, 의미상으로도 뜻하는 바가 서로 전혀 다릅니다.

이들이 눈으로 보기에 서로 잘 구별되는가 하는 문제는 단순히 글꼴에 의존적인 문제입니다만, 대부분의 LaTeX 시스템에서 표준 글꼴로 채택되어있는 Computer Modern 혹은 Latin Modern 글꼴 시리즈의 경우 각괄호는 부등호보다 훨씬 키(세로)가 크고 폭(가로)이 좁아서 확실하게 구별됩니다. 아래는 실제 Computer Modern 글꼴로 조판된 각괄호들과 부등호들입니다:

  • $ \langle,\rangle,<,> $

우리나라 초・중・고등학교 수학시간에는 아마 각괄호의 주 용도를 "일반 괄호와 의미가 같되 (결합 우선순위 강제 지정), 일반 괄호보다 한 단계 바깥쪽에 쓰이는 괄호"라고 설명했을겁니다.

하지만 계산 이론이나 기호논리학과 관련해서 제가 개인적으로 보아온 문서들에서는 (항상 그런 것은 아닙니다만) 순서쌍ordered pair이나 n-ary 튜플을 둘러싸 묶는 구획문자delimiters 용도로 오히려 더 자주 쓰였습니다:

  • N×N = {〈0,0〉, 〈0,1〉, 〈0,2〉, ...}
    DFA = 〈S, ∑, δ, s0, F〉 where ...

이는 아마도 일반 괄호와 부등호가 흔히 혼재하는 식 속에서 튜플의 구획문자를 확실히 구별하기에는 (특히 LaTeX으로 조판할 경우) 각괄호가 시각적으로 적절하기 때문이 아니었을까 추측하고 있습니다. 아래 예제는 의미는 (전혀 없으니) 신경쓰지 마시고 조판된 시각적 결과만 참고하시기 바랍니다:

  •  $ S = \{\langle(ab)^2,b\rangle \mid a\in\mathbb{N},b\in\mathbb{N}, a>b\} $
     $ f(\langle a,b\rangle) \not\equiv f(a,b) $

물론, 제가 보아온 문서들 중에도 여전히 일반 괄호를 튜플의 구획문자로 사용하는 경우도 또한 (사실은 오히려 더) 많았고, 아마 대부분의 독자들이 이런 경우를 더 많이 보셨을겁니다:

  • N×N = {(0,0),(0,1),(0,2),...}
    DFA = (S, ∑, δ, s0 , F) where ...

이는 여러가지 이유가 있을텐데, 대략 다음과 같은 이유들 중 하나 이상일 것입니다:

  • 조판하는 글꼴에 따라서는 각괄호가 부등호와 비슷하게 생겨서 오히려 의미 변별력이 떨어지거나,
  • 지금 이 위키 문서처럼 최종적으로 조판될 글꼴을 예상할 수 없고 (읽는 사람의 웹 브라우저 글꼴 설정에 따름), 심각한 경우 사용자 글꼴에 해당 문자가 들어있지 않아서 아예 안 보일지도 모르거나
  • 일부 프로그래밍 언어의 소스 코드처럼 ASCII 문자셋에 없는 글자를 문법적으로 아예 받아들이지 않거나
  • 일부 프로그래밍 언어의 소스 코드처럼 유니코드 문자를 받아들인다고 해도 키입력이 너무 번거롭기 때문.

하지만 여전히, 튜플의 구획 문자를 일반 괄호나 함수의 인자 (혹은 매개변수) 리스트의 구획 문자와 구별하는 것은 중요합니다. 특히, 함수형 프로그래밍 특유의 juxtapositioning과 나중에 설명할 고계 함수higher-order functions를 다루다보면 이 구별이 왜 중요한지 아시게 될겁니다.

따라서, 상기와 같은 사항들을 종합적으로 고려하여, 이 문서에서는 다음과 같은 규칙을 정해두겠습니다:

  • 소스 코드 예제 내부에서는 튜플의 구획문자로 반드시 해당 언어가 제공하는 구획문자만 사용합니다. 대부분의 언어에서 이것은 일반 괄호입니다.
  • 본문의 설명 중에도, 튜플의 구획문자는 특별한 이유가 없는 한 기본적으로 일반 괄호를 씁니다.
  • 만일 본문의 설명 중에 각괄호가 등장하면 이것은 거의 예외없이 튜플의 구획문자를 뜻합니다.

Juxtapositioning과 순서쌍에 관한 주의 사항

Haskell이나 ML처럼 juxtapositioning을 사용하면서 순서쌍 자료값을 나타내는 리터럴literal 표기법도 제공하는 프로그래밍 언어를 처음 접하는 사람들이 문법적은 혼란을 겪는 경우가 종종 있습니다. 이는 주로:

  • C 언어 등 널리 쓰이는 대다수 유명한 언어들에서 함수 적용을 괄호로 표기
  • C 언어에는 순서쌍 자료 값을 직접 표기하는 리터럴이 없음
  • 텍스트 콘솔을 고려하여 부득이 각괄호 대신 일반 괄호로 순서쌍을 대체 표기
  • (어디까지나 프로그래머의 편의를 위해) juxtapositioning 바로 우측에 구획 문자가 나오면 붙어있어도 제대로 파싱해줌

이상과 같은 사항들이 복합적으로 작용하여 일으키는 오해 때문입니다.

예를 들어, f는 총 두 개의 정수 인자를 취하는 함수고 g는 단 하나의 정수 순서쌍만을 인자로 취하는 함수일 때, 아래 표를 잘 살펴보시기 바랍니다. 여기서 검은색은 함수 적용을 표현하는 문법 요소이고, 붉은색은 인자 자료 (정수 혹은 순서쌍) 자체를 표현하는 문법 요소입니다:

정수 인자 2개

순서쌍 인자 1개

전통적 수식 조판법

$f(\textcolor{red}{3},\textcolor{red}{5})$

$g(\textcolor{red}{\langle 3,5\rangle})$

함수형 수식 조판법

$f\ \textcolor{red}{3\ 5}$

$g\ \textcolor{red}{\langle 3,5\rangle}$

C 문법

\texttt{f(\textcolor{red}{3},\textcolor{red}{5})}

해당 없음

Python 문법

\texttt{f(\textcolor{red}{3},\textcolor{red}{5})}

\texttt{g(\textcolor{red}{(3,5)})}

Haskell, ML 문법

\texttt{f \textcolor{red}{3 5}}

\texttt{g \textcolor{red}{(3,5)}}
\texttt{g\textcolor{red}{(3,5)}}

결국 요점은, Haskell이나 ML 등의 언어에서 g (3, 5)라고 표기할 때의 괄호/쉼표와 C나 Java 등의 언어에서 f(3, 5)라고 표기할 때의 괄호/쉼표는 그 의미가 완전히 다르다는 점입니다! "Haskell에서는 함수 적용시 괄호를 써도 되고 안써도 된다"고 생각하면 큰 오해며, 실제로는 함수의 타입이 전혀 다릅니다.

논리적 함축 (logical implication)

논리적 함축logical implication을 뜻하는 기호는 거의 모든 현대적인 문서에서 '→'이고, 꽤 드물지만 '⇒'를 쓰기도 하며, 이 둘의 의미를 구분해서 사용하는 경우도 가끔 있습니다. 이에 관해 (특히 기호적인 측면에서) 몇 가지만 부연하겠습니다:

  • Haskell 언어와 ML계열 언어들은 이 기호를 쉽게 입력할 수 있도록 '->'라는 두 글자의 조합으로 표시합니다.

  • Coq도 마찬가지 이유로 '->'라고 표시하지만, Utf8 모듈을 사용하면 아예 '→' 문자를 직접 입력하고 표시할 수 있습니다.

  • HOL 등 다른 도구들은 '==>'로 표시하기도 합니다.

  • 아주 오래된 (대략 50년대 이전) 고전 문서들과 극히 드물지만 현대 문서에서도, 이 기호를 '⊃'로 표시하는 경우가 있습니다. 사용을 권장하진 않지만, 알아두시고 혹시 눈에 띌 때 읽으실 수는 있길 바랍니다.