I, myself, really dislike &aux. It has been so long since I have seen it that I have forgotten that it even exists. We never use it; and I should add that to our style guide.
I don't even like
(let (a b c) ...)
since I prefer to think of "let" in the Scheme sense of "I am naming the result of a computation." In fact, I added a macro to our library that is like "let" but does not allow the variable to be modified. (It's not portable; it uses a CCL-specific feature.)
Unfortunately, we do not use it in practice, since it's so important for code style to be consistent and it would be very hard to change all our sources to do this, since it's hard to know from looking at code whether the "let" variable ever changes, and we have like 700MLOC of code in QRes. I wish Common Lisp had always had such a feature.
I'm not saying there's no place for let followed by side effects. It's just not the way I usually think of it.
Also, putting things in the parameter list that aren't parameters just feels weird.
I do not think my own opinions are by any means "right". These are just my biases and preferences.
-- Dan
On 12 June 2011 10:00, Daniel Weinreb dlw@alum.mit.edu wrote:
I, myself, really dislike &aux. It has been so long since I have seen it that I have forgotten that it even exists. We never use it; and I should add that to our style guide.
&aux has its uses. Sometimes it can be clearer than adding a let.
I don't even like
(let (a b c) ...)
Same thing. If you're going to do side effects (sometimes you have to) in particular when you need the binding to be visible in a scope that starts before you have a useful value to initialize it with, then it's clearer to say let (a) and make it clear it's conceptually uninitialized than say let ((a nil)) where nil is bogus and not even an admissible value for the variable's intended type. See especially unwind-protect forms.
since I prefer to think of "let" in the Scheme sense of "I am naming the result of a computation."
Call that something else than let if you want, it's a useful idiom.
Also, binding forms are annoying in that they are verbose and move the body to the right as you nest them. Instead of any ad-hoc do-it-all binding macro, I like this macro from Marco Baringer that does nesting for you:
(defmacro with-nesting ((&key) &rest things) (reduce #'(lambda (outer inner) (append outer (list inner))) things :from-end t))
In fact, I added a macro to our library that is like "let" but does not allow the variable to be modified. (It's not portable; it uses a CCL-specific feature.)
Yet Pascal just offered a portable implementation!
Here's mine.
(defmacro read-only (value name) (declare (ignore name)) value) (define-setf-expander read-only (value name &environment env) (declare (ignore value env)) (error "Thou shall not attempt to modify read-only variable ~S" name))
(defmacro let-1-constant ((var val) &body body) (let ((s (gensym))) `(let ((,s ,val)) (symbol-macrolet ((,var (read-only ,s ,var))) ,@body))))
Unfortunately, we do not use it in practice, since it's so important for code style to be consistent and it would be very hard to change all our sources to do this, since it's hard to know from looking at code whether the "let" variable ever changes, and we have like 700MLOC of code in QRes. I wish Common Lisp had always had such a feature.
That's a bogus reason not to enact a style guide for *future* code. You've even done it before.
Also, putting things in the parameter list that aren't parameters just feels weird.
See Hofstadter's "Le ton beau de Marot" about warts.
I do not think my own opinions are by any means "right". These are just my biases and preferences.
If you were sincere in this statement, then why share them?
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org Multiple instances of a same hacker with different context in his mental cache count as multiple hackers wrt documentation and testing needs.
What I dislike about &aux is that it encourages scoping a lexical variable around the entire lambda body. I prefer whenever possible to scope a local variable over the smallest region in which it is referenced. While this adds more let forms to the code, it makes the code easier to read. One knows the scope over which a variable may be used and need not eyeball the entirerty of a long function body ro be sure the variable isn't referenced somewhere distant.
&aux always reminds me of 40-year-old FORTRAN code where all variables were declared at the head of a function body, and were scoped over the entire body. A lot of more-recent C code is still like this, although modern interactive highlighting editors mitigate the unreadability somewhat. On Jun 12, 2011 8:10 AM, "Faré" fahree@gmail.com wrote:
On 12 June 2011 10:00, Daniel Weinreb dlw@alum.mit.edu wrote:
I, myself, really dislike &aux. It has been so long since I have seen it that I have forgotten that it even exists. We never use it; and I should add that to our style guide.
&aux has its uses. Sometimes it can be clearer than adding a let.
I don't even like
(let (a b c) ...)
Same thing. If you're going to do side effects (sometimes you have to) in particular when you need the binding to be visible in a scope that starts before you have a useful value to initialize it with, then it's clearer to say let (a) and make it clear it's conceptually uninitialized than say let ((a nil)) where nil is bogus and not even an admissible value for the variable's intended type. See especially unwind-protect forms.
since I prefer to think of "let" in the Scheme sense of "I am naming the result of a computation."
Call that something else than let if you want, it's a useful idiom.
Also, binding forms are annoying in that they are verbose and move the body to the right as you nest them. Instead of any ad-hoc do-it-all binding macro, I like this macro from Marco Baringer that does nesting for you:
(defmacro with-nesting ((&key) &rest things) (reduce #'(lambda (outer inner) (append outer (list inner))) things :from-end t))
In fact, I added a macro to our library that is like "let" but does not allow the variable to be modified. (It's not portable; it uses a CCL-specific feature.)
Yet Pascal just offered a portable implementation!
Here's mine.
(defmacro read-only (value name) (declare (ignore name)) value) (define-setf-expander read-only (value name &environment env) (declare (ignore value env)) (error "Thou shall not attempt to modify read-only variable ~S" name))
(defmacro let-1-constant ((var val) &body body) (let ((s (gensym))) `(let ((,s ,val)) (symbol-macrolet ((,var (read-only ,s ,var))) ,@body))))
Unfortunately, we do not use it in practice, since it's so important for code style to be consistent and it would be very hard to change all our sources to do this, since it's hard to know from looking at code whether the "let" variable ever changes, and we have like 700MLOC of code in QRes. I wish Common Lisp had always had such a feature.
That's a bogus reason not to enact a style guide for *future* code. You've even done it before.
Also, putting things in the parameter list that aren't parameters just feels weird.
See Hofstadter's "Le ton beau de Marot" about warts.
I do not think my own opinions are by any means "right". These are just my biases and preferences.
If you were sincere in this statement, then why share them?
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics•
Multiple instances of a same hacker with different context in his mental cache count as multiple hackers wrt documentation and testing needs.
pro mailing list pro@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/pro
On Sun, Jun 12, 2011 at 7:00 AM, Daniel Weinreb dlw@alum.mit.edu wrote:
I, myself, really dislike &aux.
I don't even like
(let (a b c) ...)
Agreed on both counts. &aux is just gross. Like LOOP :-) <ducks>
As for read-only variables -- yes, it would have been nice if Lisp had used ML-style references(*) from the beginning. I understand many Scheme compilers have to perform this transformation anyway -- locating local variables subject to assignment, and consing heap cells to hold their values -- in order for continuation capture to work correctly in the presence of assignment.
(* But I don't like "reference" as a term for this concept; "cell" is better.)
On Sun, Jun 12, 2011 at 8:08 AM, Faré fahree@gmail.com wrote:
Also, binding forms are annoying in that they are verbose and move the body to the right as you nest them. Instead of any ad-hoc do-it-all binding macro, I like this macro from Marco Baringer that does nesting for you:
I use multiple values far too much to tolerate typing MULTIPLE-VALUE-BIND all the time. So I am very much a fan of my binding macro, which I protest is not ad hoc at all -- it generalizes LET, LET*, and MULTIPLE-VALUE-BIND in any combination, less verbosely and with less moving of the body to the right. It's also upward compatible with CL:LET.
In case anyone's interested, it's at http://common-lisp.net/project/misc-extensions/
It doesn't do destructuring, though, so I suppose it's not quite "do-it-all". Maybe someday I will integrate fare-matcher.
Yet Pascal just offered a portable implementation [of read-only variables]!
Here's mine. [snip]
Very cute. I might start using this.
-- Scott
Hi Scott,
In case anyone's interested, it's at http://common-lisp.net/project/misc-extensions/
In the spirit of tooting my own horn, you might also want to see metabang-bind (http://common-lisp.net/project/metabang-bind).
-- Gary Warren King, metabang.com Cell: (413) 559 8738 Fax: (206) 338-4052 gwkkwg on Skype * garethsan on AIM * gwking on twitter
On Sun, Jun 12, 2011 at 1:17 PM, Gary King gwking@metabang.com wrote:
In the spirit of tooting my own horn, you might also want to see metabang-bind (http://common-lisp.net/project/metabang-bind).
I'm aware of it, thanks. I'm afraid I'm quite attached to my own LET macro, of which I wrote the first version in Zetalisp in 1980. -- I wish I had made more noise about it at the time. The multiple value binding syntax, at least, could have become part of CL:
(let ((val1 val2 val3 (form))) ...)
BIND's considerably greater functionality is bought at the price of greater verbosity in the multiple-value case, which for me is by far the most common.
-- Scott
On Sun, Jun 12, 2011 at 7:08 PM, Faré fahree@gmail.com wrote:
Also, binding forms are annoying in that they are verbose and move the body to the right as you nest them. Instead of any ad-hoc do-it-all binding macro, I like this macro from Marco Baringer that does nesting for you:
(defmacro with-nesting ((&key) &rest things) (reduce #'(lambda (outer inner) (append outer (list inner))) things :from-end t))
Is there anything that with-nesting can do, where let* or 'proper abstraction' outside the binding form (with defun, macros, labels, flet, etc) can not do? It would be helpful/educational if an example was provided.
Regards,
- Ala'a
[ Sorry for double-post Ala'a, I forgot to reply-all :( ]
WITH-NESTING reduces the nesting cost of an arbitrary number of consecutive binding forms to one level, with a highly regular and simple syntax almost inherently readable to anyone without prior exposure (I think?). It may not be the most concise syntax of all, but it has the benefit of simplicity and most importantly, sanity.
The only reason I'm not actually using it is that I don't often encounter scenarios complex enough where using it would significantly improve the situation (and I'd consider it bad style to use it if it doesn't significantly improve the situation. Usually a simple refactoring will obviate the "need" for it). As circumstantial evidence, I had to make a synthetic example to show it in a scenario where it would help...
(with-nesting () (let ((a 'a))) (destructuring-bind (b c) '(b c)) (multiple-value-bind (d e) (values 'd 'e)) (let* ((f 'f) (g (list f 'g)))) (destructuring-bind (h i j) (cons f g)) (progn 'HUGE-body (values a b c d e f g h i j))) => A, B, C, D, E, F, (F G), F, F, G
VS
(let ((a 'a)) (destructuring-bind (b c) '(b c) (multiple-value-bind (d e) (values 'd 'e) (let* ((f 'f) (g (list f 'g))) (destructuring-bind (h i j) (cons f g) (progn 'HUGE-body (values a b c d e f g h i j)))))))
On Sun, 12 Jun 2011 10:00:45 -0400, Daniel Weinreb wrote:
I, myself, really dislike &aux. It has been so long since I have seen it that I have forgotten that it even exists. We never use it; and I should add that to our style guide.
I was wondering about the use of &aux a while ago, so I asked on c.l.l:
http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/586ca399d...
The examples convinced me that it is occasionally useful. However, as the previous thread shows, it is still not part of my "active" CL vocabulary, so sometimes I don't think of it as a solution. Maybe that will change and I will remember it the next time I need it.
I don't even like
(let (a b c) ...)
I find (let (a b c) ...) very useful occasionally. I am curious how you would write this without it:
(defun map-as-rows (function vector) "Map elements of vector, collect into a matrix." (let ((vector-length (length vector)) result result-length) (dotimes (index vector-length) (let ((result-row (funcall function (aref vector index)))) (if (zerop index) (setf result-length (length result-row) result (make-array (list vector-length result-length))) (assert (= (length result-row) result-length) () "Incompatible length of results.")) (replace (make-array result-length :displaced-to result :displaced-index-offset (* index result-length)) result-row))) result))
(map-as-rows (lambda (x) (vector x (expt x 2))) #(1 2 3 4))
#2A((1 1) (2 4) (3 9) (4 16))
The only way I see is traversing the results one more time to form the matrix.
Best,
Tamas
On 6/12/2011 10:00 AM, Daniel Weinreb wrote:
I, myself, really dislike &aux. It has been so long since I have seen it that I have forgotten that it even exists. We never use it; and I should add that to our style guide.
I hate (a) typing a let and (b) giving up a level of indentation if I just need one local variable.
But I do not use &aux much. My b-if and b-when macros establish most of my local variables, and I strive anyway for a functional style.
I don't even like
(let (a b c) ...)
Yikes. With values to be named at a later line of code? A finite state machine, perhaps?
kt
On 6/12/2011 10:00 AM, Daniel Weinreb wrote:
I, myself, really dislike &aux. It has been so long since I have seen it that I have forgotten that it even exists. We never use it; and I should add that to our style guide.
I forgot to mention another reason I like &aux -- nostalgia. It is like using rplacd instead of (setf cdr), or the way some pitchers in baseball wear the old-fashioned leggings. Having come to Lisp late in the game, I like the punch card feel I get from the archaic forms, the sense of being there at the beginning.
kt