@c -*- coding: utf-8; mode: texinfo; documentlanguage: de -*- @ignore Translation of GIT committish: 5cf864d550e7148412d594cf336841791bff6f76 When revising a translation, copy the HEAD committish of the version that you are working on. See TRANSLATION for details. @end ignore @c \version "2.12.0" @node Scheme-Übung @appendix Scheme-Übung @translationof Scheme tutorial @funindex # @cindex Scheme @cindex GUILE @cindex Scheme, in einer LilyPond-Datei @cindex LISP LilyPond verwendet die Scheme-Programmiersprache sowohl als Teil der Eingabesyntax als auch als internen Mechanismus, um Programmmodule zusammenzufügen. Dieser Abschnitt ist ein sehr kurzer Überblick über die Dateneingabe mit Scheme. Wenn Sie mehr über Scheme wissen wollen, gehen Sie zu @uref{http://@/www@/.schemers@/.org}. LilyPond benutzt die GNU Guile-Implementation von Scheme, die auf dem @qq{R5RS}-Standard von Scheme basiert. Wenn Sie Scheme lernen wollen, um es innerhalb von LilyPond zu benutzen, wird es nicht empfohlen, mit einer anderen Implementation (die sich auf einen anderen Standard bezieht) zu arbeiten. Information zu Guile findet sich unter @uref{http://www.gnu.org/software/guile/}. Der @qq{R5RS}-Standard von Scheme befindet sich unter der Adresse @uref{http://www.schemers.org/Documents/Standards/R5RS/}. Die LilyPond-Installation enthält gleichzeitig auch die Guile-Implemenation von Scheme. Auf den meisten Systemen kann man in einer Scheme-sandbox experimentieren, indem man ein Kommandozeilen-Fenster öffnet und @code{guile} auffruft. Unter einigen Systemen, insbesondere unter Windows, muss man evtl. die Umgebungsvariable @code{GUILE_LOAD_PATH} auf das Verzeichnis @code{../usr/shr/guile/1.8} innerhalb des LilyPond-Installationsverzeichnisses setzen (der vollständige Pfad ist erklärt in @ref{Other sources of information}). Alternativ können Windows-Benutzer auch einfach @qq{Ausführen} im Startmenü wählen und @code{guile} schreiben. Das Grundlegendste an einer Sprache sind Daten: Zahlen, Zeichen, Zeichenketten, Listen usw. Hier ist eine Liste der Datentypen, die für LilyPond-Eingabedateien relevant sind. @table @asis @item Boolesche Variablen Werte einer Booleschen Variable sind Wahr oder Falsch. Die Scheme-Entsprechung für Wahr ist @code{#t} und für Falsch @code{#f}. @funindex ##t @funindex ##f @item Zahlen Zahlen werden wie üblich eingegeben, @code{1} ist die (ganze) Zahl Eins, während @code{-1.5} ist eine Gleitkommazahl (also eine nicht-ganze). @item Zeichenketten Zeichenketten werden in doppelte Anführungszeichen gesetzt: @example "Das ist eine Zeichenkette" @end example Zeichenketten können über mehrere Zeilen reichen: @example "Das ist eine Zeichenkette" @end example Anführungszeichen und neue Zeilen können auch mit sogenannten Fluchtsequenzen eingefügt werden. Die Zeichenkette @code{a sagt "b"} wird wie folgt eingegeben: @example "a sagt \"b\"" @end example Neue Zeilen und Backslashe werden mit @code{\n} bzw. @code{\\} eingegeben. @end table In einer Notationsdatei werden kleine Scheme-Abschnitte mit der Raute (@code{#}) eingeleitet. Die vorigen Beispiele heißen also in LilyPond: @example ##t ##f #1 #-1.5 #"Das ist eine Zeichenkette" #"Das ist eine Zeichenkette" @end example LilyPond-Kommentare (@code{%} oder @code{%@{ %@}}) können innerhalb von Scheme-Code nicht benutzt werden. Kommentare in Guile Scheme werden wie folgt notiert: @example ; Einzeiliges Kommentar #! Guile-Stil Blockkommentar (nicht schachtelbar) Diese Kommentare werden von Scheme-Programmierern selten benutzt und nie im Quellcode von LilyPond !# +@end example Merere aufeinander folgende Scheme-Ausdrücke in einer Notationsdatei können kombiniert werden, wenn man @code{begin} einsetzt. Das erlaubt es, die Anzahl an Rauten auf eins zu begrenzen. @example #(begin (define foo 0) (define bar 1)) @end example Wenn @code{#} von einer öffnenden Klammer, @code{(}, gefolgt wird, wie in dem Beispiel oben, bleibt der Parser im Scheme-Modus bis eine passende schließende Klammer, @code{)}, gefunden wird, sodass keine weiteren @code{#}-Zeichen benötigt werden, um einen Scheme-Abschnitt anzuzeigen. Für den Rest dieses Abschnitts nehmen wir an, dass die Daten immer in einer LilyPond-Datei stehen, darum wird immer die Raute verwendet. Scheme kann verwendet werden, um Berechnungen durchzuführen. Es verwendet eine @emph{Präfix}-Syntax. Um 1 und@tie{}2 zu addieren, muss man @code{(+ 1 2)} schreiben, und nicht @math{1+2}, wie in traditioneller Mathematik. @lisp #(+ 1 2) @result{} #3 @end lisp Der Pfeil @result{} zeigt an, dass das Ergebnis der Auswertung von @code{(+ 1 2)} @code{3}@tie{}ist. Berechnungen können geschachtelt werden und das Ergebnis einer Berechnung kann für eine neue Berechnung eingesetzt werden. @lisp #(+ 1 (* 3 4)) @result{} #(+ 1 12) @result{} #13 @end lisp Diese Berechnungen sind Beispiele von Auswertungen. Ein Ausdruck wie @code{(* 3 4)} wird durch seinen Wert @code{12} ersetzt. Ähnlich verhält es sich mit Variablen. Nachdem eine Variable definiert ist: @example zwoefl = #12 @end example @noindent kann man sie in Ausdrücken weiterverwenden: @example vierundzwanzig = #(* 2 zwoelf) @end example @noindent Die 24 wird in der Variablen @code{vierundzwanzig} gespeichert. Die gleiche Zuweisung kann auch vollständig in Scheme geschrieben werden: @example #(define vierundzwanzig (* 2 zwoelf)) @end example Der @emph{Name} einer Variable ist auch ein Ausdruck, genauso wie eine Zahl oder eine Zeichenkette. Er wird wie folgt eingegeben: @example #'vierundzwanzig @end example @funindex #'symbol @cindex Zitieren in Scheme Das Apostroph @code{'} verhindert, dass bei der Scheme-Auswertung @code{vierundzwanzig} durch @code{24} ersetzt wird. Anstatt dessen erhalten wir die Bezeichnung @code{vierundzwanzig}. Diese Syntax wird sehr oft verwendet, weil es manche Einstellungsveränderungen erfordern, dass Scheme-Werte einer internen Variable zugewiesen werden, wie etwa @example \override Stem #'thickness = #2.6 @end example Diese Anweisung verändert die Erscheinung der Notenhälse. Der Wert @code{2.6} wird der Variable @code{thickness} (Dicke) eines @code{Stem}-(Hals)-Objektes gleichgesetzt. @code{thickness} wird relativ zu den Notenlinien errechnet, in diesem Fall sind die Hälse also 2,6 mal so dick wie die Notenlinien. Dadurch werden Hälse fast zweimal so dick dargestellt, wie sie normalerweise sind. Um zwischen Variablen zu unterscheiden, die in den Quelldateien direkt definiert werden (wie @code{vierundzwanzig} weiter oben), und zwischen denen, die für interne Objekte zuständig sind, werden hier die ersteren @qq{Bezeichner} genannt, die letzteren dagegen @qq{Eigenschaften}. Das Hals-Objekt hat also eine @code{thickness}-Eigenschaft, während @code{vierundzwanzig} ein Bezeichner ist. @cindex Eigenschaften versus Bezeichner @cindex Bezeichner versus Eigenschaften Sowohl zweidimensionale Abstände (X- und Y-Koordinaten) als auch Größen von Objekten (Intervalle mit linker und rechter Begrenzung) werden als @code{pairs} (Paare) eingegeben. Ein Paar@footnote{In der Scheme-Terminologie wird ein Paar @code{cons} genannt und seine zwei Elemente @code{car} und @code{cdr}.} wird als @code{(erster . zweiter)} eingegeben und sie müssen mit dem Apostroph eingeleitet werden, genauso wie Symbole: @example \override TextScript #'extra-offset = #'(1 . 2) @end example Hierdurch wird das Paar (1, 2) mit der Eigenschaft @code{extra-offset} des TextScript-Objektes verknüpft. Diese Zahlen werden in Systembreiten gemessen, so dass der Befehl das Objekt eine Systembreite nach rechts verschiebt und zwei Breiten nach oben. Die zwei Elemente eines Paares können von beliebigem Inhalt sein, etwa @example #'(1 . 2) #'(#t . #f) #'("blah-blah" . 3.14159265) @end example Eine Liste wird eingegeben, indem die Elemente der Liste in Klammern geschrieben werden, mit einem Apostroph davor. Beispielsweise: @example #'(1 2 3) #'(1 2 "string" #f) @end example Die ganze Zeit wurde hier schon Listen benutzt. Eine Berechnung, wie @code{(+ 1 2)}, ist auch eine Liste (welche das Symbol @code{+} und die Nummern 1 und@tie{}2 enthält. Normalerweise werden Listen als Berechnungen interpretiert und der Scheme-Interpreter ersetzt die Liste mit dem Ergebnis der Berechnung. Um eine Liste an sich einzugeben, muss die Auswertung angehalten werden. Das geschieht, indem der Liste ein Apostroph vorangestellt wird. Für Berechnungen kann man also den Apostroph nicht verwenden. Innerhalb einer zitierten Liste (also mit Apostroph) muss man keine Anführungszeichen mehr setzen. Im Folgenden ein Symbolpaar, eine Symbolliste und eine Liste von Listen: @example #'(stem . head) #'(staff clef key-signature) #'((1) (2)) @end example @menu * Optimierungen mit Scheme:: @end menu @node Optimierungen mit Scheme @appendixsec Optimierungen mit Scheme @translationof Tweaking with Scheme Wir haben gesehen wie LilyPond-Eingabe massiv beeinflusst werden kann, indem Befehle wie etwa @code{\override TextScript #'extra-offset = ( 1 . -1)} benutzt werden. Aber es wurde gezeigt, dass Scheme noch mächtiger ist. Eine bessere Erklärung findet sich in der@ref{Scheme-Übung} und in @ruser{Schnittstellen für Programmierer}. Scheme kann auch in einfachen @code{\override}-Befehlen benutzt werden: TODO Find a simple example @c This isn't a valid example with skylining @c It works fine without padText -td @ignore @lilypond[quote,verbatim,ragged-right] padText = #(define-music-function (parser location padding) (number?) #{ \once \override TextScript #'padding = #$padding #}) \relative c''' { c4^"piu mosso" b a b \padText #1.8 c4^"piu mosso" d e f \padText #2.6 c4^"piu mosso" fis a g } @end lilypond @end ignore Es kann auch benutzt werden, um Befehle zu erstellen: @c Check this is a valid example with skylining @c It is - 'padding still works @lilypond[quote,verbatim,ragged-right] tempoPadded = #(define-music-function (parser location padding tempotext) (number? string?) #{ \once \override Score.MetronomeMark #'padding = $padding \tempo \markup { \bold $tempotext } #}) \relative c'' { \tempo \markup { "Low tempo" } c4 d e f g1 \tempoPadded #4.0 #"High tempo" g4 f e d c1 } @end lilypond Sogar ganze Musikausdrücke können eingefügt werden: @lilypond[quote,verbatim,ragged-right] pattern = #(define-music-function (parser location x y) (ly:music? ly:music?) #{ $x e8 a b $y b a e #}) \relative c''{ \pattern c8 c8\f \pattern {d16 dis} { ais16-> b\p } } @end lilypond