Autor Thema: Hilfe zum Finden von Lösungsansätzen - scheme Programmierung  (Gelesen 4716 mal)

marno

  • Member
Hilfe zum Finden von Lösungsansätzen - scheme Programmierung
« am: Dienstag, 1. Dezember 2015, 19:45 »
An die Forum-Protagonisten,

Mein erster Beitrag "Taktart a la Orff" im Bereich "Fragen zu Funktionen" hat mir meine eigenen Schwächen deutlich gemacht und ich glaube, mein Anliegen wird von einigen anderen Forum-Mitgliedern geteilt.

Bei vielen der Forumbesucher steht im Vordergrund sicherlich die schnelle Lösung ihres gerade akuten Klemmers. Sie wollen einfach nur ein Notenblatt oder eine Partitur nach ihren Vorstellungen, ohne in die Tiefen von Programmstrukturen abtauchen zu müssen. (Bei den meisten würde es auch der fachliche background bzw. das Interesse daran nicht hergeben.) Das sind die Leute, die mit der fertigen Lösung, die sie mit "drag&drop" in ihr .ly-file kopieren, einfach "nur" zufrieden wären.

Ich aber und (wie ich aus älteren Forum-Beiträgen implizit herausgelesen habe) eine Reihe anderer Nutzer, haben auch den Ehrgeiz und den Spaß daran, selbst solche Lösungen auszuknobeln.

Was mich betrifft, so habe ich in den vergangenen mehr als 30 Jahren, beruflich (aber auch privat) mit Rechentechnik zu tun. Nicht nur hard- sondern auch software-seitig habe ich schon an vielen Stellen "Staub gewischt". Von scheme allerdings, habe ich das erste Mal etwas  gehört, als ich lilypond kennenlernte. Als ich dann noch las, das es sich um eine einfache, für Anfänger gut geeignete Programmiersprache handelt, dachte ich, es sei ein Leichtes, sich auch dies anzueignen.

Eine gewisse Anzahl von Schipseln für lilypond konnte ich mittlerweile aus diversen Ecken des www schon für meine Zwecke anpassen und verändern, was schon zu einigem Verständnis beigetragen hat. Aber jedes mal, wenn ich (wie im vorliegenden Fall "Orffsche Taktangabe") mich von vorn herein an eine eigene Lösungssuche heranmache, weiß ich nicht, wie und womit ich beginnen soll.

Auch diesmal hatte ich den von Harm6 geposteten code Zeile für Zeile angesehen und mir leuchtete (fast) jedes Detail ein. Wüßte ich erstmal von wo aus und womit ich den nötigen Input herbekomme und wohin und womit ich die Ergebnisse rausschicken muß, wäre der Rest für mich sicherlich machbar. Die Informationen logisch und arithmetisch zu verknüpfen, um zu den wunschgemäß geänderten Parametern zu kommen, würde ich mir dann schon zutrauen.

Kurz gesagt: Was mir fehlt, ist der jeweilige Ansatz und ich frage mich jedesmal, wenn ich die Lösungen der Experten betrachte: Wie um Himmels willen, ist er wohl darauf gekommen?

Der "missing link" ist m.E. nicht, fehlende scheme-Kenntnis/-Erfahrung, sondern ein für mich nachvollziehbarer Ablauf für die Suche nach geeigneten Stellen, wo man in der lilypond-Umgebung "anfassen" muß. Also: Von wo und womit beziehe ich die für das Problem relevanten Informationen? Und wohin und womit schiebe ich das Ergebnis meiner Manipulation, damit das Gewünschte draus gemacht wird?

Soviel zur Vorrede. Nun zu meiner Anregung / Bitte:

Würde sich vielleicht einer der erfahrenen Experten bereit erklären, sich der Mühe zu unterziehen, anhand von wenigen, evtl. im Forum bereits bekannten Problemlösungen, seine Anfangsüberlegungen darzulegen?

Ihr könnt mir glauben, daß ich nicht einfach nur zu faul bin, die einschlägigen manuals zu lesen. Das habe ich bereits intensiv getan. Irgendwo stehe ich aber immer wieder auf dem Schlauch bei der Frage "Wonach mußt Du jetzt eigentlich suchen - und wo?"

Für jede irgendwie geartete Resonanz bin ich dankbar

Marno

harm6

  • Member
Re: Hilfe zum Finden von Lösungsansätzen - scheme Programmierung
« Antwort #1 am: Mittwoch, 2. Dezember 2015, 12:53 »
Zitat von: marno
Eine gewisse Anzahl von Schipseln für lilypond konnte ich mittlerweile aus diversen Ecken des www schon für meine Zwecke anpassen und verändern, was schon zu einigem Verständnis beigetragen hat. Aber jedes mal, wenn ich (wie im vorliegenden Fall "Orffsche Taktangabe") mich von vorn herein an eine eigene Lösungssuche heranmache, weiß ich nicht, wie und womit ich beginnen soll.

