Многострочные комментарии в схеме (RnRS)

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

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

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


person Felipe    schedule 17.09.2010    source источник


Ответы (2)


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

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

В отчетах Scheme до 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.
 )

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

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

person Eli Barzilay    schedule 17.09.2010
comment
Большое спасибо! Итак, мой код может быть полезен для ‹R5RS. Но, пожалуйста, приведите мне реальные примеры, когда это не сработает. --- А для R5RS, если этого кода недостаточно, не могли бы вы дать мне что-нибудь получше? - person Felipe; 17.09.2010
comment
Пожалуйста, дайте мне оригинальную конструкцию минусов и то, что вы хотели бы прокомментировать. Извините, но ваш пример кода не имел для меня смысла. - person Felipe; 17.09.2010
comment
если оригинал был (cons 'a foo), я думаю, вы могли бы это сделать: (cons (/ *' a * / 'temp-value) foo) если вы хотите прокомментировать' a - person Felipe; 17.09.2010
comment
и в качестве аргументов функции: (sum a b c d (/ * e * / 0) f g h) - person Felipe; 17.09.2010
comment
Да, это один случай - я добавил еще несколько примеров. - person Eli Barzilay; 17.09.2010
comment
Но вы неправильно используете! :) По умолчанию return #f, но вы можете определить другое значение. Например: используйте (+ (/ * foo / 0) 1 2) вместо (+ (/ foo * /) 1 2). И вы не дали мне хорошего решения для ‹= R5RS. Жду, спасибо! - person Felipe; 17.09.2010
comment
(1) Конечно, вы можете изменить его на 0 - но нет никакого способа узнать заранее, какое значение вам нужно; (2) даже если у вас есть какое-то магическое значение, оно не сработает при вызове list - который неизбежно получит одно дополнительное значение; (3) Я не могу дать вам решение для R5RS и ниже - я сказал, что его нет; (4) Я также сказал, что для всех практических целей это не проблема, поскольку синтаксис #|...|# был принят почти всеми реализациями (R5RS); (5) если вы ищете способ написать переносимый код R5RS, у вас будут гораздо более серьезные проблемы. - person Eli Barzilay; 18.09.2010
comment
Я забыл: (2.5) использование его в приложении-функции было всего лишь одним примером из многих, когда это не сработало. - person Eli Barzilay; 18.09.2010
comment
Хорошо, Эли. Я не полностью согласен, но я понимаю вашу точку зрения. Мое предложение по коду было просто для ограничения, и это очень полезно в большинстве случаев. Я просто спросил, есть ли у кого-нибудь что-нибудь получше, но до сих пор никто не ответил. - person Felipe; 20.09.2010
comment
SpamKids: не с чем соглашаться или не соглашаться - ваша форма работает только в ограниченном контексте, когда ожидается выражение, а то, что оно оценивает, отбрасывается. Это оставляет целую кучу контекстов, в которых он не работает как многострочный комментарий. - person Eli Barzilay; 20.09.2010
comment
Я согласен с этим, но мой вопрос все еще открыт. Я спросил: это лучший способ? (Я не спрашивал, работает ли он во всех случаях?). Извините, но это не сработало, в данном случае бесполезный ответ. - person Felipe; 20.09.2010
comment
Это лучший вариант по определению этого слова. ИМО, гораздо лучшее решение (о котором я упоминал несколько раз) - использовать #|...|#, который поддерживается всеми серьезными реализациями схемы и который является частью R6RS. Но это решение практической проблемы многострочных комментариев - если вы просто пытаетесь играть с макросами, это не имеет значения. Что касается того, что это не сработало - ну, вы разместили код, и я указал на то, что он не работает - что еще я могу сказать? Это сработало для некоторой ограниченной стоимости \ сработало \ сработало лучше? - person Eli Barzilay; 21.09.2010
comment
Еще одно замечание: его можно было бы улучшить и обработать больше случаев, если вы хотите обернуть весь код внутри некоторого макроса, этот макрос может затем выполнить обход кода и сканировать все его содержимое, удаляя вхождения /* ... */ (даже без скобок ). Но поскольку вы ограничиваетесь R5RS, тогда у вас есть только syntax-rules, и все становится намного сложнее. Выполнимо, но сложно. - person Eli Barzilay; 21.09.2010
comment
Спасибо и поздравляю! :) Теперь ваш ответ имеет смысл! Очень интересно!! Теперь могу отметить как приемлемый ответ. Я думаю, что такая игра, которую вы называете, для меня не игра и не бесполезна. Это элегантный способ показать, насколько Scheme является гибкой и мультипарадигмальной. В любом случае, у меня сейчас нет времени на домашние задания, но я ценю вашу инициативу! Пусть это для студентов, кто знает, что они могут дать вам хорошее решение? Увидимся! - person Felipe; 21.09.2010
comment
(вздох) Это имеет смысл только в предоставлении менее ограниченного решения несуществующей проблемы ... Это еще худшее решение, если рассматривать его с точки зрения практичности. Известно, что макросистема Scheme может делать такие вещи, но известно, что это очень неудобно - поэтому с точки зрения языкового дизайна заставлять меня использовать неудобную конструкцию вместо кода - это далеко не то, что я назвал бы элегантным, гибким. , или мультипарадигма. - person Eli Barzilay; 21.09.2010
comment
Ну давай же! Вы пытаетесь быть более реальным, чем король. В R5RS это настоящая проблема. Я говорю о книжном стандарте, а не об изобретениях или конкретных реализациях. И да, это показывает мощь языка, даже если это не совсем элегантно - в этом я согласен! У меня не было времени внимательно разглядывать ваш ответ, но очень скоро. Мне любопытно узнать, как это работает. Увидимся! - person Felipe; 21.09.2010
comment
@SpamKids: Я действительно упомянул, что если вы заботитесь о стандарте, то #|...|# был официально объявлен в R6RS, и даже более того: это функция, которая широко распространена, а я не Я не помню ни одного случая, когда это обсуждалось. Таким образом, для всех практических - реальных - стандартных - целей вы можете положиться на существование этой функции. В противном случае отправьте отчет об ошибке. Что касается того, как это работает - это не очень сложно, просто очень многословно и очень трудно следовать - потому что вместо реального кода он выполняет преобразования по правилам перезаписи. - person Eli Barzilay; 22.09.2010

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

#|
    This is a comment
 |#
person David Jeske    schedule 18.05.2017