Multiple lines comments in Scheme (RnRS)

2019-04-10 00:15发布

I created this solution:

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

But is it really the best or easiest way?

2条回答
闹够了就滚
2楼-- · 2019-04-10 00:44

MIT, Gnu, R6RS and R7RS support multi-line comments like this:

#|
    This is a comment
 |#
查看更多
男人必须洒脱
3楼-- · 2019-04-10 00:52

You can't do it this way -- it won't work for a number of contexts. Here are some examples that won't work:

(+ (/* 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))

There is no standard multi-line comment in the Scheme reports up to R5RS, but R6RS has added a syntax that was widely used anyway: #|...|#.

But if you really want to...

Here's what I was talking about in the comment: if you're willing to wrap the whole code in a macro, then the macro can process the whole body, which can be effective in many more contexts. Pretty much all of them except for trying to comment out syntactically invalid stuffs like the semicolon example above, or an unterminated string. You can judge for yourself whether it's really worth the effort...

(Personally, as much as I enjoy such games, I still think they're pointless. But if you really enjoy these games and you think they're useful, then see the homework section below...)

(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 ...)]))

And an example:

(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))

 )

Homework

For extra credit, extend it so you can comment out unbalanced parens. For example, make this work:

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

Obviously, the input as a whole should have balanced parens -- this means that there's not much point in implementing this kind of an extension. Even without it, what's the point in commenting out an unbalanced paren?

But if anyone got all the way here, then you must enjoy this kind of self-torture ... right?

查看更多
登录 后发表回答