lilypond-user
[Top][All Lists]
Advanced

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

Re: Define new articulation with markup or path (instead of glyph)


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 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



reply via email to

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