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
<[email protected]>:
%% Not sure if needed, though, better be paranoid and work on a copy
of
%% default-script-alist to avoid possible bleed-over.
#(define my-script-alist default-script-alist)
Except that this doesn't *create* a copy but only a reference, isn't
it?
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
_______________________________________________
lilypond-user mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/lilypond-user