openlang

빈 팔레트에 따로 케이스가 필요할까요?

스와치 편집기에서 빈 색 목록은 서로 다른 두 가지 뜻일 수 있어서, Save할 때 둘을 구분할 수 있으면 좋겠어요. 색이 유효한지는 여기서 다루지 않아요. 편집기가 받아들인 색은 모두 유효하다고 볼게요.

새로 연 스와치 편집에는 입력된 팔레트가 없어요. 그다음 사용자가 Clear를 누르고, 파란색을 넣었다가, 다시 빼요. 목록은 처음에도 비어 있고 끝에도 비어 있지만, 결정이 담긴 건 끝 쪽뿐이에요. 그때는 사용자가 일부러 빈 팔레트를 고른 거니까요.

색 목록에 entered 플래그를 함께 둘 수도 있어요. 아니면 상태에 이름을 붙여 봐도 좋겠어요. NotEntered, Empty, Colors of Color list 같은 F# 케이스 세 개로요. 마지막 색을 빼면 Empty가 되고, 편집을 초기화하면 NotEntered로 돌아가요.

아직 못 푼 부분이 하나 있어요. 이 페이로드로는 Colors []도 만들 수 있으니, 이름만으로는 값을 어떻게 만들지가 정해지지 않아요. 작은 생성 함수가 빠진 조각일지도 몰라요. 그래도 이만한 편집기라면 목록과 플래그 쪽이 더 알아보기 쉬울 수도 있고, 어느 쪽으로 기울지 아직 모르겠어요.

이어지는 대화 4

서로의 근거를 따라
  1. 고유 링크

    Maybe [Color]만으로도 세 번째 경우 없이 같은 구분이 됩니다. Nothing은 새로 시작한 편집이고, Just []는 사용자가 일부러 비운 팔레트이며, 빈 상태를 다르게 적는 두 번째 방법이 애초에 없습니다.

  2. 고유 링크

    Save부터 정하는 게 제일 쉬울 것 같아요. 새로 편집을 시작해서 아무것도 입력하지 않았다면 Save는 비활성이에요. Clear를 누른 뒤에는 빈 팔레트도 저장할 수 있어요. 파란색을 넣었다가 다시 빼도 여전히 저장할 수 있어요. 사용자가 이미 그렇게 선택했으니까요.

    이게 정해지면 생성 규칙은 하나면 돼요. 빈 리스트는 Empty, 비어 있지 않은 리스트는 Colors가 되고, 편집 코드는 그 함수 하나로만 상태를 만들어요. 그러면 일반적인 경로에서는 Colors []가 더는 나오지 않고, 비어 있지 않은 컬렉션 타입을 따로 들여올 필요도 없어요.

    편집기 밖에서 불러오는 팔레트는 그다음 단계예요. 애플리케이션 상태가 되기 전에 먼저 확인해 주세요. 케이스 이름이 그 확인을 대신해 주지는 않아요.

  3. 고유 링크

    그 Colors [] 구멍은 생성 시점에 막을 수 있다. Java라면 sealed interface Palette permits NotEntered, Empty, Colors로 두고, NotEntered와 Empty는 컴포넌트 없는 레코드로, record Colors(List<Color> values)는 빈 목록이면 예외를 던지고 List.copyOf(values)를 저장하는 간결한 생성자를 갖게 한다.

    그러면 마지막 색을 지울 때 Empty를 만들 수밖에 없다. Colors는 빈 상태로는 존재를 거부하기 때문이다. 레코드 패턴을 쓴 Palette에 대한 switch는 망라성 검사도 받으므로, 나중에 네 번째 상태가 생기면 그걸 빠뜨린 망라적 switch가 모두 깨진다. 목록과 플래그 방식은 이런 걸 하나도 얻지 못한다.

  4. 고유 링크

    그래도 Just []는 oskar91이 짚은 바로 그 구멍이에요. Elm이라면 type Palette = NotEntered | Empty | Colors Color (List Color)로 쓸 거예요. 필수 색 하나에 나머지 목록이에요. 색이 있는 팔레트는 구조상 비어 있을 수 없고, case에서 Empty 분기를 빼먹으면 컴파일러가 빠진 패턴을 이름으로 알려 줘요. 솔직히 그 오류 메시지가 이 인코딩을 좋아하는 이유의 절반이에요.

같은 질문의 다른 갈래

  1. Result는 실패한 검사를, opaque는 검사가 있었음을 보여 준다

    다들 Gleam의 값으로서의 오류를 칭찬하는데, 맞는 말이에요. Result는 정말 좋아요. 그런데 데이터 모델링에서 제가 더 기대는 건 opaque 쪽이에요. pub opaque type Email { Email(Strin…