]> git.donarmstrong.com Git - lilypond.git/blobdiff - Documentation/extending/scheme-tutorial.itely
Merge branch 'master' into lilypond/translation
[lilypond.git] / Documentation / extending / scheme-tutorial.itely
index c61c556c1ddd567c6990e4aaba68298f3e38e399..0e608682159d2302f5bfa39ce3b23e51b772cd3d 100644 (file)
@@ -4,10 +4,11 @@
     Translation of GIT committish: FILL-IN-HEAD-COMMITTISH
 
     When revising a translation, copy the HEAD committish of the
     Translation of GIT committish: FILL-IN-HEAD-COMMITTISH
 
     When revising a translation, copy the HEAD committish of the
-    version that you are working on.  See TRANSLATION for details.
+    version that you are working on.  For details, see the Contributors'
+    Guide, node Updating translation committishes..
 @end ignore
 
 @end ignore
 
-@c \version "2.12.0"
+@c \version "2.14.0"
 
 @node Scheme tutorial
 @chapter Scheme tutorial
 
 @node Scheme tutorial
 @chapter Scheme tutorial
@@ -27,9 +28,9 @@ Scheme.  If you want to know more about Scheme, see
 @uref{http://@/www@/.schemers@/.org}.
 
 LilyPond uses the GNU Guile implementation of Scheme, which is
 @uref{http://@/www@/.schemers@/.org}.
 
 LilyPond uses the GNU Guile implementation of Scheme, which is
-based on the Scheme @qq{R5RS} standard. If you are learning Scheme
+based on the Scheme @qq{R5RS} standard.  If you are learning Scheme
 to use with LilyPond, working with a different implementation (or
 to use with LilyPond, working with a different implementation (or
-referring to a different standard) is not recommended. Information
+referring to a different standard) is not recommended.  Information
 on guile can be found at @uref{http://www.gnu.org/software/guile/}.
 The @qq{R5RS} Scheme standard is located at
 @uref{http://www.schemers.org/Documents/Standards/R5RS/}.
 on guile can be found at @uref{http://www.gnu.org/software/guile/}.
 The @qq{R5RS} Scheme standard is located at
 @uref{http://www.schemers.org/Documents/Standards/R5RS/}.
@@ -67,12 +68,12 @@ Scheme.  On most systems you can experiment in a Scheme sandbox by
 opening a terminal window and typing @q{guile}.  On some systems,
 notably Windows, you may need to set the environment variable
 @code{GUILE_LOAD_PATH} to the directory @code{../usr/shr/guile/1.8}
 opening a terminal window and typing @q{guile}.  On some systems,
 notably Windows, you may need to set the environment variable
 @code{GUILE_LOAD_PATH} to the directory @code{../usr/shr/guile/1.8}
-in the LilyPond installation. For the full path to this directory
+in the LilyPond installation.  For the full path to this directory
 see @rlearning{Other sources of information}.  Alternatively, Windows
 users may simply choose @q{Run} from the Start menu and enter
 @q{guile}.
 
 see @rlearning{Other sources of information}.  Alternatively, Windows
 users may simply choose @q{Run} from the Start menu and enter
 @q{guile}.
 
-Once the guile sandbox is running, you will received a guile prompt:
+Once the guile sandbox is running, you will receive a guile prompt:
 
 @lisp
 guile>
 
 @lisp
 guile>
@@ -102,7 +103,7 @@ guile> a
 guile>
 @end lisp
 
 guile>
 @end lisp
 
-Scheme variables can be printed on the display by use of the display function:
+Scheme variables can be printed on the display by using the display function:
 
 @lisp
 guile> (display a)
 
 @lisp
 guile> (display a)
@@ -110,9 +111,9 @@ guile> (display a)
 @end lisp
 
 @noindent
 @end lisp
 
 @noindent
-Note that the value @code{2} and the guile prompt @code{guile} both
-showed up on the same line.  This can be avoided by calling the newline
-procedure or displaying a newline character.
+Note that both the value @code{2} and the guile prompt @code{guile}
+showed up on the same line.  This can be avoided by calling the
+newline procedure or displaying a newline character.
 
 @lisp
 guile> (display a)(newline)
 
 @lisp
 guile> (display a)(newline)
@@ -147,11 +148,11 @@ and False is @code{#f}.
 
 @item Numbers
 Numbers are entered in the standard fashion,
 
 @item Numbers
 Numbers are entered in the standard fashion,
-@code{1} is the (integer) number one, while @code{-1.5} is a
+@code{1} is the (integer) number one, while @w{@code{-1.5}} is a
 floating point number (a non-integer number).
 
 @item Strings
 floating point number (a non-integer number).
 
 @item Strings
-Strings are enclosed in double quotes,
+Strings are enclosed in double quotes:
 
 @example
 "this is a string"
 
 @example
 "this is a string"
@@ -197,7 +198,7 @@ For a complete listing see the Guile reference guide,
 There are also compound data types in Scheme.  The  types commonly used in
 LilyPond programming include pairs, lists, alists, and hash tables.
 
 There are also compound data types in Scheme.  The  types commonly used in
 LilyPond programming include pairs, lists, alists, and hash tables.
 
-@unnumberedsubsubsec Pairs
+@subheading 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.
 
 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.
@@ -252,8 +253,7 @@ Note:  @code{cdr} is pronounced "could-er", according Sussman and
 Abelson, see
 @uref{http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-14.html#footnote_Temp_133}
 
 Abelson, see
 @uref{http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-14.html#footnote_Temp_133}
 
-
-@unnumberedsubsubsec Lists
+@subheading Lists
 
 A very common Scheme data structure is the @emph{list}.  Formally, a
 list is defined as either the empty list (represented as @code{'()},
 
 A very common Scheme data structure is the @emph{list}.  Formally, a
 list is defined as either the empty list (represented as @code{'()},
@@ -283,7 +283,7 @@ Lists are a central part of Scheme.  In, fact, Scheme is considered
 a dialect of lisp, where @q{lisp} is an abbreviation for
 @q{List Processing}.  Scheme expressions are all lists.
 
 a dialect of lisp, where @q{lisp} is an abbreviation for
 @q{List Processing}.  Scheme expressions are all lists.
 
-@unnumberedsubsubsec Association lists (alists)
+@subheading 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.
 
 A special type of list is an @emph{association list} or @emph{alist}.
 An alist is used to store data for easy retrieval.
@@ -307,7 +307,7 @@ guile>
 
 Alists are widely used in LilyPond to store properties and other data.
 
 
 Alists are widely used in LilyPond to store properties and other data.
 
-@unnumberedsubsubsec Hash tables
+@subheading 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
 
 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
@@ -406,13 +406,14 @@ guile> (/ 7.0 3.0)
 2.33333333333333
 @end lisp
 
 2.33333333333333
 @end lisp
 
-When the scheme interpreter encounters an expression that is a list, the
-first element of the list is treated as a procedure to be evaluated
-with the arguments of the remainder of the list.  Therefore, all operators
-in Scheme are prefix operators.
+When the scheme interpreter encounters an expression that is a list,
+the first element of the list is treated as a procedure to be
+evaluated with the arguments of the remainder of the list.  Therefore,
+all operators in Scheme are prefix operators.
 
 
-If the first element of a Scheme expression that is a list passed to the
-interpreter`is @emph{not} an operator or procedure, an error will occur:
+If the first element of a Scheme expression that is a list passed to
+the interpreter is @emph{not} an operator or procedure, an error will
+occur:
 
 @lisp
 guile> (1 2 3)
 
 @lisp
 guile> (1 2 3)
@@ -427,10 +428,11 @@ ABORT: (misc-error)
 guile>
 @end lisp
 
 guile>
 @end lisp
 
-Here you can see that the interpreter was trying to treat 1 as an operator
-or procedure, and it couldn't.  Hence the error is "Wrong type to apply: 1".
+Here you can see that the interpreter was trying to treat 1 as an
+operator or procedure, and it couldn't.  Hence the error is "Wrong
+type to apply: 1".
 
 
-To create a list, then , we need to use the list operator, or we need to
+Therefore, to create a list we need to use the list operator, or to
 quote the list so that the interpreter will not try to evaluate it.
 
 @lisp
 quote the list so that the interpreter will not try to evaluate it.
 
 @lisp
@@ -471,11 +473,11 @@ The quote mark @code{'} prevents the Scheme interpreter from substituting
 @node Scheme procedures
 @subsection Scheme procedures
 
 @node Scheme procedures
 @subsection Scheme procedures
 
-Scheme procedures are executable scheme expressions that return
-a value resulting from their execution.,  They can also manipulate
+Scheme procedures are executable scheme expressions that return a
+value resulting from their execution.  They can also manipulate
 variables defined outside of the procedure.
 
 variables defined outside of the procedure.
 
-@unnumberedsubsubsec Defining procedures
+@subheading Defining procedures
 
 Procedures are defined in Scheme with define
 
 
 Procedures are defined in Scheme with define
 
@@ -501,7 +503,7 @@ guile> (average 3 12)
 15/2
 @end lisp
 
 15/2
 @end lisp
 
-@unnumberedsubsubsec Predicates
+@subheading Predicates
 
 Scheme procedures that return boolean values are often called
 @emph{predicates}.  By convention (but not necessity), predicate names
 
 Scheme procedures that return boolean values are often called
 @emph{predicates}.  By convention (but not necessity), predicate names
@@ -515,7 +517,12 @@ guile> (less-than-ten? 15)
 #f
 @end lisp
 
 #f
 @end lisp
 
-@unnumberedsubsubsec Return values
+@subheading Return values
+
+Scheme procedures always return a return value, which is the value
+of the last expression executed in the procedure.  The return
+value can be any valid Scheme value, including a complex data
+structure or a procedure.
 
 Sometimes the user would like to have multiple Scheme expressions in
 a procedure.  There are two ways that multiple expressions can be
 
 Sometimes the user would like to have multiple Scheme expressions in
 a procedure.  There are two ways that multiple expressions can be
@@ -543,7 +550,7 @@ guile> (let ((x 2) (y 3) (z 4)) (display (+ x y)) (display (- z 4))
 @node Scheme conditionals
 @subsection Scheme conditionals
 
 @node Scheme conditionals
 @subsection Scheme conditionals
 
-@unnumberedsubsubsec if
+@subheading if
 
 Scheme has an @code{if} procedure:
 
 
 Scheme has an @code{if} procedure:
 
@@ -563,7 +570,7 @@ guile> (if (> a b) "a is greater than b" "a is not greater than b")
 "a is not greater than b"
 @end lisp
 
 "a is not greater than b"
 @end lisp
 
-@unnumberedsubsubsec cond
+@subheading cond
 
 Another conditional procedure in scheme is @code{cond}:
 
 
 Another conditional procedure in scheme is @code{cond}:
 
@@ -601,20 +608,25 @@ guile> (cond ((< a b) "a is less than b")
 @node LilyPond Scheme syntax
 @subsection LilyPond Scheme syntax
 
 @node LilyPond Scheme syntax
 @subsection LilyPond Scheme syntax
 
-In a music file, snippets of Scheme code are introduced with the hash
-mark @code{#}.  So, the previous examples translated to LilyPond are
+The Guile interpreter is part of LilyPond, which means that
+Scheme can be included in LilyPond input files.  The hash mark@tie{}@code{#}
+is used to tell the LilyPond parser that the next value is a Scheme
+value.
+
+Once the parser sees a hash mark, input is passed to the Guile
+interpreter to evaluate the Scheme expression.  The interpreter continues
+to process input until the end of a Scheme expression is seen.
+
+Scheme procedures can be defined in LilyPond input files:
 
 @example
 
 @example
-##t ##f
-#1 #-1.5
-#"this is a string"
-#"this
-is
-a string"
+#(define (average a b c) (/ (+ a b c) 3))
 @end example
 
 Note that LilyPond comments (@code{%} and @code{%@{ %@}}) cannot
 @end example
 
 Note that LilyPond comments (@code{%} and @code{%@{ %@}}) cannot
-be used within Scheme code.  Comments in Guile Scheme are entered
+be used within Scheme code, even in a LilyPond input file, because
+the Guile interpreter, not the LilyPond parser, is interpreting
+the Scheme expression.  Comments in Guile Scheme are entered
 as follows:
 
 @example
 as follows:
 
 @example
@@ -627,9 +639,13 @@ as follows:
 !#
 @end example
 
 !#
 @end example
 
-Multiple consecutive scheme expressions in a music file can be
-combined using the @code{begin} operator. This permits the number
-of hash marks to be reduced to one.
+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
+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
+@code{begin} statement:
 
 @example
 #(begin
 
 @example
 #(begin
@@ -637,39 +653,34 @@ of hash marks to be reduced to one.
   (define bar 1))
 @end example
 
   (define bar 1))
 @end example
 
-@c todo -- # introduces a scheme *expression*
-@c         need the concept of an expression
-
-If @code{#} is followed by an opening parenthesis, @code{(}, as in
-the example above, the parser will remain in Scheme mode until
-a matching closing parenthesis, @code{)}, is found, so further
-@code{#} symbols to introduce a Scheme section are not required.
-
-For the rest of this section, we will assume that the data is entered
-in a music file, so we add @code{#}s everywhere.
 
 @node LilyPond variables
 @subsection LilyPond variables
 
 
 @node LilyPond variables
 @subsection LilyPond variables
 
-
-TODO -- make this read right
-
-A similar thing
-happens with variables.  After defining a variable
+LilyPond variables are stored internally in the form of Scheme
+variables.  Thus,
 
 @example
 twelve = 12
 @end example
 
 @noindent
 
 @example
 twelve = 12
 @end example
 
 @noindent
-variables can also be used in expressions, here
+is equivalent to
+
+@example
+#(define twelve 12)
+@end example
+
+This means that LilyPond variables are available
+for use in Scheme expressions.  For example, we could use
 
 @example
 
 @example
-twentyFour = (* 2 twelve)
+twentyFour = #(* 2 twelve)
 @end example
 
 @noindent
 @end example
 
 @noindent
-the number 24 is stored in the variable @code{twentyFour}.
+which would result in the number 24 being stored in the
+LilyPond (and Scheme) variable @code{twentyFour}.
 
 @node Input variables and Scheme
 @subsection Input variables and Scheme
 
 @node Input variables and Scheme
 @subsection Input variables and Scheme
@@ -687,10 +698,12 @@ traLaLa = @{ c'4 d'4 @}
 There is also a form of scoping: in the following example, the
 @code{\layout} block also contains a @code{traLaLa} variable, which is
 independent of the outer @code{\traLaLa}.
 There is also a form of scoping: in the following example, the
 @code{\layout} block also contains a @code{traLaLa} variable, which is
 independent of the outer @code{\traLaLa}.
+
 @example
 traLaLa = @{ c'4 d'4 @}
 \layout @{ traLaLa = 1.0 @}
 @end example
 @example
 traLaLa = @{ c'4 d'4 @}
 \layout @{ traLaLa = 1.0 @}
 @end example
+
 @c
 In effect, each input file is a scope, and all @code{\header},
 @code{\midi}, and @code{\layout} blocks are scopes nested inside that
 @c
 In effect, each input file is a scope, and all @code{\header},
 @code{\midi}, and @code{\layout} blocks are scopes nested inside that
@@ -698,18 +711,20 @@ toplevel scope.
 
 Both variables and scoping are implemented in the GUILE module system.
 An anonymous Scheme module is attached to each scope.  An assignment of
 
 Both variables and scoping are implemented in the GUILE module system.
 An anonymous Scheme module is attached to each scope.  An assignment of
-the form
+the form:
+
 @example
 traLaLa = @{ c'4 d'4 @}
 @end example
 
 @noindent
 @example
 traLaLa = @{ c'4 d'4 @}
 @end example
 
 @noindent
-is internally converted to a Scheme definition
+is internally converted to a Scheme definition:
+
 @example
 (define traLaLa @var{Scheme value of `@code{... }'})
 @end example
 
 @example
 (define traLaLa @var{Scheme value of `@code{... }'})
 @end example
 
-This means that input variables and Scheme variables may be freely
+This means that LilyPond variables and Scheme variables may be freely
 mixed.  In the following example, a music fragment is stored in the
 variable @code{traLaLa}, and duplicated using Scheme.  The result is
 imported in a @code{\score} block by means of a second variable
 mixed.  In the following example, a music fragment is stored in the
 variable @code{traLaLa}, and duplicated using Scheme.  The result is
 imported in a @code{\score} block by means of a second variable
@@ -765,24 +780,28 @@ define some Scheme code in a macro (to be called later), use
 @knownissues
 
 Mixing Scheme and LilyPond variables is not possible with the
 @knownissues
 
 Mixing Scheme and LilyPond variables is not possible with the
-@code{--safe} option.
-
-
+@option{--safe} option.
 
 
 @node Object properties
 @subsection Object properties
 
 
 
 @node Object properties
 @subsection Object properties
 
-This syntax will be used very frequently, since many of the layout
-tweaks involve assigning (Scheme) values to internal variables, for
-example
+Object properties are stored in LilyPond in the form of alist-chains,
+which are lists of alists.  Properties are set by adding values at
+the beginning of the property list.  Properties are read by retrieving
+values from the alists.
+
+Setting a new value for a property requires assigning a value to
+the alist with both a key and a value.  The LilyPond syntax for doing
+this is:
 
 @example
 \override Stem #'thickness = #2.6
 @end example
 
 
 @example
 \override Stem #'thickness = #2.6
 @end example
 
-This instruction adjusts the appearance of stems.  The value @code{2.6}
-is put into the @code{thickness} variable of a @code{Stem}
+This instruction adjusts the appearance of stems.  An alist entry
+@code{'(thickness . 2.6)} is added to the property list of the
+@code{Stem}
 object.  @code{thickness} is measured relative to the thickness of
 staff lines, so these stem lines will be @code{2.6} times the
 width of staff lines.  This makes stems almost twice as thick as their
 object.  @code{thickness} is measured relative to the thickness of
 staff lines, so these stem lines will be @code{2.6} times the
 width of staff lines.  This makes stems almost twice as thick as their
@@ -790,7 +809,7 @@ normal size.  To distinguish between variables defined in input files (like
 @code{twentyFour} in the example above) and variables of internal
 objects, we will call the latter @q{properties} and the former
 @q{variables.}  So, the stem object has a @code{thickness} property,
 @code{twentyFour} in the example above) and variables of internal
 objects, we will call the latter @q{properties} and the former
 @q{variables.}  So, the stem object has a @code{thickness} property,
-while @code{twentyFour} is an variable.
+while @code{twentyFour} is a variable.
 
 @cindex properties vs. variables
 @cindex variables vs. properties
 
 @cindex properties vs. variables
 @cindex variables vs. properties
@@ -802,41 +821,70 @@ while @code{twentyFour} is an variable.
 @node LilyPond compound variables
 @subsection LilyPond compound variables
 
 @node LilyPond compound variables
 @subsection LilyPond compound variables
 
-@unnumberedsubsubsec Offsets
+@subheading Offsets
 
 
-Two-dimensional offsets (X and Y coordinates) as well as object sizes
-(intervals with a left and right point) are entered as @code{pairs}.  A
-pair@footnote{In Scheme terminology, the pair is called @code{cons},
-and its two elements are called @code{car} and @code{cdr} respectively.}
-is entered as @code{(first . second)} and, like symbols, they must be quoted,
+Two-dimensional offsets (X and Y coordinates) are stored as @code{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)
 @end example
 
 
 @example
 \override TextScript #'extra-offset = #'(1 . 2)
 @end example
 
-This assigns the pair (1, 2) to the @code{extra-offset} property of the
+This assigns the pair @code{(1 . 2)} to the @code{extra-offset}
+property of the
 TextScript object.  These numbers are measured in staff-spaces, so
 this command moves the object 1 staff space to the right, and 2 spaces up.
 
 TextScript object.  These numbers are measured in staff-spaces, so
 this command moves the object 1 staff space to the right, and 2 spaces up.
 
-@unnumberedsubsubsec Extents
+Procedures for working with offsets are found in @file{scm/lily-library.scm}.
+
+@subheading Extents
 
 
-todo -- write something about 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}).
+Intervals are used to store the X- and Y- extents of printable objects.
+For X extents, the @code{car} is the left hand X coordinate, and the
+@code{cdr} is the right hand X coordinate.  For Y extents, the @code{car}
+is the bottom coordinate, and the @code{cdr} is the top coordinate.
 
 
-@unnumberedsubsubsec Property alists
+Procedures for working with intervals are found in
+@file{scm/lily-library.scm}.  These procedures should be used when possible
+to ensure consistency of code.
 
 
-todo -- write something about property alists
+@subheading Property alists
 
 
-@unnumberedsubsubsec Alist chains
+A property alist is a LilyPond data structure that is an alist whose
+keys are properties and whose values are Scheme expressions that give
+the desired value for the property.
 
 
-todo -- write something about alist chains
+LilyPond properties are Scheme symbols, such as @code{'thickness}.
+
+@subheading Alist chains
+
+An alist chain is a list containing property alists.
+
+The set of all properties that will apply to a grob is typically
+stored as an alist chain.  In order to find the value for a particular
+property that a grob should have, each alist in the chain is searched in
+order, looking for an entry containing the property key.  The first alist
+entry found is returned, and the value is the property value.
+
+The Scheme procedure @code{chain-assoc-get} is normally used to get
+grob property values.
 
 @node Internal music representation
 @subsection Internal music representation
 
 
 @node Internal music representation
 @subsection Internal music representation
 
+Internally, music is represented as a Scheme list.  The list contains
+various elements that affect the printed output.  Parsing is the process
+of converting music from the LilyPond input representation to the
+internal Scheme representation.
+
 When a music expression is parsed, it is converted into a set of
 Scheme music objects.  The defining property of a music object is that
 When a music expression is parsed, it is converted into a set of
 Scheme music objects.  The defining property of a music object is that
-it takes up time.  Time is a rational number that measures the length
-of a piece of music in whole notes.
+it takes up time.  The time it takes up is called its @emph{duration}.
+Durations are expressed as a rational number that measures the length
+of the music object in whole notes.
 
 A music object has three kinds of types:
 @itemize
 
 A music object has three kinds of types:
 @itemize
@@ -889,7 +937,6 @@ to create complicated music functions.
 * Adding articulation to notes (example)::
 @end menu
 
 * Adding articulation to notes (example)::
 @end menu
 
-
 @node Displaying music expressions
 @subsection Displaying music expressions
 
 @node Displaying music expressions
 @subsection Displaying music expressions
 
@@ -940,8 +987,7 @@ a file.
 lilypond file.ly >display.txt
 @end example
 
 lilypond file.ly >display.txt
 @end example
 
-With a bit of reformatting, the above information is
-easier to read,
+With a bit of reformatting, the above information is easier to read,
 
 @example
 (make-music 'SequentialMusic
 
 @example
 (make-music 'SequentialMusic
@@ -964,6 +1010,10 @@ pitch properties) and any extra information (in this case, an
 @node Music properties
 @subsection Music properties
 
 @node Music properties
 @subsection Music properties
 
+TODO -- make sure we delineate between @emph{music} properties,
+@emph{context} properties, and @emph{layout} properties.  These
+are potentially confusing.
+
 The @code{NoteEvent} object is the first object of the
 @code{'elements} property of @code{someNote}.
 
 The @code{NoteEvent} object is the first object of the
 @code{'elements} property of @code{someNote}.
 
@@ -1085,7 +1135,7 @@ Now we examine the input,
 @end example
 
 So in our function, we need to clone this expression (so that we
 @end example
 
 So in our function, we need to clone this expression (so that we
-have two notes to build the sequence), add @code{SlurEvents} to the
+have two notes to build the sequence), add a @code{SlurEvent} to the
 @code{'elements} property of each one, and finally make a
 @code{SequentialMusic} with the two @code{EventChords}.
 
 @code{'elements} property of each one, and finally make a
 @code{SequentialMusic} with the two @code{EventChords}.
 
@@ -1277,14 +1327,13 @@ We may verify that this music function works correctly,
 
 
 
 
 
 
-
 @ignore
 @menu
 * Tweaking with Scheme::
 @end menu
 
 @ignore
 @menu
 * Tweaking with Scheme::
 @end menu
 
-@c @node Tweaking with Scheme
-@c @section Tweaking with Scheme
+@c @nod e Tweaking with Scheme
+@c @sectio n Tweaking with Scheme
 
 We have seen how LilyPond output can be heavily modified using
 commands like
 
 We have seen how LilyPond output can be heavily modified using
 commands like