| [ < ] | [ > ] | [ << ] | [ Nach oben ] | [ >> ] | [Anfang] | [Inhalt] | [Index] | [ ? ] |
@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.
| 2.2.1 Definition von Scheme-Funktionen | ||
| 2.2.2 Benutzung von Scheme-Funktionen | ||
| 2.2.3 Leere Scheme-Funktionen |
| [ < ] | [ > ] | [ << ] | [ Nach oben ] | [ >> ] | [Anfang] | [Inhalt] | [Index] | [ ? ] |
@translationof Scheme function definitions
Die übliche Form zur Definition von Scheme-Funktionen ist:
function =
#(define-scheme-function
(Arg1 Arg2 …)
(Typ1? Typ2? …)
body)
|
wobei
parser | ganz genau das Wort parser sein muss, damit LilyPond
eine Umgebung (#{…#}) mit Zugriff
auf den Parser bekommt. |
ArgN | nte 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. |
body | Eine 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 |
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.
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] | [ ? ] |
@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] | [ ? ] |
@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.