Search code examples
syntaxmacrosschemechez-scheme

Cleanest way to make a "derived" identifier?


It's very common for Scheme macros to make "derived" identifiers, like how defining a record type foo (using the R6RS syntactic record API) will by default define a constructor called make-foo. I wanted to do something similar in my own macro, but I couldn't find any clean way within the standard libraries. I ended up writing this:

(define (identifier-add-prefix identifier prefix)
  (datum->syntax identifier
                 (string->symbol (string-append prefix
                                                (symbol->string (syntax->datum identifier)))))

I convert a syntax object (assumed to be an identifier) into a datum, convert that symbol into a string, make a new string with the prefix prepended, convert that string into a symbol, and then finally turn that symbol into an identifier in the same syntactic environment as identifier.

This works, but it seems roundabout and messy. Is there a cleaner or more idiomatic way to do this?


Solution

  • Although it might not be a hygienic macro, i suppose you could use define-syntax like this (in chicken scheme). For chicken scheme the documentation for macros is here. Also this SO question sheds some light on chicken scheme macros. Finally i don't know if this would be an idiomatic way to approach the problem.

    (use format)
    (use srfi-13)
    
    (define-syntax recgen
      (lambda (expr inject compare)
        `(define (,(string->symbol (string-append "make-" (cadr expr))) ) (format #t "called"))))
    
    #> (recgen "bar")
    #> (make-bar)
    called
    

    The single define above could be changed to a (begin ... ) that defines getters/setters or other ways to interact with the record.