Das ist genau der richtige Weg. Im Laufe der Zeit wächst das Verständnis immer weiter. Zumindest habe ich mich genauso entwickelt.

Als Beispiel kann man ruhig die "Orffsche Taktangabe" benutzen. Der finale Code ist der momentane Endpunkt einer Entwicklung.

a)
Natürlich kann man 'stencil überschreiben.
Die rein mauelle Methode wird schon hier gezeigt:
http://lsr.di.unimi.it/LSR/Item?id=554

b)
Automatisiert hier:
http://lsr.di.unimi.it/LSR/Item?id=642
Aber punktierte Noten sind nicht möglich.

c)
mein älterer post hier:
https://liarchiv.joonet.de/index.php?topic=1962.msg10743#msg10743
kann punktierte ausgeben, indem einige Berechnungen angestellt werden.
Aber noch keine brevis etc, hat auch sonst einige Beschränkungen

d)
meine neuesten Versuche hier:
https://liarchiv.joonet.de/index.php?topic=2127.0

Insoweit ist das Ganze nicht im luftleeren Raum entstanden, sondern vorläufiger Endpunkt einer Entwicklung.


Um mehr Ein- und Überblick zu bekommen wäre mein Rat die posts hier im Forum (und vielleicht auch auf der internationalen mailing-list) zu lesen, zu verstehen und an den Lösungen für Probleme zu arbeiten.
Den source-code zu studieren ist natürlich extrem hilfreich, gerade wenn Programmierkenntnisse bereits da sind.
Allerdings nicht notwendigerweise. Ich selbst bin was scheme angeht absoluter Autodidakt und habe auch keinerlei anderweitige Computer-/Software-Kenntnisse gehabt, bevor ich LilyPond entdeckt habe ;)

Gruß,
  Harm

trulli

  • Member
Re: Hilfe zum Finden von Lösungsansätzen - scheme Programmierung
« Antwort #2 am: Freitag, 4. Dezember 2015, 08:52 »
Ich selbst bin was scheme angeht absoluter Autodidakt und habe auch keinerlei anderweitige Computer-/Software-Kenntnisse gehabt, bevor ich LilyPond entdeckt habe.

Das gibt uns Scheme-Analphabeten Hoffnung.  :)

barrio

  • Member
Re: Hilfe zum Finden von Lösungsansätzen - scheme Programmierung
« Antwort #3 am: Samstag, 27. Februar 2016, 22:10 »
Hallo zusammen,

ich bin zwar weit davon entfernt Experte zu sein, würde aber gern meine (leidvollen) Anfangsversuche und meine aktuellen Strategien mitteilen. Vor einigen Jahren entbrannte mein Entthusiasmus für Lilypond. Mir schien, endlich meine beiden großen Hobbies Klassische Gitarre & Programmierung (und natürlich open source) vereinigen zu können. Ich hatte Grundkenntnisse in verschiedenen Basicdialekten, Assembler auf dem C64 :-) und ein wenig C. Scheme sollte also ein Klacks sein, dachte ich mir so...
Über viel mehr als ein paar snippets einzubinden und anzuwenden bin ich tatsächlich zunächst nicht gekommen (und selbst das nur mit intensiver Hilfe dieses Forum, danke nochmals!). Dann entdeckte ich Python, bekam viele schnelle Erfolgserlebnisse selbst bei komplexen Problemen und lernte nebenbei sehr viel über Programmierkonzepte, auch funktionale. Scheme ist wie viele wissen ein Dialekt von LISP und wird dem funktionalen Paradigma zugerechnet, soweit ich weiß. Es kommt nicht von ungefähr, dass LISP oft spöttisch mit "Lost in irritating silly parenthesis" übersetzt wird. Für einen Anfänger sind diese vielen Klammern einfach verwirrend. Eine einfache LISP-Implementierung kommt dadurch jedoch mit 6 Grammatikformen aus, Python braucht 110, insofern ist LISP vielleicht "einfach".
Dabei muss man meist gar kein Schemeexperte sein, um Musikfunktionen in Lilypond zu schreiben. Allerdings habe ich lange gebraucht, um das Prinzip des mehrfachen "switchens" zwischen Scheme und Lilypond-Syntax wirklich zu verstehen. Beispiel: Noten einfärben
colorNote =
#(define-music-function (parser location my-color)
   (color?)
   #{
     \once \override NoteHead.color = #my-color
     \once \override Stem.color = #my-color
   #})
