Lisp G*ds Only, for reasons obvious:
What is/are the big chunks of CL you have never used? Series does not count.
Motivation: my standard retort to Lisp is too big is that I use it all,
then I started thinking about using restarts to make an interactive
developer utility and realized it was Back to School time.
So my survey response:
restarts
btw, Anybody else doing interactive utility software with nothing more
than restarts?
kt
On Apr 24, 8:56 am, Kenneth Tilton <·········@gmail.com> wrote:
> What is/are the big chunks of CL you have never used?
I've never used any of the more advanced functionality of the pretty
printer, or the table-oriented FORMAT stuff.
Also, they're not part of the standard, but I've never had cause to do
anything particularly involved with FFIs or the MOP.
Cheers,
Pillsy
Pillsy wrote:
> On Apr 24, 8:56 am, Kenneth Tilton <·········@gmail.com> wrote:
>
>> What is/are the big chunks of CL you have never used?
>
> I've never used any of the more advanced functionality of the pretty
> printer, or the table-oriented FORMAT stuff.
The pretty-printer! Don't get me started! I did a C-to-Lisp translator
with that!!!
>
> Also, they're not part of the standard, but I've never had cause to do
> anything particularly involved with FFIs or the MOP.
Oh, let's count those. The MOP at least.
kt
On Apr 24, 2:56 pm, Kenneth Tilton <·········@gmail.com> wrote:
> Lisp G*ds Only, for reasons obvious:
That excludes everybody beside you and McCarthy ( who is meta god
BTW)
>
> What is/are the big chunks of CL you have never used? Series does not count.
>
> Motivation: my standard retort to Lisp is too big is that I use it all,
> then I started thinking about using restarts to make an interactive
> developer utility and realized it was Back to School time.
>
> So my survey response:
format and compound loop , but I'm actively avoiding them.
I don't think standrd is too big I'm actually pleasently surprised
every week when I find new functionality that solves my need exactly
like I wanted. Like the ANSI comitte was reading my mind and
anticipated my future needs.
bobi
http://slobodanblazeski.blogspot.com/
On Fri, 24 Apr 2009 08:56:23 -0400, Kenneth Tilton wrote:
> Lisp G*ds Only, for reasons obvious:
>
> What is/are the big chunks of CL you have never used? Series does not
> count.
>
> Motivation: my standard retort to Lisp is too big is that I use it all,
> then I started thinking about using restarts to make an interactive
> developer utility and realized it was Back to School time.
>
> So my survey response:
>
> restarts
I am certainly not a Lisp G*od, but I have found restarts extremely
useful for multivariate maximization/rootfinding. Basic scenario is
this: take f(x): R^n->R^m, looking for argmax_x f(x) if m=1
(optimization), or x s.t. f(x)=0 if n=m (rootfinding).
There are some "general" algorithms for solving these, but they impose
some restrictions on f, and fail when f is not nice. My solution was
to have the algorithm signal a condition (with enough information on
what happened) and specify some restarts ("I have hit a wall, what do
I do?").
Implementations in other languages (C, Fortran) deal with these things
in an ad-hoc manner (eg certain strategies to get out of bad places
are hardcoded), the CL solution is much more elegant. In general,
conditions/restarts are useful for numerical algorithms.
Tamas
On 24 Apr 2009 13:29:38 GMT, <······@gmail.com> wrote:
>
> In general, conditions/restarts are useful for numerical algorithms.
An interesting insight.
--
Lisp: Powering `Impossible Thoughts since 1958
* Kenneth Tilton <·························@cv.net> :
Wrote on Fri, 24 Apr 2009 08:56:23 -0400:
| btw, Anybody else doing interactive utility software with nothing more
| than restarts?
I try to use them as much as I can. They work well in `dungeon' program
scenarios --- In this context I've found Kaz's SUPER-RESTART-CASE useful
Also, you could try searching my simple CHOOSE-WITH-RESTART.
Some lisp implementations with their graphical debuggers have a nice UI
to invoke restarts. But other lisps are not so great and on this whole
prevent their widespread use. SLIME makes things a showstopper, by
truncating print the condition messages, adding intervening restarts,
and introducing outright bugs in CMUCL, so the :test condition to
control restart visibility will never work.
--
Madhu
* Kenneth Tilton <·························@cv.net> :
Wrote on Fri, 24 Apr 2009 08:56:23 -0400:
| btw, Anybody else doing interactive utility software with nothing more
| than restarts?
I try to use them as much as I can. They work well in `dungeon' program
scenarios --- In this context I've found Kaz's SUPER-RESTART-CASE useful
Also, you could try searching my simple CHOOSE-WITH-RESTART.
Some lisp implementations with their graphical debuggers have a nice UI
to invoke restarts. But other lisps are not so great and on the whole
this prevents their widespread use. SLIME is a showstopper, with its
truncating printed condition messages, adding intervening restarts, and
introducing outright bugs in CMUCL, so the :test condition to control
restart visibility will never work.
--
Madhu
Madhu wrote:
> * Kenneth Tilton <·························@cv.net> :
> Wrote on Fri, 24 Apr 2009 08:56:23 -0400:
>
> | btw, Anybody else doing interactive utility software with nothing more
> | than restarts?
>
> I try to use them as much as I can. They work well in `dungeon' program
> scenarios --- In this context I've found Kaz's SUPER-RESTART-CASE useful
> Also, you could try searching my simple CHOOSE-WITH-RESTART.
>
> Some lisp implementations with their graphical debuggers have a nice UI
> to invoke restarts. But other lisps are not so great and on the whole
> this prevents their widespread use. SLIME is a showstopper, with its
> truncating printed condition messages, adding intervening restarts, and
> introducing outright bugs in CMUCL, so the :test condition to control
> restart visibility will never work.
>
> --
> Madhu
Super, but... there /was/ a survey question!!!!!!!!
try to keep You People on topic for one message... <sigh>
kt
On Apr 24, 5:56 am, Kenneth Tilton <·········@gmail.com> wrote:
> Lisp G*ds Only, for reasons obvious:
>
> What is/are the big chunks of CL you have never used? Series does not count.
I don't use LOOP on principle. I have made only trivial use of the
MOP (a simple custom metaclass).
I think that's it for "big chunks", though there may be something I've
forgotten about. Certainly there are smaller pieces I've never used
(have I ever defined a custom method combination type? don't think
so).
-- Scott
On Apr 25, 7:17 am, Scott Burson <········@gmail.com> wrote:
> On Apr 24, 5:56 am, Kenneth Tilton <·········@gmail.com> wrote:
>
> > Lisp G*ds Only, for reasons obvious:
>
> > What is/are the big chunks of CL you have never used? Series does not count.
>
> I don't use LOOP on principle. I have made only trivial use of the
> MOP (a simple custom metaclass).
>
> I think that's it for "big chunks", though there may be something I've
> forgotten about. Certainly there are smaller pieces I've never used
> (have I ever defined a custom method combination type? don't think
> so).
>
> -- Scott
What do you use then instead of LOOP ? Smaller Lisp minds want to
know.
Regards,
Jurgen
* chthon <····································@i28g2000prd.googlegroups.com> :
Wrote on Tue, 28 Apr 2009 02:53:55 -0700 (PDT):
| On Apr 25, 7:17 am, Scott Burson <> wrote:
|> I don't use LOOP on principle. I have made only trivial use of the
|> MOP (a simple custom metaclass).
,----
| * fset_1.1/Code/wb-trees.lisp
|
| (defun WB-Set-Tree-Iterator-Canonicalize (iter)
| (declare (optimize (speed 3) (safety 0)))
| (loop
| (let ((sp (svref iter 0))
`----
So Scott Burson _has_ used LOOP to implement the mapping iterators he
_does_ use.
| What do you use then instead of LOOP ? Smaller Lisp minds want to
| know.
Myself, I slap this section on any copyright notices ALL my code.
;;;; The software MAY NOT be rewritten or refactored by removing the
;;;; use of LOOP or by the introduction of ITERATE or similar iteration
;;;; macros without prior written permission.
--
Madhu (CL:LOOP fanatic :)
On Apr 28, 1:59 pm, Slobodan Blazeski <·················@gmail.com>
wrote:
> On Apr 28, 12:47 pm, Madhu <·······@meer.net> wrote:
> > | What do you use then instead of LOOP ? Smaller Lisp minds want to
> > | know.
>
> > Myself, I slap this section on any copyright notices ALL my code.
>
> > ;;;; The software MAY NOT be rewritten or refactored by removing the
> > ;;;; use of LOOP or by the introduction of ITERATE or similar iteration
> > ;;;; macros without prior written permission.
>
> > --
> > Madhu (CL:LOOP fanatic :)
>
> Recursion and functional style usually results in a cleaner code,
> though somewhat slower. For example see your and Maciej solutionshttp://paste.lisp.org/display/54994from threadhttp://groups.google.com/group/comp.lang.lisp/browse_thread/thread/74...
> and compare it with mine below:
> The code is shorter more than 3 times. 62 lines Maciej, 62 Madhu, 19
Sorry I mean Slobodan 17, one fucntion add-list was not used. That
makes it almost 4 times shorter (~3.65 times actually).
There should be a huge gain in efficiency to compensate for such loss
of clarity.
(defun exist? (key map)
(nth-value 1 (gethash key map)))
(defun utable1 (x)
(let ((i -1) res (vars (make-hash-table)))
(labels ((add-term (y arity components)
(if (and (var? y) (present? y vars))
(gethash y vars)
(progn
(push (list (incf i) y (var-str y)
arity components) res)
(setf (gethash y vars) i))))
(at (y)
(if (consp y)
(add-term (car y) (length (cdr y))
(reverse (mapcar #'(lambda (e) (at e)) (reverse
(cdr y)))))
(add-term y 0 nil))))
(values (at (cadr x)) (at (car x)) (reverse res)))))
På Tue, 28 Apr 2009 14:03:44 +0200, skrev Slobodan Blazeski
<·················@gmail.com>:
> On Apr 28, 1:59 pm, Slobodan Blazeski <·················@gmail.com>
> wrote:
>> On Apr 28, 12:47 pm, Madhu <·······@meer.net> wrote:
>> > | What do you use then instead of LOOP ? Smaller Lisp minds want to
>> > | know.
>>
>> > Myself, I slap this section on any copyright notices ALL my code.
>>
>> > ;;;; The software MAY NOT be rewritten or refactored by removing the
>> > ;;;; use of LOOP or by the introduction of ITERATE or similar
>> iteration
>> > ;;;; macros without prior written permission.
>>
>> > --
>> > Madhu (CL:LOOP fanatic :)
>>
>> Recursion and functional style usually results in a cleaner code,
>> though somewhat slower. For example see your and Maciej
>> solutionshttp://paste.lisp.org/display/54994from
>> threadhttp://groups.google.com/group/comp.lang.lisp/browse_thread/thread/74...
>> and compare it with mine below:
>> The code is shorter more than 3 times. 62 lines Maciej, 62 Madhu, 19
> Sorry I mean Slobodan 17, one fucntion add-list was not used. That
> makes it almost 4 times shorter (~3.65 times actually).
> There should be a huge gain in efficiency to compensate for such loss
> of clarity.
> (defun exist? (key map)
> (nth-value 1 (gethash key map)))
> (defun utable1 (x)
> (let ((i -1) res (vars (make-hash-table)))
> (labels ((add-term (y arity components)
> (if (and (var? y) (present? y vars))
> (gethash y vars)
> (progn
> (push (list (incf i) y (var-str y)
> arity components) res)
> (setf (gethash y vars) i))))
> (at (y)
> (if (consp y)
> (add-term (car y) (length (cdr y))
> (reverse (mapcar #'(lambda (e) (at e)) (reverse
> (cdr y)))))
> (add-term y 0 nil))))
> (values (at (cadr x)) (at (car x)) (reverse res)))))
loss my ass, That is much clearer!
-----------------------
John Thingstad
On Apr 29, 12:43 am, "John Thingstad" <·······@online.no> wrote:
> På Tue, 28 Apr 2009 14:03:44 +0200, skrev Slobodan Blazeski
> <·················@gmail.com>:
>
>
>
>
>
> > On Apr 28, 1:59 pm, Slobodan Blazeski <·················@gmail.com>
> > wrote:
> >> On Apr 28, 12:47 pm, Madhu <·······@meer.net> wrote:
> >> > | What do you use then instead of LOOP ? Smaller Lisp minds want to
> >> > | know.
>
> >> > Myself, I slap this section on any copyright notices ALL my code.
>
> >> > ;;;; The software MAY NOT be rewritten or refactored by removing the
> >> > ;;;; use of LOOP or by the introduction of ITERATE or similar
> >> iteration
> >> > ;;;; macros without prior written permission.
>
> >> > --
> >> > Madhu (CL:LOOP fanatic :)
>
> >> Recursion and functional style usually results in a cleaner code,
> >> though somewhat slower. For example see your and Maciej
> >> solutionshttp://paste.lisp.org/display/54994from
> >> threadhttp://groups.google.com/group/comp.lang.lisp/browse_thread/thread/74...
> >> and compare it with mine below:
> >> The code is shorter more than 3 times. 62 lines Maciej, 62 Madhu, 19
> > Sorry I mean Slobodan 17, one fucntion add-list was not used. That
> > makes it almost 4 times shorter (~3.65 times actually).
> > There should be a huge gain in efficiency to compensate for such loss
> > of clarity.
> > (defun exist? (key map)
> > (nth-value 1 (gethash key map)))
> > (defun utable1 (x)
> > (let ((i -1) res (vars (make-hash-table)))
> > (labels ((add-term (y arity components)
> > (if (and (var? y) (present? y vars))
> > (gethash y vars)
> > (progn
> > (push (list (incf i) y (var-str y)
> > arity components) res)
> > (setf (gethash y vars) i))))
> > (at (y)
> > (if (consp y)
> > (add-term (car y) (length (cdr y))
> > (reverse (mapcar #'(lambda (e) (at e)) (reverse
> > (cdr y)))))
> > (add-term y 0 nil))))
> > (values (at (cadr x)) (at (car x)) (reverse res)))))
>
> loss my ass, That is much clearer!
I know it still sucks, but I can't make it suck less. If you have any
ideas for improvements I'm all ears er eyes.
Actually wait until you see step 2 of the algorithm implementation,
that's what I call ugly.
cheers
bobi
http://slobodanblazeski.blogspot.com/
>
> -----------------------
> John Thingstad
På Wed, 29 Apr 2009 08:15:57 +0200, skrev Slobodan Blazeski
<·················@gmail.com>:
>
> I know it still sucks, but I can't make it suck less. If you have any
> ideas for improvements I'm all ears er eyes.
> Actually wait until you see step 2 of the algorithm implementation,
> that's what I call ugly.
>
You are being overly critical (which is a good thing), but actually your
code (the bit's I have seem) is fine.
---------------------
John Thingstad
On 29 abr, 06:29, chthon <··············@pandora.be> wrote:
>
> Yes, know about recursion (I did read parts of SICP), but since CL
> implementations are not required to implement tail recursion, one
> cannot expect that all iterative constructs can be replaced by
> recursion.
>
> If I program in Scheme then it is almost natural to use tail
> recursion, while in Common Lisp, generally that can not be the case,
> since this is implementation dependent. So I use LOOP fairly often.
People keep saying that tail recursion in CL is implementation
dependent, but the only implementation that I tested that doesn't have
tail call optimization is ECL, and I expect that to be changed. Even
Clisp, which is not optimized, has this optimization if you compile
the function.
>
> Regards,
>
> Jurgen
On Apr 29, 5:36 pm, gugamilare <··········@gmail.com> wrote:
>
> People keep saying that tail recursion in CL is implementation
> dependent, but the only implementation that I tested that doesn't have
> tail call optimization is ECL, and I expect that to be changed. Even
> Clisp, which is not optimized, has this optimization if you compile
> the function.
Whoa, careful. In Allegro -- and LispWorks also? -- TCO is done only
for self-calls and calls to local functions. So if you have a single
LABELS expression that defines several functions they can tail-call
one another, but top-level functions do not, except for self-calls.
Or something like that; it's definitely not done in every possible
situation, as in the CMUCL family.
I still think that rather than using TCO whenever possible, it would
be better to allow the user to declare sets of mutually tail-recursive
top-level functions, and to have calls outside that set not be subject
to TCO. This would allow you to do things like code an FSA as a set
of top-level functions, while not harming debuggability in the normal
case.
-- Scott
gugamilare <··········@gmail.com> wrote:
+---------------
| chthon <··············@pandora.be> wrote:
| > If I program in Scheme then it is almost natural to use tail
| > recursion, while in Common Lisp, generally that can not be the case,
| > since this is implementation dependent. So I use LOOP fairly often.
|
| People keep saying that tail recursion in CL is implementation
| dependent, but the only implementation that I tested that doesn't have
| tail call optimization is ECL, and I expect that to be changed. Even
| Clisp, which is not optimized, has this optimization if you compile
| the function.
+---------------
Careful! What you say is true *only* in the absence of live bindings
for dynamic variables or live dynamic contexts such as UNWIND-PROTECT,
WITHOUT-ERRORS, HANDLER-BIND, HANDLER-CASE, CATCH, etc., etc., etc.
Even CL implementations which routinely do TCO for "simple" tail calls
generally cannot do TCO across such contours!! Note that the non-TCO'able
case could be as simple as this:
> (defun foo (*standard-output*)
(format t "This was *not* a tail call of FORMAT!!"))
FOO
> (with-output-to-string (s)
(foo s))
"This was *not* a tail call of FORMAT!!"
>
-Rob
-----
Rob Warnock <····@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607
On 29 abr, 22:05, ····@rpw3.org (Rob Warnock) wrote:
> gugamilare <··········@gmail.com> wrote:
>
> +---------------| chthon <··············@pandora.be> wrote:
>
> | > If I program in Scheme then it is almost natural to use tail
> | > recursion, while in Common Lisp, generally that can not be the case,
> | > since this is implementation dependent. So I use LOOP fairly often.
> |
> | People keep saying that tail recursion in CL is implementation
> | dependent, but the only implementation that I tested that doesn't have
> | tail call optimization is ECL, and I expect that to be changed. Even
> | Clisp, which is not optimized, has this optimization if you compile
> | the function.
> +---------------
>
> Careful! What you say is true *only* in the absence of live bindings
> for dynamic variables or live dynamic contexts such as UNWIND-PROTECT,
> WITHOUT-ERRORS, HANDLER-BIND, HANDLER-CASE, CATCH, etc., etc., etc.
> Even CL implementations which routinely do TCO for "simple" tail calls
> generally cannot do TCO across such contours!! Note that the non-TCO'able
> case could be as simple as this:
>
> > (defun foo (*standard-output*)
> (format t "This was *not* a tail call of FORMAT!!"))
>
> FOO
> > (with-output-to-string (s)
> (foo s))
>
> "This was *not* a tail call of FORMAT!!"
> >
>
> -Rob
>
> -----
> Rob Warnock <····@rpw3.org>
> 627 26th Avenue <URL:http://rpw3.org/>
> San Mateo, CA 94403 (650)572-2607
Ok, I've missed the special cases. But most of the cases were you need
loops, you won't need to rebind special variables.
Rob Warnock wrote:
> gugamilare <··········@gmail.com> wrote:
> +---------------
> | chthon <··············@pandora.be> wrote:
> | > If I program in Scheme then it is almost natural to use tail
> | > recursion, while in Common Lisp, generally that can not be the case,
> | > since this is implementation dependent. So I use LOOP fairly often.
> |
> | People keep saying that tail recursion in CL is implementation
> | dependent, but the only implementation that I tested that doesn't have
> | tail call optimization is ECL, and I expect that to be changed. Even
> | Clisp, which is not optimized, has this optimization if you compile
> | the function.
> +---------------
>
> Careful! What you say is true *only* in the absence of live bindings
> for dynamic variables or live dynamic contexts such as UNWIND-PROTECT,
> WITHOUT-ERRORS, HANDLER-BIND, HANDLER-CASE, CATCH, etc., etc., etc.
> Even CL implementations which routinely do TCO for "simple" tail calls
> generally cannot do TCO across such contours!!
A particularly sad case is that tail calls in CLOS methods are usually
never optimized. The reason is that the list of next methods typically
seems to be bound to an internal special variable, where it could
actually just be passed as a (lexical) parameter to the method
functions. The latter is also how the CLOS MOP specifies it, but I am
not aware of any CLOS implementation that sticks to this particular part
of the spec. (If they did, tail call optimization would be possible for
CLOS.)
Pascal
--
ELS'09: http://www.european-lisp-symposium.org/
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
Pascal Costanza wrote:
> Rob Warnock wrote:
>> gugamilare <··········@gmail.com> wrote:
>> +---------------
>> | chthon <··············@pandora.be> wrote:
>> | > If I program in Scheme then it is almost natural to use tail
>> | > recursion, while in Common Lisp, generally that can not be the case,
>> | > since this is implementation dependent. So I use LOOP fairly often.
>> | | People keep saying that tail recursion in CL is implementation
>> | dependent, but the only implementation that I tested that doesn't have
>> | tail call optimization is ECL, and I expect that to be changed. Even
>> | Clisp, which is not optimized, has this optimization if you compile
>> | the function.
>> +---------------
>>
>> Careful! What you say is true *only* in the absence of live bindings
>> for dynamic variables or live dynamic contexts such as UNWIND-PROTECT,
>> WITHOUT-ERRORS, HANDLER-BIND, HANDLER-CASE, CATCH, etc., etc., etc.
>> Even CL implementations which routinely do TCO for "simple" tail calls
>> generally cannot do TCO across such contours!!
>
> A particularly sad case is that tail calls in CLOS methods are usually
> never optimized. The reason is that the list of next methods typically
> seems to be bound to an internal special variable, where it could
> actually just be passed as a (lexical) parameter to the method
> functions. The latter is also how the CLOS MOP specifies it, but I am
> not aware of any CLOS implementation that sticks to this particular part
> of the spec. (If they did, tail call optimization would be possible for
> CLOS.)
I have to correct my statement, due to some feedback I got by private email.
I made some small tests on some Common Lisp implementations. It seems
that Clozure, CMUCL, LispWorks and SBCL optimize tail calls in CLOS
methods, while Allegro and clisp don't. (It was a very simple test, so
take this with a grain of salt.)
Pascal
--
ELS'09: http://www.european-lisp-symposium.org/
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
On May 2, 9:19 am, Pascal Costanza <····@p-cos.net> wrote:
> > A particularly sad case is that tail calls in CLOS methods are usually
> > never optimized. The reason is that the list of next methods typically
> > seems to be bound to an internal special variable, where it could
> > actually just be passed as a (lexical) parameter to the method
> > functions. The latter is also how the CLOS MOP specifies it, but I am
> > not aware of any CLOS implementation that sticks to this particular part
> > of the spec. (If they did, tail call optimization would be possible for
> > CLOS.)
>
> I have to correct my statement, due to some feedback I got by private email.
>
> I made some small tests on some Common Lisp implementations. It seems
> that Clozure, CMUCL, LispWorks and SBCL optimize tail calls in CLOS
> methods, while Allegro and clisp don't. (It was a very simple test, so
> take this with a grain of salt.)
Can you please make your test public? I'd like to respond. My own
simple test places Allegro CL in the first category, though of course
there may be reasons why you get different results. Tail merging
isn't a foregone conclusion in any setting, but is parameterized
differently in different CL implementations.
Duane
Transcript for Allegro CL 8.1 (x86-64):
CL-USER(1): (shell "cat foo.cl")
(eval-when (:compile-toplevel)
(declaim (optimize (safety 0) ;; only for simplicity
speed
(debug 0))))
(defmethod foo ((x integer) (y integer))
(bar x y))
0
CL-USER(2): :cl foo
;;; Compiling file foo.cl
;;; Writing fasl file foo.fasl
;;; Fasl write complete
; Fast loading /net/gemini/home/duane/foo.fasl
Warning: While compiling these undefined functions were referenced:
BAR from position 120 in foo.cl
CL-USER(3): (inspect (mop:generic-function-methods #'foo))
A NEW proper list @ #x10009e4ac1 with 1 element
0-> #<STANDARD-METHOD FOO (INTEGER INTEGER)>
[1i] CL-USER(4): :i 0
A NEW STANDARD-METHOD @ #x10009626b2 = #<STANDARD-METHOD
FOO
(INTEGER INTEGER)>
0 Class --------> #<STANDARD-CLASS STANDARD-METHOD>
1 PLIST --------> The symbol NIL
2 GENERIC-FUNCTION -> #<STANDARD-GENERIC-FUNCTION FOO>
3 SPECIALIZERS -> (#1=# #1#), a proper list with 2 elements
4 QUALIFIERS ---> The symbol NIL
5 LAMBDA-LIST --> ((X INTEGER) (Y INTEGER)), a proper list with 2
elements
6 FUNCTION -----> #<Function (METHOD FOO (INTEGER INTEGER))>
[1i] CL-USER(5): :i 6
A NEW #<Function (METHOD FOO (INTEGER INTEGER))>
lambda-list: NIL
0 excl-type ----> Bit field: #x88
1 flags --------> Bit field: #xa8
2 start --------> Bit field: #x00002aaaacbc6208
3 hash ---------> Bit field: #x0000000000008508
4 symdef -------> (((METHOD) . FOO) ...), a proper list with 3
elements
5 code ---------> short simple CODE vector (12) = #(35657 13934
25599 ...)
6 formals ------> The symbol NIL
7 cframe-size --> fixnum 0 [#x0000000000000000]
8 immed-args ---> fixnum 0 [#x0000000000000000]
9 locals -------> fixnum 0 [#x0000000000000000]
10 <constant> ---> The symbol BAR
[1i] CL-USER(6): (disassemble *)
;; disassembly of #<Function (METHOD FOO (INTEGER INTEGER))>
;; formals: [none]
;; constant vector:
0: BAR
;; code start: #x2aaaacbc6208:
0: 49 8b 6e 36 movq rbp,[r14+54] ; BAR
4: ff 63 d0 jmp *[rbx-48]
7: 90 nop
[1i] CL-USER(7):
·····@franz.com wrote:
> On May 2, 9:19 am, Pascal Costanza <····@p-cos.net> wrote:
>
>>> A particularly sad case is that tail calls in CLOS methods are usually
>>> never optimized. The reason is that the list of next methods typically
>>> seems to be bound to an internal special variable, where it could
>>> actually just be passed as a (lexical) parameter to the method
>>> functions. The latter is also how the CLOS MOP specifies it, but I am
>>> not aware of any CLOS implementation that sticks to this particular part
>>> of the spec. (If they did, tail call optimization would be possible for
>>> CLOS.)
>> I have to correct my statement, due to some feedback I got by private email.
>>
>> I made some small tests on some Common Lisp implementations. It seems
>> that Clozure, CMUCL, LispWorks and SBCL optimize tail calls in CLOS
>> methods, while Allegro and clisp don't. (It was a very simple test, so
>> take this with a grain of salt.)
>
> Can you please make your test public? I'd like to respond. My own
> simple test places Allegro CL in the first category, though of course
> there may be reasons why you get different results.
Sure, no problem. It might as well be that I just misunderstand what I see.
Here is the code:
(declaim (optimize (speed 3) (space 3) (safety 0) (debug 0)))
(defmethod foo (x)
(if (next-method-p)
(call-next-method)
(bar x)))
(defun bar (x) (error "baz"))
The invocation of next-method-p and call-next-method is to ensure that
the compiler doesn't optimize the list of next methods away.
Here is a session:
CL-USER(1): (compile-file "test")
;;; Compiling file test.lisp
; While compiling BAR:
Warning: Variable X is never used.
;;; Writing fasl file test.fasl
;;; Fasl write complete
#P"/Users/costanza/Muell/test.fasl"
T
NIL
CL-USER(2): (load "test")
; Fast loading /Users/costanza/Muell/test.fasl
T
CL-USER(3): (foo 3)
Error: baz
Restart actions (select using :continue):
0: Return to Top Level (an "abort" restart).
1: Abort entirely from this (lisp) process.
[1] CL-USER(4): :bt
Evaluation stack:
BAR <-
(:INTERNAL (:EFFECTIVE-METHOD 1 NIL ...) 0) <- EVAL <-
TPL:TOP-LEVEL-READ-EVAL-PRINT-LOOP <- TPL:START-INTERACTIVE-TOP-LEVEL
...so there seems to be a method for foo on the stack, right?
Pascal
--
ELS'09: http://www.european-lisp-symposium.org/
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
On Apr 30, 2:36 am, gugamilare <··········@gmail.com> wrote:
> People keep saying that tail recursion in CL is implementation
> dependent, but the only implementation that I tested that doesn't have
> tail call optimization is ECL, and I expect that to be changed.
ECL does not have tail call optimization for _interpreted_ code.
Compiled code, for suitable optimization speeds, does implement tail
self-call optimization. It can not implement that optimization for
calls to other functions because it depends on C compilers --- well
actually gcc may do that optimization for you also under suitable
optimization parameters.
Juanjo
On Apr 28, 3:47 am, Madhu <·······@meer.net> wrote:
> * chthon <····································@i28g2000prd.googlegroups.com> :
> Wrote on Tue, 28 Apr 2009 02:53:55 -0700 (PDT):
>
> | On Apr 25, 7:17 am, Scott Burson <> wrote:
> |> I don't use LOOP on principle. I have made only trivial use of the
> |> MOP (a simple custom metaclass).
>
> ,----
> | * fset_1.1/Code/wb-trees.lisp
> |
> | (defun WB-Set-Tree-Iterator-Canonicalize (iter)
> | (declare (optimize (speed 3) (safety 0)))
> | (loop
> | (let ((sp (svref iter 0))
> `----
>
> So Scott Burson _has_ used LOOP to implement the mapping iterators he
> _does_ use.
Only the trivial CLtL1 form, to which I have no objection. With no
keywords, it's just a do-forever loop. (I think when most people
speak of LOOP they mean the nontrivial form, but I suppose I should
have noted the exception.)
-- Scott
On Apr 28, 2:53 am, chthon <··············@pandora.be> wrote:
>
> What do you use then instead of LOOP ? Smaller Lisp minds want to
> know.
The first question is whether the loop is to be imperative (passes
through a series of states having some side-effect) or functional
(computes a value of some kind). This is a stylistic question;
functional iteration can always be done imperatively, but is often
clearer when expressed functionally. On the other hand, some
iterations are imperative by their nature, and seem too hard to me to
express functionally (I guess Haskell users find ways). I like the
functional style a lot, which is why I created FSet, and I probably
use it more than most CL users, but if an iteration seems naturally
imperative I don't usually fight to make it functional.
So, for imperative loops where the iterations are in one-to-one
correspondence with the members of a specific collection, I use DOLIST
or (with FSet) DO-SET, DO-SEQ, or DO-MAP. In more complex situations,
where the iterations are not in one-to-one correspondence with any set
known in advance, I will use one of DO (yes I really use good old DO),
WHILE (my own macro which expands to DO in the obvious way), or (as
Madhu helpfully pointed out) the trivial CLtL1 form of LOOP. This
form of LOOP has no keywords but just loops forever; it is useful in
cases where the exit test is not naturally placed at the top of the
loop, e.g.:
(loop
(let ((foo ...))
(when (terminate? foo)
(return))
(do-something-with foo)))
For functional iteration there are really three sets of important
functions. The Common Lisp builtins are MAPCAR, REDUCE, and REMOVE-IF-
NOT. With my FSet types there are IMAGE (similar to MAPCAR but not
the same), REDUCE again, and FILTER (like REMOVE-IF-NOT). And finally
there is my macro GMAP which combines functionality from all these and
more. I use all three of these sets freely in my own code, which
probably is not the best thing from the point of view of the poor sod
who has to read it :)
I've mentioned GMAP here once or twice. I'm quite fond of it, but
I've never been able to interest anyone else in using it, AFAIK. It's
somewhat like Waters' Series package, but far simpler in both concept
and implementation. Nevertheless, in my experience, it handles a lot
of cases very elegantly.
All GMAP does is generalize CL:MAP in two ways: first by providing an
extensible set of result constructors, and secondly by providing an
extensible set of argument generators. So where CL:MAP can only
generate arguments to the mapped function by iterating over sequences,
and can only produce some sequence type as its result, GMAP (being a
macro) has syntax that lets you specify how to generate each argument,
and also how to collect up the results (so it combines the
functionality of MAP and REDUCE).
You can find GMAP and FSet, respectively, at:
http://common-lisp.net/project/misc-extensions/
http://common-lisp.net/project/fset/
I would give some examples here, but I'm out of time at the moment.
-- Scott
* Scott Burson Wrote on Tue, 28 Apr 2009 19:21:02 -0700 (PDT):
| On Apr 28, 2:53 am, chthon <··············@pandora.be> wrote:
|>
|> What do you use then instead of LOOP ? Smaller Lisp minds want to
|> know.
|
| The first question is whether the loop is to be imperative (passes
| through a series of states having some side-effect) or functional
| (computes a value of some kind). This is a stylistic question;
| functional iteration can always be done imperatively, but is often
| clearer when expressed functionally.
| So, for imperative loops where the iterations are in one-to-one
| correspondence with the members of a specific collection, I use DOLIST
| or (with FSet) DO-SET, DO-SEQ, or DO-MAP. In more complex situations,
| where the iterations are not in one-to-one correspondence with any set
| known in advance, I will use one of DO (yes I really use good old DO),
I don't think there is any "style" distinction between DO/DO* and
extended LOOP --- it's just a matter of catering to base tastes. (Yes I
think a `fine distinction' is helpful here :)
[...]
| For functional iteration there are really three sets of important
| functions. The Common Lisp builtins are MAPCAR, REDUCE, and
| REMOVE-IF- NOT.
Note CL already implements a subtle plan in encouraging functional
iteration with generic sequences by not providing the equivalent loop
keywords. My conspiracy sensors say this may have been be an oversight.
If your code should deal with all cl:sequences you would automatically
prefer
(MAP nil (lambda (X) ...) SEQUENCE)
over
(DOLIST) or (LOOP FOR x IN list) or (LOOP FOR x ACROSS vector)
| I've mentioned GMAP here once or twice. I'm quite fond of it, but
| I've never been able to interest anyone else in using it, AFAIK. It's
| somewhat like Waters' Series package, but far simpler in both concept
| and implementation. Nevertheless, in my experience, it handles a lot
| of cases very elegantly.
|
| All GMAP does is generalize CL:MAP in two ways: first by providing an
| extensible set of result constructors, and secondly by providing an
| extensible set of argument generators. So where CL:MAP can only
| generate arguments to the mapped function by iterating over sequences,
| and can only produce some sequence type as its result, GMAP (being a
| macro) has syntax that lets you specify how to generate each argument,
| and also how to collect up the results (so it combines the
| functionality of MAP and REDUCE).
|
| You can find GMAP and FSet, respectively, at:
|
| http://common-lisp.net/project/misc-extensions/
| http://common-lisp.net/project/fset/
--
Madhu
On Apr 28, 2:53 am, chthon <··············@pandora.be> wrote:
>
> What do you use then instead ofLOOP? Smaller Lisp minds want to
> know.
Arrgh -- I wrote a long reply to this yesterday, but Google evidently
dropped it on the floor. Crap!
I will try again, but probably not until this weekend.
-- Scott
On Apr 24, 2:56 pm, Kenneth Tilton <·········@gmail.com> wrote:
> Lisp G*ds Only, for reasons obvious:
>
> What is/are the big chunks of CL you have never used? Series does not count.
>
> Motivation: my standard retort to Lisp is too big is that I use it all,
> then I started thinking about using restarts to make an interactive
> developer utility and realized it was Back to School time.
>
> So my survey response:
>
> restarts
>
> btw, Anybody else doing interactive utility software with nothing more
> than restarts?
I have used everything sooner or later. And there are many things I
would like to use but that are not completely standardized (e.g.,
MOP). As an example, I was dubious about symbol macros. Then I found
out why they are there. Some things are so useful that I
reimplemented them in other languages. Notably the pretty printer. I
even dabbled in method combinations to play around with AOP.
Cheers
--
Marco
On Apr 24, 2:56 pm, Kenneth Tilton <·········@gmail.com> wrote:
>
> What is/are the big chunks of CL you have never used? Series does not count.
Readtable stuff.
On 24 Apr, 13:56, Kenneth Tilton <·········@gmail.com> wrote:
> Lisp G*ds Only, for reasons obvious:
>
> What is/are the big chunks of CL you have never used? Series does not count.
>
> Motivation: my standard retort to Lisp is too big is that I use it all,
> then I started thinking about using restarts to make an interactive
> developer utility and realized it was Back to School time.
>
> So my survey resI tend to learn CL on demand and don't count myself as a guru. Probably its easier to characterise what I do use and then do the subtraction.
Stuff I do use regularly
================
The basic pure functional subset of the early era very intensively
I/O
FORMAT a lot though probably not the full regalia of options.
Read/write from/to files
set is about the only destructive operation I use.
Stuff I have used very occasionally
=========================
But inside Qi (I don't actually program in Qi using these things)
hash-table lookups
progv
conditions (slightly)
features (sigh; wish CL was more specified sometimes)
blocks, return and jumps for encoding Prolog cuts and optimising
pattern-matching
readtable
And no CLOS, RPLACA, bit twiddling, LOOP, DO etc.
Mark
Stuff I never use: eval
Stuff nobody uses but me: nreconc
--
European Lisp Symposium, May 2009: http://www.european-lisp-symposium.org
European Lisp Workshop, July 2009: http://elw.bknr.net/2009
Scientific site: http://www.lrde.epita.fr/~didier
Music (Jazz) site: http://www.didierverna.com
Didier Verna <······@lrde.epita.fr> wrote:
+---------------
| Stuff I never use: eval
| Stuff nobody uses but me: nreconc
+---------------
Stuff I never used before 'cuz I never noticed them 'til now
(thanks, Didier!):
REVAPPEND
NRECONC
Stuff I know about but almost never use (not sure why):
ELT (dunno why, maybe learned AREF & NTH first?)
MAP-INTO
MERGE
SUBLIS/NSUBLIS
BUTLAST/NBUTLAST
LDIFF/TAILP
Any of the explicit PPRINT-* functions (except as invoked
indirectly via FORMAT directives)
SCHAR
REMHASH/CLRHASH/SXHASH
WITH-HASH-TABLE-ITERATOR (tend to use LOOP forms instead)
Logical pathnames (too Unix-centric, I guess)
TARCE/UNTRACE/STEP
Other than simple bits of CLOS (but do use method dispatch on STRUCTUREs)
SYMBOL-PLIST
COMPLEX numbers (just haven't had the need yet)
BIT vectors (but I do *lots* of bit-banging on integers!!)
Stuff I use a lot and consider underappreciated [especially by
those who think that the regexp hammer fits all "nails"]:
MISMATCH
SEARCH (esp. as weird-but-useful :TEST arg to other sequence funcs)
POSITION-IF
Stuff I use occasionally in "unusual"(?) ways:
TREE-EQUAL (to walk *one* tree! ["tree1" == "tree2", with :TEST arg])
NSUBST/NSUBST-IF (ditto)
-Rob
-----
Rob Warnock <····@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607
On 25 abr, 23:49, ····@rpw3.org (Rob Warnock) wrote:
> Didier Verna <······@lrde.epita.fr> wrote:
> +---------------
> | Stuff I never use: eval
> | Stuff nobody uses but me: nreconc
> +---------------
>
> Stuff I never used before 'cuz I never noticed them 'til now
> (thanks, Didier!):
>
> REVAPPEND
> NRECONC
Hum... I didn't know these either, though I am not a G*d Lisper. If I
ever needed this function I would probably use reverse followed by
append instead, so I understand why no one knows about it.
>
> Stuff I know about but almost never use (not sure why):
>
> ELT (dunno why, maybe learned AREF & NTH first?)
> MAP-INTO
> MERGE
> SUBLIS/NSUBLIS
> BUTLAST/NBUTLAST
> LDIFF/TAILP
> Any of the explicit PPRINT-* functions (except as invoked
> indirectly via FORMAT directives)
> SCHAR
> REMHASH/CLRHASH/SXHASH
> WITH-HASH-TABLE-ITERATOR (tend to use LOOP forms instead)
> Logical pathnames (too Unix-centric, I guess)
> TARCE/UNTRACE/STEP
> Other than simple bits of CLOS (but do use method dispatch on STRUCTUREs)
> SYMBOL-PLIST
> COMPLEX numbers (just haven't had the need yet)
> BIT vectors (but I do *lots* of bit-banging on integers!!)
>
> Stuff I use a lot and consider underappreciated [especially by
> those who think that the regexp hammer fits all "nails"]:
>
> MISMATCH
> SEARCH (esp. as weird-but-useful :TEST arg to other sequence funcs)
> POSITION-IF
>
> Stuff I use occasionally in "unusual"(?) ways:
>
> TREE-EQUAL (to walk *one* tree! ["tree1" == "tree2", with :TEST arg])
> NSUBST/NSUBST-IF (ditto)
>
> -Rob
>
> -----
> Rob Warnock <····@rpw3.org>
> 627 26th Avenue <URL:http://rpw3.org/>
> San Mateo, CA 94403 (650)572-2607
If I would mention everything I never used, I would need to see the
hyperspec. There are so many functions, I never used at least a third
of it.
··········@gmail.com wrote:
> On 25 abr, 23:49, ····@rpw3.org (Rob Warnock) wrote:
>> Didier Verna <······@lrde.epita.fr> wrote:
>> +---------------
>> | Stuff I never use: eval
>> | Stuff nobody uses but me: nreconc
>> +---------------
>>
>> Stuff I never used before 'cuz I never noticed them 'til now
>> (thanks, Didier!):
>>
>> REVAPPEND
>> NRECONC
>
> Hum... I didn't know these either, though I am not a G*d Lisper. If I
> ever needed this function I would probably use reverse followed by
> append instead, so I understand why no one knows about it.
>> Stuff I know about but almost never use (not sure why):
>>
>> ELT (dunno why, maybe learned AREF & NTH first?)
>> MAP-INTO
>> MERGE
>> SUBLIS/NSUBLIS
>> BUTLAST/NBUTLAST
>> LDIFF/TAILP
>> Any of the explicit PPRINT-* functions (except as invoked
>> indirectly via FORMAT directives)
>> SCHAR
>> REMHASH/CLRHASH/SXHASH
>> WITH-HASH-TABLE-ITERATOR (tend to use LOOP forms instead)
>> Logical pathnames (too Unix-centric, I guess)
>> TARCE/UNTRACE/STEP
>> Other than simple bits of CLOS (but do use method dispatch on STRUCTUREs)
>> SYMBOL-PLIST
>> COMPLEX numbers (just haven't had the need yet)
>> BIT vectors (but I do *lots* of bit-banging on integers!!)
>>
>> Stuff I use a lot and consider underappreciated [especially by
>> those who think that the regexp hammer fits all "nails"]:
>>
>> MISMATCH
>> SEARCH (esp. as weird-but-useful :TEST arg to other sequence funcs)
>> POSITION-IF
>>
>> Stuff I use occasionally in "unusual"(?) ways:
>>
>> TREE-EQUAL (to walk *one* tree! ["tree1" == "tree2", with :TEST arg])
>> NSUBST/NSUBST-IF (ditto)
>>
>> -Rob
>>
>> -----
>> Rob Warnock <····@rpw3.org>
>> 627 26th Avenue <URL:http://rpw3.org/>
>> San Mateo, CA 94403 (650)572-2607
>
> If I would mention everything I never used, I would need to see the
> hyperspec. There are so many functions, I never used at least a third
> of it.
Not to deprecate more detailed offerings for they too serve by opening
eyes, but the survey is looking for undiscovered continents, not street
addresses. Big stuff like blackbelt format, loop, conditions, MOP,
pprint, restarts. symbol macros and tagbody feel continenty even though
they are atomic.
kzo
Didier Verna wrote:
> Stuff I never use: eval
> Stuff nobody uses but me: nreconc
Not true, I also use nreconc. ;)
Pascal
--
ELS'09: http://www.european-lisp-symposium.org/
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
Pascal Costanza <··@p-cos.net> writes:
> Didier Verna wrote:
>> Stuff I never use: eval
>> Stuff nobody uses but me: nreconc
>
> Not true, I also use nreconc. ;)
I've used it more than once, and REVAPPEND too.
If they weren't so useful, they wouldn't have made it into the standard ;-)
--
__Pascal Bourguignon__
On Apr 24, 2:56 pm, Kenneth Tilton <·········@gmail.com> wrote:
> Lisp G*ds Only, for reasons obvious:
>
> What is/are the big chunks of CL you have never used? Series does not count.
I've only made very light use of the pretty printer, and all the
tabulated-output stuff in FORMAT I've never touched. Also, the CLtL2
environments stuff along with Franz's modern reworking of it.
> Motivation: my standard retort to Lisp is too big is that I use it all,
> then I started thinking about using restarts to make an interactive
> developer utility and realized it was Back to School time.
>
> So my survey response:
>
> restarts
>
> btw, Anybody else doing interactive utility software with nothing more
> than restarts?
Yeah, sometimes. I was motivated to learn about them the first time I
wanted to add an option to the restart list when presented with the
MCL debugger. Nowadays I see a lot of Ltk buttons that behind the
scenes just select a restart.
On Apr 24, 7:56 am, Kenneth Tilton <·········@gmail.com> wrote:
> What is/are the big chunks of CL you have never used? Series does not count.
Some of the big things that CL waves around that I don't use much are
bignums, and really I don't call EVAL that much (FUNCALL and APPLY all
the time, of course). And yeah, I don't use restarts that much
(ever?) programming, debugging they come up all the time though!
Speaking of debugging I don't really use STEP, since we have TRACE. I
rarely use LOOP, and if I have used method combination it was only
once.
If you are looking for candidates for least necessary function, I
think I have only called Y-OR-N-P just to prove to myself it was
actually in there. But I tend to do most of my interaction with lisp
through web pages, or analyzing data in the REPL or dumping it to
files to load and plot in R.
> Motivation: my standard retort to Lisp is too big is that I use it all,
> then I started thinking about using restarts to make an interactive
> developer utility and realized it was Back to School time.
While I don't use all of it all of the time I do seem to use quite a
bit, and it's nice to have learned one language that has most of what
I need most of the time. I think a more interesting "survey question"
would be what do you find yourself reimplementing over and over that's
not already in there?
For me I don't use arrays and vectors that much, but a nice queue
would be helpful. And I constantly bring in my map all files in a
directory code. (Surprisingly map-plist doesn't exist either.)
Because of the kind of work I do, unification and memoization seem to
come up everywhere too.
Kevin
kevinlivingston <···············@gmail.com> wrote:
+---------------
| While I don't use all of it all of the time I do seem to use quite a
| bit, and it's nice to have learned one language that has most of what
| I need most of the time.
+---------------
Yes, indeed!
+---------------
| I think a more interesting "survey question" would be what do you find
| yourself reimplementing over and over that's not already in there?
+---------------
My standard utilities package:
(defpackage :org.rpw3.utils
(:nicknames :utils)
(:use :cl :ext)
(:export
;; Readmacros:
#:set-sharp-bang-reader ; Enable #! as a comment (for shell scripts).
#:set-sharp-dollar-reader ; Experimental LAMBDA abbreviation [c.f. FN].
#:set-zero-x-reader ; C-style hex numbers, e.g. 0x1234. [BUGGY!]
;; Macros:
#:deflex ; "Global lexical variables" (sort of).
#:fn ; Alias for LAMBDA.
#:dbgv ; Debug printing of forms & values.
#:dbgvht ; Same, but outputs as HTML.
#:with-output-to-file ; Save typing in the most common output case.
;; String-hacking functions:
#:getenv ; Portable version.
#:strcat ; Syntactic sugar [with a compiler macro, too].
#:join-strings ; STRCAT with infix separators.
#:join-strings/sql-quoted ; JOIN-STRINGS with SQL-quoting of some chars.
#:stringify ; Coerce items in atom/list/tree to strings.
#:file-string ; Suck up a whole file into a string.
#:file-lines ; ...into a list of strings (lines).
#:file-forms ; ...into a list of forms (s-exprs).
#:stream-string ; Same as above, but for an open stream
#:stream-lines
#:stream-forms
#:\0x ; A FORMAT printer for hex, e.g. "~2/0x/".
;; Time-formatters [see also CMUCL's EXT:FORMAT-UNIVERSAL-TIME]:
#:format-time-ctime
#:format-time-iso8601
;; Misc. other
#:iota ; (count &optional (start 0) (step 1))
#:mean
#:median
#:std-dev
;; CMUCL MP convenience functions for servers that leave a REPL running:
#:ensure-idle-process-running ; Initial REPL -> idle proc; new proc -> REPL.
#:restart-top-level ; If accidentally kill REPL proc.
#:break-top-level ; Recover from certain tricky typos.
))
And some support for web hacking:
(defpackage :org.rpw3.cgi.uri
(:nicknames :uri)
(:use :cl :ext :htout :utils)
(:export
;; Functions
#:read/parse-http-request
#:query-string-alist
#:cgi-lookup
#:cgi-lookup-all
#:request-env
#:request-binding
#:split-path
#:extract/trim-bindings
#:match-query/bindings
#:match-assoc
#:build-continuation
#:decode-hex
#:url-decode
#:register-uri-handler
#:find-uri-handler
#:not-found-page
#:forbidden-page
#:fallback-page
#:internal-error-page
#:list-html-table
;; Structures
#:http-request
#:http-server
#:uri-handler
...[and friends]...
...[other misc.]...
))
-Rob
-----
Rob Warnock <····@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607
····@rpw3.org (Rob Warnock) writes:
> kevinlivingston <···············@gmail.com> wrote:
> +---------------
> | I think a more interesting "survey question" would be what do you find
> | yourself reimplementing over and over that's not already in there?
> +---------------
Yes, indeed.
I think the function I find myself typing in most frequently is
(defun listify (thing)
(if (listp thing)
thing
(list thing)))
I also get a lot of use out of this hack:
(defun whitespace-char-p (ch)
(case ch
(#.(loop for i below char-code-limit
for ch = (code-char i)
unless (with-input-from-string (in (string ch))
(peek-char t in nil))
collect ch)
t)
(t nil)))
And the usual WITH-GENSYMS and LET*/GENSYMS (an inadvertent rewrite of
ONCE-ONLY).
> #:with-output-to-file ; Save typing in the most common output case.
I have a SAFELY-WRITING macro which opens a stream onto a fresh file
(using :IF-EXISTS NIL), and either renames the file into place on
successful completion or deletes it on failure. It's based on a more
complicated infrastructure of stuff which handles multiple files and
other operations such as file deletion.
> #:stringify ; Coerce items in atom/list/tree to strings.
I have a function with this name, but it's simpler:
(defun stringify (thing)
(typecase thing
(string thing)
(symbol (symbol-name thing))
(t (princ-to-string thing))))
-- [mdw]
Mark Wooding <···@distorted.org.uk> wrote:
+---------------
| ····@rpw3.org (Rob Warnock) writes:
| > #:with-output-to-file ; Save typing in the most common output case.
|
| I have a SAFELY-WRITING macro which opens a stream onto a fresh file
| (using :IF-EXISTS NIL), and either renames the file into place on
| successful completion or deletes it on failure. It's based on a more
| complicated infrastructure of stuff which handles multiple files and
| other operations such as file deletion.
+---------------
Mine does the opposite extreme of "safety": it unconditionally
writes over the file whether or not it exists [unless you supply
a different explicit :IF-EXISTS]:
(defmacro with-output-to-file ((stream filename
&key (direction :output) (if-exists :supersede)
&rest rest &allow-other-keys)
&body body)
`(with-open-file (,stream ,filename
:direction ,direction :if-exists ,if-exists ,@rest)
,@body))
+---------------
| > #:stringify ; Coerce items in atom/list/tree to strings.
|
| I have a function with this name, but it's simpler:
| (defun stringify (thing)
| (typecase thing
| (string thing)
| (symbol (symbol-name thing))
| (t (princ-to-string thing))))
+---------------
Mine translates NIL to "", rather than "NIL", mainly because
of what I tend to use it for [building web pages & other docs].
-Rob
-----
Rob Warnock <····@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607
* (Rob Warnock) <································@speakeasy.net> :
Wrote on Mon, 27 Apr 2009 21:56:00 -0500:
| kevinlivingston <···············@gmail.com> wrote:
| +---------------
| | While I don't use all of it all of the time I do seem to use quite a
| | bit, and it's nice to have learned one language that has most of what
| | I need most of the time.
| +---------------
From my .cmucl-init.lisp, which incidentally works across allegro and
lispworks too, here is a selection of some 45/266 '^(def.*' lines.
Most of it should be familiar to all of you. :)
function compose (&rest functions) ; composes functions as if by m-v-c
function group2 (list &key (test #'eql) (key #'identity)) ·············@registered.motzarella.org
function nshuffle (seq &aux (len (length seq)))
function mapsome (predicate list &rest more-lists)
function delete-nth (list position)
function plist-sans-keys (plist &rest keys) ; <················@naggum.no>
function popmax (list &optional (cmp #'>) &key key)
function insert-ordered (item list &optional (predicate #'<) &key key test test-not)
macro pushnew-ordered (obj place predicate &rest keys &environment env)
function ordered-intersection (list1 list2 predicate)
function suffixp (suffix sequence &key (test #'equalp) &aux idx)
function prefixp (prefix sequence &key (test #'equalp) &aux idx)
function flatten (x &aux stack result)
function tree-depth (tree &aux (global-depth 0) stack) ; madhu 061123
function position-ordered (elem array &optional (predicate #'<) &key (test #'eql) (start 0) end)
function round-to-accuracy (value digits-after-decimal-point)
macro case-equal (which &body clauses)
macro ecase-equal (which &body clauses)
macro continuing-from-errors ((&rest condition-types) &body body)
function substr (string &optional (start 0) end)
function string-split (char-bag string &key (start 0) end (collect-empty t))
function $tring-reader (stream $ arg) ; doesnt escape backslash
function copy-buffered-io (input output &key (block-size 4096) element-type buffer)
function slurp-file (pathname &optional buffer &key element-type)
function slurp-stream (stream &optional buffer &key element-type chunk-size)
function string->file (string filename)
function stream->file (stream filename &key element-type buffer-size buffer)
function read-lines-from-stream (stream &optional lines-array start end &key hint)
function write-lines-to-stream (lines-array &optional stream start end)
function slurp-lines (pathname &optional (start 0) end &key lines-array)
function dump-lines (lines-array pathname &optional (start 0) end)
macro with-decompressed-stream (stream compressed-file-pathname ..)
macro with-flames-to-devnull (&body body)
macro undefmethod (function-name &rest args)
macro choose-with-restarts-internal (choices &body body)
function package-add-nicknames (pkg &rest nicknames)
function package-remove-nicknames (pkg &rest nicknames)
function clean-syms (pkg)
macro with-slots-in-package ((&rest slot-vars) obj pkg &body body)
function hashtable->alist
function hashtable->plist
function lc (pathname &key library-p binary-directory ;; compile and load
dry-run force source-directory source-file-types
create-directories)
function pwd ()
function cd ()
function ps ()
function delete-directory (path)
macro in-directory (directory &body forms)
function symbolic-link-p (pathname &optional (stats (stat2 pathname)))
function directory-p (pathname &optional (stats (stat2 pathname)))
function regular-file-p (pathname &optional (stats (stat2 pathname)))
function iso-8601-date (&key stream utime tzsuppress-time-p suppress-tz-p)
macro with-file-dates-preserved ((pathname) &body body)
function probe-directory (p)
function dired (path &optional f (depth 0) maxdepth &aux p) ; `unix find'
function wildify (root &rest components) ;; make a **;*.*.* logical pathname
macro with-open-pipe ((stream command &key (shell-type "/bin/sh")) &body body)
--
Madhu
* (Rob Warnock) <································@speakeasy.net> :
Wrote on Mon, 27 Apr 2009 21:56:00 -0500:
| +---------------
| | I think a more interesting "survey question" would be what do you find
| | yourself reimplementing over and over that's not already in there?
| +---------------
|
| My standard utilities package:
From my .cmucl-init.lisp, which incidentally works across allegro and
lispworks too, here is a selection of some 45/266 '^(def.*' lines.
Most of it should be familiar to all of you. :)
function compose (&rest functions) ; composes functions as if by m-v-c
function group2 (list &key (test #'eql) (key #'identity)) ·············@registered.motzarella.org
function nshuffle (seq &aux (len (length seq)))
function mapsome (predicate list &rest more-lists)
function delete-nth (list position)
function plist-sans-keys (plist &rest keys) ; <················@naggum.no>
function popmax (list &optional (cmp #'>) &key key)
function insert-ordered (item list &optional (predicate #'<) &key key test test-not)
macro pushnew-ordered (obj place predicate &rest keys &environment env)
function ordered-intersection (list1 list2 predicate)
function suffixp (suffix sequence &key (test #'equalp) &aux idx)
function prefixp (prefix sequence &key (test #'equalp) &aux idx)
function flatten (x &aux stack result)
function tree-depth (tree &aux (global-depth 0) stack) ; madhu 061123
function position-ordered (elem array &optional (predicate #'<) &key (test #'eql) (start 0) end)
function round-to-accuracy (value digits-after-decimal-point)
macro case-equal (which &body clauses)
macro ecase-equal (which &body clauses)
macro continuing-from-errors ((&rest condition-types) &body body)
function substr (string &optional (start 0) end)
function string-split (char-bag string &key (start 0) end (collect-empty t))
function $tring-reader (stream $ arg) ; doesnt escape backslash
function copy-buffered-io (input output &key (block-size 4096) element-type buffer)
function slurp-file (pathname &optional buffer &key element-type)
function slurp-stream (stream &optional buffer &key element-type chunk-size)
function string->file (string filename)
function stream->file (stream filename &key element-type buffer-size buffer)
function read-lines-from-stream (stream &optional lines-array start end &key hint)
function write-lines-to-stream (lines-array &optional stream start end)
function slurp-lines (pathname &optional (start 0) end &key lines-array)
function dump-lines (lines-array pathname &optional (start 0) end)
macro with-decompressed-stream (stream compressed-file-pathname ..)
macro with-flames-to-devnull (&body body)
macro undefmethod (function-name &rest args)
macro choose-with-restarts-internal (choices &body body)
function package-add-nicknames (pkg &rest nicknames)
function package-remove-nicknames (pkg &rest nicknames)
function clean-syms (pkg)
macro with-slots-in-package ((&rest slot-vars) obj pkg &body body)
function hashtable->alist
function hashtable->plist
function lc (pathname &key library-p binary-directory ;; compile and load
dry-run force source-directory source-file-types
create-directories)
function pwd ()
function cd ()
function ps ()
function delete-directory (path)
macro in-directory (directory &body forms)
function symbolic-link-p (pathname &optional (stats (stat2 pathname)))
function directory-p (pathname &optional (stats (stat2 pathname)))
function regular-file-p (pathname &optional (stats (stat2 pathname)))
function iso-8601-date (&key stream utime tzsuppress-time-p suppress-tz-p)
macro with-file-dates-preserved ((pathname) &body body)
function probe-directory (p)
function dired (path &optional f (depth 0) maxdepth &aux p) ; `unix find'
function wildify (root &rest components) ;; make a **;*.*.* logical pathname
macro with-open-pipe ((stream command &key (shell-type "/bin/sh")) &body body)
--
Madhu
På Tue, 28 Apr 2009 13:34:56 +0200, skrev Madhu <·······@meer.net>:
>
> * (Rob Warnock) <································@speakeasy.net> :
> Wrote on Mon, 27 Apr 2009 21:56:00 -0500:
> | +---------------
> | | I think a more interesting "survey question" would be what do you
> find
> | | yourself reimplementing over and over that's not already in there?
> | +---------------
> |
> | My standard utilities package:
>
> From my .cmucl-init.lisp, which incidentally works across allegro and
> lispworks too, here is a selection of some 45/266 '^(def.*' lines.
>
> Most of it should be familiar to all of you. :)
>
From the look of it you should study the , directive of SLIME.
, l - load asdf library
, cd - change directory
, pwd - print working directory and so on.
a lot of that stuff is already done..
-----------------------
John Thingstad
* "John Thingstad" <·················@pandora> :
Wrote on Tue, 28 Apr 2009 13:51:27 +0200:
| On Tue, 28 Apr 2009 13:34:56 +0200, skrev Madhu <·······@meer.net>:
|> * (Rob Warnock) <································@speakeasy.net> :
|> Wrote on Mon, 27 Apr 2009 21:56:00 -0500:
|> | +---------------
|> | | I think a more interesting "survey question" would be what do you
|> | | find yourself reimplementing over and over that's not already in
|> | | there?
|> | +---------------
|> | My standard utilities package:
|> From my .cmucl-init.lisp, which incidentally works across allegro and
|> lispworks too, here is a selection of some 45/266 '^(def.*' lines.
|>
|> Most of it should be familiar to all of you. :)
|
| From the look of it you should study the , directive of SLIME.
| a lot of that stuff is already done..
Well, I wrote this stuff before SLIME existed. At that time only CLOCC
was available, but it was someone else's init file anyway :)
[More precisely I started writing it before SLIME existed... I'm still
writing it. Like the .emacs, the perfect init file is a lifelong task]
Also I don't use SLIME exclusively and need the convenience commands
most on barebores REPs.
--
Madhu
On Apr 27, 5:52 am, kevinlivingston <···············@gmail.com> wrote:
> I think a more interesting "survey question"
> would be what do you find yourself reimplementing over and over that's
> not already in there?
Here are some selected chunks of my utilities package.
(defun row-major-subscripts (array rmi)
"Returns the list of subscripts associated with the row-major-index
RMI in array ARRAY, so that
\(row-major-aref array rmi) = (apply #'aref array rmi)"
(let ((dims (reverse (array-dimensions array)))
(subs '()))
(labels ((collect-sub (rmi)
(if (null dims)
subs
(multiple-value-bind (remains index)
(floor rmi (pop dims))
(push index subs)
(collect-sub remains)))))
(collect-sub rmi))))
(defun hash-table->alist (hash-table)
(let ((alist '()))
(maphash (lambda (k v)
(push (cons k v) alist))
hash-table)
alist))
(defun class-name-of (object)
"Returns the symbol that names the class of OBJECT."
(class-name (class-of object)))
(defun lambda-list-keyword-p (x)
"Checks to see whether X is a lambda list keyword."
(member x '(&rest &aux &key &optional &allow-other-keys)))
(defun zip (&rest more-lists)
(apply #'mapcan #'list more-lists))
(defun riffle (list thing)
(and (not (null list))
(cons (first list)
(loop
:for elt :in (rest list)
:collect thing
:collect elt))))
Cheers,
Pillsy
On Apr 29, 6:06 pm, szergling <···············@gmail.com> wrote:
> On Apr 29, 10:51 am, Pillsy <·········@gmail.com> wrote:
> > (defun zip (&rest more-lists)
> > (apply #'mapcan #'list more-lists))
> CL-USER> (zip '(1 2 3) '(4 5 6))
> (1 4 2 5 3 6)
> This actually looks like a real zipper!
> Doesn't zip usually refer to this (eg Python)?
> CL-USER> (defun zip (&rest lists)
> (apply #'mapcar #'list lists))
> ZIP
Hah. I'd never actually used the function in another language, just
heard it described. :)
I think my ZIP is more useful, though of course I'll have to find a
new name. Maybe I'll call that one RIFFLE and rename the old RIFFLE to
something else....
Cheers,
Pillsy
On 2009-04-27, kevinlivingston <···············@gmail.com> wrote:
> While I don't use all of it all of the time I do seem to use quite a
> bit, and it's nice to have learned one language that has most of what
> I need most of the time. I think a more interesting "survey question"
> would be what do you find yourself reimplementing over and over that's
> not already in there?
If you're implementing it over and over again, maybe it's hard to pin down
the requirements.
But what have you implemented once and then successfully reused many times?
> For me I don't use arrays and vectors that much, but a nice queue
> would be helpful.
A deque in Common Lisp can be made without encapsulation. Simply take two
assignable locations which hold lists, and treat them as the opposite
outward-facing ends of the dequeue. One of them holds the head piece, the other
the tail piece. Adding to the head or tail is therefore done using the standard
PUSH macro, using one location or the other. All you need is a funky pop
macro which can remove an element from either end. It takes both locations
as arguments. To pop from the opposite end, reverse the arguments.
http://paste.lisp.org/display/71592
There there are two implementations; a naive simple one, and an optimized one.
Even though popping involves reversing a list, the amortized cost of the
operations is O(1). I.e. pushing a large number N of items into one end and
popping them out the other is O(N). (This is true of the simple implementation
too, but the simple implementation is susceptible to ``silly flip'' behavior,
when confronted with certain obvious patterns of use, which inflate the
complexity.)
On 2009-04-27, kevinlivingston <···············@gmail.com> wrote:
> On Apr 24, 7:56 am, Kenneth Tilton <·········@gmail.com> wrote:
>> What is/are the big chunks of CL you have never used? Series does not count.
>
> Some of the big things that CL waves around that I don't use much are
> bignums
How do you know you don't use bignums? The knee between fixnums and bignums is
implementation-defined. What if it occurs at +/- 255?
If you use exact numbers at all in your CL programs, you benefit from bignums,
because you are free from worrying about annoying corner cases, like ``what if
adding these two numbers overflows 32 bits''?
If you don't have bignums, you have to validate that no overflows happen.
So even if your algorithms don't obviously require bignums, you still have
the safety net there. A safety net is valuable even if nobody falls down.
If you never wrote a program that exhibited a type mismatch, would you say that
you don't ``use'' type checking? :)
On Apr 28, 3:10 pm, Kaz Kylheku <········@gmail.com> wrote:
> How do you know you don't use bignums? The knee between fixnums and bignums is
> implementation-defined. What if it occurs at +/- 255?
Easy. Quoting the HyperSpec, "The type fixnum is required to be a
supertype of (signed-byte 16)."
Kenneth Tilton wrote:
> Lisp G*ds Only, for reasons obvious:
>
> What is/are the big chunks of CL you have never used?
I have never used the numerical tower.
And I have never used fourth, fifth, sixth, seventh, eighth, ninth and
tenth. That's a pretty big chunk, right? ;)
Pascal
--
ELS'09: http://www.european-lisp-symposium.org/
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
On Tue, 28 Apr 2009 15:07:10 +0200, <··@p-cos.net> wrote:
> Kenneth Tilton wrote:
>> Lisp G*ds Only, for reasons obvious:
>>
>> What is/are the big chunks of CL you have never used?
>
> I have never used the numerical tower.
Tower???
--
Lisp: Powering `Impossible Thoughts since 1958
GP lisper wrote:
> On Tue, 28 Apr 2009 15:07:10 +0200, <··@p-cos.net> wrote:
>> Kenneth Tilton wrote:
>>> Lisp G*ds Only, for reasons obvious:
>>>
>>> What is/are the big chunks of CL you have never used?
>> I have never used the numerical tower.
>
> Tower???
Built in a response to the Tower of Babel, leading to a runaway tower
race that sapped the economies of orators and mathematicians for ... not
sure where this is going... ah, yes, Towers of Hanoi.... hang on... OK,
based on my performance tonight my softball team is renaming itself The
Faceplants....where was I?
GP lisper <········@clouddancer.com> wrote:
+---------------
| <··@p-cos.net> wrote:
| > Kenneth Tilton wrote:
| >> Lisp G*ds Only, for reasons obvious:
| >> What is/are the big chunks of CL you have never used?
| >
| > I have never used the numerical tower.
|
| Tower???
+---------------
(*sigh*) Kids these days... ;-}
http://en.wikipedia.org/wiki/Numerical_tower
Numerical tower
In Scheme and some other Lisp dialects, a numerical tower is the set
of data types that represent numbers in a given programming language.
Each type in the tower conceptually "sits on" a more fundamental type,
so an integer is a rational number and a number, but the inverse
is not necessarily true, i.e. not every number is an integer; this
asymmetry implies that a language can allow implicit coercions of
numerical types - without creating semantic problems - in only one
direction: ...
And as usual, CL is more a "ball of mud" than Scheme... ;-}
The CLHS doesn't use the term "numerical tower" per se, but CL's
numerical tower is implicit in the class precedence lists of its
numeric types [though the "purity" of the class tower is marred
slightly by a few mild restrictions on the COMPLEX and RATIO classes]:
- t
- number
- complex ; includes #c(real 0.0) but excludes #c(rational 0)
- real
- float
- short-float
- single-float
- double-float
- long-float
- rational
- ratio ; n/d, (and (not (zerop n)) (plusp d) (= (gcd x y) 1))
- integer
- fixnum
- bignum
Also note that while UNSIGNED-BYTE, & SIGNED-BYTE are subtypes of
INTEGER, such values of such types can be in either class FIXNUM
or BIGNUM, so that {UN,}SIGNED-BYTE are *not* "classes" per se,
and thus are not in any of the numeric class precedence lists.
[The CLHS uses a list of Supertypes for these, instead.] Which
also means that, contrary to what one might otherwise expect, BIT,
as a subtype of UNSIGNED-BYTE, is not a sub-*class* of FIXNUM.
That is, while CL's numeric *classes* are a tree, its numeric
*types* are a DAG.
-Rob
-----
Rob Warnock <····@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607