Haskell #14 (Let it be)

--

이번 장에서는 where바인딩과 유사한 let 바인딩에 대해서 알아봅니다. 일종의 변수 선언 처럼 보이는 let에는 어떤 특징과 제약이 있는지 알아보겠습니다.

Ref: Syntax in Functions-Let it be?

이전 챕터에서 where를 사용해서 가드나 함수내에서 사용될 변수를 함수의 마지막에 정의하는 것을 보았습니다. let은 어디서나 사용될 수 있고 그 자체로 표현식(expression)이지만 매우 지역적이라서 가드의 범위도 넘어가지 않습니다. let 바인딩은 패턴 매칭 등 하스켈의 어떤 구성에서든 값과 이름을 바인딩하기위해 사용됩니다.

위 예제는 높이와 반지름으로 원통의 표면적을 구하는 함수 입니다.

let의 형태는 “let <bindings> in <expression>”입니다. <bindings>에서는 <expression>에서 접근할 수 있는 이름들을 선언합니다. 위 예제의 경우는 where 바인딩을 사용해서 정의할 수도 있습니다. 여기서 이름들이 주의할 것은 한개의 컬럼에 정렬되어야 한다는 것입니다. 이 예제에서 let과 where의 차이점이 단지 let은 바인딩을 먼저하고 사용한다는 것입니다.

let과 where의 차이점은 let이 그 자체로서 표현식(expression)이고, where는 문법적인 구조물이라는 점입니다. 따라서 let은 표현식인 if 구문이나 if else 구문의 거의 어디에서나 사용될 수 있습니다.

let 바인딩이 지역 범위에서 사용될 수 있는 함수 선언에도 사용될 수 있습니다.

한개 라인에 여러개의 변수를 바인딩 할때는 동일 컬럼에 정렬할 수 없고, 세미콜론(;)을 사용해서 바인딩이 가능합니다

이전에도 언급했듯이 let 바인딩에서도 패턴매칭을 사용할 수 있습니다. 따라서 튜플을 사용한 패턴 매칭을 사용하여 바인딩하면 세미콜론(;)을 사용하지 않아도 됩니다.

let 바인딩은 리스트 정의내에서도 사용될 수 있습니다. 따라서 이전 챕터에서 작성했던 calcBmis 함수를 where 대신 let을 사용해서 재작성할 수 있습니다.

let은 리스트 정의 내에서 리스트 필터링하는 동작은 하지않고 단지 이름들을 바인딩하는 역할만 수행합니다. 리스트 정의내에서 정의된 let은 “|” 이전의 출력 부분(output function)에서도 참조할 수 있습니다. 하지만 “(w, h) <- xs” 부분에서는 let 바인딩보다 먼저 정의되었기 때문에 사용할 수 없습니다.

리스트 정의 내에서 let을 사용할때는 “|” 이전 부분에서 정의되었기때문에 in 부분은 생략할 수 있습니다. 하지만 “predicate”에서 let in 바인딩을 사용할 수 있고, 이름의 범위도 predicate에서만 보이도록 선언할 수 있습니다.

in 부분은 함수를 선언할때나 GHCi에서 직접적으로 상수를 선언할 때 생략될 수 있습니다. 또한 전역적으로 사용될 수 있도록 선언할 수도 있습니다.

만약 let 바인딩이 정말 좋다면 왜 항상 where 바인딩 대신 let 바인딩을 사용하지 않을까요? let 바인딩은 표현식(expression)이고 그것의 범위가 지역에 한정되기 때문에 가드들을 가로지르며 사용될 수 없습니다. 또한 함수에서 사용된 후에 이름이 오면 함수의 변수들의 이름과 타입 선언이 함수의 몸체에 가깝다는 특징이 가독성을 좋게하여 where가 선호되기도 합니다.

--

--