위치·줄·열 세기(Counting Positions, Lines, and Columns)

위치·줄·열 세기(Counting Positions, Lines, and Columns)

포트에서 데이터를 읽고 쓸 때 그 위치를 바이트 단위로 추적하는 게 기본이에요. 원하면 문자·줄·열 단위로도 추적할 수 있습니다.

출처: Racket Reference

본문

기본적으로 Racket은 포트의 위치를 그 포트에서 읽거나 쓴 바이트 수로 추적합니다(file-position으로 접근·변경되는 읽기/쓰기 위치와는 무관합니다). 선택적으로 Racket은 바이트 대신 (UTF-8 디코딩 후의) 문자 단위로 위치를 추적할 수 있고, 줄 위치(line location)와 열 위치(column location)도 추적할 수 있습니다. 이 선택적 추적은 port-count-lines!port-count-lines-enabled 파라미터를 통해 포트마다 특별히 활성화해야 합니다. 포트의 위치·줄·열 위치는 read-syntax가 사용합니다. 위치와 줄 위치는 1부터 번호가 매겨지고, 열 위치는 0부터 번호가 매겨집니다.

줄을 셀 때 Racket은 줄바꿈(linefeed), 리턴(return), 리턴-줄바꿈 조합을 (모든 플랫폼에서) 하나의 줄 종결자이자 하나의 위치로 취급합니다. 각 탭은 열 수를 다음 8의 배수 하나 전으로 진행시킵니다. 128에서 253 범위의 바이트 시퀀스가 문자의 UTF-8 인코딩을 형성하면, 각 바이트마다 위치/열이 한 번씩 증가하고, 완전한 인코딩 시퀀스가 발견되면 적절히 감소합니다. 포트의 UTF-8 디코딩에 대한 자세한 정보는 Ports도 함께 보세요.

위치는 그 값이 fixnum으로 표현될 수 있는 한 어떤 포트에 대해서도 알려집니다(이는 예를 들어 syntax-error 보고 같은 현실적인 응용에서는 충분히 넘치는 추적입니다). 포트의 위치가 가장 큰 fixnum 값을 넘으면 포트의 위치는 알 수 없게 되고, 줄·열 추적은 비활성화됩니다. 리턴-줄바꿈 조합은 줄·열 세기가 활성화된 경우에만 하나의 문자 위치로 취급됩니다.

사용자 정의 포트(custom port)는 위 규칙의 적용을 받지 않는 자체 세기 함수를 정의할 수 있습니다. 단, 세기 함수는 port-count-lines!로 추적이 특별히 활성화된 경우에만 호출됩니다.

port-count-lines!

procedure

(port-count-lines! port) → void?
  port : port?

포트에 대해 줄 위치와 열 위치 세기를 켭니다. 세기는 언제든 켤 수 있지만, 보통 포트에서 데이터를 읽거나 쓰기 전에 켭니다. 줄 세기가 켜지는 시점에는 port-next-location이 보통 마지막 결과로 (포트가 열린 뒤부터 읽은 바이트 수 + 1) 대신 (줄 세기가 활성화된 뒤부터 읽은 문자 수 + 1)을 보고하기 시작합니다.

포트가 생성될 때 port-count-lines-enabled 파라미터의 값이 참이면, 그 포트에 대해 줄 세기가 자동으로 활성화됩니다. 줄 세기는 활성화된 후에는 포트에 대해 비활성화할 수 없습니다.

port-counts-lines?

procedure

(port-counts-lines? port) → boolean?
  port : port?

port에 대해 줄 위치와 열 위치 세기가 활성화되었으면 #t, 그 외에는 #f를 반환합니다.

port-next-location

procedure

(port-next-location port)
 → (or/c exact-positive-integer? #f)
    (or/c exact-nonnegative-integer? #f)
    (or/c exact-positive-integer? #f)
  port : port?

세 값을 반환합니다: 다음으로 읽거나 쓸 항목의 줄 번호에 대한 정수 또는 #f, 다음 항목의 열에 대한 정수 또는 #f, 그리고 다음 항목의 위치에 대한 정수 또는 #f. 다음 열과 위치는 보통 포트에서 바이트를 읽거나 쓸 때 증가하지만, port에 대해 줄/문자 세기가 활성화되어 있으면 열과 위치 결과는 UTF-8 인코딩 시퀀스를 끝내는 바이트를 읽거나 쓴 뒤 감소할 수 있습니다.

포트에 대해 줄 세기가 활성화되어 있지 않으면 처음 두 결과는 #f이고, 마지막 결과는 지금까지 읽은 바이트 수 + 1입니다. 줄 세기가 활성화되는 시점에는 보통 처음 두 결과가 #f가 아니게 되고, 마지막 결과는 바이트 대신 문자를, 보통 줄 세기가 활성화된 시점부터 보고하기 시작합니다.

줄 세기가 활성화되어 있어도, 포트가 어떤 이유로든 줄·열·위치를 추적할 수 없다면 #f 값을 반환할 수 있습니다.

set-port-next-location!

procedure

(set-port-next-location! port line column position) → void?
  port : port?
  line : (or/c exact-positive-integer? #f)
  column : (or/c exact-nonnegative-integer? #f)
  position : (or/c exact-positive-integer? #f)

port의 다음 줄, 열, 위치를 설정합니다. port에 대해 줄 세기가 활성화되지 않았거나 port가 자체 세기 함수를 정의하는 사용자 정의 포트라면 set-port-next-location!은 효과가 없습니다.

port-count-lines-enabled 파라미터

parameter

(port-count-lines-enabled) → boolean?
(port-count-lines-enabled on?) → void?
  on? : any/c

새로 생성된 포트에 대해 줄 세기를 자동으로 활성화할지 결정하는 파라미터입니다. 기본값은 #f입니다.

더 알아보기