Макрос Racket для преобразования всех, кроме s-выражений - PullRequest
1 голос
/ 14 июля 2020

Я пытаюсь понять, как создать макрос ракетки, который просто преобразует в строку все содержимое, кроме s-выражений, которые он оставит в покое.

Я дошел до того, что выяснил, как это сделать преобразовать все в строку

  #+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)"

Но понятия не имею, как проверить, является ли что-то s-выражением или нет.

Как мне это сделать?

Ответы [ 2 ]

4 голосов
/ 14 июля 2020

«s-выражение» - это список / пара синтаксиса, поэтому вы можете сопоставить образцы для () и (a . b), например:

#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")
2 голосов
/ 14 июля 2020

Если мы используем обычное определение процедуры atom? в качестве ссылки:

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

Тогда мы могли бы определить предикат s-выражения как:

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

И, конечно, , вам нужно будет применить это рекурсивно к каждому из элементов s-выражения.

...