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
-@c \version "2.12.0"
+@c \version "2.14.0"
@node Scheme tutorial
@chapter Scheme tutorial
@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
-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/}.
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}.
-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>
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)
@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)
@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
-Strings are enclosed in double quotes,
+Strings are enclosed in double quotes:
@example
"this is a string"
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.
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 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.
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
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)
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
@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.
-@unnumberedsubsubsec Defining procedures
+@subheading Defining procedures
Procedures are defined in Scheme with define
@lisp
guile> (average 3 12)
15/2
-@end list
+@end lisp
-@unnumberedsubsubsec Predicates
+@subheading Predicates
Scheme procedures that return boolean values are often called
@emph{predicates}. By convention (but not necessity), predicate names
#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
@node Scheme conditionals
@subsection Scheme conditionals
-@unnumberedsubsubsec if
+@subheading if
-@unnumberedsubsubsec cond
+Scheme has an @code{if} procedure:
+@example
+(if test-expression true-expression false-expression)
+@end example
+
+@var{test-expression} is an expression that returns a boolean
+value. If @var{test-expression} returns @code{#t}, the if
+procedure returns the value of @var{true-expression}, otherwise
+it returns the value of @var{false-expression}.
+
+@lisp
+guile> (define a 3)
+guile> (define b 5)
+guile> (if (> a b) "a is greater than b" "a is not greater than b")
+"a is not greater than b"
+@end lisp
+
+@subheading 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)
+ ...
+ (test-expression-n result-expression-sequence-n))
+@end example
+
+For example:
+
+@lisp
+guile> (define a 6)
+guile> (define b 8)
+guile> (cond ((< a b) "a is less than b")
+... ((= a b) "a equals b")
+... ((> a b) "a is greater than b"))
+"a is less than b"
+@end lisp
@node Scheme in LilyPond
@section Scheme in LilyPond
@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
-##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
-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
!#
@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
(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
-
-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
-variables can also be used in expressions, here
+is equivalent to
@example
-twentyFour = (* 2 twelve)
+#(define twelve 12)
+@end example
+
+This means that LilyPond variables are available
+for use in Scheme expressions. For example, we could use
+
+@example
+twentyFour = #(* 2 twelve)
@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
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
+
@c
In effect, each input file is a scope, and all @code{\header},
@code{\midi}, and @code{\layout} blocks are scopes nested inside that
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
-is internally converted to a Scheme definition
+is internally converted to a Scheme definition:
+
@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
Scheme code is evaluated as soon as the parser encounters it. To
define some Scheme code in a macro (to be called later), use
-@ref{Void functions}, or
+@ref{Void scheme functions}, or
@example
#(define (nopc)
@knownissues
Mixing Scheme and LilyPond variables is not possible with the
-@code{--safe} option.
-
-
+@option{--safe} option.
@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
-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
@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
@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
-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.
-@unnumberedsubsubsec Extents
+Procedures for working with offsets are found in @file{scm/lily-library.scm}.
+
+@subheading 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.
+
+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 extents
+@subheading 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
+the desired value for the property.
-todo -- write something about property alists
+LilyPond properties are Scheme symbols, such as @code{'thickness}.
-@unnumberedsubsubsec Alist chains
+@subheading Alist chains
-todo -- write something about 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
+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
-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
* Adding articulation to notes (example)::
@end menu
-
@node Displaying music expressions
@subsection Displaying music expressions
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
pitch properties) and any extra information (in this case, an
@code{AbsoluteDynamicEvent} with a @code{"f"} text property.
+@funindex{\void}
+@code{\displayMusic} returns the music it displays, so it will get
+interpreted as well as displayed. To avoid interpretation, write
+@code{\void} before @code{\displayMusic}.
@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}.
@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}.
-
@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