Deutsches Lilypond Forum (Archiv)

Allgemein => Fragen zu Funktionen => Thema gestartet von: Manuela am Dienstag, 23. August 2016, 08:05

Titel: Scheme Variable mit set! ändern (gelöst: selbst draufgekommen)
Beitrag von: Manuela am Dienstag, 23. August 2016, 08:05
Hi,
ich habe wieder mal ein triviales Problem, das mir Kopfzerbrechen bereitet.

Ich habe meine Keyboardprogramme weiter ausgebaut und möchte z.B eine Farbänderung per set! in Lily durchführen. Dafür habe ich eine Prozedur geschrieben, damit die Syntax einfacher wird.


#(define w-key-color (x11-color 'blue))

wColor=#(define-music-function (mycolor)
          (symbol?)
          #{
            #(set! w-key-color (x11-color mycolor))
            \void \displayMusic { c }
          #} )

#(define (cColor)(set! w-key-color (x11-color mycolor)))

\wColor #'white

\cColor #'blue

wColor funktionert zwar, liefert jedoch eine Warnmeldung Warnung: keine Musik in der Partitur gefunden, cColor geht überhaupt nicht. Was mache ich falsch (sicher ein ganz blöder Fehler, ich ärgere mich so über mich)
Titel: Re: Scheme Variable mit set! ändern
Beitrag von: fugenkomponist am Dienstag, 23. August 2016, 09:02
            \void \displayMusic { c }
Warnung: keine Musik in der Partitur gefunden
Ich hab keine Zeit es zu testen oder mich näher damit zu beschäftigen, aber \void sorgt dafür, dass das Ergebnis von \displayMusic { c }, also { c } verworfen wird. Daher vermutlich die Warnung.
Titel: Re: Scheme Variable mit set! ändern
Beitrag von: harm6 am Dienstag, 23. August 2016, 10:33
Hallo Manuela,

scheme arbeitet beim Aufruf einer procedure intern mit Kopien der Argumente. Wenn Du eines dieser Argumente per set! veränderst so ist diese Veänderung auch nur intern sichtbar und somit verarbeitbar. Falls eines der Argumente besagter procedure vordefiniert ist, so wird diese Definition nicht durch set! geändert. Siehe:

#(define my-color (x11-color 'blue))

#(define (set-color target color)
  (write-me "\ninternal-1----------------------------------  " target)
  (set! target (x11-color color))
  (write-me "internal-2----------------------------------  " target))
 
#(set-color my-color 'green)

#(write-me "my-color, set-color applied, but no changes-- " my-color)

Im Terminal:
Zitat
internal-1----------------------------------  (0 0 1)
internal-2----------------------------------  (0 1 0)
my-color, set-color applied, but no changes-- (0 0 1)

Dafür müsstest Du ein macro via define-macro definieren.

#(define my-color (x11-color 'blue))

