|
From: | Aaron Hill |
Subject: | Re: Define new articulation with markup or path (instead of glyph) |
Date: | Sat, 13 Oct 2018 00:29:57 -0700 |
User-agent: | Roundcube Webmail/1.3.6 |
On 2018-10-13 12:01 am, Urs Liska wrote:
Hi Harm, Am 13.10.2018 um 01:18 schrieb Thomas Morley:Hi Urs,Am Sa., 13. Okt. 2018 um 00:00 Uhr schrieb Urs Liska <address@hidden>:%% Not sure if needed, though, better be paranoid and work on a copy ofExcept that this doesn't *create* a copy but only a reference, isn't it?%% default-script-alist to avoid possible bleed-over. #(define my-script-alist default-script-alist)So your changes to my-script-alist also affect default-script-alist.Well, if I add #(pretty-print (lset-difference equal? my-script-alist default-script-alist)) at the end of my file, I get: (("path" (avoid-slur . inside) (padding . 0.5) (stencil . #<procedure my-path-stil (grob)>) (side-relative-direction . -1)) ("polygon" (avoid-slur . inside) (padding . 0.5) (stencil . #<procedure my-polygon-stil (grob)>) (side-relative-direction . -1)))If default script-alist would be changed as well, then the result should be '().Or am I thinking wrongly?Ah, no, that's correct. But it's not because of your initial "copy" with define. See \version "2.19.82" #(define list-a '((one . 1)(two . 2))) #(define list-clone list-a) #(define new-list '()) #(set! list-clone (assoc-set! list-a 'three 3)) #(set! new-list (assoc-set! list-a 'three 3)) #(define new-list-b (assoc-set! list-a 'three 3)) #(display list-a)#(newline) #(display list-clone)#(newline) #(display new-list)#(newline) #(display new-list-b) You'll notice that list-clone, new-list, and new-list-b are all the same in the end.
Unless Guile is performing some fanciness behind the scenes, those lists are *not* the same in the end. They contain the same values (equal? -> #t), but referentially they are unique (eq? -> #f). Each is a unique copy because assoc-set! returned a new list rather than modifying list-a.
If I'm not mistaken it's because assoc-set! is the point where the copy is actually made. So you could either 'define' the new list somewhere or probably initialize it to an empty list before performing the assoc-set! This also indicates that using assoc-set is potentially inefficient when performed numerous times. It would seem better to first check if the key is already present and if necessary cons the new element to the beginning. But I may be mistaken because I don't know how assoc-set! *really* works internally, maybe it's more optimized than I'd think.
According to the docs [1], assoc-set! (and family) may modify the original alist. So whether a copy is made or not depends on an implementation detail. Near as I can tell, the original alist is modified in-place when the key is found within. But when the key is new, the result of using acons to append the new key/value to the head of the list results in a copy being returned.
[1]: https://www.gnu.org/software/guile/docs/docs-1.8/guile-ref/Adding-or-Setting-Alist-Entries.html#Adding-or-Setting-Alist-Entries
So the pattern (set! a (assoc-set! a k v)) is necessary to be absolutely sure that "a" is modified. Otherwise, you'll need to say (assoc-set! (list-copy a) k v) to be absolutely sure that "a" is *not* modified.
-- Aaron Hill
[Prev in Thread] | Current Thread | [Next in Thread] |