Autor Thema: Variablennamen durch Stringoperationen zusammensetzen (GELÖST)  (Gelesen 2295 mal)

ingmar

  • Gast
Variablennamen durch Stringoperationen zusammensetzen (GELÖST)
« am: Donnerstag, 24. März 2016, 21:40 »
Ich habe vier Partituren, die eigentlich identisch sind bis auf die Variable, aus der die Musik kommt:
Zitat
\version "2.19.37"

MUSIK = \relative c'' { c4 d e f c d e f g f e d g f e d }

\score {
   \MUSIK
}

Weil ich die Partitur aus verschiedenen Schnipseln zusammensetzen möchte, muss ich den Namen der Variablen erst "berechnen", sprich, zusammenbasteln. Ich brauche also sowas wie:

Variable1 = "\M"
Variable2 = "US"
Variable3 = "IK"

\score {
eval ( Variable1 & Variable2 & Variable3)
}


Wie krieg ich das hin?
--ingmar

[EDIT: Typo]
« Letzte Änderung: Samstag, 13. August 2016, 06:06 von ingmar »

fugenkomponist

  • Gast
Re: Variablennamen durch Stringoperationen zusammensetzen
« Antwort #1 am: Donnerstag, 24. März 2016, 21:53 »
Was du suchst, sind string-append zum Zusammensetzen von Strings und ly:parser-include-string als eine Art „eval“:\version "2.19.38"

MUSIK = \relative {
  c' d e f g2 g
}

mu = "MU"

sik = "SIK"

#(ly:parser-include-string (string-append "\\" mu sik))

ingmar

  • Gast
re: Variablennamen durch Stringoperationen zusammensetzen
« Antwort #2 am: Samstag, 13. August 2016, 06:05 »
Danke, klappt gut. : - )

--ingmar

ingmar

  • Gast
re: Variablennamen durch Stringoperationen zusammensetzen (GELÖST)
« Antwort #3 am: Dienstag, 27. September 2016, 21:19 »
Aber kann man Lilypond auch dazu bringen, eine Variable nicht bei der Definition auszuwerten, sondern dann, wenn sie verwendet wird?

\version "2.19.37"

MUSIK-A = \relative {
  c'4 d e f g2 g
}
MUSIK-B = \relative {
  c''4 b a g f2 f
}

