From: Dave
Subject: [newbie] iterate over chars?
Date: 
Message-ID: <QWk1b.256874$Ny5.7883314@twister2.libero.it>
Hi lisper.

Does a function of this kind exist?

>(defun remove-chars (clist chars)                     
    (do ((px 0 (1+ px)))                                 
        ((>= px (length chars)) 'done)                   
        (setf clist (remove (string (char chars px)) 
                      clist :test 'equal))) clist) 

>(remove-chars (list "a" "b" "c" "a" "d" "e" "f") "afd")

>("b" "c" "e")


Help me to reduce this function using the power of Lisp. :-)

Thanks all in advance.
Dave

From: Christophe Rhodes
Subject: Re: [newbie] iterate over chars?
Date: 
Message-ID: <sq8ypm3vqc.fsf@lambda.jcn.srcf.net>
"Dave" <·········@iol.it> writes:

>>(defun remove-chars (clist chars)                     
>     (do ((px 0 (1+ px)))                                 
>         ((>= px (length chars)) 'done)                   
>         (setf clist (remove (string (char chars px)) 
>                       clist :test 'equal))) clist) 
>
>>(remove-chars (list "a" "b" "c" "a" "d" "e" "f") "afd")
>
>>("b" "c" "e")
>
> Help me to reduce this function using the power of Lisp. :-)

As you've defined the API:

(defun remove-chars (clist chars)
  (remove-if (lambda (x) (search x chars)) clist))

but note that a one-element string is not a character, so maybe

* (defun remove-chars* (clist chars)
    (remove-if (lambda (x) (find x chars)) clist))

REMOVE-CHARS*
* (remove-chars* (list #\a #\b #\c #\a #\d #\e #\f) "afd")

(#\b #\c #\e)
* (remove-chars* "abcadef" "afd")

"bce"

would be a better fit to your problem?

Christophe
-- 
http://www-jcsu.jesus.cam.ac.uk/~csr21/       +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%")    (pprint #36rJesusCollegeCambridge)
From: Dave
Subject: Re: [newbie] iterate over chars?
Date: 
Message-ID: <ISl1b.257031$Ny5.7886754@twister2.libero.it>
"Christophe Rhodes" <·····@cam.ac.uk> wrote:

> but note that a one-element string is not a character, so maybe
> 
> * (defun remove-chars* (clist chars)
>     (remove-if (lambda (x) (find x chars)) clist))
> 
> REMOVE-CHARS*
> * (remove-chars* (list #\a #\b #\c #\a #\d #\e #\f) "afd")
> 
> (#\b #\c #\e)
> * (remove-chars* "abcadef" "afd")
> 
> "bce"
> 
> would be a better fit to your problem?
> 

Excuse me,
I had forgotten to say that atoms can be greater than one character.

example: (list "a" "bx" "cam" "a" "d" "e" "f")


Greetings
Dave
From: Christophe Rhodes
Subject: Re: [newbie] iterate over chars?
Date: 
Message-ID: <sqzni22dq5.fsf@lambda.jcn.srcf.net>
"Dave" <·········@iol.it> writes:

> "Christophe Rhodes" <·····@cam.ac.uk> wrote:
>
>> but note that a one-element string is not a character, so maybe
>> 
>> * (defun remove-chars* (clist chars)
>>     (remove-if (lambda (x) (find x chars)) clist)) [...]
>
> Excuse me,
> I had forgotten to say that atoms can be greater than one character.
>
> example: (list "a" "bx" "cam" "a" "d" "e" "f")

You need to specify your problem more clearly, then, because it's
insufficiently obvious to me what you would like the return value of
  (remove-chars (list "a" "bx" "cam" "a" "d" "e" "f") "adf")
to be.  Try to articulate the algorithm you would like, not just the
return value in this particular case; then you'll be closer to being
able to write it yourself.

Christophe
-- 
http://www-jcsu.jesus.cam.ac.uk/~csr21/       +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%")    (pprint #36rJesusCollegeCambridge)
From: Dave
Subject: Re: [newbie] iterate over chars?
Date: 
Message-ID: <flr1b.257997$Ny5.7906014@twister2.libero.it>
"Christophe Rhodes" wrote:
 
> You need to specify your problem more clearly, then, because it's
> insufficiently obvious to me what you would like the return value of
>   (remove-chars (list "a" "bx" "cam" "a" "d" "e" "f") "adf")
> to be.  Try to articulate the algorithm you would like, not just the
> return value in this particular case; then you'll be closer to being
> able to write it yourself.
> 
> Christophe


Hi, 
I need to remove the punctuation from a user's typed sentence.
I'm writing a chatbot to learn Lisp.
An very very short explanation of my idea:
----------------------------------------------------------------

[step 1]

cl>;;(setq sentence (read-line))
cl>(setq sentence "how, are' you??")          ;;notice the typed punctuation errors!!

[step 2]

cl>(replace sentence "," " , ")                ;; another my function
cl>(replace sentence "'" " ' ")
cl>(replace sentence "?" " ? ")

cl>(print sentence)
cl>"how ,  are '  you ?  ? "

[step 3]

cl>(setq wlist (split-string sentence #\space))   ;; another my function..
cl>(setq result (last wlst))                      ;; save result

cl>(print wlist)
cl>("how" "," "are" "'" "you" "?" "?")

[step 4]

cl>(defun remove-chars (clist chars)              ;; new function
     (remove-if (lambda (x) (search x chars)) clist))

cl>(remove-chars wlist "?,';:.")

cl>(print wlist)
cl>("how" "are" "you")


That's all or almost.. :-)

----------------------------------------------------------------
Greetings
Dave
From: Ed Symanzik
Subject: Re: [newbie] iterate over chars?
Date: 
Message-ID: <bi5vpg$1c5q$1@msunews.cl.msu.edu>
Dave wrote:

> cl>(setq wlist (split-string sentence #\space))   ;; another my function..

This is almost there by itself.  Modify this function to take a string
of delimiters.

(spilt-string sentence " ?,';:.")
From: Ed Symanzik
Subject: Re: [newbie] iterate over chars?
Date: 
Message-ID: <bi62fk$1ev0$1@msunews.cl.msu.edu>
Ed Symanzik wrote:
> Dave wrote:
> 
>> cl>(setq wlist (split-string sentence #\space))   ;; another my 
>> function..
> 
> 
> This is almost there by itself.  Modify this function to take a string
> of delimiters.
> 
> (spilt-string sentence " ?,';:.")
> 

This is an awful abuse of loop.

(defun split-string (string &optional (delimiter " "))
   (loop for i = 0
         then (or (position-if (lambda (c) (not (find c delimiter)))
                               string :start (1+ j))
                  (loop-finish))
         as j = (position-if (lambda (c) (find c delimiter))
                             string :start i)
         collect (subseq string i j)
         while j))

 > (split-string "how, are' you??" " ?,';:.")
("how" "are" "you")
From: Dave
Subject: Re: [newbie] iterate over chars?
Date: 
Message-ID: <ppI1b.259672$Ny5.7961661@twister2.libero.it>
"Ed Symanzik" <···@msu.edu> ha scritto nel messaggio ··················@msunews.cl.msu.edu...
> Ed Symanzik wrote:
> > Dave wrote:
> > 
> >> cl>(setq wlist (split-string sentence #\space))   ;; another my 
> >> function..
> > 
> > 
> > This is almost there by itself.  Modify this function to take a string
> > of delimiters.
> > 
> > (spilt-string sentence " ?,';:.")
> > 
> 
> This is an awful abuse of loop.
> 
> (defun split-string (string &optional (delimiter " "))
>    (loop for i = 0
>          then (or (position-if (lambda (c) (not (find c delimiter)))
>                                string :start (1+ j))
>                   (loop-finish))
>          as j = (position-if (lambda (c) (find c delimiter))
>                              string :start i)
>          collect (subseq string i j)
>          while j))
> 
>  > (split-string "how, are' you??" " ?,';:.")
> ("how" "are" "you")
> 

This function seems very interesting!
I need to adapt it to Xlisp because I use it.

Thanks for your help!
Best regards
Dave
From: Matthieu Villeneuve
Subject: Re: [newbie] iterate over chars?
Date: 
Message-ID: <3f45dcd7$0$26413$626a54ce@news.free.fr>
"Dave" <·········@iol.it> wrote in message
·····························@twister2.libero.it...
> Hi lisper.
>
> Does a function of this kind exist?
>
> >(defun remove-chars (clist chars)
>     (do ((px 0 (1+ px)))
>         ((>= px (length chars)) 'done)
>         (setf clist (remove (string (char chars px))
>                       clist :test 'equal))) clist)

You can use REMOVE-IF:

(defun remove-chars (clist chars)
  (remove-if #'(lambda (c)
                 (position c chars :test #'string=))
             clist))


--
Matthieu Villeneuve
From: Dave
Subject: Re: [newbie] iterate over chars?
Date: 
Message-ID: <ISl1b.257032$Ny5.7886674@twister2.libero.it>
"Matthieu Villeneuve" <········@nospam.matthieu-villeneuve.net> ha
scritto nel messaggio
>
> (defun remove-chars (clist chars)
>   (remove-if #'(lambda (c)
>                  (position c chars :test #'string=))
>              clist))
>

Lambda?
I need to study on (lambda) again..

Greetings
Dave
From: Joe Marshall
Subject: Re: [newbie] iterate over chars?
Date: 
Message-ID: <u189hdhe.fsf@ccs.neu.edu>
"Dave" <·········@iol.it> writes:

> "Matthieu Villeneuve" <········@nospam.matthieu-villeneuve.net> ha
> scritto nel messaggio
>>
>> (defun remove-chars (clist chars)
>>   (remove-if #'(lambda (c)
>>                  (position c chars :test #'string=))
>>              clist))
>>
>
> Lambda?
> I need to study on (lambda) again..

Yes.

Think of REMOVE-IF as a template and the LAMBDA is
just a marker saying `don't evaluate this now, put
it in the template'.  

It is often useful to think of lambda as meaning
`don't do this now'.  (there are other aspects of it,
but get comfortable with this one).
From: Mario S. Mommer
Subject: Re: [newbie] iterate over chars?
Date: 
Message-ID: <fzu18aynf6.fsf@cupid.igpm.rwth-aachen.de>
"Dave" <·········@iol.it> writes:
> "Matthieu Villeneuve" <········@nospam.matthieu-villeneuve.net> ha
> scritto nel messaggio
> >
> > (defun remove-chars (clist chars)
> >   (remove-if #'(lambda (c)
> >                  (position c chars :test #'string=))
> >              clist))
> >
> 
> Lambda?
> I need to study on (lambda) again..

Well, it is as if he had written

(defun remove-chars (clist chars)
   (labels ((helper (c)
               (position c chars :test #'string=)))
   (remove-if #'helper clist))

but without giving the helper function a name.
From: Jacek Generowicz
Subject: Re: [newbie] iterate over chars?
Date: 
Message-ID: <tyfsmntc0jh.fsf@pcepsft001.cern.ch>
Mario S. Mommer <········@yahoo.com> writes:

> "Dave" <·········@iol.it> writes:
>
> > Lambda?
> > I need to study on (lambda) again..
> 
> Well, it is as if he had written
> 
> (defun remove-chars (clist chars)
>    (labels ((helper (c)
>                (position c chars :test #'string=)))
>    (remove-if #'helper clist))
> 
> but without giving the helper function a name.

Chances are that if he needs to study lambda again, then he'd need to
study labels again (or, probably, for the first time) :-)

It is as if he had written:

  (defun helper (c)
    (position c chars :test #'string=))

  (defun remove-chars (clist chars)
    (remove-if #'helper clist))

lambda is like saying "the function whole body looks as follows ..."
From: Dave
Subject: Re: [newbie] iterate over chars?
Date: 
Message-ID: <glr1b.257998$Ny5.7906086@twister2.libero.it>
"Jacek Generowicz" <················@cern.ch> wrote:

> Chances are that if he needs to study lambda again, then he'd need to
> study labels again (or, probably, for the first time) :-)
> 

probably.. ;-)

Dave
From: Janis Dzerins
Subject: Re: [newbie] iterate over chars?
Date: 
Message-ID: <twkptix6h2y.fsf@gulbis.latnet.lv>
"Matthieu Villeneuve" <········@nospam.matthieu-villeneuve.net> writes:

> "Dave" <·········@iol.it> wrote in message
> ·····························@twister2.libero.it...
> > Hi lisper.
> >
> > Does a function of this kind exist?
> >
> > >(defun remove-chars (clist chars)
> >     (do ((px 0 (1+ px)))
> >         ((>= px (length chars)) 'done)
> >         (setf clist (remove (string (char chars px))
> >                       clist :test 'equal))) clist)
> 
> You can use REMOVE-IF:
> 
> (defun remove-chars (clist chars)
>   (remove-if #'(lambda (c)
>                  (position c chars :test #'string=))
>              clist))

Am I missing something?  What's wrong with this:

(defun remove-chars (list chars)
  (remove-if #'(lambda (char)
                 (find char chars :test #'char=))
             list))

I.e. you don't have to convert characters to strings.

-- 
Janis Dzerins

  Common Lisp -- you get more than what you see.
From: Matthieu Villeneuve
Subject: Re: [newbie] iterate over chars?
Date: 
Message-ID: <3f461bf5$0$26436$626a54ce@news.free.fr>
"Janis Dzerins" <·····@latnet.lv> wrote in message
····················@gulbis.latnet.lv...
> "Matthieu Villeneuve" <········@nospam.matthieu-villeneuve.net> writes:
>
> > "Dave" <·········@iol.it> wrote in message
> > ·····························@twister2.libero.it...
> > > Hi lisper.
> > >
> > > Does a function of this kind exist?
> > >
> > > >(defun remove-chars (clist chars)
> > >     (do ((px 0 (1+ px)))
> > >         ((>= px (length chars)) 'done)
> > >         (setf clist (remove (string (char chars px))
> > >                       clist :test 'equal))) clist)
> >
> > You can use REMOVE-IF:
> >
> > (defun remove-chars (clist chars)
> >   (remove-if #'(lambda (c)
> >                  (position c chars :test #'string=))
> >              clist))
>
> Am I missing something?  What's wrong with this:
>
> (defun remove-chars (list chars)
>   (remove-if #'(lambda (char)
>                  (find char chars :test #'char=))
>              list))
>
> I.e. you don't have to convert characters to strings.

The way the problem was presented by the original post, LIST is a list of 1
character _strings_, so #'char= wouldn't work.

Anyway, I don't like my solution too much (I prefer Christophe's, using
SEARCH instead of POSITION), and the problem seems wrongly (or weirdly)
specified.


--
Matthieu Villeneuve
From: Frode Vatvedt Fjeld
Subject: Re: [newbie] iterate over chars?
Date: 
Message-ID: <2h7k56rqln.fsf@vserver.cs.uit.no>
"Dave" <·········@iol.it> writes:

> Hi lisper.
>
> Does a function of this kind exist?
>
>>(defun remove-chars (clist chars)                     
>     (do ((px 0 (1+ px)))                                 
>         ((>= px (length chars)) 'done)                   
>         (setf clist (remove (string (char chars px)) 
>                       clist :test 'equal))) clist) 
>

>>(remove-chars (list "a" "b" "c" "a" "d" "e" "f") "afd")
>
>>("b" "c" "e")
>
> Help me to reduce this function using the power of Lisp. :-)

Note that there's a difference between the string "a" and the
character #\a. What you're removing here are strings (of length one),
not really characters. So the problem as you state it does suggest
that perhaps you should reconsider how you represent things. That
said, your function is naturally expressed as

  (remove-if (lambda (c) (find (char c 0) "afd"))
             (list "a" "b" "c" "a" "d" "e" "f"))

=> ("b" "c" "e")

But, like I said, if you know you are working with characters, don't
use strings:

  (remove-if (lambda (c) (member c '(#\a #\f #\d)))
             (list #\a #\b #\c #\a #\d #\e #\f))

=> (#\b #\c #\e)

..but this is almost the same as:

  (set-difference (list #\a #\b #\c #\a #\d #\e #\f)
                  '(#\a #\f #\d))

=> (#\e #\c #\b)

-- 
Frode Vatvedt Fjeld
From: Rob Warnock
Subject: Re: [newbie] iterate over chars?
Date: 
Message-ID: <eAOdnS84irT0cNiiXTWc-w@speakeasy.net>
Frode Vatvedt Fjeld  <······@cs.uit.no> wrote:
+---------------
| "Dave" <·········@iol.it> writes:
| > Does a function of this kind exist?
| >>(defun remove-chars (clist chars)                     
...
| ... perhaps you should reconsider how you represent things.
| That said, your function is naturally expressed as
| 
|   (remove-if (lambda (c) (find (char c 0) "afd"))
|              (list "a" "b" "c" "a" "d" "e" "f"))
| 
| => ("b" "c" "e")
+---------------

Actually, since a string is a sequence too, what seems more natural
to me is:

	> (remove-if (lambda (c) (find c "afd"))
		     "abcadef")

	"bce"
	> 


-Rob

-----
Rob Warnock, PP-ASEL-IA		<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607