하스켈/변수와 함수

이 장에 나오는 모든 예제는 하스켈 소스 파일로 저장할 수 있다. 저장한 파일은 GHCi에서 불러올 수 있다. 실습할 때 Prelude>라는 글자는 따라 치면 안 된다. 예제에서 이 프롬프트가 나오면 그 다음에 나오는 코드를 GHCi에 따라 쳐보라는 의미이다. 프롬프트가 없다면 예제 코드를 파일에 적고 실행하면 된다.

변수

+/-

준비하기 장에서 GHCi를 계산기로 써봤다. 짧은 계산을 할 때는 지금도 충분히 실용적이지만 긴 계산을 하거나 하스켈 프로그램을 작성하려면 중간 결과를 추적해야 한다.

값에 이름을 붙이면 중간 결과를 보관할 수 있다. 이때 붙이는 이름을 변수(variables)라고 한다. 프로그램이 실행될 때 변수는 변수가 가리키는 값으로 대체된다. 예를 들어 아래 계산을 보자.

Prelude> 3.141592653 * 5^2
78.539816325

위 계산은 공식  에 따라 반지름이 5인 원의 넓이를 나타낸다.   값은 입력하기도 번거롭고 외우기도 어렵다. 프로그래밍은 반복적이고 기계적인 암기 작업을 기계에 위임함으로써 무의미한 반복을 피할 수 있게 해준다. 복잡한 계산을 기계에 맡기면 사람은 더 중요한 문제에 집중할 수 있다. 하스켈에는 이미 pi라는 변수가 내장되어 있고 pi에 12자리 이상의   값이 저장되어 있다. 변수를 사용하면 명확하고 정확도 높은 코드를 작성할 수 있다.

Prelude> pi
3.141592653589793
Prelude> pi * 5^2
78.53981633974483

계산할 때 변수 pi와 값 3.141592653589793은 서로 바꿔 쓸 수 있다.

하스켈 소스 파일

+/-

GHCi에서 작업하는 것 외에도 코드를 하스켈 소스 파일(기본적으로 평문이다.)에 저장할 수 있다. 이때 확장자는 .hs를 사용한다. 소스 파일 작업을 할 때는 주로 코딩에 적합한 텍스트 에디터를 사용한다.(위키백과 텍스트 에디터 문서를 보자.) 텍스트 에디터는 문법 강조 기능이 있다. 문법 강조는 코드에 색을 칠해 코드를 읽기 쉽고 이해하기 쉽게 만든다. 하스켈 프로그래머는 Vim이나 Emacs를 많이 쓴다.

정리를 위해서 별도 디렉터리를 만들자. 이 디렉터리에 연습 문제를 풀면서 만들 하스켈 파일을 저장할 것이다. 디렉터리 이름은 HaskellWikibook으로 하자. 디렉터리에 새 파일을 만들어 아래 코드를 적고 Varfun.hs라는 이름으로 저장하자.

r = 5.0

위 코드는 변수 r을 값 5.0으로 정의한다.

코드 제일 왼쪽에 공백이 있으면 안 된다. 나중에 하스켈 들여쓰기 규칙을 찾아보자.

터미널 HaskellWikibook 디렉터리에서 GHCi를 실행하고 :load 명령어로 Varfun.hs 파일을 불러 오자.

Prelude> :load Varfun.hs
[1 of 1] Compiling Main             ( Varfun.hs, interpreted )
Ok, modules loaded: Main.

:load:l로 줄여서 :l Varfun.hs처럼 쓸 수 있다.

만약 아래와 같은 에러가 발생했다면 현재 디렉터리에 Varfun.hs가 없어서 그런 것이다.

Could not find module 'Varfun.hs'

GHCi 안에서 :cd 명령어로 디렉터리를 이동할 수 있다.(예를 들어 :cd HaskellWikibook처럼 사용한다.)

파일을 불러오면 GHCi 프롬프트가 Prelude에서 Main으로 바뀐다. 이제 새로 정의한 변수 r을 계산에 사용할 수 있다.

*Main> r
5.0
*Main> pi * r^2
78.53981633974483

원의 넓이 구하는 공식에 변수 이름을 할당해서 계산을 더 쉽게 해보자. 소스 파일 내용을 다음과 같이 바꾸자.

r = 5.0
area = pi * r ^ 2

파일을 저장하고 GHCi에서 :reload 명령어를 입력해서 파일을 다시 불러오자.(:r로 줄여 써도 된다.)

*Main> :reload
Compiling Main             ( Varfun.hs, interpreted )
Ok, modules loaded: Main.
*Main>

이제 사용할 수 있는 변수는 rarea로 총 두 개이다.

*Main> area
78.53981633974483
*Main> area / r
15.707963267948966

let 키워드를 이용하면 소스 파일 없이도 GHCi 프롬프트에서 바로 변수를 정의할 수 있다.

Prelude> let area = pi * 5 ^ 2

let은 가끔 사용하면 편하지만 모든 변수를 이런 식으로 정의하면 복잡한 일은 하기 어렵다. 소스 파일에 저장하는 방식을 사용하자.

주석

+/-

소스 파일에는 동작하는 코드말고 동작하지 않고 메모처럼 적는 글자도 있는데 주석(comments)이라고 한다. 하스켈 주석 종류는 두 가지이다. 첫 번째는 --로 시작하는 주석이다. -- 오른쪽에 쪽에 적은 것은 주석이 된다.

x = 5     -- x는 5이다.
y = 6     -- y는 6이다.
-- z = 7  -- z는 주석이라 정의가 안 된다.

위 코드에서 실제 하스켈 코드인 xy는 정의가 되지만 z는 주석이라서 정의가 안 된다.

두 번째는 코드를 {- ... -}로 감싸는 것이다. 이 방식은 한 줄뿐만 아니라 여러 줄을 주석으로 만들 수 있다.

answer = 2 * {-
  이렇게 여러 줄 주석을 쓸 수 있다.
  -} 3 {- 이 방식으로 한 줄 주석도 가능하다. -} * 7

한 줄 주석과 여러 줄 주석을 합쳐서 실행할 코드를 주석으로 바꾸거나 그 반대로 할 수 있다. 아래와 같은 주석이 있다고 하자.

{--
foo :: String
foo = "bar"
--}

이때 다음과 같이 } 하나를 빼면 코드가 된다.

{--}
foo :: String
foo = "bar"
--}

프로그램 일부를 설명하거나 메모를 남길 때 주석을 사용한다. 주석이 너무 많은 코드는 읽기 어렵다. 어떤 코드를 수정할 때는 관련 주석도 같이 수정해야 한다. 코드는 바뀌었는데 주석은 예전 그대로라면 읽는 사람이 혼란스러울 것이다.