From: Slava Akhmechet
Subject: Improving coding style - lisp processing
Date: 
Message-ID: <87k5u965r0.fsf@gmail.com>
I repeatedly find myself in trouble when I need to do list processing
that involves dealing with multiple values at once. For example,
consider a function that takes an argument list and removes a
particular keyword parameter:

(remove-keyword-parameter '(1 :a 1 :b 2 :c 3) :b)
=> (1 :a 1 :c 3)

What's an elegant functional (and/or lispy) solution to this problem?
The solution I came up with is, IMO, very convoluted:

(defun remove-keyword-parameter (parameter-list keyword)
  (let (remove)
    (loop for i in parameter-list
          when (eql i keyword)
            do (setf remove t)
          else when remove
            do (setf remove nil)
          else unless remove
            collect i)))

Could someone suggest a better way?
            
-- 
Regards,
Slava Akhmechet.

From: Dan Bensen
Subject: Re: Improving coding style - lisp processing
Date: 
Message-ID: <f4lkf2$593$1@wildfire.prairienet.org>
Slava Akhmechet wrote:
> (remove-keyword-parameter '(1 :a 1 :b 2 :c 3) :b)
> => (1 :a 1 :c 3)
> What's an elegant functional (and/or lispy) solution to this problem?

This is a standard vanilla solution:

(defun remove-keyword-parameter (list keyword)
   (do ((target '())
        (source list (cdr source)))
       ((not source) (nreverse target))
       (let ((param (car source)))
         (if (eql param keyword)
             (setf source (cdr source))
           (push param target)))))

-- 
Dan
www.prairienet.org/~dsb/
From: choppa
Subject: Re: Improving coding style - lisp processing
Date: 
Message-ID: <1181646039.071640.225960@x35g2000prf.googlegroups.com>
On 12 Jun., 08:34, Slava Akhmechet <·········@gmail.com> wrote:
> I repeatedly find myself in trouble when I need to do list processing
> that involves dealing with multiple values at once. For example,
> consider a function that takes an argument list and removes a
> particular keyword parameter:
>
> (remove-keyword-parameter '(1 :a 1 :b 2 :c 3) :b)
> => (1 :a 1 :c 3)
>
> What's an elegant functional (and/or lispy) solution to this problem?
> The solution I came up with is, IMO, very convoluted:
>

How about some straightforward recursion?

(defun remove-keyword-parameter (alist key)
  (cond
    ((null alist) nil)
    ((not (keywordp (first alist)))  ;; as the list might as well
contain single variables
     (cons (first alist)
	   (remove-keyword-parameter (rest alist) key)))
    ((eq key (first alist))
     (remove-keyword-parameter (rest (rest alist)) key))
    (t (append (list (first alist) (second alist))
	       (remove-keyword-parameter (rest (rest alist)) key)))))

Cheers, Christoph
From: Rob St. Amant
Subject: Re: Improving coding style - lisp processing
Date: 
Message-ID: <f4m51d$98f$1@blackhelicopter.databasix.com>
Slava Akhmechet <·········@gmail.com> writes:

> I repeatedly find myself in trouble when I need to do list processing
> that involves dealing with multiple values at once. For example,
> consider a function that takes an argument list and removes a
> particular keyword parameter:
>
> (remove-keyword-parameter '(1 :a 1 :b 2 :c 3) :b)
> => (1 :a 1 :c 3)
>
> What's an elegant functional (and/or lispy) solution to this problem?
> The solution I came up with is, IMO, very convoluted:
>
> (defun remove-keyword-parameter (parameter-list keyword)
>   (let (remove)
>     (loop for i in parameter-list
>           when (eql i keyword)
>             do (setf remove t)
>           else when remove
>             do (setf remove nil)
>           else unless remove
>             collect i)))
>
> Could someone suggest a better way?

No one has yet suggested this (which may indicate it's problematic in
some way), but here's a quick and dirty solution:

(defun remove-keyword-parameter (parameter-list keyword)
  (let ((copy (copy-list parameter-list)))
    (remf (rest copy) keyword)
    copy))

This has the advantage over the function above of handling cases in
which the same list elements can be appear as keys or values.
From: Leandro Rios
Subject: Re: Improving coding style - lisp processing
Date: 
Message-ID: <466e8fc5$0$1346$834e42db@reader.greatnowhere.com>
> 
> Could someone suggest a better way?
>             

I like recursion:

(defun remove-keyword-parameter (parameters keyword)
   (cond ((null parameters) nil)
	((eq (car parameters) keyword) (remove-keyword-parameter
					(cddr parameters) keyword))
	(t (cons (car parameters)
		 (remove-keyword-parameter (cdr parameters) keyword)))))
From: Pascal Costanza
Subject: Re: Improving coding style - lisp processing
Date: 
Message-ID: <5d70n0F31je6rU1@mid.individual.net>
Slava Akhmechet wrote:
> I repeatedly find myself in trouble when I need to do list processing
> that involves dealing with multiple values at once. For example,
> consider a function that takes an argument list and removes a
> particular keyword parameter:
> 
> (remove-keyword-parameter '(1 :a 1 :b 2 :c 3) :b)
> => (1 :a 1 :c 3)
> 
> What's an elegant functional (and/or lispy) solution to this problem?
> The solution I came up with is, IMO, very convoluted:
> 
> (defun remove-keyword-parameter (parameter-list keyword)
>   (let (remove)
>     (loop for i in parameter-list
>           when (eql i keyword)
>             do (setf remove t)
>           else when remove
>             do (setf remove nil)
>           else unless remove
>             collect i)))
> 
> Could someone suggest a better way?

(loop for (key value) on plist by #'cddr
       unless (eql key keyword)
       nconc (list key value))


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Leandro Rios
Subject: Re: Improving coding style - lisp processing
Date: 
Message-ID: <466e910d$0$1349$834e42db@reader.greatnowhere.com>
Pascal Costanza escribi�:
> Slava Akhmechet wrote:
>>
>> Could someone suggest a better way?
> 
> (loop for (key value) on plist by #'cddr
>       unless (eql key keyword)
>       nconc (list key value))
> 
> 
> Pascal
> 

Hi,

It's nice, but it won't work with the test case the OP posted, because 
the first parameter is not a plist:

(defun remove-keyword-parameter (plist keyword)
   (loop for (key value) on plist by #'cddr
	unless (eql key keyword)
	nconc (list key value)))

CL-USER> (remove-keyword-parameter '(1 :a 1 :b 2 :c 3) :b)
(1 :A 1 :B 2 :C 3 NIL)

Leandro
From: Pascal Costanza
Subject: Re: Improving coding style - lisp processing
Date: 
Message-ID: <5d7m84F33g1v0U1@mid.individual.net>
Leandro Rios wrote:
> Pascal Costanza escribi�:
>> Slava Akhmechet wrote:
>>>
>>> Could someone suggest a better way?
>>
>> (loop for (key value) on plist by #'cddr
>>       unless (eql key keyword)
>>       nconc (list key value))
>>
>>
>> Pascal
>>
> 
> Hi,
> 
> It's nice, but it won't work with the test case the OP posted, because 
> the first parameter is not a plist:
> 
> (defun remove-keyword-parameter (plist keyword)
>   (loop for (key value) on plist by #'cddr
>     unless (eql key keyword)
>     nconc (list key value)))
> 
> CL-USER> (remove-keyword-parameter '(1 :a 1 :b 2 :c 3) :b)
> (1 :A 1 :B 2 :C 3 NIL)

(loop for (key value) on (cdr plist) by #'cddr
       unless (eql key keyword)
       nconc (list key value))


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Nicolas Neuss
Subject: Re: Improving coding style - lisp processing
Date: 
Message-ID: <87ir9teh9o.fsf@ma-patru.mathematik.uni-karlsruhe.de>
Slava Akhmechet <·········@gmail.com> writes:

> (remove-keyword-parameter '(1 :a 1 :b 2 :c 3) :b)
> => (1 :a 1 :c 3)
> 
> What's an elegant functional (and/or lispy) solution to this problem?
> The solution I came up with is, IMO, very convoluted:

Not simple, but efficient:

http://groups.google.de/group/comp.lang.lisp/browse_thread/thread/4e8451c55102f4df/2520fe9bc7749328?lnk=gst&q=naggum+sans+macro&rnum=1&hl=de#2520fe9bc7749328

Yours, Nicolas
From: Nicolas Neuss
Subject: Re: Improving coding style - lisp processing
Date: 
Message-ID: <87ejkhegyi.fsf@ma-patru.mathematik.uni-karlsruhe.de>
Nicolas Neuss <········@mathematik.uni-karlsruhe.de> writes:

> http://groups.google.de/group/comp.lang.lisp.. (very long)

And this link does  probably work better:

http://groups.google.de/group/comp.lang.lisp/msg/2520fe9bc7749328

Nicolas
From: Alan Crowe
Subject: Re: Improving coding style - lisp processing
Date: 
Message-ID: <86bqflfbfg.fsf@cawtech.freeserve.co.uk>
Slava Akhmechet <·········@gmail.com> writes:

> I repeatedly find myself in trouble when I need to do list processing
> that involves dealing with multiple values at once. For example,
> consider a function that takes an argument list and removes a
> particular keyword parameter:
> 
> (remove-keyword-parameter '(1 :a 1 :b 2 :c 3) :b)
> => (1 :a 1 :c 3)
> 
> What's an elegant functional (and/or lispy) solution to this problem?

Here is a CL industrial grime solution that uses an obscure
but standard function.

CL-USER> (defun omit (key plist)
           (multiple-value-bind (key value tail)
               (get-properties plist (list key))
               (declare (ignore key value))
             (append (ldiff plist tail)
                     (cddr tail))))
OMIT

CL-USER> (omit :b '(:A 1 :b 2 :c 3))
(:A 1 :C 3)

Alan Crowe
Edinburgh
Scotland
From: Vassil Nikolov
Subject: Re: Improving coding style - lisp processing
Date: 
Message-ID: <kabqfksnp7.fsf@localhost.localdomain>
On Tue, 12 Jun 2007 06:34:11 GMT, Slava Akhmechet <·········@gmail.com> said:
| ...
| consider a function that takes an argument list and removes a
| particular keyword parameter:

| (remove-keyword-parameter '(1 :a 1 :b 2 :c 3) :b)
| => (1 :a 1 :c 3)

  1. How is it determined where the keyword parameters start?

  2. What do e.g. the following return:
     (remove-keyword-parameter '(:b :a 1 :b 2 :c 3) :b)
     (remove-keyword-parameter '(1 :a 1 :b) :b)
     (remove-keyword-parameter '(:b :b 2 :c 3) :b)

  ---Vassil.


-- 
The truly good code is the obviously correct code.
From: Kent M Pitman
Subject: Re: Improving coding style - lisp processing
Date: 
Message-ID: <u1wgga92v.fsf@nhplace.com>
Vassil Nikolov <···············@pobox.com> writes:

> On Tue, 12 Jun 2007 06:34:11 GMT, Slava Akhmechet <·········@gmail.com> said:
> | ...
> | consider a function that takes an argument list and removes a
> | particular keyword parameter:
> 
> | (remove-keyword-parameter '(1 :a 1 :b 2 :c 3) :b)
> | => (1 :a 1 :c 3)
> 
>   1. How is it determined where the keyword parameters start?
> 
>   2. What do e.g. the following return:
>      (remove-keyword-parameter '(:b :a 1 :b 2 :c 3) :b)
>      (remove-keyword-parameter '(1 :a 1 :b) :b)
>      (remove-keyword-parameter '(:b :b 2 :c 3) :b)

Wow, I'm glad someone finally noticed this!  I couldn't believe
everyone was just talking past it.  Not that it's not hard to come up with
a theory, but you're right that there are several ways it could be done.

Incidentally, as an aside, it's worth mentioning just for counterpoint
that the following result is kind of fun even though only partly on-topic.
This isn't offered as a real solution so much as a chance to provoke a few
people who don't know about this feature to read up on it for the few cases
where it would work:

 (defun lazy-alternative-to-removing-keyword-parameter (parameter-list keyword)
   (declare (ignore keyword))
   (list* :allow-other-keys t parameter-list))

Using that as a base, and going back to the questions Vassil asks:

The stated example had a 1 at the start of the list, suggesting there
were some preceding arguments.  So I'm assuming the so-called
parameter-list is really "the list of keyword parameters after you've
cdr'd past the non-keyword ones".)  To really handle that, you'd want,
at minimum some way to know how many positional args; the easy way is
just to pass that as an argument, and in most cases that'd be fine.
(The only alternative that springs to mind other than that is to take
and interpret an arglist, but that's a minor pain and in fact overkill
given the information this really needs is much simpler.)

 (defun lazy-alternative-to-removing-keyword-parameter (parameter-list keyword
                                                        &optional (offset 0))
   (declare (ignore keyword))
   (append (firstn offset parameter-list)
           (list* :allow-other-keys t (nthcdr offset parameter-list))))

if only you had a firstn function.  But I'm sure that's easy enough
for people to crank out (if they don't already have it in a personal
library) that it's not worth showing here.

There's a way to do this with a single loop statement, too, but I'll
spare you.  Gotta leave something to the imagination.

Even if you think I'm cheating by using :allow-other-keys, at least
the offset technique can be used for skipping the other args.
From: Dan Bensen
Subject: Re: Improving coding style - lisp processing
Date: 
Message-ID: <f4okdl$44v$1@wildfire.prairienet.org>
Kent M Pitman wrote:
> Vassil Nikolov <···············@pobox.com> writes:
>> On Tue, 12 Jun 2007 06:34:11 GMT, Slava Akhmechet <·········@gmail.com> said:
>> | consider a function that takes an argument list and removes a
>> | particular keyword parameter
>>   2. What do e.g. the following return:
>>      (remove-keyword-parameter '(:b :a 1 :b 2 :c 3) :b)
>>      (remove-keyword-parameter '(1 :a 1 :b) :b)
>>      (remove-keyword-parameter '(:b :b 2 :c 3) :b)
> 
> Wow, I'm glad someone finally noticed this!  I couldn't believe
> everyone was just talking past it.

Actually, all of the non-plist responses work as long as
the target keyword is followed by a value, and it's easy
to add a case for no value.

-- 
Dan
www.prairienet.org/~dsb/
From: Vassil Nikolov
Subject: Re: Improving coding style - lisp processing
Date: 
Message-ID: <kabqfiugvc.fsf@localhost.localdomain>
On Wed, 13 Jun 2007 06:34:56 -0500, Dan Bensen <··········@cyberspace.net> said:

| Kent M Pitman wrote:
|| Vassil Nikolov <···············@pobox.com> writes:
||| On Tue, 12 Jun 2007 06:34:11 GMT, Slava Akhmechet <·········@gmail.com> said:
||| | consider a function that takes an argument list and removes a
||| | particular keyword parameter
||| 2. What do e.g. the following return:
||| (remove-keyword-parameter '(:b :a 1 :b 2 :c 3) :b)
||| (remove-keyword-parameter '(1 :a 1 :b) :b)
||| (remove-keyword-parameter '(:b :b 2 :c 3) :b)
|| Wow, I'm glad someone finally noticed this!  I couldn't believe
|| everyone was just talking past it.

| Actually, all of the non-plist responses work as long as
| the target keyword is followed by a value, and it's easy
| to add a case for no value.

  Well, perhaps they do, but I'd still like to know exactly what it
  means for them to work in this context.  The half dozen or so
  implementations that were posted do not all produce equal results
  for all cases, but that may or may not matter depending on the
  description of the problem.  This obviously relates also to Kent
  Pitman's post about describing a problem separately from describing
  a (suggested) solution.

  ---Vassil.


-- 
The truly good code is the obviously correct code.