[ < ] [ > ]   [ << ] [ Nach oben ] [ >> ]         [Anfang] [Inhalt] [Index] [ ? ]

2.2 Scheme-Funktionen

@translationof Scheme functions

Scheme-Funktionen sind Scheme-Prozeduren, die Scheme-Ausdrücke aus einer Eingabe erstellen können, die in LilyPond-Syntax geschrieben wurde. Sie können in so gut wie allen Fällen aufgerufen werden, in denen es erlaubt ist, # zur Angabe eines Wertes in Scheme-Syntax einzusetzen. Während Scheme auch eigene Funktionen besitzt, handelt % dieses kapitel von syntaktischen Funktionen, Funktionen, die Argumente in LilyPond-Syntax annehmen.


[ < ] [ > ]   [ << ] [ Nach oben ] [ >> ]         [Anfang] [Inhalt] [Index] [ ? ]

2.2.1 Definition von Scheme-Funktionen

@translationof Scheme function definitions

Die übliche Form zur Definition von Scheme-Funktionen ist:

 
function =
#(define-scheme-function
     (Arg1 Arg2 …)
     (Typ1? Typ2? …)
   body)

wobei

parserganz genau das Wort parser sein muss, damit LilyPond eine Umgebung (#{…#}) mit Zugriff auf den Parser bekommt.
ArgNnte Argument
TypN?eine Scheme-Typenprädikat, für welches argN #t ausgeben muss. Manche dieser Prädikate werden vom Parser besonders erkannt, siehe unten. Es gibt auch eine Spezialform (predicate? default), um optionale Argumente anzugeben. Wenn das eigentlich Argument fehlt, während die Funktion aufgerufen wird, wird der Standardwert anstelle eingesetzt. Standardwerte werden bei ihrer Definition evaluiert (gilt auch für LilyPond-Codeabschnitte), so dass man besser einen speziellen Wert schreibt, den man einfach erkennen kann, wenn der Wert während der Ausführung der Position evaluiert weren soll. Wenn man das Prädikat in Klammern setzt, aber kein Standardwert folt, wird #f als Standard eingesetzt. Standardwerte werden weder bei der Definition noch bei der Ausführung mit predicate? verifiziert, sodass man selber verantworlich für funktionsfähige Werte ist. Standardwerte, die musikalische Ausdrücke darstellen, werden kopiert und origin auf den Parameter location gesetzt.
bodyEine Folge von Scheme-Formeln, die der Reihe nach ausgewertet werden, wobei die letzte als Ausgabewert der Scheme-Funktion eingesetzt wird. Sie kann LilyPond-Codeabschnitte enthalten, eingeschlossen mit Raute-Klammern ( #{…#} ), wie beschrieben in LilyPond-Codeabschnitte. Innerhalb von LilyPond-Codeabschnitten wird mit # auf Funktionsargumente (etwa ‘#Arg1’) verwiesen oder ein neuer Scheme-Ausdruck mit Funktionsargumenten begonnen (etwa ‘#(cons Arg1 Arg2)’). Wo normale Scheme-Ausdrücke mit # nicht funktionieren, kann man auf direkte Scheme-Ausdrücke zurückgreifen, die mit $ begonnen werden (etwa ‘$music’).

Wenn die Funktion eine musikalische Funktion ausgibt, bekommt sie einen Wert von origin. zugewiesen.

Einige Typenprädikate werden vom Parser besonders behandelt, weil er sonst die Argumente nicht zuverlässig erkennen könnte. Im Moment handelt es sich um ly:pitch? und ly:duration?.

Die Eignung der Argumente für alle anderen Prädikate wird festgestellt, indem das Prädikat aufgerufen wird, nachdem LilyPond es schon in einen Scheme-Ausdruck umgewandelt hat. Demzufolge kann das Argument in Scheme-Syntax angegeben werden, wenn nötig (beginnend mit # oder als Result des Aufrufes einer Scheme-Funktion), aber LilyPond konvertiert auch eine Reihe von LilyPond-Strukturen nach Scheme, bevor dann tatsächlich die Prädikate überprüft werden. Bei den letzteren handelt es sich im Moment um music (Noten), postevents, simple strings (einfache Zeichenketten mit oder ohne Anführungszeichen) numbers (Zahlen), markup (Beschriftung) und markup lists (Beschriftungslisten), score (Partitur), book (Buch), bookpart (Buchteil), Kontextdefinitions- und Ausgabedefinitionsumgebungen.

Für einige Arten von Ausdrücken (wie die meisten Noten, die nicht in Klammern geschrieben werden) muss LilyPond weiter nach vorne schauen als der Ausdruck selber reicht, um das Ende des Ausdrucks zu bestimmen. Wenn solche Ausdrücke für optionale Argumente mit einbezogen würden, indem ihre Prädikate ausgewählt würden, könnte LilyPond nicht mehr zurückgehen, wenn es feststellt, dass der Ausdruck nicht zu dem Parameter passt. Darum müssen manche Formen von Noten möglicherweise in Klammern eingeschlossen werden, damit LilyPond sie akzeptiert. Es gibt auch einige andere Mehrdeutigkeiten, die LilyPond durch Testen von Prädikatfunktionen eingrenzt: ist etwa ‘-3’ die Anmerkung für einen Fingersatz oder eine negative Zahl? Ist "a" 4 im Gesangskontext eine Zeichenkette gefolgt von einer Zahl oder ein Gesangstextereignis mit der Dauer 4? LilyPond entscheidet, indem es Prädaikate befragt. Das heißt, dass man zu durchlässige Prädikate wie scheme? vermeiden sollte, wenn man eine bestimmmte Verwendung beabsichtigt und nicht nur eine Funktion für die allgemeine Verwendung schreibt.

Eine Liste der möglichen vordefinierten Typenprädikte findet sich in (notation)Vordefinierte Typprädikate in Abschnitt ‘Vordefinierte Typprädikate’ in Notationsreferenz.

Siehe auch

Notationsreferenz (notation)Vordefinierte Typprädikate in Abschnitt ‘Vordefinierte Typprädikate’ in Notationsreferenz.

Installierte Dateien: ‘lily/music-scheme.cc’, ‘scm/c++.scm’, ‘scm/lily.scm’.


[ < ] [ > ]   [ << ] [ Nach oben ] [ >> ]         [Anfang] [Inhalt] [Index] [ ? ]

2.2.2 Benutzung von Scheme-Funktionen

@translationof Scheme function usage

Scheme-Funktionen können überall aufgerufen werden, wo ein Scheme-Ausdruck beginnend mit # geschrieben werden kann. Man kann eine Scheme-Funktion aufrufen, indem man ihrer Bezeichnung \ voranstellt und Argumente hinten anfügt. Wenn ein optionales Argumentenprädikat nicht mit einem Argument übereinstimmt, lässt LilyPond dieses und alle folgenden Argumente aus und ersetzt sie durch ihre Standardwerte und „speichert“ das Argument, das nicht gepasst hat, bis zum nächsten zwingenden Argument. Da das gespeicherte Argument auch noch irgendwo untergebracht werden muss, werden optionale Argumente nicht wirklich als optional angesehen, es sei denn, sie werden von einem zwingenden Argument gefolgt.

Es gibt eine Ausnahme: Wenn man \default anstelle eines optionalen Arguments schreibt, wird dieses und alle folgenden Argumente ausgelassen und durch ihre Standardwerte ersetzt. Das funktioniert auch, wenn kein zwingendes Argument folgt, weil \default nicht gespeichert werden muss. Die Befehle mark und key benützten diesen Trick, um ihr Standardverhalten zur verfügung zu stellen, wenn sie \default nachgestellt haben.

Abgesehen von Stellen, wo ein Scheme-Wert benötigt ist, gibt es wenige Stellen, wo #-Ausdrücke zwar für ihre (Neben-)Wirkung akzeptiert und ausgewertet, aber ansonsten ignoriert werden. Meistens handelt es sich dabei um Stellen, wo eine Zuweisung auch in Ordnung wäre.

Weil es eine schlechte Idee ist, einen Wert auszugeben, der in einigen Kontexten misinterpretiert werden könnte, sollte man Scheme-Funktionen nur in den Fällen benutzen, in welchen sie immer einen sinnvollen Wert ausgeben, und leere Scheme-Funktionen an anderen stellen einsetzen. Siehe auch siehe Abschnitt Leere Scheme-Funktionen.


[ < ] [ > ]   [ << ] [ Nach oben ] [ >> ]         [Anfang] [Inhalt] [Index] [ ? ]

2.2.3 Leere Scheme-Funktionen

@translationof Void scheme functions

Manchmal wird eine Prozedur ausgeführt, um eine Aktion zu machen und nicht, um einen Wert auszugeben. Einige Programmiersprachen (wie C oder Scheme) setzen Funktionen für beide Konzepte ein und verwerfen einfach den Rückgabewert (normalerweise, indem einem Ausdruck erlaubt wird, als Aussage zu funktionieren und das Ergebnis ignoriert wird). Das ist klug, aber auch fehleranfällig: die meisten C-Kompilierer haben heutzutage Warnungen für verschiedene nicht-„gültige“ Ausdrücke, die verworfen werden. Viele Funktionen, die eine Aktion ausführen, werden von den Scheme-Standards als Funktionen betrachtet, deren Wiedergabewert unspezifiert ist. Der Scheme-Interpreter von LilyPond, Guile, hat den eindeutigen Wert *unspecified*, der normalerweise (etwa wenn man set! direkt auf eine Variable anwendet), aber leider nicht konsistent in diesen Fällen ausgegeben wird.

Indem man eine LilyPond-Funktion mit define-void-function definiert, geht man sicher, dass dieser Spezialwert (der einzige Wert, der das Prädikat void? erfüllt) wiedergegeben wird.

 
noPointAndClick =
#(define-void-function
     ()
     ()
   (ly:set-option 'point-and-click #f))
...
\noPointAndClick   % Point and Click deaktivieren

Wenn man einen Ausdruck nur wegen seiner Nebeneffekte evaluieren will und keinen der möglicherweise ausgegebenen Werte interpretiert haben will, kann man dem Ausdruck \void voranstellen:

 
\void #(hashq-set! eine-Tabelle ein-Schlüssel ein-Wert)

Auf diese Weise kann man sicher sein, dass LilyPond dem ausgegebenen Wert keine Bedeutung zuweist, unabhängig davon, wo er angetroffen wird. Das funktioniert auch für musikalische Funktionen wie \displayMusic.


[ < ] [ > ]   [ << ] [ Nach oben ] [ >> ]

Dieses Dokument wurde erzeugt von gub am 13. Juli 2020 durch texi2html 1.82.

Andere Sprachen: English, español, français.
Über die automatische Sprachauswahl.