Haskell #14 (Let it be)
이번 장에서는 where바인딩과 유사한 let 바인딩에 대해서 알아봅니다. 일종의 변수 선언 처럼 보이는 let에는 어떤 특징과 제약이 있는지 알아보겠습니다.
이전 챕터에서 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가 선호되기도 합니다.