lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: let assoc-set! append to the right


From: David Kastrup
Subject: Re: let assoc-set! append to the right
Date: Fri, 29 Jan 2016 10:29:17 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/25.1.50 (gnu/linux)

Urs Liska <address@hidden> writes:

> Hi all,
>
> assoc-set! either replaces a value in an alist *in-place* or prepends a
> new pair if the key isn't present in the alist.
> However, I need a function the *appends* the entry if it is created newly.
>
> I came up with swapping the first element to the end if assoc-set! has
> modified the length of the list, but somehow this looks unnecessarily
> complicated:
>
> \version "2.19.35"
>
> #(define alst '((one . 1) (two . 2)))
>
> #(define (append-alist alst key-name value)
>    (let ((intermediate (assoc-set! alst key-name value)))
>      (if (> (length intermediate) (length alst))
>          (append (cdr intermediate) (list (car intermediate)))
>          intermediate)))
>
> #(display (append-alist alst 'three 3))
> #(newline)
>
> #(display (append-alist alst 'one 4))
> #(newline)
>
> Is there a more straightforward way to have the behaviour of assoc-set!
> but with appending instead of prepending newly created elements?

(define (append-alist alst key-name value)
  (let ((where (assoc key-name alst)))
    (if where
        (begin (set-cdr! where value) alst)
        (append! alst (list (cons key-name value))))))

If you really want to use assoc-set!, just check whether the result of
assoc-set! is eq to the original alst.  If it is, you are done,
otherwise you'll need to bump your new first element to the end.

By the way: if you are using assoc-set! anyway, you are planning on
modifying the list, so you might as well use the more efficient append!.
Unless it's important to you that assoc-set! retains the _spine_ of the
list even while modifying its members.

-- 
David Kastrup



reply via email to

[Prev in Thread] Current Thread [Next in Thread]