From: Robert Strandh
Subject: Q: what idiom for inserting an element in a list
Date: 
Message-ID: <85d6sqbug5.fsf@eta.emi.u-bordeaux.fr>
Hello,

I am looking for an idiom for inserting an element (let's say
destructively) at a certain position in a list.  Even better, to
splice in a list at a certain position in an other list.  

For instance:

* (setf *l* (list 1 2 3 4 5 6 7))

(1 2 3 4 5 6 7)
* (insert-by-position 'a *l* 3)

(1 2 3 A 4 5 6 7)
* *l*

(1 2 3 A 4 5 6 7)
*

Is there an existing idiom that I should use?

-- 
Robert Strandh

From: Kent M Pitman
Subject: Re: Q: what idiom for inserting an element in a list
Date: 
Message-ID: <sfw7kiy8uq8.fsf@shell01.TheWorld.com>
Robert Strandh <·······@labri.u-bordeaux.fr> writes:

> Hello,
> 
> I am looking for an idiom for inserting an element (let's say
> destructively) at a certain position in a list.  Even better, to
> splice in a list at a certain position in an other list.  
> 
> For instance:
> 
> * (setf *l* (list 1 2 3 4 5 6 7))
> 
> (1 2 3 4 5 6 7)
> * (insert-by-position 'a *l* 3)
> 
> (1 2 3 A 4 5 6 7)
> * *l*
> 
> (1 2 3 A 4 5 6 7)
> *
> 
> Is there an existing idiom that I should use?

Don't look for idioms.

Make functions.

If you later find your function can be implemented more efficiently, do so
centrally.  But don't make clever use of some idiomatic thing to avoid writing
a function with a useful name.

[Incidentally, don't expect that insertion can work by side-effect.  
 Insertion at position 0 will not be able to.  Always do
   (setq *l* (insert-by-position 'a *l* 3))
 and make sure INSERT-BY-POSITION returns the right value to make this work.
 (Although you might want to check out DEFINE-MODIFY-MACRO if you want a
 macro interface.)]
From: Robert Strandh
Subject: Re: Q: what idiom for inserting an element in a list
Date: 
Message-ID: <854re1ivlz.fsf@eta.emi.u-bordeaux.fr>
Kent M Pitman <······@world.std.com> writes:

> Don't look for idioms.
> 
> Make functions.

I was thinking of doing both.  Writing a function that uses the
idiom. 

> If you later find your function can be implemented more efficiently, do so
> centrally.  But don't make clever use of some idiomatic thing to avoid writing
> a function with a useful name.

Sure.

> [Incidentally, don't expect that insertion can work by side-effect.  
>  Insertion at position 0 will not be able to.  Always do
>    (setq *l* (insert-by-position 'a *l* 3))
>  and make sure INSERT-BY-POSITION returns the right value to make this work.

Yes, I actually knew that.  Thanks. 
-- 
Robert Strandh
From: Tim Moore
Subject: Re: Q: what idiom for inserting an element in a list
Date: 
Message-ID: <aj4tm6$hgm$0@216.39.145.192>
On 10 Aug 2002 17:32:42 +0200, Robert Strandh <·······@labri.u-bordeaux.fr> 
wrote:
>Hello,
>
>I am looking for an idiom for inserting an element (let's say
>destructively) at a certain position in a list.  Even better, to
>splice in a list at a certain position in an other list.  
>
>For instance:
>
>* (setf *l* (list 1 2 3 4 5 6 7))
>
>(1 2 3 4 5 6 7)
>* (insert-by-position 'a *l* 3)
>
>(1 2 3 A 4 5 6 7)
>* *l*
>
>(1 2 3 A 4 5 6 7)
>*
>
>Is there an existing idiom that I should use?

Idiomatic or not, here's what I'd do:

(defun insert-by-position (val list pos)
  (if (zerop pos)
      (cons val list)
    (let ((old-tail (nthcdr (1- pos) list)))
      (setf (cdr old-tail) (cons val (cdr old-tail)))
      list)))

Tim
From: Pascal Bourguignon
Subject: Re: Q: what idiom for inserting an element in a list
Date: 
Message-ID: <87znvtrdkd.fsf@thalassa.informatimago.com>
······@sea-tmoore-l.dotcast.com (Tim Moore) writes:

> On 10 Aug 2002 17:32:42 +0200, Robert Strandh <·······@labri.u-bordeaux.fr> 
> wrote:
> >Hello,
> >
> >I am looking for an idiom for inserting an element (let's say
> >destructively) at a certain position in a list.  Even better, to
> >splice in a list at a certain position in an other list.  
> >
> >For instance:
> >
> >* (setf *l* (list 1 2 3 4 5 6 7))
> >
> >(1 2 3 4 5 6 7)
> >* (insert-by-position 'a *l* 3)
> >
> >(1 2 3 A 4 5 6 7)
> >* *l*
> >
> >(1 2 3 A 4 5 6 7)
> >*
> >
> >Is there an existing idiom that I should use?
> 
> Idiomatic or not, here's what I'd do:
> 
> (defun insert-by-position (val list pos)
>   (if (zerop pos)
>       (cons val list)
>     (let ((old-tail (nthcdr (1- pos) list)))
>       (setf (cdr old-tail) (cons val (cdr old-tail)))
>       list)))
> 
> Tim

Which is  not very regular: 

    - (insert-by-position 'A '(1 2 3) 2) won't work generaly (you
      can't change the cdr of a literal list such as '(1 2 3)).

    - (insert-by-position 'A *l* 0) does not change *l* while
      (insert-by-position 'A *l* 1) does. This is quite gratuitous.
    

Personnaly, I prefer:

(defun insert-by-position-r (val list pos)
  (if (= pos 0) 
      (cons val list) 
    (cons (car list) (insert-by-position val (cdr list) (1- pos))))
  );;insert-by-position

To be used as:  (setq new-list (insert-by-position-r (val old-list pos)))
Otherwise, a macro is in order, to handle the case val=0.

  
-- 
__Pascal_Bourguignon__                   http://www.informatimago.com/
----------------------------------------------------------------------
From: Joel Ray Holveck
Subject: Re: Q: what idiom for inserting an element in a list
Date: 
Message-ID: <y7cadntem0m.fsf@sindri.juniper.net>
>> (defun insert-by-position (val list pos)
[snip]
> Which is  not very regular: 
>     - (insert-by-position 'A '(1 2 3) 2) won't work generaly (you
>       can't change the cdr of a literal list such as '(1 2 3)).
>     - (insert-by-position 'A *l* 0) does not change *l* while
>       (insert-by-position 'A *l* 1) does. This is quite gratuitous.
[snip]
> Personnaly, I prefer:
> (defun insert-by-position-r (val list pos)
[snip]

The situation is no different with SORT, or any other destructive
function.

However, we now have an implementation of both INSERT-BY-POSITION and
NINSERT-BY-POSITION (renamed for regularity with most other CL
destructive functions), and the user can use whichever he finds most
appropriate-- remembering all the normal caveats associated with
destructive functions.

joelh
From: Robert Strandh
Subject: Re: Q: what idiom for inserting an element in a list
Date: 
Message-ID: <857kixivqn.fsf@eta.emi.u-bordeaux.fr>
Pascal Bourguignon <·············@example.com> writes:

> ······@sea-tmoore-l.dotcast.com (Tim Moore) writes:
>
> > (defun insert-by-position (val list pos)
> >   (if (zerop pos)
> >       (cons val list)
> >     (let ((old-tail (nthcdr (1- pos) list)))
> >       (setf (cdr old-tail) (cons val (cdr old-tail)))
> >       list)))
> > 
> > Tim
> 
> Which is  not very regular: 
> 
>     - (insert-by-position 'A '(1 2 3) 2) won't work generaly (you
>       can't change the cdr of a literal list such as '(1 2 3)).
> 
>     - (insert-by-position 'A *l* 0) does not change *l* while
>       (insert-by-position 'A *l* 1) does. This is quite gratuitous.

Tim's solution is `destructive' (which means exactly that you can't
change literals and that it has this `gratuitous' behavior), which is
what I asked for.  

-- 
Robert Strandh
From: Robert Strandh
Subject: Re: Q: what idiom for inserting an element in a list
Date: 
Message-ID: <85adntivz3.fsf@eta.emi.u-bordeaux.fr>
······@sea-tmoore-l.dotcast.com (Tim Moore) writes:

> Idiomatic or not, here's what I'd do:
> 
> (defun insert-by-position (val list pos)
>   (if (zerop pos)
>       (cons val list)
>     (let ((old-tail (nthcdr (1- pos) list)))
>       (setf (cdr old-tail) (cons val (cdr old-tail)))
>       list)))

OK, that's very close to the one I finally settled on.  Though, I used 
`push' instead of `setf'.

Thanks,
-- 
Robert Strandh
From: Hrvoje Niksic
Subject: Re: Q: what idiom for inserting an element in a list
Date: 
Message-ID: <sxs7kiwhlbi.fsf@florida.munich.redhat.com>
Robert Strandh <·······@labri.u-bordeaux.fr> writes:

> Hello,
>
> I am looking for an idiom for inserting an element (let's say
> destructively) at a certain position in a list.  Even better, to
> splice in a list at a certain position in an other list.  
>
> For instance:
>
> * (setf *l* (list 1 2 3 4 5 6 7))
>
> (1 2 3 4 5 6 7)
> * (insert-by-position 'a *l* 3)
>
> (1 2 3 A 4 5 6 7)
> * *l*
>
> (1 2 3 A 4 5 6 7)
> *
>
> Is there an existing idiom that I should use?

Hardly idiomatic, but my first impulse was to try something like this:

    (push 'a (nthcdr 3 *l*))

But Common Lisp doesn't seem to define a SETF method for NTHCDR.  I
wonder why?  Emacs's `cl.el' defines it, and this example works there.
From: Erik Naggum
Subject: Re: Q: what idiom for inserting an element in a list
Date: 
Message-ID: <3238123557311163@naggum.no>
* Hrvoje Niksic <·······@xemacs.org>
| Hardly idiomatic, but my first impulse was to try something like this:
| 
|     (push 'a (nthcdr 3 *l*))
| 
| But Common Lisp doesn't seem to define a SETF method for NTHCDR.  I
| wonder why?  Emacs's `cl.el' defines it, and this example works there.

  You would of course use (setf (cdr (nthcdr ...)) ...).

-- 
Erik Naggum, Oslo, Norway

Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.
From: Barry Margolin
Subject: Re: Q: what idiom for inserting an element in a list
Date: 
Message-ID: <7ZP59.3$h1.1784@paloalto-snr1.gtei.net>
In article <················@naggum.no>, Erik Naggum  <····@naggum.no> wrote:
>* Hrvoje Niksic <·······@xemacs.org>
>| Hardly idiomatic, but my first impulse was to try something like this:
>| 
>|     (push 'a (nthcdr 3 *l*))
>| 
>| But Common Lisp doesn't seem to define a SETF method for NTHCDR.  I
>| wonder why?  Emacs's `cl.el' defines it, and this example works there.
>
>  You would of course use (setf (cdr (nthcdr ...)) ...).

Except that doesn't work for the 0 case.  If SETF of NTHCDR were defined,
it could expand (setf (nthcdr n l) x) into:

(if (zerop n)
    (setf l x)
    (setf (cdr (nthcdr (1- n))) x))

(with appropriate stuff to fix order of evaluation and prevent multiple
evaluation, of course), rather than requiring the user to special case 0.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.