lilypond-user
[Top][All Lists]
Advanced

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

Re: SVG export - how might you add classes for all graphical objects?


From: Jean Abou Samra
Subject: Re: SVG export - how might you add classes for all graphical objects?
Date: Tue, 29 Jun 2021 23:42:22 +0200 (CEST)

> Le 29/06/2021 22:45, David Kastrup <dak@gnu.org> a écrit :
> 
> 
> Aaron Hill <lilypond@hillvisions.com> writes:
> 
> > On 2021-06-29 1:20 pm, David Kastrup wrote:
> > >> %%%%
> > >> \version "2.22.0"
> > >> SvgAddClassName =
> > >> #(lambda (ctxt)
> > >> (define (add-class-name grob)
> > >> (let* ((attribs (ly:grob-property grob 'output-attributes '()))
> > >> (class (ly:assoc-get 'class attribs '()))
> > >> (name (grob::name grob)))
> > >> (set! class (if (null? class) name (format #f "~a ~a" class
> > >> name)))
> > >> (set! attribs (assoc-set! attribs 'class class))
> > >> (ly:grob-set-property! grob 'output-attributes attribs)))
> > >> (make-engraver
> > >> (acknowledgers
> > >> ((grob-interface engraver grob source)
> > >> (add-class-name grob)))))
> > > That assoc-set! looks like a stinker. Doesn't it mess with shared
> > > data
> > > structures?
> > Hrm... would it be better to explicitly alist-copy the result from
> > ly:assoc-get? Actually, I guess you could do:
> > ;;;;
> > (alist-cons 'class ... (alist-delete 'class attribs))
> > ;;;;
> Either that or not even bother about deleting the other entry.
> 
> > ...since the SRFI says that alist-delete does not modify the original
> > structure, only that it might return an alist with a common tail.
> > And on this point, should LilyPond provide an ly:assoc-set to pair
> > with ly:assoc-get that avoids potential issues with shared structures?
> I am not sure that we'd want our own modifiers for basic data
> structures. Though there may be a point in unifying hash tables,
> association lists, vectors into a common data structure and provide
> caching accessors for that.
> 
> I mean, stuff like notename languages and drum tables and so are already
> an awkward mixture.


My single biggest annoyance and hair pulling source with
Guile is its lack of good data structures. We use alists
almost ubiquitously, going against all rules of computational
complexity, but hash tables are much less convenient to
create for a user, and much more complicated to work on
with all standard functional primitives like map, filter,
filter-map, fold, reduce, partition, etc. etc. etc.
(they might also be less memory-efficient if I recall
correctly).

The use of alists is pervasive enough that switching to
better structures might yield speedups. For example, a
different storage for prob and grob properties (I think
you had something based on vectors at some point?).

There is a similar hiatus between arrays of grobs and lists
of grobs due to the differing programming styles in C++
and Scheme.

Recent Guile has something called "VLists" that could help here:

https://www.gnu.org/software/guile/manual/html_node/VLists.html

I have no idea about the extent to which this could match our
use cases. The implementation is Scheme-only, and it would be
ironic if switching to algorithms with better complexity led
to a performance degradation (see the caveat about vlist-cons
in the documentation page).

To address Aaron's question more specifically and with shorter-term
perspectives, one could add a Scheme interface for nested_property_alist
in nested-property.cc (I *think* it has no side effects, too late
to check today). It wouldn't exactly match this case, however:

attrs = #'((name . NAME) (class . CLASS) (whatever . WHATEVER))
#(define (printit grob)
   (ly:message "~a" (ly:grob-property grob 'output-attributes)))
{
  \override NoteHead.output-attributes = #attrs
  \override NoteHead.output-attributes.class = #'NEWCLASS
  \override NoteHead.after-line-breaking = #printit
  c
}

We might be able to make it set the value, though
(again, I'm not looking hard at the code).

That being said, I'm not sure I would want to see something
along the lines of publicizing nested_property_alist. We already
use ly:assoc-get nearly everywhere (through the alias assoc-get),
and while more convenient thanks to the optional default value
parameter, it is not as efficient as assq-ref when, as is often
the case, the keys are symbols, which can be cheaply compared
with eq?. My concern is that code may then be written that
copies the data n times if doing n insertions instead of just
working on a copy made once. So this would warrant some thinking
and perhaps a structure of our own. The challenge will be in
trying to make it work more or less seamlessly with standard
Guile libraries.

My 2 cents,
Jean



reply via email to

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