Die Magie passiert durch die Raute #: colorNote ist eine Lilypondvariable, der wir mit = #( eine Schemefunktion zuweisen, ABER nur der Kopf der Funktion ist in Scheme, wir hüpfen einfach mit #{ zurück zur Lilypondsyntax! Damit nicht genug, mit #my-color greifen wir -in Lilypondsyntax- auf das Argument mycolor aus der Schemefunktion zu. Wenn man es einmal kapiert hat erscheint es so selbstverständlich, dass man mal eben 3x die Syntax wechselt. Dieses "Zusammenspiel" von Scheme- & Lilypondsyntax ist m. E. ein wichtiges Grundprinzip, da man so ohne tiefe Schemekenntnisse eine Menge machen kann. Wem das jetzt zu schnell ging, der schaut am besten hier http://lilypondblog.org/2014/03/music-functions-1-getting-to-grips-with-scheme-in-lilypond/
Damit reduzieren sich viele Probleme auf die Fragestellung: Welche properties (hier: color) welcher Musikobjekte (hier: NoteHead & Stem) muss ich wie und ggf. in welcher Abfolge modifizieren, damit das gewünschte Resultat rauskommt. Hierbei hilft oft die Internals Reference, die alle Musikobjekte mit ihren properties auflistet und dann: Ausprobieren. Sehr hilfreich dabei erscheint mir, ein bischen über die interne Arbeitsweise von Lilypond zu verstehen, v. a. Grundprinzip das jedes spätere grafische Objekt (GROB) von genau EINEM "engraver" in EINEM Kontext erstellt wird. Das würde jetzt hier den Rahmen sprengen, für Interessierte hier eine Masterarbeit (!) zur Architektur von Lilypond. http://lilypond.org/pdf/thesis-erik-sandberg

So, ich hoffe ich konnte damit mehr ent- als verwirren. Bei anhaltendem Frust kann ich wie o. g. nur wärmstens eine kleine Pythonexkursion (mit späterer Rückkehr) empfehlen :-).

Viele Grüße
barrio

erich

  • Member
Re: Hilfe zum Finden von Lösungsansätzen - scheme Programmierung
« Antwort #4 am: Sonntag, 28. Februar 2016, 08:44 »
Hallo allen

Gutes Therma!

Damit nicht genug, mit #my-color greifen wir -in Lilypondsyntax- auf das Argument mycolor aus der Schemefunktion zu.
Müsste wohl auf das Argument my-color heißen.
Gruß Erich
« Letzte Änderung: Sonntag, 28. Februar 2016, 09:25 von erich »

fugenkomponist

  • Member
Re: Hilfe zum Finden von Lösungsansätzen - scheme Programmierung
« Antwort #5 am: Sonntag, 28. Februar 2016, 09:05 »
Nein, #my-color ist da schon richtig. Was barrio meinte: Innerhalb des Lilypond-Blocks #{ #} nutzen wir per # wieder die Scheme-Syntax und rufen my-color auf. So, wie es ja auch sonst bei \overrides ab und zu passiert.
Gab ein Missverständnis, es ging wohl um my-color vs. mycolor, nicht my-color vs. #my-color (erich hats inzwischen aufgeklärt).
« Letzte Änderung: Sonntag, 28. Februar 2016, 10:11 von fugenkomponist »

erich

  • Member
Re: Hilfe zum Finden von Lösungsansätzen - scheme Programmierung
« Antwort #6 am: Sonntag, 28. Februar 2016, 09:20 »
Hallo allen

Der "missing link" ist m.E. nicht, fehlende scheme-Kenntnis/-Erfahrung, sondern ein für mich nachvollziehbarer Ablauf für die Suche nach geeigneten Stellen, wo man in der lilypond-Umgebung "anfassen" muß. Also: Von wo und womit beziehe ich die für das Problem relevanten Informationen? Und wohin und womit schiebe ich das Ergebnis meiner Manipulation, damit das Gewünschte draus gemacht wird?
Das geht mir noch immer so: Ich kenne viele Programmiersprachen von Assembler auf der Z22 und Algol-60, LISP bis Python. Vielleicht liegt darin der Unterschied zwischen mir und harm, dass harm nicht - wie im Gegensatz zu mir -  durch eine Unzahl von programmiersprachlichen Paradigmen belastet ist.

Schwierig wird es eben, wenn man sich selbst auf Fehlersuche begibt, wenn man nicht nur etwas hinbekommen will sondern wissen will, warum oder wie etwas geht. Vielleicht helfen mir die Ausführungen von Erik Sandberg weiter, ich werde sie lesen.

Mir fehlt die Möglichkeit, einen Zwischenschritt einzulegen:

