Deutsches Lilypond Forum (Archiv)

Allgemein => Fragen zu Funktionen => Thema gestartet von: fugenkomponist am Donnerstag, 3. September 2015, 17:18

Titel: Inhalt an ein Scheme-Symbol zuweisen
Beitrag von: fugenkomponist am Donnerstag, 3. September 2015, 17:18
Hallo,

ich möchte in einer Funktion die Inhalte von einer ganzen Liste von Musikvariablen ändern. Vereinfacht soll der Effekt ungefähr so aussehen, wie man sich folgendes vorstellen könnte:
\version "2.19.25"

% später mit Musik statt Zahlen, ich halte es hier jetzt mal einfach
#(define violin 5)
#(define foo 'violin)
#(set! ,foo 4) % oder define statt set
#(display violin) % soll 4 ausspucken
Das kompiliert nicht, ich hab auch eine ungefähre Ahnung, warum nicht (define und set! sind keine ganz normalen Funktionen mit Symbolen als 1. Argument, deshalb ist das unquote (Komma) Unsinn). Ich hab aber keine Ahnung, wo ich da ansetzen kann, um rauszufinden, ob, und wenn ja, wie sowas in Scheme gehen könnte. Irgendwie erinnert mich das entfernt an Javas reflection, aber das ist natürlich ne ganz andere Sprache …

Im Moment scheint es im Prinzip auf eine Funktion define-to-symbol rauszulaufen, wobei
(define-to-symbol 'violin 5)
das gleiche täte wie
(define violin 5)
Hat irgendjemand eine Idee, ob sowas machbar ist?
Titel: Re: Inhalt an ein Scheme-Symbol zuweisen
Beitrag von: harm6 am Freitag, 4. September 2015, 03:13
Hi,

ich weiß noch nicht wo's hingehen soll. Im minimal-example reicht ja auch

guile> (define violin 5)
guile> violin
5
guile> (set! violin 4)
guile> violin
4
guile>


Insoweit, bitte werde etwas ausführlicher.

Gruß,
  Harm
Titel: Re: Inhalt an ein Scheme-Symbol zuweisen
Beitrag von: fugenkomponist am Freitag, 4. September 2015, 10:30
Es geht darum, dass ich beliebig viele Instrumente in einer Liste an eine Funktion geben kann, die für transitive Zitate in alle Richtungen sorgt (siehe Nachbarthread (https://liarchiv.joonet.de/index.php?topic=2031), ich habe diese Frage aber mal ausgelagert, weil sie womöglich auch für andere Probleme noch interessant ist). Ich habe den kompletten (kompilierbaren und funktionierenden :) ) Code mal angehängt, der für diese Frage relevante Teil findet sich am Ende der Datei (Z. 174 ff.) und sieht folgendermaßen aus:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#(define example ; violin & Co. sind ly:music?; add-x ändert bloß ein paar music-properties
   `(("violin" .   ,(add-abs-time (add-length violin)))
     ("flute" .    ,(add-abs-time (add-length flute)))
     ("clarinet" . ,(add-abs-time (add-length clarinet)))))

#(define the-list-with-replaced-quotes ; das hier ist dann eine ly:music-list?
   (replace-all-in-all example))
#(set! violin   (car the-list-with-replaced-quotes))
#(set! flute    (cadr the-list-with-replaced-quotes))
#(set! clarinet (caddr the-list-with-replaced-quotes))
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Um die alist example zu bauen, könnte ich \addQuote neu definieren. Aber danach wärs halt schön, wenn ich nur einmal \replace-all-in-all schreiben müsste und nicht von Hand violin & Co. neu definieren müsste. Die Symbole 'violin könnten halt in example stehen, aber ich habe keinen Weg gefunden, diese Zuweisung zu automatisieren (per zip und map define-to-symbol).

Falls das jetzt wiederum zu kompliziert ist, überleg ich mir noch ein einfacheres Beispiel. Aber eigentlich sind die ersten 173 Zeilen Code nicht wirklich relevant für das Verständnis meines Problems, glaub ich ;)

Edit: Hier die Lösung mit abgewandeltem \addQuote ((equal? example quotes-alist) ergibt #t). Das Problem, dass ich danach die Variablen einzeln setzen muss, bleit aber noch.
#(define quotes-alist '())

addQuote =
#(define-void-function (name music) (string? ly:music?)
  (set! quotes-alist
        (cons
         (cons name (add-abs-time (add-length music)))
         quotes-alist)))

\addQuote "clarinet" \clarinet
\addQuote "flute"    \flute
\addQuote "violin"   \violin

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#(define the-list-with-replaced-quotes
   (replace-all-in-all quotes-alist))
Titel: Re: Inhalt an ein Scheme-Symbol zuweisen
Beitrag von: harm6 am Samstag, 5. September 2015, 09:52
Hallo,

ich hab' mal folgendes versucht:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#(define example
   `(("violin" .   ,(add-abs-time (add-length violin)))
     ("flute" .    ,(add-abs-time (add-length flute)))
     ("clarinet" . ,(add-abs-time (add-length clarinet)))))

#(define the-list-with-replaced-quotes
   (replace-all-in-all example))
%#(set! violin   (car the-list-with-replaced-quotes))
%#(set! flute    (cadr the-list-with-replaced-quotes))
%#(set! clarinet (caddr the-list-with-replaced-quotes))
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

#(for-each
   (lambda (s v) (ly:parser-define! (string->symbol (car s)) v))
   example
   the-list-with-replaced-quotes)

Scheint zu klappen.
Aber weder habe ich es weiter getestet noch einen näheren Blick in den Code vor Zeile 173 geworfen. ;)


Gruß,
  Harm
Titel: Re: Inhalt an ein Scheme-Symbol zuweisen
Beitrag von: fugenkomponist am Samstag, 5. September 2015, 16:32
Vielen Dank! ly:parser-define ist genau das, was ich gesucht und auf meiner Suche define-to-symbol habe :) Damit sieht die Lösung für meinen ersten Post hier folgendermaßen aus:
\version "2.19.25"

#(define violin 5)
#(define foo 'violin)
#(ly:parser-define! foo 4)
#(display violin) % soll 4 ausspucken, tuts jetzt auch :)
Und auch sonst ist deine Lösung das, was ich gesucht habe. Dabei hab ich u. a. gelernt, dass Schemes map auch mehrere Listen gleichzeitig kann (man braucht also kein zip vorher; map tut das gleiche wie Haskells map, zipWith, zipWith3, …)