From: verec
Subject: popold
Date: 
Message-ID: <43bd2588$0$87296$5a6aecb4@news.aaisp.net.uk>
I want to be able to conditionally compile/evaluate

forms, so I thought that the perfect tool was the

combination of the #+ reader macro together with the

contents of the *features* list.



(defun +feature (feature)

  (pushnew feature *features*))

  

(defun -feature (feature)

  (hum-ho ... how do I remove???

  

Trip to the dreaded CLHS

http://www.lispworks.com/documentation/HyperSpec/Body/f_rm_rm.htm



      "delete, when sequence is a list, is permitted to setf any

       part, car or cdr, of the top-level list structure in that

       sequence."



Hey? "permitted"? 



And indeed, with LW:


CL-USER 1 > (defvar *test-list* '(1 2 3))
*test-list*

CL-USER 2 > (delete 1 *test-list*)
(2 3)

CL-USER 3 > *test-list*
(1 2 3)


OK. I've got to setf by myself then.

But then why would I need to use delete when it does

exactly what remove does?



(defmacro popold (item list)
  `(setf ,list (remove ,item ,list)))

  

(defun -feature (feature)

  (popold feature *features*))

  

Let's recap:



(defmacro popold (item list)
  `(setf ,list (remove ,item ,list)))

(defun +feature (feature)
  (pushnew feature *features*))

(defun -feature (feature)
  (popold feature *features*))

(+feature :dbg)

#+dbg (format t ":dbg active~%")
#-dbg (format t ":dbg inactive~%")

(-feature :dbg)

#+dbg (format t ":dbg active~%")
#-dbg (format t ":dbg inactive~%")



; popold
; +feature
; -feature
; (lispworks:top-level-form 5)
; (lispworks:top-level-form 6)
:dbg active
; (lispworks:top-level-form 7)
; (lispworks:top-level-form 8)
:dbg inactive


Now to the questions.



1. if I'm only interested in portable CL, why would

   I ever consider using delete rather than remove

   since there is no guarantee that the target

   sequence is modified?



2. my own popold macro is obviously built as a counterpart

   to pushnew. Does CL have any "popold" by another name

   that I simply missed?

   

3. Regarding the *features* list, while the CLHS says

http://www.lispworks.com/documentation/HyperSpec/Body/v_featur.htm

   that it is a list, I've got that feeling that it is

   some kind of "system resource" that is OK to "look but don't touch"

   

   I could obviously (defvar *my-features*) and be done with

   it, but I don't really sense whether my use of that

   builtin *features* list is appropriate or not.


Any advice?

   

Many Thanks

--

JFB

From: Edi Weitz
Subject: Re: popold
Date: 
Message-ID: <u4q4ig3qh.fsf@agharta.de>
On Thu, 5 Jan 2006 13:56:24 +0000, verec <·····@mac.com> wrote:

> 1. if I'm only interested in portable CL, why would I ever consider
> using delete rather than remove since there is no guarantee that the
> target sequence is modified?

DELETE, like other destructive operations, is there because it can be
potentially faster[1] if it operates on large structures.  You
can/should use it if you know that the list you're working with is
"yours" and will be thrown away anyway.  Otherwise you must not use
it.

But you have to keep in mind that destructive and non-destructive
functions are always used the same way, it's

  (setq new-list (remove item old-list))

and it's

  (setq new-list (delete item old-list)).

> 3. Regarding the *features* list [...] I've got that feeling that it
> is some kind of "system resource" that is OK to "look but don't
> touch"

Nah, it's OK to modify it but usually you shouldn't remove features
you haven't put there yourself.  Many libraries add something to
*FEATURES*.

HTH,
Edi.

[1] Consider this example:

  CL-USER 23 > (defun range (n)
                 (loop for i below n collect i))
  RANGE

  CL-USER 24 > (compile 'range)
  RANGE
  NIL
  NIL

  CL-USER 25 > (defun foo (fn)
                 (funcall fn 2 (range 1000000))
                 (values))
  FOO

  CL-USER 26 > (compile 'foo)
  FOO
  NIL
  NIL

  CL-USER 27 > (time (foo #'remove))
  Timing the evaluation of (FOO (FUNCTION REMOVE))

  user time    =      0.570
  system time  =      0.010
  Elapsed time =   0:00:01
  Allocation   = 11216 bytes standard / 22005555 bytes conses
  0 Page faults

  CL-USER 28 > (time (foo #'delete))
  Timing the evaluation of (FOO (FUNCTION DELETE))

  user time    =      0.140
  system time  =      0.010
  Elapsed time =   0:00:00
  Allocation   = 7504 bytes standard / 11004796 bytes conses
  0 Page faults

Note that REMOVE /must/ allocate a new list with 1,000,000 elements
while DELETE can re-use the old list and just "uncouple a pointer," so
to say.


-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Pascal Bourguignon
Subject: Re: popold
Date: 
Message-ID: <87psn6eo5b.fsf@thalassa.informatimago.com>
verec <·····@mac.com> writes:
> 1. if I'm only interested in portable CL, why would
>    I ever consider using delete rather than remove
>    since there is no guarantee that the target
>    sequence is modified?

Because with DELETE you portably indicate to the lisp implementation
that you wouldn't mind some memory saving.

(remove x l) is O(length(l)) in space.
(delete x l) can be O(0) in space.

(both are O(length(l)) in time).


> 2. my own popold macro is obviously built as a counterpart
>    to pushnew. Does CL have any "popold" by another name
>    that I simply missed?

No.

    
> 3. Regarding the *features* list, while the CLHS says
> http://www.lispworks.com/documentation/HyperSpec/Body/v_featur.htm
>    that it is a list, I've got that feeling that it is
>    some kind of "system resource" that is OK to "look but don't touch"
>    
>    I could obviously (defvar *my-features*) and be done with
>    it, but I don't really sense whether my use of that
>    builtin *features* list is appropriate or not.

I think it's appropriate.

Of course, you should be careful in modifying this list,  but if you
don't add or remove features that will imply trying to load or run
code that will generate errors or nasal daemons, then it should be
quite benign to modify it.

One thing you can do to avoid problems is to push on it only symbols
in your own package:

(defpackage "COM.MAC.VEREC.MY-APP")
(pushnew 'COM.MAC.VEREC.MY-APP::MY-FEATURE *features*)
#+COM.MAC.VEREC.MY-APP::MY-FEATURE (print :ok)

This way, you're almost sure that nobody else in his sane mind would
have created a package named with a domain name reserved to you, and
pushed a feature symbol in this package.

Note that if you name your package CL-STUFF, it won't work, everybody
name their package CL-STUFF, which is perfectly all right when there
is no Internet, but Internet exists since only about 40 years, you
cannot expect a lot of people to realize it so fast...  (Yes, I know,
I'm still optimisitic and think that there will be so many lisp
developers that there will be several competing SMTP or SPLIT-SEQUENCE
or TYPESETTING or PNG packages...).

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

ATTENTION: Despite any other listing of product contents found
herein, the consumer is advised that, in actuality, this product
consists of 99.9999999999% empty space.
From: Pascal Costanza
Subject: Re: popold
Date: 
Message-ID: <424peaF1h6d51U1@individual.net>
verec wrote:

> 1. if I'm only interested in portable CL, why would
> 
>   I ever consider using delete rather than remove
> 
>   since there is no guarantee that the target
> 
>   sequence is modified?

'delete is the destructive counterpart to 'remove. Like all destructive 
versions of otherwise applicative functions (nconc vs. append, nreverse 
vs reverse, etc.), they are all just "permitted" to be destructive, but 
not required (with a few exceptions).

Those destructive functions are typically only used to improve 
performance characteristics - especially to reduce the memory overhead 
that the applicative versions typically create. However, you have to be 
careful when using the destructive functions - don't use them on data 
that you haven't created yourself, unless you really know what you are 
doing (or unless the documentation of some other API explicitly tells 
that it's ok to do so, and/or under what circumstances it's ok to do so).

These considerations hold for conses/lists. For other data structures, 
like arrays, structs and objects, destructive operations are more 
typical and straightforward to use.

> 2. my own popold macro is obviously built as a counterpart
> 
>   to pushnew. Does CL have any "popold" by another name
> 
>   that I simply missed?

No, but some Common Lisp implementations provide (the better named) 
removef and deletef. It's relatively straightforward to implement them:

(define-modify-macro removef (item &rest keys)
   (lambda (place item &rest keys &key test test-not start end key)
     (declare (ignorable test test-not start end key))
     (apply #'remove item place keys))
   "Removes an item from a sequence.")

> 3. Regarding the *features* list, while the CLHS says
> 
> http://www.lispworks.com/documentation/HyperSpec/Body/v_featur.htm
> 
>   that it is a list, I've got that feeling that it is
> 
>   some kind of "system resource" that is OK to "look but don't touch"
> 
>  
>   I could obviously (defvar *my-features*) and be done with
> 
>   it, but I don't really sense whether my use of that
> 
>   builtin *features* list is appropriate or not.

What does the documentation say?



Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: verec
Subject: Re: popold
Date: 
Message-ID: <43bd418a$0$87295$5a6aecb4@news.aaisp.net.uk>
( let's see if I can avoid the double new line mess this time )-:

On 2006-01-05 14:15:50 +0000, Edi Weitz <········@agharta.de> said:

> But you have to keep in mind that destructive and non-destructive
> functions are always used the same way, it's
> 
>   (setq new-list (remove item old-list))
> 
> and it's
> 
>   (setq new-list (delete item old-list)).

OK.... but that seems a bit weird. If old-list is bound
("points") to '(1 2 3) and I (delete 2 old-list), then
it's a bit of a mystery why I would have '(1 3) as the
result while old-list would still refer to '(1 2 3).
Though, I do see why (delete 1 old-list) would return '(2 3)
while old-list would still refer to '(1 2 3).

Is this car hijacking from under old-list feet the only
reason why setf is necessary, or am I missing deeper reasons?

> Note that REMOVE /must/ allocate a new list with 1,000,000 elements
> while DELETE can re-use the old list and just "uncouple a pointer," so
> to say.

Got it. Thanks.

On 2006-01-05 14:37:52 +0000, Pascal Bourguignon <····@mouse-potato.com> said:

> Because with DELETE you portably indicate to the lisp implementation
> that you wouldn't mind some memory saving.
> 
> (remove x l) is O(length(l)) in space.
> (delete x l) can be O(0) in space.
> 
> (both are O(length(l)) in time).

Thanks. I guess I get the picture now.

> Note that if you name your package CL-STUFF, it won't work, everybody
> name their package CL-STUFF, which is perfectly all right when there
> is no Internet, but Internet exists since only about 40 years, you
> cannot expect a lot of people to realize it so fast...  (Yes, I know,
> I'm still optimisitic and think that there will be so many lisp
> developers that there will be several competing SMTP or SPLIT-SEQUENCE
> or TYPESETTING or PNG packages...).

Why does it matter to you that CL ever gets "popular" ?
If, as I am slowly beginning to appreciate, CL lives up to
Paul Graham's promises :-) then I'd rather keep it as a secret
weapon :-)

On 2006-01-05 14:40:11 +0000, Pascal Costanza <··@p-cos.net> said:

>> 2. my own popold macro is obviously built as a counterpart
>>   to pushnew. Does CL have any "popold" by another name
>>   that I simply missed?
> 
> No, but some Common Lisp implementations provide (the better named) 
> removef and deletef. It's relatively straightforward to implement them:
> 
> (define-modify-macro removef (item &rest keys)
>    (lambda (place item &rest keys &key test test-not start end key)
>      (declare (ignorable test test-not start end key))
>      (apply #'remove item place keys))
>    "Removes an item from a sequence.")

Thanks. Why do you think that "removef/deletef" are better names?
I chose "popold" for obvious symetrical reasons. What would be
the opposite of "removef": "appendf" ? (Blimey! not "nconcf" I hope!)

And what's the story behing that "f" suffix ?

Many Thanks
--
JFB
From: Brian Downing
Subject: Re: popold
Date: 
Message-ID: <sKbvf.708575$xm3.121815@attbi_s21>
In article <·························@news.aaisp.net.uk>,
verec  <·····@mac.com> wrote:
> OK.... but that seems a bit weird. If old-list is bound
> ("points") to '(1 2 3) and I (delete 2 old-list), then
> it's a bit of a mystery why I would have '(1 3) as the
> result while old-list would still refer to '(1 2 3).
> Though, I do see why (delete 1 old-list) would return '(2 3)
> while old-list would still refer to '(1 2 3).

See this example:

CL-USER 2 > (let ((old-list (list 1 2 3)))
               (values (delete 1 old-list)
                       old-list))
(2 3)
(1 2 3)

It is more efficient to just return the cdr instead of horribly
mangling the list in some fashion.

> Is this car hijacking from under old-list feet the only
> reason why setf is necessary, or am I missing deeper reasons?

Here's an excercise for you:

Write a function MY-DELETE such that this behavior is realized:

(let ((old-list (list 1)))
  (my-delete 1 old-list)
  old-list)
=> NIL

I think you'll understand after that.

-bcd
-- 
*** Brian Downing <bdowning at lavos dot net> 
From: Brian Downing
Subject: Re: popold
Date: 
Message-ID: <bLbvf.466949$084.221550@attbi_s22>
In article <·······················@attbi_s21>,
Brian Downing  <·············@lavos.net> wrote:
> In article <·························@news.aaisp.net.uk>,
> verec  <·····@mac.com> wrote:
> > OK.... but that seems a bit weird. If old-list is bound
> > ("points") to '(1 2 3) and I (delete 2 old-list), then
> > it's a bit of a mystery why I would have '(1 3) as the
> > result while old-list would still refer to '(1 2 3).
> > Though, I do see why (delete 1 old-list) would return '(2 3)
> > while old-list would still refer to '(1 2 3).
> 
> See this example:
> 
> CL-USER 2 > (let ((old-list (list 1 2 3)))
>                (values (delete 1 old-list)
>                        old-list))
> (2 3)
> (1 2 3)
> 
> It is more efficient to just return the cdr instead of horribly
> mangling the list in some fashion.

Ignore this - I didn't read all your text.  Sorry.

-bcd
From: Edi Weitz
Subject: Re: popold
Date: 
Message-ID: <u7j9er403.fsf@agharta.de>
On Thu, 5 Jan 2006 15:55:55 +0000, verec <·····@mac.com> wrote:

> And what's the story behing that "f" suffix ?

  <http://groups.google.de/group/comp.lang.lisp/browse_frm/thread/d4e1118d87d22aa7/ffad99a26dfa6b2e#ffad99a26dfa6b2e>

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Barry Margolin
Subject: Re: popold
Date: 
Message-ID: <barmar-7742A0.01330106012006@comcast.dca.giganews.com>
In article <·························@news.aaisp.net.uk>,
 verec <·····@mac.com> wrote:

> ( let's see if I can avoid the double new line mess this time )-:
> 
> On 2006-01-05 14:15:50 +0000, Edi Weitz <········@agharta.de> said:
> 
> > But you have to keep in mind that destructive and non-destructive
> > functions are always used the same way, it's
> > 
> >   (setq new-list (remove item old-list))
> > 
> > and it's
> > 
> >   (setq new-list (delete item old-list)).
> 
> OK.... but that seems a bit weird. If old-list is bound
> ("points") to '(1 2 3) and I (delete 2 old-list), then
> it's a bit of a mystery why I would have '(1 3) as the
> result while old-list would still refer to '(1 2 3).

That normally won't happen.  Although the spec doesn't require 
destructive modification, practically all implementations do it.

> Is this car hijacking from under old-list feet the only
> reason why setf is necessary, or am I missing deeper reasons?

Pretty much.  You also need it when you're deleting all the elements, 
since the result will be NIL, not a cons.

And since you have to do this, it allows the language spec to be lenient 
about requiring a specific type of destructive behavior.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***