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.
Robert Strandh <stra...@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.
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.)]
>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)))
tmo...@sea-tmoore-l.dotcast.com (Tim Moore) writes: > On 10 Aug 2002 17:32:42 +0200, Robert Strandh <stra...@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.
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
> - (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.
>> (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.
Robert Strandh <stra...@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.
* Hrvoje Niksic <hnik...@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.
In article <3238123557311...@naggum.no>, Erik Naggum <e...@naggum.no> wrote:
>* Hrvoje Niksic <hnik...@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:
(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, bar...@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.