메아리 저널

나루의 자료형 (4)

이전 글에서 이어진다. 아, 이전 글이 8월에 쓰여진 건데 뭐 바뀐 거 있나요? 라고 물어 보신다면 그 쪽은 하나도 바뀐 게 없다고 말씀드려야 겠다. -_-;

문자

문자와 문자열을 구별해야 할 필요가 있느냐, 또는 문자와 정수를 구별해야 할 필요가 있느냐는 많은 언어들에서 논쟁거리 내지는 주된 안주거리가 되는 주제이다. 몇 가지 예를 들어 보면:

  • C와 C++는 문자와 문자열을 구별하며, 문자는 작은 따옴표에, 문자열은 큰 따옴표에 감싼다.
  • 루비는 문자열을 쓸 수 있지만 문자열의 각 문자는 정수(Fixnum)로 표현된다.
  • 파이썬은 문자열만이 존재하며 문자는 길이가 1인 문자열로 처리한다.

나루에서 이 셋 중 어떤 선택을 할 지 심각하게 고민한 결과 다음과 같은 결론을 얻었다. (여기까지 네 달 걸렸다. -_-)

  • 문자가 따로 존재한다 하여도 문자열과 연산이 가능하여야 한다. (문자와 문자열을 연결한다거나…)
  • 문자가 따로 존재한다면, 문자와 숫자는 구별되어야 한다. (문자는 엄밀하게 말하면 번호가 붙은 '심볼'과 비슷하다. 그 번호도 제한되어 있고, 이름도 붙어 있는. 숫자와 문자를 섞어서 쓸 수 있는 건 원하지 않는다.)
  • 따옴표는 문자열에만 쓰여야 한다. (예전에도 말했지만 문법 강조할 때 귀찮다.)
  • 스크립팅 용으로는 문자열과 문자의 구분이 없는 것이 도움이 될 수 있다. 하지만 좀 더 저수준으로 들어 가면 이 구분은 꼭 필요하다. 또한 전자의 경우에도 최적화 과정에서 내부적으로 길이가 1인 문자열을 특수 처리하는 게 도움이 될 수도 있다.

뭐 이런 저런 이유로 나루에서는 문자 형과 문자열 형이 따로 있다. 덤으로 이 문자열이라는 게 유니코드 문자열이기 때문에, 바이트만으로 이루어진 바이트 배열 형도 따로 지원한다. (바이트 배열 형은 거기에 들어 가는 값에 별도의 자료형을 배당하지 않고 정수로 처리한다. 당연한가?)

…서론이 너무 길었다. 이제 문법 얘기를 하자.

나루의 문자 리터럴은 ?로 시작한다. 이건 루비에서 따 온 건데, 처음 생각에는 `를 사용할까 싶었는데 이게 입력하기도 귀찮고 일부 키보드에는 아예 글쇠가 없다길래 (파이썬 3에서도 `` 문법이 같은 이유로 사라진다!) 제꼈다. 하지만 전체적인 문법은 사실 루비보다는 R6RS의 문자 리터럴(#\newline 같은 거)과 비슷하다.

?a   ?b   ?c   ?d   ?A   ?B   ?C   ?D   ?1   ?2   ?3
?\n   ?\xa0   ?\uac00   ?\U00012345   ?\123456
?newline   ?space   ?"Hangul Syllable Na"

눈에 확 들어 오지 않는가? 문자 리터럴 문법에서는 문자를 직접 줘서 값을 표현하거나, 탈출열(escape sequence)을 쓰거나, 아니면 space 같은 이름을 사용할 수도 있다. 여기서 등장하는 탈출열은 모두 문자열에서 그대로 쓸 수 있다. (예를 들어 마지막의 \123456은 코드 포인트가 10진법 123456인 것을 나타내며, 문자열에서도 같은 의미이다.)

문자열

나루의 문자열(또는 바이트 배열)은 다음과 같이 생겼다.

'asdf'     "asdf"

물론 두 문자열 리터럴을 나란히 놓으면 한 문자열로 합쳐진다는 건 여기서도 동일하다. 바이트 배열은 앞에 접두사를 붙여 다음과 같이 쓴다.

b'asdf'    b"asdf"

약간 고려해야 할 점은, 예를 들어서 소스 코드 문자 인코딩이 ASCII랑 호환 안 된다면 (EBCDIC라고 치자) 저 바이트 배열은 어떻게 해석되어야 하나? 라는 것이다. 나루 설계하면서 맨날 하는 게 선택이긴 하지만 이번에도 선택의 시간이 다가 왔는데, 두 가지 가능성이 있다.

  • a와 같은 문자의 코드를 엄밀하게 정의하고, 나머지는 탈출열로만 쓰게 한다.
  • 소스 코드 상에 나타난 바이트열의 형태 그대로 사용한다.
  • 그냥 바이트 배열 문법을 바꾼다. (응?)

나루의 선택은 두 번째, 즉 소스 코드 상에 나타난 바이트열의 형태 그대로 사용한다는 것이다. (좀 더 정확하게 말하면, 소스 코드 인코딩을 써서 다시 바이트로 바꾼다고 해야 겠다. 그러지 않으면 유니코드 디코딩 과정 자체가 어려워진다.) 이렇게 하면 소스 코드 인코딩이 바뀌면 내용이 바뀔 수도 있다는 치명적인 문제가 있긴 하지만, 뭐 사실 다른 방법이 없다는 것도 문제긴 하다.

대신 나루는 소스 코드 인코딩이 바뀌어도 내용이 바뀔 걱정이 없는 문법을 하나 더 제공한다. (접두사는 x로 줄여 쓸 수도 있다.)

bx'61 73 64 66'

또 다른 형태의 문자열 리터럴로는 날 문자열(raw string)이 있다. 이건 파이썬의 그것이라기보다는 C#에서나 볼 수 있는 날 문자열에 더 가깝다: 즉, 역슬래시는 아무 의미도 가지지 않는다.

r'asdf\nasdf\'   br"asdf\nasdf\"

마지막으로 유니코드 문자열에만 존재하는 표현식을 담은 문자열(interpolating string)이 있다. 이건 루비의 문법과 비슷하게 #를 사용하며, 접두사도 정확히 #이다.

#'''\
Hello, #var!
#(greeting())
'''

위의 예제에서 쓰였듯이 파이썬의 세따옴표 문법은 문자열 리터럴 안에 개행 문자를 포함할 때 쓸 수 있다.

다음에는…

흔히 정규 표현식이라 부르는 패턴에 대한 설명이 이어질 예정이다. 아, 수식 문법부터 먼저 다뤄야 하나?

전체 글 목록은 다음과 같다.

이 글은 완결되지 않았지만, 그 이후로 나루의 lexical syntax 구상은 크게 변하지 않았다. 다만 패턴은 기본 문법에서 제외된 것 같다. (2010-04-03)

이 글은 본래 http://mearie.org/journal/2007/12/datatype-in-naru-part-4에 썼던 것을 옮겨 온 것입니다.


(rev 1d46270eb038)