openlang

with-lenient-parse가 에러를 로깅하는데도 SBCL이 여전히 디버거로 빠져요

hosts 파일에 잘못된 줄이 있으면 로그만 남기고 계속 로드하도록 매크로를 하나 짰어요. 전체 코드는 이거예요:

(defmacro with-lenient-parse ((&key (log t)) &body body)
  `(handler-bind ((missing-field
                    (lambda (c)
                      (when ,log
                        (format *error-output* "skipping: ~A~%" c))
                      nil))
                  (bad-port
                    (lambda (c)
                      (when ,log
                        (format *error-output* "warn: ~A~%" c))
                      nil)))
     ,@body))

parse-line에는 skip-line restart가 있는데, 이걸 실제로 호출하는 곳이 있는지는 잘 모르겠어요. 입력은 한 줄에 호스트 하나씩 name addr [port] 형식이고, sh run.sh로 실행해요.

파일에 web-02(addr 없음)가 있으면 stderr에 skipping: line 2: missing addr가 찍혀요. 그다음에 SBCL이 똑같은 missing-field 에러로 디버거에 빠지고 스크립트가 죽어요. 핸들러에서 리턴하면 parse-line이 그 줄에 대해 nil을 리턴할 거라고 생각했는데, 아닌가 봐요.

거기를 넘어가려고 web-02 줄을 지웠어요. 이번에는 warn: line 4: bad port abc가 찍히고, 그다음에 privileged-p에서 NIL is not of type NUMBER라는 type error가 나요. 그 함수는 파싱이랑 아무 상관이 없는데요. port 컨디션은 warning 서브클래스를 그냥 signal하는 거고, 제가 쓴 코드에서 그걸 fatal로 취급하는 곳도 없어요.

이게 버그 두 개인가요, 아니면 핸들러가 걸리는 방식을 제가 하나 잘못 이해한 건가요? 이 매크로는 호출하는 쪽에 실제로 뭘 보장하는 건가요? 트랜스크립트를 기억에 의존해서 쓰는 거라 전체 백트레이스는 못 붙여요.

영어에서 번역원문 보기

이어지는 대화 2

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

    하나를 잘못 이해하신 거라고 생각해요. handler-bind 핸들러가 그냥 리턴하면 처리를 거절한 거라서, 컨디션이 다음 핸들러로 넘어가고, 남은 게 없으면 디버거로 가요. parse-line에서 nil을 리턴해 주는 건 아무것도 없어요. 핸들러 안에서 restart를 직접 호출해야 해요: (invoke-restart 'skip-line).

    bad-port도 똑같아요. signal은 nil을 리턴하니까 privileged-p에서 port가 nil로 남는 거예요.

    https://www.lispworks.com/documentation/HyperSpec/Body/m_handle.htm

    영어에서 번역원문 보기
  2. 고유 링크

    restart 수정에 대해 작은 주의사항이 있어요 (핸들러가 스택이 풀리기 전에 실행되니까 편하긴 해요). find-restart로 감싸 주세요. skip-line이 활성 상태가 아니면 그냥 invoke-restart를 쓸 때 에러가 나거든요.

    (lambda (c)
      (let ((r (find-restart 'skip-line c)))
        (when r (invoke-restart r))))
    영어에서 번역원문 보기

같은 질문의 다른 갈래

  1. 빈 리덕션은 항등원을 돌려준다

    빈 벡터를 리덕션한다. APL은 답한다. 프리미티브마다 항등원이 있다. 더하기는 0. 곱하기와 논리곱은 1. ⌈/⍬는 인터프리터가 가진 가장 작은 음수다. 호출하는 쪽에 특수 처리가 없다. 리덕션 전에 길이를 확인하지도 않는…

    답글 3최근 활동 apl
  2. 매크로 대부분이 const와 static이 됐다

    Nim은 매크로를 쓰기 쉽게 해 준다. 그게 문제다. macro에 손대기 전에 더 싼 도구부터 본다. const는 매크로를 돌리는 바로 그 VM이 컴파일 시점에 평가한다. 그래서 평범한 proc으로 만든 조회 테이블은 그냥…

    답글 3최근 활동 nim
  3. it, _1, 그리고 여전히 쓰는 블록 이름

    Ruby 3.4에 블록 매개변수를 가리키는 it이 들어왔습니다. 덕분에 users.map { it.name }은 거의 문장처럼 읽힙니다. 저는 _1보다 이쪽이 좋습니다. 그쪽은 늘 파서가 흘리고 간 무언가처럼 보였습니다. P…

    답글 0최근 활동 ruby