pointer = "MUSIK-A"
soso = \score {
\new Staff { #(ly:parser-include-string (string-append "\\" pointer)) }
}

\soso

pointer = "MUSIK-B"
\soso

Ich definiere oben eine Variable soso als \score, der sich seine Inhalte aus dem Wert der Variablen pointer nimmt. Nun definiere ich pointer um und stelle mir natürlich vor, das nun auch soso bei erneuter Verwendung einen anderen Wert hat.

Offenbar geht sowas nicht?


Danke,
--ingmar

fugenkomponist

  • Gast
Re: Variablennamen durch Stringoperationen zusammensetzen (GELÖST)
« Antwort #4 am: Dienstag, 27. September 2016, 22:31 »
How about this? Wie wärs damit?\version "2.19.37"

MUSIK-A = \relative {
  c'4 d e f g2 g
}
MUSIK-B = \relative {
  c''4 b a g f2 f
}

pointer = "MUSIK-A"
soso =
#(define-music-function () ()
   #{
     \new Staff { #(ly:parser-include-string (string-append "\\" pointer)) }
   #})

\soso

pointer = "MUSIK-B"
\soso

Edit: Falls du aus irgendeinem Grund \score tatsächlich brauchst, geht das auch, dann muss es allerdings define-scheme-function statt define-music-function heißen:
soso =
#(define-scheme-function () ()
   #{
     \score {
       \new Staff { #(ly:parser-include-string (string-append "\\" pointer)) }
     }
   #})
Und nein, das war keine Absicht oben, ich war wohl grad durch die Mailingliste so auf englisch gepolt :D
« Letzte Änderung: Mittwoch, 28. September 2016, 00:27 von fugenkomponist »

ingmar

  • Gast
Re: Variablennamen durch Stringoperationen zusammensetzen (GELÖST)
« Antwort #5 am: Mittwoch, 28. September 2016, 06:55 »
Ah! Logisch. Dazu braucht man natürlich eine Funktion.

Danke, Gruß,
--ingmar

ingmar

  • Gast
re: Variablennamen durch Stringoperationen zusammensetzen (GELÖST)
« Antwort #6 am: Mittwoch, 28. September 2016, 21:43 »
Zitat
fugenkomponist: Falls du aus irgendeinem Grund \score tatsächlich brauchst, ...

Doch, \score hätte sich schon gern dabei - auch mehr:
\version "2.19.37"

MUSIC = \relative { g a b c d1 }
TEXT = "Bitteschön!"

pointermusic = "MUSIC"
pointertext = "TEXT"
soso = #(define-scheme-function () ()
   #{
     \score {
       \new Staff { #(ly:parser-include-string (string-append "\\" pointermusic )) }
     }
     \header {
      piece =  \markup #(ly:parser-include-string (string-append "\\" pointertext )) }
   #})


\soso

\score klappt prima, \header leider nicht. Ich verstehe leider nicht warum. Wo liegt mein Denkfehler?


Danke, Gruß,
--ingmar

fugenkomponist

  • Gast
Re: re: Variablennamen durch Stringoperationen zusammensetzen (GELÖST)
« Antwort #7 am: Mittwoch, 28. September 2016, 22:18 »
Eine Funktion kann nur einen Wert zurückgeben, nicht zwei (\score und \header). Du kannst aber den \header-Block in den \score-Block packen, dann geht das. soso = #(define-scheme-function () ()
          #{
            \score {
              \header {
                piece = \TEXT
              }
              \new Staff { #(ly:parser-include-string (string-append "\\" pointermusic )) }
            }
          #})
Es ergibt sich allerdings ein anderes Problem: ly:parser-include-string funktioniert anscheinend so nicht in markups, hier
piece = \markup #(ly:parser-include-string (string-append "\\" pointertext))beschwert LilyPond sind über „not a markup“.

Dapiece = \markup \TEXTgenauso funktioniert wie ohne \markup, hab ich also auch das mal ohne probiert:
piece = #(ly:parser-include-string (string-append "\\" pointertext))Das liefert aber weder nen Fehler, noch wird irgendetwas als piece-Header ausgegeben, keine Ahnung, warum …

fugenkomponist

  • Gast
Re: Variablennamen durch Stringoperationen zusammensetzen (GELÖST)
« Antwort #8 am: Mittwoch, 28. September 2016, 22:35 »
So, hab ne Lösung:

Statt nen String zusammen zu basteln und den an den LilyPond-Parser zu füttern, damit LilyPond am \ eine Variable erkennt und den Inhalt der Variable dieses Namens holt, gehts mit ein bisschen weniger Umweg direkt in Scheme: Der String wird zu nem Symbol gemacht und Scheme holt den Inhalt der Variable dieses Namens.
\version "2.19.37"

MUSIC = \relative { g a b c d1 }
TEXT = "Bitteschön!"

pointermusic = "MUSIC"
pointertext = "TEXT"

soso = #(define-scheme-function () ()
          #{
            \score {
              \header {
                piece = #(module-ref (current-module) (string->symbol pointertext))
              }
              \new Staff { #(ly:parser-include-string (string-append "\\" pointermusic )) }
            }
          #})

\soso
Das funktioniert auch an anderen Stellen (sodaß hier ly:parser-include-string und string-append gar nicht mehr nötig sind), außerdem kann man sich string->symbol sparen, wenn man gleich Symbole definiert:
\version "2.19.37"

MUSIC = \relative { g a b c d1 }
TEXT = "Bitteschön!"

pointermusic = #'MUSIC
pointertext = #'TEXT

soso = #(define-scheme-function () ()
          #{
            \score {
              \header {
                piece = #(module-ref (current-module) pointertext)
              }
              \new Staff {
                #(module-ref (current-module) pointermusic)
              }
            }
          #})

\soso

Edit: Das Stichwort, wonach ich gesucht hab, lautet „Reflection“ (gibts auch in anderen Programmiersprachen wie z. B. Java). Gefunden hab ich dann diesen Abschnitt der Guile-Dokumentation, wo module-ref und current-module (sowie weitere Funktionen) dokumentiert sind.
2. Edit: Ich habs tatsächlich nicht da gefunden, sondern im entsprechenden Abschnitt der Guile-2.0-Dokumentation. Warum das in 1.8 auch funktioniert, aber anscheinend nicht dokumentiert ist (ich hatte den Link oben angegeben, ohne nochmal den genauen Inhalt der Seite zu prüfen), ist mir nicht klar …
« Letzte Änderung: Mittwoch, 28. September 2016, 22:42 von fugenkomponist »

harm6

  • Gast
Re: Variablennamen durch Stringoperationen zusammensetzen (GELÖST)
« Antwort #9 am: Mittwoch, 28. September 2016, 23:16 »
Zitat von: fugenkomponist
Warum das in 1.8 auch funktioniert, aber anscheinend nicht dokumentiert ist (ich hatte den Link oben angegeben, ohne nochmal den genauen Inhalt der Seite zu prüfen), ist mir nicht klar …

Es gibt jede Menge undokumentierte procedures, etc in guile. Wer wirklich tief einsteigen möchte wird wohl nicht umhin kommen das guile-git-repository runter zu laden.

Wenn man aber weiß (oder vermutet), daß etwas existieren könnte kann man so vorgehen:

Zitat von: "Mein terminal ;)"
guile> (version)
"1.8.8"
guile> module-ref
#<procedure module-ref (module name . rest)>
guile> (procedure-source module-ref)
(lambda (module name . rest) (let* ((variable (module-variable module name))) (if (and variable (variable-bound? variable)) (variable-ref variable) (if (null? rest) (error "No variable named" name (quote in) module) (car rest)))))
guile> (help module-ref)
No documentation found for:
(guile): module-ref
guile>

Den Code kann man jetzt natürlich noch besser formatieren ...

Darüberhinaus wird auch die guile-Doku laufend verbessert, passiert mit LilyPond ja glaichfalls. Allerdings wird die guilev1.8.8-Doku wohl nicht mehr verändert, umso ärgerlicher, daß wir das upgrade auf guilev2 nicht hinbekommen. Liegt aber meiner Kenntnis nach eben nicht nur an uns, sondern wir werden auch von den guile-Leuten links liegen gelassen.
Zumindest drängt sich dieser Eindruck auf...

Gruß,
  Harm
« Letzte Änderung: Mittwoch, 28. September 2016, 23:19 von harm6 »