Writing a macro that behaves differently depending on context

I'm trying to define a macro 'def' which behaves differently depending on where it appears. If it appears in the top-level, it expands to a normal 'define' and adds the definition to a hash. If it appears in a local context, it works more as a 'let' and nothing is added to the hash.
So, how can a macro be aware of where it appears?

2 Likes

I’m a bit confused about the requirements. What do you mean by “expands to a normal” and “adds the definition to a hash”? In particular, is this a hash at run-time or compile-time? I also don’t understand what you mean by “it works more as a and nothing is added to the hash”. It looks like the sentence is incomplete.

In any case, yes, during macro expansion, you can use syntax-local-context to see which context you are in. Here’s an example that illustrates how to use it:

#lang racket

(define-syntax (test stx)
  (case (syntax-local-context)
    [(expression) #'"expression context"]
    [(top-level) #'"REPL context"]
    [(module module-begin) #'"module context"]
    [else #'"internal definition context"]))

test 
;=expand=> "module context"
;=eval=>   "module context"

(values test)
;=expand=> (values "expression context") 
;=eval=>   "expression context"

(let ()
  test) 
;=expand=> (let-values () "internal definition context") 
;=eval=>   "internal definition context"

Furthermore, if you evaluate "test" at the REPL, you will get "REPL context" back.

4 Likes

whoops, I put some Racket words between angle brackets so they were interpreted as HTML and didn't show in my final post. Edited using ' ' instead for clarity.
Anyway, you pointed me in the direction I needed, thanks!