Guide, node Updating translation committishes..
@end ignore
-@c \version "2.15.20"
+@c \version "2.19.22"
@node Scheme tutorial
@chapter Scheme tutorial
users may simply choose @q{Run} from the Start menu and enter
@q{guile}.
-However, a hands-on Scheme sandbox with all of Lilypond loaded is
+However, a hands-on Scheme sandbox with all of LilyPond loaded is
available with this command line:
@example
lilypond scheme-sandbox
There are also compound data types in Scheme. The types commonly used in
LilyPond programming include pairs, lists, alists, and hash tables.
-@subheading Pairs
+@menu
+* Pairs::
+* Lists::
+* Association lists (alists)::
+* Hash tables::
+@end menu
+
+@node Pairs
+@unnumberedsubsubsec Pairs
The foundational compound data type of Scheme is the @code{pair}. As
might be expected from its name, a pair is two values glued together.
@lisp
guile> (define mypair (cons 123 "hello there")
-... )
+@dots{} )
guile> (car mypair)
123
guile> (cdr mypair)
Abelson, see
@uref{http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-14.html#footnote_Temp_133}
-@subheading Lists
+@node Lists
+@unnumberedsubsubsec Lists
-A very common Scheme data structure is the @emph{list}. Formally, a
-list is defined as either the empty list (represented as @code{'()},
-or a pair whose @code{cdr} is a list.
+A very common Scheme data structure is the @emph{list}. Formally,
+a @q{proper} list is defined to be either the empty list with its
+input form @code{'()} and length@tie{}0, or a pair whose
+@code{cdr} in turn is a shorter list.
There are many ways of creating lists. Perhaps the most common is
with the @code{list} procedure:
(1 2 3 "abc" 17.5)
@end lisp
-As can be seen, a list is displayed in the form of individual elements
-separated by whitespace and enclosed in parentheses. Unlike a pair,
-there is no period between the elements.
+Representing a list as individual
+elements separated by whitespace and enclosed in parentheses
+is actually a compacted rendition of the actual dotted pairs
+constituting the list, where the dot and an immediately following
+starting paren are removed along with the matching closing paren.
+Without this compaction, the output would have been
+@lisp
+(1 . (2 . (3 . ("abc" . (17.5 . ())))))
+@end lisp
-A list can also be entered as a literal list by enclosing its
-elements in parentheses, and adding a quote:
+As with the output, a list can also be entered (after adding a
+quote to avoid interpretation as a function call) as a literal
+list by enclosing its elements in parentheses:
@lisp
guile> '(17 23 "foo" "bar" "bazzle")
a dialect of lisp, where @q{lisp} is an abbreviation for
@q{List Processing}. Scheme expressions are all lists.
-@subheading Association lists (alists)
+@node Association lists (alists)
+@unnumberedsubsubsec Association lists (alists)
A special type of list is an @emph{association list} or @emph{alist}.
An alist is used to store data for easy retrieval.
Alists are widely used in LilyPond to store properties and other data.
-@subheading Hash tables
+@node Hash tables
+@unnumberedsubsubsec Hash tables
A data structure that is used occasionally in LilyPond. A hash table
is similar to an array, but the indexes to the array can be any type
value resulting from their execution. They can also manipulate
variables defined outside of the procedure.
-@subheading Defining procedures
+@menu
+* Defining procedures::
+* Predicates::
+* Return values::
+@end menu
+
+@node Defining procedures
+@unnumberedsubsubsec Defining procedures
Procedures are defined in Scheme with define
15/2
@end lisp
-@subheading Predicates
+@node Predicates
+@unnumberedsubsubsec Predicates
Scheme procedures that return boolean values are often called
@emph{predicates}. By convention (but not necessity), predicate names
#f
@end lisp
-@subheading Return values
+@node Return values
+@unnumberedsubsubsec Return values
Scheme procedures always return a return value, which is the value
of the last expression executed in the procedure. The return
@lisp
guile> (let ((x 2) (y 3) (z 4)) (display (+ x y)) (display (- z 4))
-... (+ (* x y) (/ z x)))
+@dots{} (+ (* x y) (/ z x)))
508
@end lisp
@node Scheme conditionals
@subsection Scheme conditionals
-@subheading if
+@menu
+* if::
+* cond::
+@end menu
+
+@node if
+@unnumberedsubsubsec if
Scheme has an @code{if} procedure:
"a is not greater than b"
@end lisp
-@subheading cond
+@node cond
+@unnumberedsubsubsec cond
Another conditional procedure in scheme is @code{cond}:
@example
(cond (test-expression-1 result-expression-sequence-1)
(test-expression-2 result-expression-sequence-2)
- ...
+ @dots{}
(test-expression-n result-expression-sequence-n))
@end example
like human language is structured into words and sentences. LilyPond
has a lexer that recognizes tokens (literal numbers, strings, Scheme
elements, pitches and so on), and a parser that understands the syntax,
-@ruser{LilyPond grammar}. Once it knows that a particular syntax rule
+@rcontrib{LilyPond grammar}. Once it knows that a particular syntax rule
applies, it executes actions associated with it.
The hash mark@tie{}@code{#} method of embedding Scheme is a natural fit
Another way to call the Scheme interpreter from LilyPond is the use of
dollar@tie{}@code{$} instead of a hash mark for introducing Scheme
-expressions. In this case, Lilypond evaluates the code right after the
+expressions. In this case, LilyPond evaluates the code right after the
lexer has read it. It checks the resulting type of the Scheme
expression and then picks a token type (one of several
@code{xxx_IDENTIFIER} in the syntax) for it. It creates a @emph{copy}
the expression is void (Guile's value of @code{*unspecified*}), nothing
at all is passed to the parser.
-This is, in fact, exactly the same mechanism that Lilypond employs when
+This is, in fact, exactly the same mechanism that LilyPond employs when
you call any variable or music function by name, as @code{\name}, with
-the only difference that the name is determined by the Lilypond lexer
+the only difference that the name is determined by the LilyPond lexer
without consulting the Scheme reader, and thus only variable names
-consistent with the current Lilypond mode are accepted.
+consistent with the current LilyPond mode are accepted.
-The immediate action of @code{$} can lead to surprises, @ref{Input
-variables and Scheme}. Using @code{#} where the parser supports it is
-usually preferable.
+The immediate action of @code{$} can lead to surprises, see
+@ref{Importing Scheme in LilyPond}. Using @code{#} where the
+parser supports it is usually preferable. Inside of music expressions,
+expressions created using @code{#} @emph{are} interpreted as
+music. However, they are @emph{not} copied before use. If they are
+part of some structure that might still get used, you may need to use
+@code{ly:music-deep-copy} explicitly.
@funindex $@@
@funindex #@@
@end example
For the rest of this section, we will assume that the data is entered
-in a music file, so we add@tie{}@code{#}s at the beginning of each Scheme
+in a music file, so we add a @code{#} at the beginning of each Scheme
expression.
All of the top-level Scheme expressions in a LilyPond input file can
-be combined into a single Scheme expression by the use of the
+be combined into a single Scheme expression by use of the
@code{begin} statement:
@example
@end example
@noindent
-which would result in the number 24 being stored in the
-LilyPond (and Scheme) variable @code{twentyFour}.
-
-The usual way to refer to Lilypond variables, @ref{LilyPond Scheme
-syntax}, is to call them using a backslash, i.e., @code{\twentyFour}.
-Since this creates a copy of the value for most of LilyPond's internal
-types, in particular music expressions, music functions don't usually
-create copies of material they change. For this reason, music
-expressions given with @code{#} should usually not contain material that
-is not either created from scratch or explicitly copied rather than
-directly referenced.
+which would result in the number @emph{24} being stored in the LilyPond
+(and Scheme) variable @code{twentyFour}.
+
+Scheme allows modifying complex expressions in-place and LilyPond makes
+use of this @q{in-place modification} when using music functions. But
+when music expressions are stored in variables rather than entered
+directly the usual expectation, when passing them to music functions,
+would be that the original value is unmodified. So when referencing a
+music variable with leading backslash (such as @code{\twentyFour}),
+LilyPond creates a copy of that variable's music value for use in the
+surrounding music expression rather than using the variable's value
+directly.
+
+Therefore, Scheme music expressions written with the @code{#} syntax
+should be used for material that is created @q{from scratch} (or that is
+explicitly copied) rather than being used, instead, to directly
+reference material.
+
+@seealso
+Extending:
+@ref{LilyPond Scheme syntax}.
+
@node Input variables and Scheme
@subsection Input variables and Scheme
is internally converted to a Scheme definition:
@example
-(define traLaLa @var{Scheme value of `@code{... }'})
+(define traLaLa @var{Scheme value of `@code{@dots{}}'})
@end example
This means that LilyPond variables and Scheme variables may be freely
been written as
@example
-...
+@dots{}
$(make-sequential-music newLa)
@end example
You can use @code{$} with a Scheme expression anywhere you could use
@code{\@var{name}} after having assigned the Scheme expression to a
variable @var{name}. This replacement happens in the @q{lexer}, so
-Lilypond is not even aware of the difference.
+LilyPond is not even aware of the difference.
One drawback, however, is that of timing. If we had been using @code{$}
instead of @code{#} for defining @code{newLa} in the above example, the
written as
@example
-...
-@{ $@@newLa @}
+@dots{}
+@{ #@@newLa @}
@end example
Here, every element of the list stored in @code{newLa} is taken in
sequence and inserted into the list, as if we had written
@example
-@{ $(first newLa) $(second newLa) @}
+@{ #(first newLa) #(second newLa) @}
@end example
Now in all of these forms, the Scheme code is evaluated while the
#(define (nopc)
(ly:set-option 'point-and-click #f))
-...
+@dots{}
#(nopc)
@{ c'4 @}
@end example
this is:
@example
-\override Stem #'thickness = #2.6
+\override Stem.thickness = #2.6
@end example
This instruction adjusts the appearance of stems. An alist entry
@node LilyPond compound variables
@subsection LilyPond compound variables
-@subheading Offsets
+@menu
+* Offsets::
+* Fractions::
+* Extents::
+* Property alists::
+* Alist chains::
+@end menu
+
+@node Offsets
+@unnumberedsubsubsec Offsets
Two-dimensional offsets (X and Y coordinates) are stored as @emph{pairs}.
The @code{car} of the offset is the X coordinate, and the @code{cdr} is
the Y coordinate.
@example
-\override TextScript #'extra-offset = #'(1 . 2)
+\override TextScript.extra-offset = #'(1 . 2)
@end example
This assigns the pair @code{(1 . 2)} to the @code{extra-offset}
Procedures for working with offsets are found in @file{scm/lily-library.scm}.
-@subheading Fractions
+@node Fractions
+@unnumberedsubsubsec Fractions
Fractions as used by LilyPond are again stored as @emph{pairs}, this
time of unsigned integers. While Scheme can represent rational numbers
means @code{(2 . 4)} in Scheme, and @code{#2/4} in LilyPond means
@code{1/2} in Scheme.
-@subheading Extents
+@node Extents
+@unnumberedsubsubsec Extents
Pairs are also used to store intervals, which represent a range of numbers
from the minimum (the @code{car}) to the maximum (the @code{cdr}).
@file{scm/lily-library.scm}. These procedures should be used when possible
to ensure consistency of code.
-@subheading Property alists
+@node Property alists
+@unnumberedsubsubsec Property alists
A property alist is a LilyPond data structure that is an alist whose
keys are properties and whose values are Scheme expressions that give
LilyPond properties are Scheme symbols, such as @code{'thickness}.
-@subheading Alist chains
+@node Alist chains
+@unnumberedsubsubsec Alist chains
An alist chain is a list containing property alists.
When writing a music function it is often instructive to inspect how
a music expression is stored internally. This can be done with the
-music function @code{\displayMusic}
+music function @code{\displayMusic}.
@example
@{
'text
"f"))
'duration
- (ly:make-duration 2 0 1 1)
+ (ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch 0 0 0))))
@end example
By default, LilyPond will print these messages to the console along
with all the other messages. To split up these messages and save
-the results of @code{\display@{STUFF@}}, redirect the output to
-a file.
+the results of @code{\display@{STUFF@}}, you can specify an optional
+output port to use:
@example
-lilypond file.ly >display.txt
+@{
+ \displayMusic #(open-output-file "display.txt") @{ c'4\f @}
+@}
@end example
-With a combined bit of Lilypond and Scheme magic, you can actually
-let Lilypond direct just this output to a file of its own:
-
+This will overwrite a previous output file whenever it is called; if you
+need to write more than one expression, you would use a variable for
+your port and reuse it:
@example
@{
- $(with-output-to-file "display.txt"
- (lambda () #@{ \displayMusic @{ c'4\f @} #@}))
+ port = #(open-output-file "display.txt")
+ \displayMusic \port @{ c'4\f @}
+ \displayMusic \port @{ d'4 @}
+ #(close-output-port port)
@}
@end example
+Guile's manual describes ports in detail. Closing the port is actually
+only necessary if you need to read the file before LilyPond finishes; in
+the first example, we did not bother to do so.
A bit of reformatting makes the above information easier to read:
@example
(make-music 'SequentialMusic
'elements (list
- (make-music 'NoteEvent
+ (make-music 'NoteEvent
'articulations (list
- (make-music 'AbsoluteDynamicEvent
- 'text
- "f"))
- 'duration (ly:make-duration 2 0 1 1)
- 'pitch (ly:make-pitch 0 0 0))))
+ (make-music 'AbsoluteDynamicEvent
+ 'text
+ "f"))
+ 'duration (ly:make-duration 2 0 1/1)
+ 'pitch (ly:make-pitch 0 0 0))))
@end example
-A @code{@{ ... @}} music sequence has the name @code{SequentialMusic},
-and its inner expressions are stored as a list in its @code{'elements}
-property. A note is represented as a @code{NoteEvent} object (storing
-the duration and pitch properties) with attached information (in this
-case, an @code{AbsoluteDynamicEvent} with a @code{"f"} text property)
-stored in its @code{articulations} property.
+A @code{@{ @dots{} @}} music sequence has the name
+@code{SequentialMusic}, and its inner expressions are stored as a list
+in its @code{'elements} property. A note is represented as a
+@code{NoteEvent} object (storing the duration and pitch properties) with
+attached information (in this case, an @code{AbsoluteDynamicEvent} with
+a @code{"f"} text property) stored in its @code{articulations} property.
@funindex{\void}
@code{\displayMusic} returns the music it displays, so it will get
@node Music properties
@subsection Music properties
+@ignore
TODO -- make sure we delineate between @emph{music} properties,
@emph{context} properties, and @emph{layout} properties. These
are potentially confusing.
+@end ignore
Let's look at an example:
(make-music
'NoteEvent
'duration
- (ly:make-duration 2 0 1 1)
+ (ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch 0 0 0))
@end example
(list (make-music
'NoteEvent
'duration
- (ly:make-duration 2 0 1 1)
+ (ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch 0 0 0))))
@end example
(make-music
'NoteEvent
'duration
- (ly:make-duration 2 0 1 1)
+ (ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch 0 0 0))
@end example
Then the note pitch is accessed through the @code{'pitch} property
-of the @code{NoteEvent} object,
+of the @code{NoteEvent} object.
@example
#(display-scheme-music
(ly:make-pitch 0 0 0)
@end example
-The note pitch can be changed by setting this @code{'pitch} property,
+The note pitch can be changed by setting this @code{'pitch} property.
@funindex \displayLilyMusic
(ly:make-pitch 0 1 0)) ;; set the pitch to d'.
\displayLilyMusic \someNote
===>
-d'
+d'4
@end example
'span-direction
-1))
'duration
- (ly:make-duration 2 0 1 1)
+ (ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch 0 5 0))
(make-music
'span-direction
1))
'duration
- (ly:make-duration 2 0 1 1)
+ (ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch 0 5 0))))
@end example
must be added @q{inside} the note (in its @code{articulations}
property).
-Now we examine the input,
+Now we examine the input.
@example
\displayMusic a'
(make-music
'NoteEvent
'duration
- (ly:make-duration 2 0 1 1)
+ (ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch 0 5 0))))
@end example
So in our function, we need to clone this expression (so that we have
two notes to build the sequence), add a @code{SlurEvent} to the
@code{'articulations} property of each one, and finally make a
-@code{SequentialMusic} with the two @code{EventChords}. For adding to a
+@code{SequentialMusic} with the two @code{NoteEvent} elements. For adding to a
property, it is useful to know that an unset property is read out as
@code{'()}, the empty list, so no special checks are required before we
put another element at the front of the @code{articulations} property.
@example
-doubleSlur = #(define-music-function (parser location note) (ly:music?)
+doubleSlur = #(define-music-function (note) (ly:music?)
"Return: @{ note ( note ) @}.
`note' is supposed to be a single note."
(let ((note2 (ly:music-deep-copy note)))
@subsection Adding articulation to notes (example)
The easy way to add articulation to notes is to merge two music
-expressions into one context, as explained in @ruser{Creating contexts}.
+expressions into one context.
However, suppose that we want to write a music function that does this.
This will have the additional advantage that we can use that music
function to add an articulation (like a fingering instruction) to a
single note inside of a chord which is not possible if we just merge
independent music.
-A @code{$variable} inside the @code{#@{...#@}} notation is like
+A @code{$variable} inside the @code{#@{@dots{}#@}} notation is like
a regular @code{\variable} in classical LilyPond notation. We
know that
@noindent
but for the sake of this example, we will learn how to do this in
-Scheme. We begin by examining our input and desired output,
+Scheme. We begin by examining our input and desired output.
@example
% input
(make-music
'NoteEvent
'duration
- (ly:make-duration 2 0 1 1)
+ (ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch -1 0 0))))
=====
'articulation-type
"accent"))
'duration
- (ly:make-duration 2 0 1 1)
+ (ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch -1 0 0))
@end example
too!)
@example
-"Add an accent..."
+"Add an accent@dots{}"
@end example
@noindent
@code{articulations} property, we can return @code{note-event}, hence
the last line of the function.
-Now we transform the @code{add-accent} function into a music
-function (a matter of some syntactic sugar and a declaration of the type
-of its sole @q{real} argument).
+Now we transform the @code{add-accent} function into a music function (a
+matter of some syntactic sugar and a declaration of the type of its
+argument).
@example
-addAccent = #(define-music-function (parser location note-event)
+addAccent = #(define-music-function (note-event)
(ly:music?)
"Add an accent ArticulationEvent to the articulations of `note-event',
which is supposed to be a NoteEvent expression."
note-event)
@end example
-We may verify that this music function works correctly,
+We then verify that this music function works correctly:
@example
\displayMusic \addAccent c4
We have seen how LilyPond output can be heavily modified using
commands like
-@code{\override TextScript #'extra-offset = ( 1 . -1)}. But
+@code{\override TextScript.extra-offset = ( 1 . -1)}. But
we have even more power if we use Scheme. For a full explanation
of this, see the @ref{Scheme tutorial}, and
@ref{Interfaces for programmers}.
@ignore
@lilypond[quote,verbatim,ragged-right]
-padText = #(define-music-function (parser location padding) (number?)
+padText = #(define-music-function (padding) (number?)
#{
- \once \override TextScript #'padding = #padding
+ \once \override TextScript.padding = #padding
#})
-\relative c''' {
- c4^"piu mosso" b a b
+\relative {
+ c'''4^"piu mosso" b a b
\padText #1.8
c4^"piu mosso" d e f
\padText #2.6
@lilypond[quote,verbatim,ragged-right]
-tempoPadded = #(define-music-function (parser location padding tempotext)
- (number? string?)
+tempoPadded = #(define-music-function (padding tempotext)
+ (number? markup?)
#{
- \once \override Score.MetronomeMark #'padding = $padding
+ \once \override Score.MetronomeMark.padding = #padding
\tempo \markup { \bold #tempotext }
#})
-\relative c'' {
+\relative {
\tempo \markup { "Low tempo" }
- c4 d e f g1
- \tempoPadded #4.0 #"High tempo"
+ c''4 d e f g1
+ \tempoPadded #4.0 "High tempo"
g4 f e d c1
}
@end lilypond
Even music expressions can be passed in:
@lilypond[quote,verbatim,ragged-right]
-pattern = #(define-music-function (parser location x y) (ly:music? ly:music?)
+pattern = #(define-music-function (x y) (ly:music? ly:music?)
#{
- $x e8 a b $y b a e
+ #x e8 a b #y b a e
#})
\relative c''{