> Is 'Semantics Engineering with PLT Redex' where I should get started on > language-engineering?
Concretely, I think Robby's suggestion will look something like this: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #lang racket ;; Let's create a custom structure for procedures that remember certain things. (struct proc/data (proc data) #:property prop:procedure (lambda (pd . args) (apply (proc/data-proc pd) args))) ;; We can manually create such instances... (define f (proc/data ;; implementation: (lambda (x) (* x x)) ;; with associated metadata: "this is the square function")) ;; It can be called: (f 16) ;; but we can also retrieve its metadata: (proc/data-data f) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; For more information on this, see: http://docs.racket-lang.org/reference/procedures.html#(def._((lib._racket/private/base..rkt)._prop~3aprocedure)) Now that we can record metadata with a procedure-like value, let's look at what kinds of data we'd like to capture. Concretely, your question sounds like you want something about module-level bindings. That kind of information should be accessible at compile-time. We can try to write a macro to save that information for us. Continuing: let's have a "def" form that remembers some information we determine ate compile time. Save the above coide into a file called "def.rkt". We'll be adding the following extra lines to it: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; I think we need the following definition to use splicing-let-syntax: (require racket/splicing) ;; This "def" will try to automatically bundle a metadata or a proc/data; this information is ;; the module path, which it can determine during compilation. (define-syntax (def stx) (syntax-case stx () [(_ (name . args) body ...) (syntax/loc stx ;; Question to others: how can this be simplified? (splicing-let-syntax ([get-literal-metadata (lambda (stx) #`(#%datum . #,(format "~s" (variable-reference->resolved-module-path (#%variable-reference)))))]) (define name (proc/data (lambda args body ...) (get-literal-metadata)))))])) (provide def (struct-out proc/data)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; I'm not sure if this is the cleanest way to do it, so hopefully someone can help correct me. :) This creates a "def" form that can define functions. It uses the proc/data we defined earlier, and it does a minor bit of compile-time computation to figure out module paths. Finally, let's try using it! Create 'def-test.rkt' with the following content: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #lang racket (require "def.rkt") (def (h x) (string-append "hi, I'm " x)) (h "bob") (proc/data-data h) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; If you run this program, you should see: ############################## "hi, I'm bob" "#<resolved-module-path:'def-test>" ############################## which shows that the "h" function we create with 'def' is a callable thing, and it also has runtime metadata that remembers where it came from. For more information, see: http://docs.racket-lang.org/guide/pattern-macros.html ____________________ Racket Users list: http://lists.racket-lang.org/users