dotimes — 정해진 횟수만큼 반복
dotimes — 정해진 횟수만큼 반복
리스트를 순회할 땐 dolist, 그리고 몇 번 반복할지가 미리 정해져 있을 때는 dotimes가 어울려요. "세 번만 돌려" 같은 정해진 횟수의 반복은 dotimes가 훨씬 간결하게 표현해 줘요.
본문
dotimes는 0부터 시작하는 정수들을 차례로 var에 묶어가며 본문을 실행하는 반복 매크로예요. 몇 번 돌지가 count-form에 담겨 있어요.
dotimes (var count-form [result-form]) declaration* {tag | statement}*
=> result*
count-form을 평가한 값이 0이나 음수면 본문은 아예 실행되지 않아요. 그렇지 않으면 count-form의 값보다 작은 정수 0, 1, 2, ...를 var에 묶어 각각 본문을 실행해요. 반복이 끝나면 result-form을 평가하는데, 이때 var는 본문이 실제로 실행된 횟수로 묶여 있어요.
(dotimes (temp-one 10 temp-one)) ; => 10
본문이 비어 있어도 var는 10번 묶였으니, result-form으로 temp-one을 돌려주면 10이 나와요. 본문에서 횟수를 직접 세는 것도 해요요.
(setq temp-two 0) ; => 0
(dotimes (temp-one 10 t) (incf temp-two))
=> T
temp-two ; => 10
dotimes는 문자열을 처리할 때도 유용해요. 인덱스로 문자를 하나씩 꺼내 비교할 수 있죠. 아래는 부분 문자열이 회문(palindrome)인지 검사하는 함수예요.
(dotimes (k (floor (- end start) 2) t)
(unless (char-equal (char string (+ start k))
(char string (- end k 1)))
(return nil)))
(palindromep "Able was I ere I saw Elba") ; => T
(palindromep "A man, a plan, a canal--Panama!") ; => NIL
구두점을 지우고 비교하면 아래처럼 성립해요.
(palindromep
(remove-if-not #'alpha-char-p
"A man, a plan, a canal--Panama!"))
=> T
dolist와 마찬가지로 dotimes 폼 전체는 nil이라는 암묵적 블록으로 감싸여 있고, 본문은 암묵적 tagbody예요. 그래서 return으로 즉시 빠져나가거나 go로 특정 위치로 점프할 수 있어요. var의 묶음 범위는 count-form을 포함하지 않고, result-form은 포함해요.
함께 보기
do, dolist, tagbody