openlang

(x, x)는 두 값이 같다는 뜻이 아니다

OCaml의 (x, x)를 "두 값이 같다"로 읽는 학습자가 계속 나와요. 그런 뜻도 아니고, 애초에 허용되지도 않아요.

처음 배우는 사람은 대개 두 설명 중 하나를 떠올려요. 하나는 앞의 x가 구성 요소에 이름을 붙이고 뒤의 x가 그 값과 비교한다는 설명이에요. 다른 하나는 패턴 안의 변수마다 새 바인딩이 생기니까 같은 이름을 두 번 쓰면 그냥 오류라는 설명이고요. OCaml은 패턴 변수가 선형이어야 한다고 정해 두었으니 맞는 쪽은 두 번째예요. 컴파일러가 이 패턴을 거부해요.

작은 연습 문제로는 이걸 (left, right) when left = right와 그 아래 대체 분기로 바꿔요. 먼저 (3, 3)이 어느 분기로 가는지 예상하게 해요. 그다음 두 번째 값만 바꿔서 (3, 4)로 다시 물어봐요.

결국 전하고 싶은 건 부분에 이름을 붙이는 일과 그 값들 사이의 관계를 검사하는 일이 다르다는 점이에요. 바인딩 규칙을 먼저 말해 줄지, 틀린 설명이 먼저 깨지게 둘지는 아직 왔다 갔다 하고 있어요.

이어지는 대화 3

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

    네, 저라면 예상을 두 번으로 나눠요. 어느 분기가 선택되는지 묻기 전에 먼저 이름에 어떤 값이 들어가는지 물어봐요. 가드 없는 쌍 패턴에 (3, 4)를 넣으면 left = 3, right = 4가 돼요. 이것만으로도 두 값이 같아야 쌍이 매칭된다는 생각에 대한 구체적인 반례가 돼요.

    그다음 가드를 넣고 다시 물어봐요. 두 구성 요소는 여전히 묶이고, 동등 검사는 실패하고, 선택은 대체 분기로 넘어가요. 두 예상을 따로 받아 두면 학습자의 이해가 어디서 어긋나는지 보여요. 이름이 값을 얻는 방식은 정확히 알면서도, 가드가 실패하면 쌍의 모양부터 맞지 않은 거라고 믿을 수 있거든요.

  2. 고유 링크

    등식으로 읽는 버릇은 아마 정규식에서 왔을 거예요. Perl에서 /(\w)\1/은 정말로 같은 글자 두 번이라는 뜻이에요. \1은 첫 번째 그룹이 잡은 것과 똑같아야 하는 역참조니까요. 이런 걸 몇 번 써 본 사람은 (x, x)를 보고 같은 규칙이라고 생각하죠. 소리 내서 짚어 줄 만해요. 묶는 패턴과 비교하는 패턴은 생김새가 똑같을 수 있고, 정규식 버릇은 꽤 끈질기거든요.

같은 질문의 다른 갈래

  1. RISC-V 호출 규약, -O0으로 읽을까 -O2로 읽을까

    호출 규약은 레지스터 표를 외울 때보다 실제 컴파일러 출력에서 읽어 낼 때 더 잘 남는다. 좋은 연습은 int 매개변수 세 개를 받아 합을 돌려주는 C 함수를 RV32용으로 -O0에서 한 번, -O2에서 한 번 컴파일해 보는…