ReScript in Korean

Let 바인딩

원문

다른 언어에서 "let 바인딩"은 "변수 선언" 이라 할 수 있습니다. let은 값과 변수 이름을 묶는(bind) 것입니다. "let 바인딩"을 하면 이후 코드에서 바인딩 된 변수를 참조할 수 있습니다.

let greeting = "hello!"
let score = 10
let newScore = 10 + score
var greeting = 'hello!';
var score = 10;
var newScore = 20;

블록 스코프

스코프는 {}을 사용해 지정할 수 있습니다.

let message = {
let part1 = "hello"
let part2 = "world"
part1 ++ " " ++ part2
}
/* `part1` and `part2`는 여기서 접근할 수 없습니다! */
var message = 'hello world';

암시적으로 스코프의 마지막 줄에 있는 값이 반환됩니다.

디자인 결정

리스크립트 if, while 구문과 함수도 같은 블록 스코프 방식입니다. 아래 예제가 잘 돌아가는 이유는 특별히 if 스코프 때문이 아니라 위에서 방금 본 스코프 문법과 같기 때문입니다.

if displayGreeting {
let message = "Enjoying the docs so far?"
Js.log(message)
}
/* `message`는 여기서 접근할 수 없습니다! */
if (displayGreeting) {
console.log('Enjoying the docs so far?');
}

바인딩은 불변입니다

let 바인딩은 "불변", 즉 "변경이 불가능합니다". 불변은 리스크립트의 타입 시스템이 최적화와 추론을 다른 언어보다 잘할 수 있도록 도와줍니다. (또한 다른 것에도 많은 도움이 됩니다)

쉐도잉

바인딩이 불변이라는 제한은 처음에는 실용적이지 않게 들릴 수 있습니다. 그러면 어떻게 값을 변경할까요? 보통 2가지 방법이 있습니다.

첫째는 많은 경우에 우리가 실제로 원하는 것은 변수의 값을 변경하는 것이 아닌 것을 눈치채야 합니다. 예를 들어 다음 JavaScript 패턴이 있습니다.

var result = 0;
result = calculate(result);
result = calculateSomeMore(result);

이건 그냥 각 계산의 중간 단계를 거치고 싶은 것 뿐입니다. 사실 result의 값을 변경할 필요가 전혀 없습니다! JS 코드로 이렇게 쓸 수 있습니다.

var result1 = 0;
var result2 = calculate(result1);
var result3 = calculateSomeMore(result2);

ReScript에서는 이것 역시 작동합니다.

let result1 = 0
let result2 = calculate(result1)
let result3 = calculateSomeMore(result2)
var result1 = 0;
var result2 = calculate(0);
var result3 = calculateSomeMore(result2);

또한, 같은 이름으로 let 바인딩을 재사용하면 이전 바인딩이 같은 이름인 바인딩에 의해 가려집니다. 때문에 다음처럼 작성할 수 있습니다.

let result = 0
let result = calculate(result)
let result = calculateSomeMore(result)
var result = calculate(0);
var result$1 = calculateSomeMore(result);

(하지만 위 예시는 명확성을 해치기 때문에 권장하는 방법이 아닙니다)

사실 쉐도잉 규칙에 의해 이것도 컴파일 되는 유효한 코드입니다.

let result = "hello"
Js.log(result) /* prints "hello" */
let result = 1
Js.log(result) /* prints 1 */
var result = 1;
console.log('hello');
console.log(1);

여기서 참조하는 바인딩은 위에서 가장 가까운 바인딩입니다. 값의 변경은 일어나지 않았습니다! 만일 여러분이 정말 바인딩 된 값을 변경하고 싶다면, 예를 들어 값을 통해 바인딩을 변경하고 싶다면 뮤테이션 기능을 참고하시면 됩니다. 뮤테이션은 많은 코드를 건드리게 되고 조금 무거운 기능입니다.

Private let bindings

Private let bindings은 7.2 버전에서 소개됐습니다.

모듈 시스템에서는 기본적으로 모든것이 public입니다. 어떤 값을 숨기는 유일한 방법은 별도의 모듈 선언으로 나누어 public 필드와 그것의 타입을 표시하는 것입니다. 밑의 예제에서는 모듈 A의 b에만 접근이 가능합니다.

module A: {
let b: int
} = {
let a = 3
let b = 4
}

%%private 키워드로 직접 private 필드를 만들 수 있습니다. 여기서도 A의 a는 외부에서 접근할 수 없습니다.

module A = {
%%private(let a = 3)
let b = 4
}

%%private는 파일 수준 모듈에서도 적용이 가능하기 때문에 개발자는 특정 필드를 숨기기 위해 별도의 인터페이스 파일을 만들 필요가 없습니다.

참고 인터페이스 파일 분리는 더 나은 성능을 제공하기 때문에 여전히 베스트 프랙티스입니다. 인터페이스로 나눈 파일은 별도의 컴파일 단위이며 문서화에도 더 좋습니다.

%%private 키워드는 다음의 경우 유용합니다.

  • 빠른 프로토타이핑. 프로토타이핑 하는 동안 여전히 일부 값을 숨기고 싶을 수 있습니다. 이 때 인터페이스 파일은 아직 완성되지 않았을 경우가 있겠죠. 이럴 경우 %%private 키워드를 유용하게 쓸 수 있습니다.