George Mauer
George Mauer

Reputation: 122052

Racket macro to stringify all but s-expressions

I am trying to figure out how to create a racket macro that will simply convert to a string all contents except for s-expressions which it will leave alone.

I got as far as figuring out how to stringify everything

  #+begin_src racket
    (define-syntax (stringify-all stx)
      (syntax-case stx ()
        [(_ args ...)
         #'(begin
             (~s 'args)
             ...)]))

    (stringify-all one 2 (add1 2))
  #+end_src

  #+RESULTS:
  : "one"
  : "2"
  : "(add1 2)"

But have no clue how to test whether something is an s-expression or not.

How do I do that?

Upvotes: 1

Views: 117

Answers (2)

Sorawee Porncharoenwase
Sorawee Porncharoenwase

Reputation: 6502

"s-expression" is syntax list/pair, so you can pattern match for () and (a . b), like this:

#lang racket

(require (for-syntax (only-in racket/format ~s)))

(define-for-syntax (compute stx)
  (syntax-case stx ()
    [() #'null]
    [(a . b) #`(cons #,(compute #'a) #,(compute #'b))]
    [_ (~s (syntax-e stx))]))

(define-syntax (stringify-all stx)
  (syntax-case stx ()
    [(_ args ...)
     #`(begin #,@(map compute (syntax->list #'(args ...))))]))

(stringify-all one 2 (add1 2))

;; "one"
;; "2"
;; '("add1" "2")

Upvotes: 4

Óscar López
Óscar López

Reputation: 235994

If we use the usual definition of the atom? procedure as reference:

(defne (atom? exp)
  (and (not (null? exp))
       (not (pair? exp))))

Then we could define an s-expression predicate as:

(define (s-exp? exp)
  (or (null? exp)
      (pair? exp)))

And of course, you'd need to apply this recursively to each of the elements of an s-expression.

Upvotes: 2

Related Questions