Ich würde gerne das, was \displayMusic ausgibt, als dump zur Verfügung haben, das ich außerhalb von LP modifizieren kann und dann unter LP wieder verwenden kann.

Ich habe auch noch nicht entdeckt, wie man Funktionen hintereinander ausführen kann also eine funktionale Verknüpfung bequem programmieren kann.

Aber der anweisungsorientierte Ansatz von LP gefällt mir sehr!

Gruß Erich

fugenkomponist

  • Member
Re: Hilfe zum Finden von Lösungsansätzen - scheme Programmierung
« Antwort #7 am: Sonntag, 28. Februar 2016, 09:47 »
Ich habe auch noch nicht entdeckt, wie man Funktionen hintereinander ausführen kann also eine funktionale Verknüpfung bequem programmieren kann.
Das fänd ich auch interessant; ich kenne so Sachen wie
increment = (1+)
square x = x * x
squareAndIncrement = increment . square
aus Haskell (das ist so schon kompletter lauffähiger Code, der Aufruf squareAndIncrement 5 ergibt dann 26; hier ist wohlgemerkt 1+ kein Funktionsname wie in Scheme, sondern die Funktion + schonmal auf das erste Argument 1 angewendet, somit erwartet increment selbst nur noch ein weiteres Argument). Ich habe das Gefühl, dass sowas in Scheme immer auf lambda-Ausdrücke hinausläuft … Die gibts in Haskell auch (und alternativ könnte ich außerdem das Argument wie bei square schon vorher angeben), aber so eine kurze Schreibweise ist doch viel angenehmer auf Dauer.

Edit: Mir ist wieder eingefallen, wie das heißt: Funktionen höherer Ordnung/higher order functions. Sowas gibts in Scheme anscheinend doch, hab zumindest das hier gefunden; compose sieht so aus, als wärs das, was wir suchen (und was in Haskell einfach (.) heißt). Ich bin mir aber nicht sicher, ob/wie ich increment ohne lambda definieren könnte …

2. Edit: Folgendes funktioniert jedenfalls nicht:
\version "2.19.36"
#(define (increment) (+ 1))
#(display (procedure? increment)) % ##t
#(display (increment 3))
Achso, das liegt vermutlich daran, dass + beliebig viele Argumente nimmt.
« Letzte Änderung: Sonntag, 28. Februar 2016, 09:56 von fugenkomponist »

fugenkomponist

  • Member
Re: Hilfe zum Finden von Lösungsansätzen - scheme Programmierung
« Antwort #8 am: Sonntag, 28. Februar 2016, 10:23 »
Ich würde gerne das, was \displayMusic ausgibt, als dump zur Verfügung haben, das ich außerhalb von LP modifizieren kann und dann unter LP wieder verwenden kann.
Mir ist nicht ganz klar, was du hier meinst. Du kannst genau diese Ausgabe in deine LilyPond-Datei reinpacken und noch ein # davor setzen (weil es sich ja um Scheme-Code handelt), schon bekommst du die gleiche Notenausgabe.

Oder ging es darum, wie du in Scheme diese Struktur veränderst? Dafür sind music-map und verwandte Funktionen (mit einem lambda-Ausdruck, der die eigentliche Veränderung ausführt), ly:music-property, ly:music-set-property, music-is-of-type? und einige weitere zuständig. Eine (unvollständige?) Liste solcher Funktionen findet sich in der Internals Reference.

erich

  • Member
Re: Hilfe zum Finden von Lösungsansätzen - scheme Programmierung
« Antwort #9 am: Sonntag, 28. Februar 2016, 11:42 »
Hallo fugenkomponist,

Zitat
Du kannst genau diese Ausgabe in deine LilyPond-Datei reinpacken und noch ein # davor setzen (weil es sich ja um Scheme-Code handelt), schon bekommst du die gleiche Notenausgabe.

guter Hinweis, danke!

Gruß Erich

p.s. ich habe das mal ausprobiert; was fehlt ist allesdings das Environment. So taugt es noch nicht als Austauschformat.
« Letzte Änderung: Sonntag, 28. Februar 2016, 13:42 von erich »

Manuela

  • Member
Re: Hilfe zum Finden von Lösungsansätzen - scheme Programmierung
« Antwort #10 am: Donnerstag, 3. März 2016, 12:21 »

Ich würde gerne das, was \displayMusic ausgibt, als dump zur Verfügung haben, das ich außerhalb von LP modifizieren kann und dann unter LP wieder verwenden kann.


Ich weiß zwar nicht genau, warum es funktioniert, aber ich glaube, du meinst das:

{
  #(with-output-to-file "display.txt"
      (lambda () #{ \displayMusic { c'4\f } #}))
}