From: Dustin Withers
Subject: Removing Strings from a list
Date: 
Message-ID: <1160159707.867807.110750@m73g2000cwd.googlegroups.com>
Hello All,

My first attempt at this hasn't worked and I was hoping for some
insight.  I'm trying to remove all string from a list and return them
as a list.

This is my first attempt:
(let ((elements ()))
	      (dolist item *LIST*
		      (if (stringp item)
			  (push (pop *LIST*) elements)
			  ()))
	      elements)

What is wrong with this?  It causes the error:

Execution of a form compiled with errors.
Form:
  (DOLIST ITEM
 *LIST*
  (IF (STRINGP ITEM) (PUSH (POP *LIST*) ELEMENTS)))
Compile-time error:
  (in macroexpansion of (DOLIST ITEM *LIST* ...))
(hint: For more precise location, try *BREAK-ON-SIGNALS*.)
error while parsing arguments to DEFMACRO DOLIST:
  bogus sublist
    ITEM
  to satisfy lambda-list
    (SB-DEBUG:VAR LIST &OPTIONAL (SB-IMPL::RESULT NIL))
   [Condition of type SB-INT:COMPILED-PROGRAM-ERROR]

Thanks for any help,
-dustin

From: bradb
Subject: Re: Removing Strings from a list
Date: 
Message-ID: <1160160001.359860.21570@e3g2000cwe.googlegroups.com>
Dustin Withers wrote:
> Hello All,
>
> My first attempt at this hasn't worked and I was hoping for some
> insight.  I'm trying to remove all string from a list and return them
> as a list.
>
> This is my first attempt:
> (let ((elements ()))
> 	      (dolist item *LIST*
DOLIST syntax is (dolist (x list) ...)
http://www.lisp.org/HyperSpec/Body/mac_dolist.html

Also, you can use REMOVE to do what you want.

Cheers
Brad
From: Zach Beane
Subject: Re: Removing Strings from a list
Date: 
Message-ID: <m3fye1l128.fsf@unnamed.xach.com>
"Dustin Withers" <·········@gmail.com> writes:

> I'm trying to remove all string from a list and return them as a
> list.
> 
> This is my first attempt:
> (let ((elements ()))
> 	      (dolist item *LIST*
> 		      (if (stringp item)
> 			  (push (pop *LIST*) elements)
> 			  ()))
> 	      elements)
> 
> What is wrong with this?


"bradb" <··············@gmail.com> writes:

> DOLIST syntax is (dolist (x list) ...)
> http://www.lisp.org/HyperSpec/Body/mac_dolist.html

Actually, DOLIST syntax is:

    (dolist (var list-form [result-form]) ...)

I use RESULT-FORM a lot. I wouldn't solve the original problem with
dolist, but if I did, it might look something like this:

   (let ((elements '()))
     (dolist (item *list* elements)
       (when (stringp item)
         (push item elements))))

Zach
From: Lars Rune Nøstdal
Subject: Re: Removing Strings from a list
Date: 
Message-ID: <pan.2006.10.06.21.24.34.745298@gmail.com>
On Fri, 06 Oct 2006 11:40:01 -0700, bradb wrote:

> Dustin Withers wrote:
>> Hello All,
>>
>> My first attempt at this hasn't worked and I was hoping for some
>> insight.  I'm trying to remove all string from a list and return them
>> as a list.
>>
>> This is my first attempt:
>> (let ((elements ()))
>> 	      (dolist item *LIST*
> DOLIST syntax is (dolist (x list) ...)
> http://www.lisp.org/HyperSpec/Body/mac_dolist.html
> 
> Also, you can use REMOVE to do what you want.

Yeah, I'd use `remove-if' or `delete-if' I think (check the hyperspec for
differences):

cl-user> (remove-if #'stringp '(a b c "hey" 1234 "ho"))
(a b c 1234)
cl-user> (defparameter *list* '(a b c "hey" 1234 "ho"))
*list*
cl-user> (setf *list* (delete-if #'stringp *list*))
(a b c 1234)
cl-user> *list*
(a b c 1234)

-- 
Lars Rune Nøstdal
http://lars.nostdal.org/
From: Rahul Jain
Subject: Re: Removing Strings from a list
Date: 
Message-ID: <87zmc9i81l.fsf@nyct.net>
"Dustin Withers" <·········@gmail.com> writes:

> Hello All,
>
> My first attempt at this hasn't worked and I was hoping for some
> insight.  I'm trying to remove all string from a list and return them
> as a list.

Looks like you're trying to use the PARTITION function that some of us
have contributed to.

Um... but it seems to be superseded by SPLIT-SEQUENCE... didn't
PARTITION do something different? Separate the seq into multiple seqs
based on some criterion?

-- 
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
From: Geoffrey Summerhayes
Subject: Re: Removing Strings from a list
Date: 
Message-ID: <1160164473.615285.119690@h48g2000cwc.googlegroups.com>
Rahul Jain wrote:
> "Dustin Withers" <·········@gmail.com> writes:
>
> > Hello All,
> >
> > My first attempt at this hasn't worked and I was hoping for some
> > insight.  I'm trying to remove all string from a list and return them
> > as a list.
>
> Looks like you're trying to use the PARTITION function that some of us
> have contributed to.
>
> Um... but it seems to be superseded by SPLIT-SEQUENCE... didn't
> PARTITION do something different? Separate the seq into multiple seqs
> based on some criterion?

I don't believe so, IIRC, SPLIT-SEQUENCE got its name because
enough people argued that the name PARTITION was confusing.

---
Geoff
From: Rahul Jain
Subject: Re: Removing Strings from a list
Date: 
Message-ID: <87vemxi4e2.fsf@nyct.net>
"Geoffrey Summerhayes" <·······@hotmail.com> writes:

> I don't believe so, IIRC, SPLIT-SEQUENCE got its name because
> enough people argued that the name PARTITION was confusing.

Yes, I do remember that confusion, and thought we decided to have a
PARTITION that would actually perform a partition of a sequence. Oh
well, I guess I was confused. ;)

-- 
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
From: Pascal Bourguignon
Subject: Re: Removing Strings from a list
Date: 
Message-ID: <87zmc9mdlt.fsf@thalassa.informatimago.com>
"Dustin Withers" <·········@gmail.com> writes:
> My first attempt at this hasn't worked and I was hoping for some
> insight.  I'm trying to remove all string from a list and return them
> as a list.

This is problematic.

There is not list data type in lisp.

We build lists as a pun on cons cells or nil.

(deftype proper-list () (or null (cons t list)))
(deftype list        () (or null cons))

The consequence, is that when a variable refers the first cons of a
list, and given that parameter passing is always done by value, not by
reference, we cannot meaningfully remove the first cons of the list
from this list.

Another way to see it is that these chaining of cons cells allow for
sharing of the tail of the lists, and the whole lists can be seen as
their own tail:

      (let ((a (list 1 2 3)))
        (let ((b a))
           ;; here, we cannot remove 1 from the list a and have it removed
           ;; too from the list b!
           ))


The second case where problems would occur is with empty lists, since
they are all NIL, and you cannot modify NIL. Well for your problem
this wouldn't matter since you can't remove anything from NIL, but
with this conception you couldn't add elements to your list.



So if you really persist in wanting to do what you say you are wanting
to do, then you should create a list data type.

(defstruct mylist elements)

Then you can write:

(defun delete-strings-from-mylist-and-return-them (mylist)
   (loop
      :for item :in (mylist-elements mylist)
      :if (stringp item) :collect item :into strings
      :else              :collect item :into others
      :finally (setf (mylist-elements mylist) others)
               (return strings)))

      

[53]> (defparameter *ml* (make-mylist :elements (list 1 2 "one" "two" 'one 'two)))
*ML*
[54]> (delete-strings-from-mylist-and-return-them *ml*)
("one" "two")
[55]> *ml*
#S(MYLIST :ELEMENTS (1 2 ONE TWO))
[56]> 

Note that my implementation doesn't modify the list inside the mylist,
it creates a two lists.  This to avoid suprizing results, and to allow
to put a literal list inside a mylist:


[56]> (defparameter *ml* (make-mylist :elements '(1 2 "one" "two" 'one 'two)))
*ML*
[57]> (delete-strings-from-mylist-and-return-them *ml*)
("one" "two")
[58]> *ml*
#S(MYLIST :ELEMENTS (1 2 'ONE 'TWO))
[59]> (defparameter *l* (list 1 2 "one" "two" 'one 'two))
*L*
[60]> (defparameter *ml* (make-mylist :elements *l*))
*ML*
[61]> (delete-strings-from-mylist-and-return-them *ml*)
("one" "two")
[62]> *ml*
#S(MYLIST :ELEMENTS (1 2 ONE TWO))
[63]> *l*
(1 2 "one" "two" ONE TWO)
[64]> 

If you use destructive functions (such as POP, DELETE  or DELETE-IF)
on the elements of the mylist, then you have to be very careful never
pass literal list (or tails), and to make sure that any other
structure sharing is not done unconciously.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Kitty like plastic.
Confuses for litter box.
Don't leave tarp around.
From: Dustin Withers
Subject: Re: Removing Strings from a list
Date: 
Message-ID: <1160165489.988623.278360@m73g2000cwd.googlegroups.com>
Wow, cool.  Thanks everybody for these great answers.

-dustin

Pascal Bourguignon wrote:
> "Dustin Withers" <·········@gmail.com> writes:
> > My first attempt at this hasn't worked and I was hoping for some
> > insight.  I'm trying to remove all string from a list and return them
> > as a list.
>
> This is problematic.
>
> There is not list data type in lisp.
>
> We build lists as a pun on cons cells or nil.
>
> (deftype proper-list () (or null (cons t list)))
> (deftype list        () (or null cons))
>
> The consequence, is that when a variable refers the first cons of a
> list, and given that parameter passing is always done by value, not by
> reference, we cannot meaningfully remove the first cons of the list
> from this list.
>
> Another way to see it is that these chaining of cons cells allow for
> sharing of the tail of the lists, and the whole lists can be seen as
> their own tail:
>
>       (let ((a (list 1 2 3)))
>         (let ((b a))
>            ;; here, we cannot remove 1 from the list a and have it removed
>            ;; too from the list b!
>            ))
>
>
> The second case where problems would occur is with empty lists, since
> they are all NIL, and you cannot modify NIL. Well for your problem
> this wouldn't matter since you can't remove anything from NIL, but
> with this conception you couldn't add elements to your list.
>
>
>
> So if you really persist in wanting to do what you say you are wanting
> to do, then you should create a list data type.
>
> (defstruct mylist elements)
>
> Then you can write:
>
> (defun delete-strings-from-mylist-and-return-them (mylist)
>    (loop
>       :for item :in (mylist-elements mylist)
>       :if (stringp item) :collect item :into strings
>       :else              :collect item :into others
>       :finally (setf (mylist-elements mylist) others)
>                (return strings)))
>
>
>
> [53]> (defparameter *ml* (make-mylist :elements (list 1 2 "one" "two" 'one 'two)))
> *ML*
> [54]> (delete-strings-from-mylist-and-return-them *ml*)
> ("one" "two")
> [55]> *ml*
> #S(MYLIST :ELEMENTS (1 2 ONE TWO))
> [56]>
>
> Note that my implementation doesn't modify the list inside the mylist,
> it creates a two lists.  This to avoid suprizing results, and to allow
> to put a literal list inside a mylist:
>
>
> [56]> (defparameter *ml* (make-mylist :elements '(1 2 "one" "two" 'one 'two)))
> *ML*
> [57]> (delete-strings-from-mylist-and-return-them *ml*)
> ("one" "two")
> [58]> *ml*
> #S(MYLIST :ELEMENTS (1 2 'ONE 'TWO))
> [59]> (defparameter *l* (list 1 2 "one" "two" 'one 'two))
> *L*
> [60]> (defparameter *ml* (make-mylist :elements *l*))
> *ML*
> [61]> (delete-strings-from-mylist-and-return-them *ml*)
> ("one" "two")
> [62]> *ml*
> #S(MYLIST :ELEMENTS (1 2 ONE TWO))
> [63]> *l*
> (1 2 "one" "two" ONE TWO)
> [64]>
>
> If you use destructive functions (such as POP, DELETE  or DELETE-IF)
> on the elements of the mylist, then you have to be very careful never
> pass literal list (or tails), and to make sure that any other
> structure sharing is not done unconciously.
>
> --
> __Pascal Bourguignon__                     http://www.informatimago.com/
> Kitty like plastic.
> Confuses for litter box.
> Don't leave tarp around.
From: Dustin Withers
Subject: Re: Removing Strings from a list
Date: 
Message-ID: <1160166286.869596.140050@i42g2000cwa.googlegroups.com>
Pascal,

This is for use with the EDI parser I'm trying to put together. I'm
writing the Lexical Analyzer for the grammar we were talking about in a
different thread.

Here is what I have...(not taking into account what's been stated in
this thread)
(defun parsed-edi-lexer (list)
  (let ((lst list))
    #'(lambda ()
	(if (listp (car lst))
	    (progn
	      (setf lst (append (car lst) (cdr lst)))
	      (if (car lst)
		  (let ((segment (pop lst)))
			(values (intern segment) segment))
		  (values nil nil)))
	    (values 'elements (reverse
			       (let ((elements ()))
				 (dolist (item lst)
				   (if (stringp item)
				       (push (pop lst) elements)))
				 elements)))))))

This is to be called by a grammar defined using CL-YACC.  Any opinions?
;)

-dustin
Pascal Bourguignon wrote:
> "Dustin Withers" <·········@gmail.com> writes:
> > My first attempt at this hasn't worked and I was hoping for some
> > insight.  I'm trying to remove all string from a list and return them
> > as a list.
>
> This is problematic.
>
> There is not list data type in lisp.
>
> We build lists as a pun on cons cells or nil.
>
> (deftype proper-list () (or null (cons t list)))
> (deftype list        () (or null cons))
>
> The consequence, is that when a variable refers the first cons of a
> list, and given that parameter passing is always done by value, not by
> reference, we cannot meaningfully remove the first cons of the list
> from this list.
>
> Another way to see it is that these chaining of cons cells allow for
> sharing of the tail of the lists, and the whole lists can be seen as
> their own tail:
>
>       (let ((a (list 1 2 3)))
>         (let ((b a))
>            ;; here, we cannot remove 1 from the list a and have it removed
>            ;; too from the list b!
>            ))
>
>
> The second case where problems would occur is with empty lists, since
> they are all NIL, and you cannot modify NIL. Well for your problem
> this wouldn't matter since you can't remove anything from NIL, but
> with this conception you couldn't add elements to your list.
>
>
>
> So if you really persist in wanting to do what you say you are wanting
> to do, then you should create a list data type.
>
> (defstruct mylist elements)
>
> Then you can write:
>
> (defun delete-strings-from-mylist-and-return-them (mylist)
>    (loop
>       :for item :in (mylist-elements mylist)
>       :if (stringp item) :collect item :into strings
>       :else              :collect item :into others
>       :finally (setf (mylist-elements mylist) others)
>                (return strings)))
>
>
>
> [53]> (defparameter *ml* (make-mylist :elements (list 1 2 "one" "two" 'one 'two)))
> *ML*
> [54]> (delete-strings-from-mylist-and-return-them *ml*)
> ("one" "two")
> [55]> *ml*
> #S(MYLIST :ELEMENTS (1 2 ONE TWO))
> [56]>
>
> Note that my implementation doesn't modify the list inside the mylist,
> it creates a two lists.  This to avoid suprizing results, and to allow
> to put a literal list inside a mylist:
>
>
> [56]> (defparameter *ml* (make-mylist :elements '(1 2 "one" "two" 'one 'two)))
> *ML*
> [57]> (delete-strings-from-mylist-and-return-them *ml*)
> ("one" "two")
> [58]> *ml*
> #S(MYLIST :ELEMENTS (1 2 'ONE 'TWO))
> [59]> (defparameter *l* (list 1 2 "one" "two" 'one 'two))
> *L*
> [60]> (defparameter *ml* (make-mylist :elements *l*))
> *ML*
> [61]> (delete-strings-from-mylist-and-return-them *ml*)
> ("one" "two")
> [62]> *ml*
> #S(MYLIST :ELEMENTS (1 2 ONE TWO))
> [63]> *l*
> (1 2 "one" "two" ONE TWO)
> [64]>
>
> If you use destructive functions (such as POP, DELETE  or DELETE-IF)
> on the elements of the mylist, then you have to be very careful never
> pass literal list (or tails), and to make sure that any other
> structure sharing is not done unconciously.
>
> --
> __Pascal Bourguignon__                     http://www.informatimago.com/
> Kitty like plastic.
> Confuses for litter box.
> Don't leave tarp around.
From: Lars Rune Nøstdal
Subject: Re: Removing Strings from a list
Date: 
Message-ID: <pan.2006.10.06.21.30.31.445382@gmail.com>
On Fri, 06 Oct 2006 11:35:07 -0700, Dustin Withers wrote:

> 		      (if (stringp item)
> 			  (push (pop *LIST*) elements)
> 			  ()))

As a sidenote - it is ok to not supply the else-part of an `if':


cl-user> (let ((items '("string" 'not-a-string)))
           (dolist (item items)
             (if (stringp item)
                 (write-line "found a string"))))
found a string
nil

..or to make it more clear that there is no else-part you can use `when':

cl-user> (let ((items '("string" 'not-a-string)))
           (dolist (item items)
             (when (stringp item)
               (write-line "found a string"))))
found a string
nil

-- 
Lars Rune Nøstdal
http://lars.nostdal.org/