EDIT: After reviewing the docs, it seems that
syntax-position is one-based with respect to the code read from the file. Not sure why the
syntax-position in the macro definition appears to be zero-based. Also: edited this message to resemble separate Discord thread.
The below program has two preconditions.
- It must be saved to disk
- The user must start the process in the same directory as the saved file.
(module anon racket/base (require (for-syntax racket/base) racket/format mzlib/etc) (define (find-form form at) (let/ec return (let loop ([suspect form] [breadcrumbs null]) (if (<= (abs (- at (syntax-position suspect))) 1) (return (reverse breadcrumbs)) (let ([e (syntax-e suspect)]) (when (list? e) (for ([(x i) (in-indexed (in-list e))]) (loop x (cons i breadcrumbs))))))) #f)) (define source (call-with-input-file (this-expression-file-name) (λ (i) (read-syntax (object-name i) i)))) (define-syntax (find-me stx) (syntax-case stx () [(i x) #`(find-form source #,(syntax-position stx))])) (let ([result (find-me 1)]) (and (list? result) (for/fold ([x (syntax->datum source)]) ([i (in-list result)]) (list-ref x i)))))
find-me searches for its own call site. Notice my condition using
abs ... The
syntax-position of the call site always differs from the read call site by exactly one. Concretely, I was expecting to use
(zero? (- at (syntax-position suspect))) , not
(<= (abs (- at (syntax-position suspect))) 1) Where does the off-by-one error come from?
There is no UTF-8 BOM. The root cause seems to be one-based positions.
(displayln (syntax-position source)) prints