Here's another implementation you might consider. In this version you can 
view the body of `phone-numbers` as a language consisting of the `number` 
and `number-list` syntactic forms. The language also supports its own kind 
of macros---phone number macros---that can expand to forms of the 
`phone-numbers` body language. `number` and `add-prefix` aren't allowed 
outside of `phone-numbers`, because they're thought of as a part of that 
language rather than Racket expressions on their own. 
`expand+extract-number` is a tiny macro expander for the language.

```
#lang racket

(require (for-syntax syntax/parse syntax/apply-transformer))

(define-syntax number
  (lambda (stx)
    (raise-syntax-error #f "number can only be used in phone-numbers 
syntax" stx)))
(define-syntax number-list
  (lambda (stx)
    (raise-syntax-error #f "number-list can only be used in phone-numbers 
syntax" stx)))

(begin-for-syntax
  (struct phone-number-macro (proc)
    #:property prop:procedure
    (lambda (s stx) (raise-syntax-error #f "phone number macros can only be 
used in phone-numbers syntax" stx))))

(define-syntax (phone-numbers stx)
  (define (expand+extract-number stx)
    (syntax-parse stx
      #:literals (number number-list)
      [(number s:string)
       (list #'s)]
      [(number-list num ...)
       (apply append (map expand+extract-number (syntax->list #'(num 
...))))]
      [(head . rest)
       #:do [(define v (syntax-local-value #'head (lambda () #f)))]
       #:when (phone-number-macro? v)
       (expand+extract-number
        (local-apply-transformer (phone-number-macro-proc v)
                                 this-syntax
                                 'expression
                                 '()))]))

  (syntax-parse stx
    [(_ num ...)
     (define expanded-nums
       (apply append (map expand+extract-number (syntax->list #'(num 
...)))))
     #`(list #,@expanded-nums)]))

(phone-numbers
 (number "123")
 (number-list (number "123")))

(define-syntax add-prefix
  (phone-number-macro
   (syntax-parser
     [(_ prefix ((~literal number) str) ...)
      #:with (prefixed ...) (map (λ (s)
                                   (datum->syntax
                                    this-syntax
                                    (string-append (syntax-e #'prefix)
                                                   (syntax-e s))))
                                 (attribute str))
      #'(number-list (number prefixed) ...)])))

(phone-numbers
 (add-prefix "555"
             (number "1212")
             (number "2121"))
 (number "1234"))
```


On Tuesday, August 20, 2019 at 6:13:21 PM UTC-4, Brian Adkins wrote:
>
> Consider the following two macros:
>
> (require (for-syntax syntax/parse))
>
> (define-syntax (phone-numbers stx)
>   (syntax-parse stx
>     [(_ ((~literal number) phone) ...)
>      #'(list phone ...)]))
>
> (define x (phone-numbers
>            (number "1212")
>            (number "2121"))) ; ==> '("1212" "2121")
>
> (define-syntax (add-prefix stx)
>   (syntax-parse stx
>     [(_ prefix ((~literal number) str) ...)
>      #'(list (list 'number (string-append prefix str)) ...)]))
>
> (define y (add-prefix "555"
>                       (number "1212")
>                       (number "2121"))) ; ==> '((number "5551212") (number 
> "5552121"))
>
> I would like to be able to do the following:
>
> (phone-numbers
>  (add-prefix "555"
>              (number "1212")
>              (number "2121"))
>  (number "1234")) ; ==> '("5551212" "5552121" "1234")
>
> I was hoping it would be possible to do this without modifying the 
> phone-numbers macro. In other words, to have the result of expanding 
> add-prefix macro call be:
>
> (number "5551212") (number "5552121")
>
> So that it would appear to the phone-numbers macro as if the user had 
> actually typed:
>
> (phone-numbers
>   (number "5551212")
>   (number "5552121")
>   (number "1234"))
>
> Is it possible to do this w/o the explicit cooperation of the 
> phone-numbers macro?
>
> Brian Adkins
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/262b8824-ab94-47a1-b6be-88216c0de937%40googlegroups.com.

Reply via email to