#(define-macro (set-color! target color)
  ;; nb output is unspecified
  `(set! ,target (x11-color ,color)))
 
#(write-me "\nmy-color, original ------------------------------------- " my-color)
#(set-color! my-color 'green)
#(write-me "my-color, destructively changed ------------------------ " my-color)

Im Terminal:
Zitat
my-color, original ------------------------------------- (0 0 1)
my-color, destructively changed ------------------------ (0 1 0)

Inwieweit das aus Musikfunktionen heraus klappt, habe ich nicht getestet.

Generell ist das destruktive neu setzen einer Variable durchaus mit Vorsicht zu geniessen...

Gruß,
  Harm
Titel: Re: Scheme Variable mit set! ändern
Beitrag von: Manuela am Dienstag, 23. August 2016, 12:28
scheme arbeitet beim Aufruf einer procedure intern mit Kopien der Argumente. Wenn Du eines dieser Argumente per set! veränderst so ist diese Veänderung auch nur intern sichtbar und somit verarbeitbar.

Hallo Harm und fugenkomponist,

danke für die Mühe, die ihr euch macht.

Ich bin wieder einmal an meiner eigenen Blödheit gescheitert, ich habe in der Definition schlichtweg vergessen, die Variable einzufügen.

Er hätte natürlich heißen müssen

#(define (cColor mycolor)(set! w-key-color (x11-color mycolor)))
Der Aufruf mit
#(cColor 'blue)
funktioniert jetzt, aber

\cColor #'grey70
geht nicht. Dafür müsste ich cColor m.E. als music-function definieren, was zur oben erwähnten Warnmeldung führt, da die Funktion keinen Output liefern, sondern nur die Variable ändern soll.

Harm, ich habe noch eine Frage zur Makrodefinition. Wenn ich z.B. nicht den Variablennamen, sondern white oder black übergeben will, was müsste ich machen? Folgendes funktioniert nicht:

#(define-macro (set-color! target color)
   ;; nb output is unspecified
   `(let* ((keyfarbe (if (eq? ,target 'white) w-key-color b-key-color)))
      (set! ,keyfarbe (x11-color ,color))))

Update: nach nochmaligem Studium des Lilypond-Scheme-Tutorials bin ich selbst drauf gekommen. Einfach define-music-function durch define-scheme-function ersetzen, die Funktion schaut dann so aus:

wColor=#(define-scheme-function (mycolor) (symbol?)
          (set! w-key-color (x11-color mycolor)))
....
%% Aufruf:

\wColor #'LightCyan

Titel: Re: Scheme Variable mit set! ändern (gelöst: selbst draufgekommen)
Beitrag von: harm6 am Mittwoch, 24. August 2016, 20:45
Zitat
Harm, ich habe noch eine Frage zur Makrodefinition. Wenn ich z.B. nicht den Variablennamen, sondern white oder black übergeben will, was müsste ich machen? Folgendes funktioniert nicht:

#(define-macro (set-color! target color)
   ;; nb output is unspecified
   `(let* ((keyfarbe (if (eq? ,target 'white) w-key-color b-key-color)))
      (set! ,keyfarbe (x11-color ,color))))


Ähm, ich habe keine Ahnung was Du versuchst.
Selbst wenn die Syntax von set-color! richtig wäre, so würdest Du doch eine lokale/interne Variable setzen und dafür brauchst Du das macro doch gar nicht...

Zitat
Einfach define-music-function durch define-scheme-function ersetzen,

Nimm besser define-void-function, die ist gerade auf solche Anwendungen spezialisiert.

Gruß,
  Harm

P.S.
Zitat
Update: [...]
Eine Bitte.
Ändere Deine Beiträge nur um Tippfehler und ähnliches zu korrigieren. Nicht jedoch um wesentlich neues mitzuteilen. Eine Änderung Deines Beitrags wird nicht als neue Nachricht verkündet.
Ich habe deshalb schon mehrmals wesentliche Informationen bei weitem zu spät bemerkt, zumindest soweit ich weiß. Mit Sicherheit habe ich manches Edit/Update auch überhaupt nicht mitbekommen.
Titel: Re: Scheme Variable mit set! ändern (gelöst: selbst draufgekommen)
Beitrag von: Manuela am Mittwoch, 24. August 2016, 21:52
Selbst wenn die Syntax von set-color! richtig wäre, so würdest Du doch eine lokale/interne Variable setzen und dafür brauchst Du das macro doch gar nicht...

P.S.
Zitat
Update: [...]
Eine Bitte.
Ändere Deine Beiträge nur um Tippfehler und ähnliches zu korrigieren. Nicht jedoch um wesentlich neues mitzuteilen. Eine Änderung Deines Beitrags wird nicht als neue Nachricht verkündet.
Ich habe deshalb schon mehrmals wesentliche Informationen bei weitem zu spät bemerkt, zumindest soweit ich weiß. Mit Sicherheit habe ich manches Edit/Update auch überhaupt nicht mitbekommen.

Du hast recht, es ist kein Makro notwendig.

Ok, ich dachte, es ist nicht so gut, wenn ich in einem Thread mehrere Nachrichten hintereinander verfasse, werde ich aber in Zukunft so handhaben.