all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Setting the nth element of a list
@ 2009-06-04 21:08 Nordlöw
  2009-06-04 22:06 ` Drew Adams
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Nordlöw @ 2009-06-04 21:08 UTC (permalink / raw)
  To: help-gnu-emacs

This simple example changes the second element in the list x:

(setq x '(a nil c))
(setcar (cdr x 'b)

How do I generalize this to a function that sets (changes) the nth
element of a list (for side effects only)?

Thanks in advance,
Nordlöw


^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: Setting the nth element of a list
  2009-06-04 21:08 Setting the nth element of a list Nordlöw
@ 2009-06-04 22:06 ` Drew Adams
  2009-06-04 22:35 ` Lennart Borgman
  2009-06-05  2:25 ` Barry Margolin
  2 siblings, 0 replies; 12+ messages in thread
From: Drew Adams @ 2009-06-04 22:06 UTC (permalink / raw)
  To: 'Nordlöw', help-gnu-emacs

> (setcar (cdr x 'b)
> 
> How do I generalize this to a function that sets (changes) the nth
> element of a list (for side effects only)?

Use setcar with nthcdr.





^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Setting the nth element of a list
  2009-06-04 21:08 Setting the nth element of a list Nordlöw
  2009-06-04 22:06 ` Drew Adams
@ 2009-06-04 22:35 ` Lennart Borgman
  2009-06-05  2:25 ` Barry Margolin
  2 siblings, 0 replies; 12+ messages in thread
From: Lennart Borgman @ 2009-06-04 22:35 UTC (permalink / raw)
  To: Nordlöw; +Cc: help-gnu-emacs

Use nthcdr

On Thu, Jun 4, 2009 at 11:08 PM, Nordlöw <per.nordlow@gmail.com> wrote:
> This simple example changes the second element in the list x:
>
> (setq x '(a nil c))
> (setcar (cdr x 'b)
>
> How do I generalize this to a function that sets (changes) the nth
> element of a list (for side effects only)?
>
> Thanks in advance,
> Nordlöw
>




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Setting the nth element of a list
  2009-06-04 21:08 Setting the nth element of a list Nordlöw
  2009-06-04 22:06 ` Drew Adams
  2009-06-04 22:35 ` Lennart Borgman
@ 2009-06-05  2:25 ` Barry Margolin
  2009-06-05 13:06   ` Nordlöw
  2 siblings, 1 reply; 12+ messages in thread
From: Barry Margolin @ 2009-06-05  2:25 UTC (permalink / raw)
  To: help-gnu-emacs

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 612 bytes --]

In article 
<8a7c4d36-195d-4517-827e-7fbeca7ae03f@r34g2000vba.googlegroups.com>,
 Nordlöw <per.nordlow@gmail.com> wrote:

> This simple example changes the second element in the list x:
> 
> (setq x '(a nil c))
> (setcar (cdr x 'b)
> 
> How do I generalize this to a function that sets (changes) the nth
> element of a list (for side effects only)?
> 
> Thanks in advance,
> Nordlöw

(require 'cl-macs)
(setf (nth n x) 'b)

-- 
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Setting the nth element of a list
  2009-06-05  2:25 ` Barry Margolin
@ 2009-06-05 13:06   ` Nordlöw
  2009-06-05 13:10     ` Nordlöw
  2009-06-05 20:51     ` Barry Margolin
  0 siblings, 2 replies; 12+ messages in thread
From: Nordlöw @ 2009-06-05 13:06 UTC (permalink / raw)
  To: help-gnu-emacs

On Jun 5, 4:25 am, Barry Margolin <bar...@alum.mit.edu> wrote:
> In article
> <8a7c4d36-195d-4517-827e-7fbeca7ae...@r34g2000vba.googlegroups.com>,
>
>  Nordlöw <per.nord...@gmail.com> wrote:
> > This simple example changes the second element in the list x:
>
> > (setq x '(a nil c))
> > (setcar (cdr x 'b)
>
> > How do I generalize this to a function that sets (changes) the nth
> > element of a list (for side effects only)?
>
> > Thanks in advance,
> > Nordlöw
>
> (require 'cl-macs)
> (setf (nth n x) 'b)
>
> --
> Barry Margolin, bar...@alum.mit.edu
> Arlington, MA
> *** PLEASE post questions in newsgroups, not directly to me ***
> *** PLEASE don't copy me on replies, I'll read them in the group ***

Okey, here is my solution:

(defun setnthcar (n list x)
  "Set N:th element of LIST to X for side effects only."
  (setcar (nthcdr n list) x))

Comments on that?

How do I accomplish the same with arrays? Using aref I guess. Here is
my mockup that doesn't yet do what I want:

(defun setnthref (n array x)
  "Set N:th element of ARRAY to X for side effects only."
  (set (aref array n) x))

Thanks in advance,
Nordlöw


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Setting the nth element of a list
  2009-06-05 13:06   ` Nordlöw
@ 2009-06-05 13:10     ` Nordlöw
  2009-06-05 13:25       ` Pascal J. Bourguignon
  2009-06-05 20:51     ` Barry Margolin
  1 sibling, 1 reply; 12+ messages in thread
From: Nordlöw @ 2009-06-05 13:10 UTC (permalink / raw)
  To: help-gnu-emacs

On Jun 5, 3:06 pm, Nordlöw <per.nord...@gmail.com> wrote:
> On Jun 5, 4:25 am, Barry Margolin <bar...@alum.mit.edu> wrote:
>
>
>
> > In article
> > <8a7c4d36-195d-4517-827e-7fbeca7ae...@r34g2000vba.googlegroups.com>,
>
> >  Nordlöw <per.nord...@gmail.com> wrote:
> > > This simple example changes the second element in the list x:
>
> > > (setq x '(a nil c))
> > > (setcar (cdr x 'b)
>
> > > How do I generalize this to a function that sets (changes) the nth
> > > element of a list (for side effects only)?
>
> > > Thanks in advance,
> > > Nordlöw
>
> > (require 'cl-macs)
> > (setf (nth n x) 'b)
>
> > --
> > Barry Margolin, bar...@alum.mit.edu
> > Arlington, MA
> > *** PLEASE post questions in newsgroups, not directly to me ***
> > *** PLEASE don't copy me on replies, I'll read them in the group ***
>
> Okey, here is my solution:
>
> (defun setnthcar (n list x)
>   "Set N:th element of LIST to X for side effects only."
>   (setcar (nthcdr n list) x))
>
> Comments on that?
>
> How do I accomplish the same with arrays? Using aref I guess. Here is
> my mockup that doesn't yet do what I want:
>
> (defun setnthref (n array x)
>   "Set N:th element of ARRAY to X for side effects only."
>   (set (aref array n) x))
>
> Thanks in advance,
> Nordlöw

Okey I found a solution:

(defun setnthref (n array x)
  "Set N:th element of ARRAY to X for side effects only."
  (setf (aref array n) x))
;; (equal (let ((l '[a b c])) (setnthref 1 l 'B) l) '[a B c])

Is this the most efficient way? I see that setf() is quite
complicated.

/Nordlöw


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Setting the nth element of a list
  2009-06-05 13:10     ` Nordlöw
@ 2009-06-05 13:25       ` Pascal J. Bourguignon
  2009-06-05 13:57         ` Nordlöw
  0 siblings, 1 reply; 12+ messages in thread
From: Pascal J. Bourguignon @ 2009-06-05 13:25 UTC (permalink / raw)
  To: help-gnu-emacs

Nordlöw <per.nordlow@gmail.com> writes:

> On Jun 5, 3:06 pm, Nordlöw <per.nord...@gmail.com> wrote:
>> On Jun 5, 4:25 am, Barry Margolin <bar...@alum.mit.edu> wrote:
>>
>>
>>
>> > In article
>> > <8a7c4d36-195d-4517-827e-7fbeca7ae...@r34g2000vba.googlegroups.com>,
>>
>> >  Nordlöw <per.nord...@gmail.com> wrote:
>> > > This simple example changes the second element in the list x:
>>
>> > > (setq x '(a nil c))
>> > > (setcar (cdr x 'b)
>>
>> > > How do I generalize this to a function that sets (changes) the nth
>> > > element of a list (for side effects only)?
>>
>> > > Thanks in advance,
>> > > Nordlöw
>>
>> > (require 'cl-macs)
>> > (setf (nth n x) 'b)
>>
>>
>> Okey, here is my solution:
>>
>> (defun setnthcar (n list x)
>>   "Set N:th element of LIST to X for side effects only."
>>   (setcar (nthcdr n list) x))
>>
>> Comments on that?

It's awful, since there's is already a more standard and more general
mechanism to do that: (setf (nth n x) 'b)


>> How do I accomplish the same with arrays? Using aref I guess. Here is
>> my mockup that doesn't yet do what I want:
>>
>> (defun setnthref (n array x)
>>   "Set N:th element of ARRAY to X for side effects only."
>>   (set (aref array n) x))
>>
>> Thanks in advance,
>> Nordlöw
>
> Okey I found a solution:
>
> (defun setnthref (n array x)
>   "Set N:th element of ARRAY to X for side effects only."
>   (setf (aref array n) x))
> ;; (equal (let ((l '[a b c])) (setnthref 1 l 'B) l) '[a B c])
>
> Is this the most efficient way? I see that setf() is quite
> complicated.

Setf is a macro that is quite complicated, but it generates the best
code to properly update a place.

(require 'cl)
(macroexpand '(setf (aref (aref (nth (incf a) list-of-arrays) (incf i)) n) 42))
-->
(let* ((#1=--cl-var-- (aref (nth (incf a) list-of-arrays) (incf i)))
       (#2=--cl-var-- n))
  (aset #1# #2# 42))

There's nothing more efficient to set an array than aset.
Once you've found the array to set...

So there's no need to define a setnthref for an array, since (setf
(aref a n) v) does the job better.


There's also no need to define a setnthcar for a list, since (setf
(nth l n) v) does the job better.


And if you don't know whether you have a list or a vector, there's no
need to define anything, since (setf (elt sequence n) v) works better.

(let (x)
   (setf (elt (setf x (funcall (if (oddp (random 2))
                                   (function list)
                                   (function vector)) 
                               1 2 3))
               1) 
         0)
   x)
--> [1 0 3] or (1 0 3)


-- 
__Pascal Bourguignon__


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Setting the nth element of a list
  2009-06-05 13:25       ` Pascal J. Bourguignon
@ 2009-06-05 13:57         ` Nordlöw
  2009-06-05 15:08           ` Pascal J. Bourguignon
  2009-06-05 16:56           ` bigfaceworm
  0 siblings, 2 replies; 12+ messages in thread
From: Nordlöw @ 2009-06-05 13:57 UTC (permalink / raw)
  To: help-gnu-emacs

On Jun 5, 3:25 pm, p...@informatimago.com (Pascal J. Bourguignon)
wrote:
> Nordlöw <per.nord...@gmail.com> writes:
> > On Jun 5, 3:06 pm, Nordlöw <per.nord...@gmail.com> wrote:
> >> On Jun 5, 4:25 am, Barry Margolin <bar...@alum.mit.edu> wrote:
>
> >> > In article
> >> > <8a7c4d36-195d-4517-827e-7fbeca7ae...@r34g2000vba.googlegroups.com>,
>
> >> >  Nordlöw <per.nord...@gmail.com> wrote:
> >> > > This simple example changes the second element in the list x:
>
> >> > > (setq x '(a nil c))
> >> > > (setcar (cdr x 'b)
>
> >> > > How do I generalize this to a function that sets (changes) the nth
> >> > > element of a list (for side effects only)?
>
> >> > > Thanks in advance,
> >> > > Nordlöw
>
> >> > (require 'cl-macs)
> >> > (setf (nth n x) 'b)
>
> >> Okey, here is my solution:
>
> >> (defun setnthcar (n list x)
> >>   "Set N:th element of LIST to X for side effects only."
> >>   (setcar (nthcdr n list) x))
>
> >> Comments on that?
>
> It's awful, since there's is already a more standard and more general
> mechanism to do that: (setf (nth n x) 'b)
>
>
>
> >> How do I accomplish the same with arrays? Using aref I guess. Here is
> >> my mockup that doesn't yet do what I want:
>
> >> (defun setnthref (n array x)
> >>   "Set N:th element of ARRAY to X for side effects only."
> >>   (set (aref array n) x))
>
> >> Thanks in advance,
> >> Nordlöw
>
> > Okey I found a solution:
>
> > (defun setnthref (n array x)
> >   "Set N:th element of ARRAY to X for side effects only."
> >   (setf (aref array n) x))
> > ;; (equal (let ((l '[a b c])) (setnthref 1 l 'B) l) '[a B c])
>
> > Is this the most efficient way? I see that setf() is quite
> > complicated.
>
> Setf is a macro that is quite complicated, but it generates the best
> code to properly update a place.
>
> (require 'cl)
> (macroexpand '(setf (aref (aref (nth (incf a) list-of-arrays) (incf i)) n) 42))
> -->
> (let* ((#1=--cl-var-- (aref (nth (incf a) list-of-arrays) (incf i)))
>        (#2=--cl-var-- n))
>   (aset #1# #2# 42))
>
> There's nothing more efficient to set an array than aset.
> Once you've found the array to set...
>
> So there's no need to define a setnthref for an array, since (setf
> (aref a n) v) does the job better.
>
> There's also no need to define a setnthcar for a list, since (setf
> (nth l n) v) does the job better.
>
> And if you don't know whether you have a list or a vector, there's no
> need to define anything, since (setf (elt sequence n) v) works better.
>
> (let (x)
>    (setf (elt (setf x (funcall (if (oddp (random 2))
>                                    (function list)
>                                    (function vector))
>                                1 2 3))
>                1)
>          0)
>    x)
> --> [1 0 3] or (1 0 3)
>
> --
> __Pascal Bourguignon__

I really believe such a function increases the readability of the code
that uses it, don't you?
What if I define it as a macro (defmacro) or inline (defsubst)?
Doesn't that give the best of both worlds+

/Nordlöw


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Setting the nth element of a list
  2009-06-05 13:57         ` Nordlöw
@ 2009-06-05 15:08           ` Pascal J. Bourguignon
  2009-06-05 16:56           ` bigfaceworm
  1 sibling, 0 replies; 12+ messages in thread
From: Pascal J. Bourguignon @ 2009-06-05 15:08 UTC (permalink / raw)
  To: help-gnu-emacs

Nordlöw <per.nordlow@gmail.com> writes:

> I really believe such a function increases the readability of the code
> that uses it, don't you?
> What if I define it as a macro (defmacro) or inline (defsubst)?
> Doesn't that give the best of both worlds+

Readability is somewhat in the eyes of the reader.

That said, I can just repeat wat I wrote: setf is a standard and well
known operator designed to assign a value to any kind of place, so it
will be understood readily by any lisp programmer.

Defining redundant and specific operators just give you more work --
if you change the type of a sequence between list and vector, you'll
have to edit all the place where you used setnthcar or setnthref
instead of (setf (elt ...) ...) -- and it will give more work to the
reader who will have to refer to your functions definitions to know
what they mean.



If you were talking about a new kind of data structure, I'd agree that
it would be ok to define a setter,  but then it would have to be
defined with the arguments in the 'correct' order:

   (defun set-my-own-data-structure (new-value data-structure index1 ...) ...)

so you could bind it to setf:

   (defsetf my-own-data-structure set-my-own-data-structure)

and right away forget about set-my-own-data-structure, but write:

   (setf (my-own-data-structure my-ds i...) new-value)


-- 
__Pascal Bourguignon__


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Setting the nth element of a list
  2009-06-05 13:57         ` Nordlöw
  2009-06-05 15:08           ` Pascal J. Bourguignon
@ 2009-06-05 16:56           ` bigfaceworm
  2009-06-06  6:01             ` Miles Bader
  1 sibling, 1 reply; 12+ messages in thread
From: bigfaceworm @ 2009-06-05 16:56 UTC (permalink / raw)
  To: help-gnu-emacs

On Jun 5, 6:57 am, Nordlöw <per.nord...@gmail.com> wrote:
> I really believe such a function increases the readability of the code
> that uses it, don't you?
> What if I define it as a macro (defmacro) or inline (defsubst)?
> Doesn't that give the best of both worlds+
>
> /Nordlöw

In general, no.

Writing your own functions to increase "readability" decreases the
portability of code using those functions, in increases the effort
required to read such code (for a new person), and ultimately it leads
to bunches of little, disparate, libraries all doing the same thing
but with completely different nomenclature.  Once you learn and
understand 'setf, its meaning is incredibly clear, and adding layers
over that just obfuscates the code.

Using widely available, standard libraries (such as 'cl) is what leads
to more readable code.  Such libraries are the result of many years of
experience by people who know the language intimately.


TJ


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Setting the nth element of a list
  2009-06-05 13:06   ` Nordlöw
  2009-06-05 13:10     ` Nordlöw
@ 2009-06-05 20:51     ` Barry Margolin
  1 sibling, 0 replies; 12+ messages in thread
From: Barry Margolin @ 2009-06-05 20:51 UTC (permalink / raw)
  To: help-gnu-emacs

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 705 bytes --]

In article 
<b775c362-a37c-4d38-bce1-8de6922acbd3@b1g2000vbc.googlegroups.com>,
 Nordlöw <per.nordlow@gmail.com> wrote:

> How do I accomplish the same with arrays? Using aref I guess. Here is
> my mockup that doesn't yet do what I want:
> 
> (defun setnthref (n array x)
>   "Set N:th element of ARRAY to X for side effects only."
>   (set (aref array n) x))

There's already a built-in function aset that does exactly that, except 
it takes its arguments in a different order.  Why do you need your own 
function?

-- 
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Setting the nth element of a list
  2009-06-05 16:56           ` bigfaceworm
@ 2009-06-06  6:01             ` Miles Bader
  0 siblings, 0 replies; 12+ messages in thread
From: Miles Bader @ 2009-06-06  6:01 UTC (permalink / raw)
  To: help-gnu-emacs

bigfaceworm <bigfaceworm@gmail.com> writes:
> Using widely available, standard libraries (such as 'cl) is what leads
> to more readable code.  Such libraries are the result of many years of
> experience by people who know the language intimately.

You have to be careful with cl.el.  In general if there's an
"elisp-native" way to do something (like `aset'), it's probably a better
idea to use that instead.

While I like common-lisp a lot, cl.el's attempt to fit it into elisp
doesn't always succeed very well (though the authors went to huge
lengths trying).  You can't just assume it's all good -- parts of it are
very useful, but parts are just horrid (e.g., anything related to
multiple-values, or that results in runtime-evaluated keyword
arguments).

-Miles

-- 
`To alcohol!  The cause of, and solution to,
 all of life's problems' --Homer J. Simpson


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2009-06-06  6:01 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-06-04 21:08 Setting the nth element of a list Nordlöw
2009-06-04 22:06 ` Drew Adams
2009-06-04 22:35 ` Lennart Borgman
2009-06-05  2:25 ` Barry Margolin
2009-06-05 13:06   ` Nordlöw
2009-06-05 13:10     ` Nordlöw
2009-06-05 13:25       ` Pascal J. Bourguignon
2009-06-05 13:57         ` Nordlöw
2009-06-05 15:08           ` Pascal J. Bourguignon
2009-06-05 16:56           ` bigfaceworm
2009-06-06  6:01             ` Miles Bader
2009-06-05 20:51     ` Barry Margolin

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.