리스크립트에서 단일 페이로드로 이루어진 배리언트와 단일 필드로 이루어진 레코드를 살펴봅시다.
type name = Name(string)let studentName = Name("Joe")type greeting = {message: string}let hi = {message: "hello!"}
var studentName = /* Name */ {_0: 'Joe',};var hi = {message: 'hello!',};
자바스크립트 출력을 보면, studentName
또는 hi
가 자바스크립트 객체에 포함된 것을 볼 수 있습니다. (자세한 내용은 배리언트의 자바스크립트 결과물과 레코드의 자바스크립트 결과물을 참고하세요)
성능이 중요하거나 간혹 특수한 자바스크립트 인터롭이 필요한 상황에서는 리스크립트가 제공하는 언랩(혹은 언박스) 기능을 사용할 수 있습니다.
언랩은 단일 필드 레코드 혹은 단일 페이로드-단일 생성자 배리언트가 JS로 변환될 때, 해당 객체의 래퍼를 벗겨냅니다.
타입 선언 위에 @unboxed
라고 달면 됩니다.
@unboxedtype name = Name(string)let studentName = Name("Joe")@unboxedtype greeting = {message: string}let hi = {message: "hello!"}
var studentName = 'Joe';var hi = 'hello!';
변환 결과는 깔끔합니다.
사용하기
왜 싱글 페이로드를 가진 배리언트 또는 레코드가 필요할까요? 왜 그냥 페이로드를 넘기지 않을까요? 아래에서 배리언트의 사용 예를 알아보겠습니다.
아래와 같이 로컬 좌표계와 월드 좌표계를 쓰는 게임이 있습니다.
type coordinates = {x: float, y: float}let renderDot = (coordinates) => {Js.log3("Pretend to draw at:", coordinates.x, coordinates.y)}let toWorldCoordinates = (localCoordinates) => {{x: localCoordinates.x +. 10.,y: localCoordinates.x +. 20.,}}let playerLocalCoordinates = {x: 20.5, y: 30.5}renderDot(playerLocalCoordinates)
function renderDot(coordinates) {console.log('Pretend to draw at:', coordinates.x, coordinates.y);}function toWorldCoordinates(localCoordinates) {return {x: localCoordinates.x + 10,y: localCoordinates.x + 20,};}var playerLocalCoordinates = {x: 20.5,y: 30.5,};renderDot(playerLocalCoordinates);
이런, 뭔가 잘못되었습니다. renderDot
은 전역 좌표를 기준으로 렌더링하는데 인자로 로컬 좌표가 전달됐습니다.
이제 코드를 수정해서 잘못된 좌표 타입이 전달되지 못하게 막아봅시다.
type coordinates = {x: float, y: float}@unboxed type localCoordinates = Local(coordinates)@unboxed type worldCoordinates = World(coordinates)let renderDot = (World(coordinates)) => {Js.log3("Pretend to draw at:", coordinates.x, coordinates.y)}let toWorldCoordinates = (Local(coordinates)) => {World({x: coordinates.x +. 10.,y: coordinates.x +. 20.,})}let playerLocalCoordinates = Local({x: 20.5, y: 30.5})/* 이제 이렇게 호출하면 오류가 발생합니다! *//* renderDot(playerLocalCoordinates) *//* 대산 이렇게 사용하도록 강제합니다. */renderDot(playerLocalCoordinates->toWorldCoordinates)
function renderDot(coordinates) {console.log('Pretend to draw at:', coordinates.x, coordinates.y);}function toWorldCoordinates(coordinates) {return {x: coordinates.x + 10,y: coordinates.x + 20,};}var playerLocalCoordinates = {x: 20.5,y: 30.5,};renderDot(toWorldCoordinates(playerLocalCoordinates));
이제 renderDot
은 worldCoordinates
만을 입력으로 받습니다.
배리언트 타입으로 구분 + 인자 구조분해를 써서 더 안전한 코드를 만들었습니다. 성능 저하 없이요.
unboxed
속성 덕분에 배리언트 래퍼 없이 깔끔하게 JS 코드로 컴파일됐습니다. 결과를 살펴보세요.