Несколько строк в схеме (RnRS)

Я создал это решение:

; use like this:
; (/* content ... */ <default-return>)
; or
; (/* content ... */) => #f
(define-syntax /*
  (syntax-rules (*/)
    ((/* body ... */) #f)
    ((/* body ... */ r) r)))

Но действительно ли это лучший или простой способ?

Ответ 1

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

(+ (/* foo */) 1 2)

(define (foo a (/* b */) c) ...)

(/* foo; bar */)

(/*x*/)

(let ((x (/* 1 */) 2))
  ...)

(let ((/* (x 1) */)
      (x 2))
  ...)

(car '((/* foo */) 1 2 3))

В отчетах Схемы до R5RS нет стандартного многострочного комментария, но R6RS добавил синтаксис, который широко использовался в любом случае: #|...|#.

Но если вы действительно хотите...

Вот что я говорил в комментарии: если вы готовы обернуть весь код в макрос, то макрос может обрабатывать все тело, что может быть эффективным во многих других контекстах. Почти все из них, за исключением попытки прокомментировать синтаксически недействительные вещи, например, пример с запятой, или строку без прерывания. Вы можете судить сами, действительно ли это стоит усилий...

(Лично, насколько мне нравятся такие игры, я все еще думаю, что они бессмысленны. Но если вам действительно нравятся эти игры, и вы думаете, что они полезны, то см. раздел домашней работы ниже...)

(define-syntax prog (syntax-rules () [(_ x ...) (prog~ (begin x ...))]))
(define-syntax prog~
  (syntax-rules (/* */)
    [(prog~ (/* x ...) b ...)
     ;; comment start => mark it (possibly nested on top of a previous mark)
     (prog~ (x ...) /* b ...)]
    [(prog~ (*/ x ...) /* b ...)
     ;; finished eliminating a comment => continue
     (prog~ (x ...) b ...)]
    [(prog~ (*/ x ...) b ...)
     ;; a comment terminator without a marker => error
     (unexpected-comment-closing)]
    [(prog~ (x0 x ...) /* b ...)
     ;; some expression inside a comment => throw it out
     (prog~ (x ...) /* b ...)]
    [(prog~ ((y . ys) x ...) b ...)
     ;; nested expression start => save the context
     (prog~ (y . ys) prog~ ((x ...) (b ...)))]
    [(prog~ (x0 x ...) b ...)
     ;; atomic element => add it to the body
     (prog~ (x ...) b ... x0)]
    [(prog~ () prog~ ((x ...) (b ...)) nested ...)
     ;; nested expression done => restore context
     (prog~ (x ...) b ... (nested ...))]
    [(prog~ () /* b ...)
     ;; input done with an active marker => error
     (unterminated-comment-error)]
    [(prog~ () b ...)
     ;; all done, no markers, not nested => time for the burp.
     (b ...)]))

И пример:

(prog

 (define x 1)

 (display (+ x 2)) (newline)

 /*
 (display (+ x 10))
 /* nested comment! */
 (/ 5 0)
 */

 (define (show label /* a label to show in the output, before x */
               x /* display this (and a newline), then returns it */)
   (display label)
   (display x)
   (newline)
   x
   /* this comment doesn't prevent the function from returning x */)

 (let ([x 1] /* some comment here */ [y 2])
   (show "result = " /* now display the result of show... */
         (show "list = " (list x /* blah blah */ y)))
   'done /* just a value to return from the `let' expression */)

 (show "and ... " '(even works /* boo! */ inside a quote))

 )

Домашнее задание

За дополнительным кредитом продлите его, чтобы вы могли комментировать несбалансированные парсеры. Например, выполните следующие действия:

(prog
 blah blah /* junk ( junk */ blah blah /* junk ) junk */ blah blah.
 )

Очевидно, что входной сигнал в целом должен иметь сбалансированные парсы - это означает, что в реализации такого рода расширения не так много смысла. Даже без этого, какой смысл комментировать несбалансированный пар?

Но если кто-то все здесь, значит, вы должны наслаждаться такой самовнушением... правильно?

Ответ 2

MIT, Gnu, R6RS и R7RS поддерживают многострочные комментарии следующим образом:

#|
    This is a comment
 |#