On Fri, Sep 29, 2006 at 09:06:08PM -0700, Per Bothner wrote:
> >Firstly, when the comment expression is the last subexpression, it
> >does not break up the trailing parens with the closing lexeme. Of the
> >following two forms, I consider the former more aesthetically pleasing
> >than the latter.
> >
> > (+
> > (- foo
> > bar
> > #;
> > (this is
> > a
> > long
> > (expression (that
> > has
> > many
> > parens)))))
> >
> >
> > (+
> > (- foo
> > bar
> > #|
> > (this is
> > a
> > long
> > (expression (that
> > has
> > many
> > parens)))|#))
>
> Aa I said above: you really don't want this in production code, or more
> generally anything that is 'checked in" (to a source-code repository).
> What is the purpose?
One that immediately occurs to me is when one replaces a simple
definition with an optimized definition, and you want to leave the
original definition as a comment. A contrived example:
(define (f x)
#;
(+ (* x x)
(* x x))
(let ((x* (* x x)))
(+ x* x*)))
I guess ultimately I see #; as a case of say-what-you-mean. I'm not
commenting out a paragraph of text, I'm commenting out an expression.
> If you want to comment out a fragment of production code you need to
> explain *why* it is commented out, using *text* - and so it's no
> longer an s-expr.
The comment and the elided expression don't have to be part of the
same comment.
(define (f x)
;; The original version
#;
(+ (* x x)
(* x x))
;; The optimized version
(let ((x* (* x x)))
(+ x* x*)))
> Furthermore, it seldom makes sense to comment out an s-expr, especially
> in a functional (or mostly-functional) language. You comment out a
> parameter to a function, and the function suddenly has the wrong arity.
> It only makes sense for side-effecting actions whose values are ignored,
> or rare parameters to variable-arity functions.
Even without side-effects (which removes the need for variadic LAMBDA,
BEGIN and DEFINE), you still have variadic COND, CASE, AND, OR, LET,
LET* and LETREC (within the binding parameter), DO (within the binding
and test parameters), LET-SYNTAX, LETREC-SYNTAX and SYNTAX-RULES.
I hardly think these are "rare". It's also kind of uncommon for a
Scheme document to have only one definition at the top level.
>> Secondly, because #; guarantees to comment out exactly one expression,
>> I do not need to look for the closing lexeme. In the above example,
>> it would be quite easy for a student to accidentally write
>>
>> (+
>> (- foo
>> bar
>> #|
>> (this is
>> a
>> long
>> (expression (that
>> has
>> many
>> parens))|#)))
>>
>> producing a syntactic error that is potentially very difficult to
>> detect (without a smart editor).
>
> But since you should always use a smart editor, this point is moot.
Except, of course, when reading a physical printout or PDF.
> It is also moot because the example is not an illustration of
> something anyone would want to do - it's a contrived example
> without motivation.
Very well, here is a real-world example, from some throwaway code to
turn OpenOffice documents into a plain text format. Excuse the
exorbitant length.
(define transform
(lambda (e)
(sxml-match e
;; Promote content of single-content blocks
[(*TOP* ,(x)) x]
[(document-content ,(x)) x]
[(span ,(x)) x]
[(sequence ,(x)) x]
[(creation-date ,(x)) x]
[(editing-cycles ,(x)) x]
[(text-box ,(x)) x]
[(body . ,xs)
(fold body "" (map transform (reverse xs)))] ; hack to prevent stack overflow.
#;
[(body ,(x) ...)
(body x ...)]
[(p (line-break) ,x ...) ; drop leading line-break
(transform (list 'p x ...))]
[(p ,x ... (line-break)) ; drop trailing line-break
(transform (list 'p x ...))]
[(p (s) ,x ...) ; drop leading s
(transform (list 'p x ...))]
[(p ,x ... (s)) ; drop trailing s
(transform (list 'p x ...))]
[(p ,(x) ...)
(p x ...)]
;;; This is a hack to fix a very specific problem in a very, very stupid document.
#;
[(h (_at_ . ,as) (p (image . ,xs) . ,ys) ,z)
(body (transform `(h (_at_ . ,as) ,z))
(transform `(p (image . ,xs) . ,ys)))]
#;
[(p (image . ,xs) . ,ys)
(body (transform (cons 'image xs))
(transform (cons 'p ys)))]
[(h (_at_ (level ,n)) ,(x) ...)
(h (string->number n) (string-append x ...))]
[(a (_at_ (href ,(href)) . ,attributes) ,(name))
(if (string-ci=? href name)
href
(a href name))]
[(image (_at_ (href ,(url)) . ,attributes))
(image url)]
[(date (_at_ (date-value ,iso-date) . ,attributes) ,x)
iso-date]
[(table-of-content)
table-of-content]
[(s)
s]
[(line-break) line-break]
[(table ,(x) ...)
(table x ...)]
[(table-row ,(x) ...)
(table-row x ...)]
[(table-cell ,(x) ...)
(table-cell x ...)]
[(ordered-list . ,xs)
(ordered-list xs)]
[(unordered-list . ,xs)
(unordered-list xs)]
;; Everything else is unchanged
(,x (->string x)))))
To take an excerpt, it is easy to see that
#;
[(body ,(x) ...)
(body x ...)]
comments out exactly one clause, whereas
#|
[(body ,(x) ...)
(body x ...)]
|#
requires the (human) reader to look for the closing lexeme.
> >Thirdly, it is safe for an editor to assume that the expression
> >commented out by #; is a symbolic expression, rather than arbitrary
> >text. This means it can safely provide the same indenting and
> >structured editing facilities that it provides outside of comments.
> >For example, if the buffer contains
> >
> > #;-!- A
> >
> >then typing ( could usefully insert both opening and closing
> >parentheses:
> >
> > #;(-!-) A
> >
> >And if the buffer contains
> >
> > #;(foo bar-!- baz)
> >
> >then typing Return could usefully indent after adding a newline:
> >
> > #;(foo bar
> > -!-baz)
> >
> >In the above examples, -!- indicates the position of the cursor.
>
> But without any meaningful examples showing the use of s-expr comments
> in real code it seems the feature should go away for lack of usefulness.
See above for such an example.
> I.e. the proponents of #; need to illustrate how using #; is better
> that #|...|# in real code, or at least during development (debugging).
> I have seen no such examples.
> --
> --Per Bothner
> per_at_bothner.com http://per.bothner.com/
--
Trent Buck, Student Errant
Received on Sat Sep 30 2006 - 00:58:30 UTC