Many languages have a variable (or preprocessor macro) called
__file__ whose value is the pathname of the current source file. Likewise
__LINE__ for the the source line number.
You probably need this less in Racket than you imagine. For example:
We wouldn’t test that
main.rkt; instead we’d use a
(module+ main <your code here>).
To get a data file
foo.datlocated in the same directory as a source file we’d use
(define-runtime-path foo.dat "foo.dat"). If we’re a package or executable this works regardless of where our files happen to get installed.
But if you really did need a
__FILE__ in Racket, how would you do it?
You could use
#'42 instead. The only important thing about
#'here is that it’s a syntax object representing syntax from the current source file. The
#' prefix is what matters; it’s reader shorthand for the
syntax function. So
#'here is read as
here), which you could also use if you don’t mind typing a few more keys.
1 2 3
In some Lisps, a macro works on a plain s-expression — the
(+ 1 1). A syntax object in Racket contains the s-expression, and also information such as source location (line, column, position, span) and lexical scope.1
So in Racket, you simply need to make some syntax object in your source file, like
#'here, and feed it to syntax object accessors like
What if you want to write
__LINE__ like in other languages? You could define these as macros in a file, and
require and use where desired:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#lang racket/base (provide __FILE__ __LINE__) (require (for-syntax racket/base)) (define-syntax (__FILE__ stx) ;; `stx` comes from where the macro was invoked, so give _that_ to ;; `syntax-source`. (with-syntax ([file (syntax-source stx)]) (syntax-case stx () [_ #'file]))) (define-syntax (__LINE__ stx) ;; `stx` comes from where the macro was invoked, so give _that_ to ;; `syntax-line`. (with-syntax ([line (syntax-line stx)]) (syntax-case stx () [_ #'line])))
In this case, we care about the source file and line from where the macro was invoked — from where we typed
__LINE__. So we’re careful to give that input
source-line. (Whereas if we used some made-up syntax object literal like
#'here, it would give us the source or line of
#'here in the macro definition.)
It turns out that learning how to do a
__FILE__ in Racket ends up being a gentle, practical introduction to syntax objects.
You might be wondering, why isn’t there an error that no identifier named
hereis defined? Great question. A syntax object such as
(syntax here)is basically quoted data — like
(quote here). We’re not
evaluating the syntax. ↩