]> git.donarmstrong.com Git - lilypond.git/blobdiff - Documentation/extending/scheme-tutorial.itely
Remove unnecessary std
[lilypond.git] / Documentation / extending / scheme-tutorial.itely
index 64bb01a28cd8a3b2cd1277ffa360a18375fcae05..24865121692f8eb705d2d670cebbb71897b72823 100644 (file)
@@ -8,12 +8,11 @@
     Guide, node Updating translation committishes..
 @end ignore
 
-@c \version "2.12.0"
+@c \version "2.15.20"
 
 @node Scheme tutorial
 @chapter Scheme tutorial
 
-@funindex #
 @cindex Scheme
 @cindex GUILE
 @cindex Scheme, in-line code
@@ -28,9 +27,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
-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/}.
@@ -68,12 +67,19 @@ 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}
-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:
+However, a hands-on Scheme sandbox with all of Lilypond loaded is
+available with this command line:
+@example
+lilypond scheme-sandbox
+@end example
+
+@noindent
+Once the sandbox is running, you will receive a guile prompt:
 
 @lisp
 guile>
@@ -103,7 +109,7 @@ guile> a
 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)
@@ -111,9 +117,9 @@ 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)
@@ -148,11 +154,11 @@ and False is @code{#f}.
 
 @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"
@@ -406,13 +412,14 @@ guile> (/ 7.0 3.0)
 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)
@@ -427,10 +434,11 @@ ABORT: (misc-error)
 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
@@ -471,8 +479,8 @@ The quote mark @code{'} prevents the Scheme interpreter from substituting
 @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.
 
 @subheading Defining procedures
@@ -517,6 +525,11 @@ guile> (less-than-ten? 15)
 
 @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
 combined.  The first is the @code{begin} procedure, which allows
@@ -600,21 +613,68 @@ guile> (cond ((< a b) "a is less than b")
 
 @node LilyPond Scheme syntax
 @subsection LilyPond Scheme syntax
+@funindex $
+@funindex #
 
-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.  There are several
+methods for including Scheme in LilyPond.
+
+The simplest way is to use a hash mark@tie{}@code{#} before a Scheme
+expression.
+
+Now LilyPond's input is structured into tokens and expressions, much
+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
+applies, it executes actions associated with it.
+
+The hash mark@tie{}@code{#} method of embedding Scheme is a natural fit
+for this system.  Once the lexer sees a hash mark, it calls the Scheme
+reader to read one full Scheme expression (this can be an identifier, an
+expression enclosed in parentheses, or several other things).  After the
+Scheme expression is read, it is stored away as the value for an
+@code{SCM_TOKEN} in the grammar.  Once the parser knows how to make use
+of this token, it calls Guile for evaluating the Scheme expression.
+Since the parser usually requires a bit of lookahead from the lexer to
+make its parsing decisions, this separation of reading and evaluation
+between lexer and parser is exactly what is needed to keep the execution
+of LilyPond and Scheme expressions in sync.  For this reason, you should
+use the hash mark@tie{}@code{#} for calling Scheme whenever this is
+feasible.
+
+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
+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}
+of the value and uses that for the value of the token.  If the value of
+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
+you call any variable or music function by name, as @code{\name}, with
+the only difference that its end is determined by the Lilypond lexer
+without consulting the Scheme reader, and thus only variable names
+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.
+
+Now let's take a look at some actual Scheme code.  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 lexer, is reading
+the Scheme expression.  Comments in Guile Scheme are entered
 as follows:
 
 @example
@@ -627,9 +687,13 @@ as follows:
 !#
 @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
@@ -637,39 +701,43 @@ of hash marks to be reduced to one.
   (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
+#(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)
+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}.
+
+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.
 
 @node Input variables and Scheme
 @subsection Input variables and Scheme
@@ -687,10 +755,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}.
+
 @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
@@ -698,18 +768,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
-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
@@ -718,9 +790,6 @@ imported in a @code{\score} block by means of a second variable
 @lilypond[verbatim]
 traLaLa = { c'4 d'4 }
 
-%% dummy action to deal with parser lookahead
-#(display "this needs to be here, sorry!")
-
 #(define newLa (map ly:music-deep-copy
   (list traLaLa traLaLa)))
 #(define twice
@@ -731,27 +800,39 @@ traLaLa = { c'4 d'4 }
 
 @c Due to parser lookahead
 
-In this example, the assignment happens after the parser has
-verified that nothing interesting happens after
-@code{traLaLa = @{ ... @}}.  Without the dummy statement in the
-above example, the @code{newLa} definition is executed before
-@code{traLaLa} is defined, leading to a syntax error.
+This is actually a rather interesting example.  The assignment will only
+take place after the parser has ascertained that nothing akin to
+@code{\addlyrics} follows, so it needs to check what comes next.  It
+reads @code{#} and the following Scheme expression @emph{without}
+evaluating it, so it can go ahead with the assignment, and
+@emph{afterwards} execute the Scheme code without problem.
 
 The above example shows how to @q{export} music expressions from the
 input to the Scheme interpreter.  The opposite is also possible.  By
-wrapping a Scheme value in the function @code{ly:export}, a Scheme
+placing it after @code{$}, a Scheme
 value is interpreted as if it were entered in LilyPond syntax.
 Instead of defining @code{\twice}, the example above could also have
 been written as
 
 @example
 ...
-@{ #(ly:export (make-sequential-music (list newLa))) @}
+@{ $(make-sequential-music (list newLa)) @}
 @end example
 
-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
+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.
+
+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
+following Scheme definition would have failed because @code{traLaLa}
+would not yet have been defined.  For an explanation of this timing
+problem, @ref{LilyPond Scheme syntax}.
+
+In any case, evaluation of Scheme code happens in the parser at latest.
+If you need it to be executed at a later point of time, @ref{Void scheme
+functions}, or store it in a macro:
 
 @example
 #(define (nopc)
@@ -765,24 +846,28 @@ define some Scheme code in a macro (to be called later), use
 @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
@@ -790,7 +875,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,
-while @code{twentyFour} is an variable.
+while @code{twentyFour} is a variable.
 
 @cindex properties vs. variables
 @cindex variables vs. properties
@@ -804,39 +889,68 @@ while @code{twentyFour} is an variable.
 
 @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.
 
+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.
+
+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.
 
 @subheading Property alists
 
-todo -- write something about 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.
+
+LilyPond properties are Scheme symbols, such as @code{'thickness}.
 
 @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
@@ -939,8 +1053,18 @@ a file.
 lilypond file.ly >display.txt
 @end example
 
-With a bit of reformatting, the above information is
-easier to read,
+With a combined bit of Lilypond and Scheme magick, you can actually
+let Lilypond direct just this output to a file of its own:
+
+@example
+@{
+  $(with-output-to-file "display.txt"
+      (lambda () #@{ \displayMusic @{ c'4\f @} #@}))
+@}
+@end example
+
+
+A bit of reformatting makes the above information easier to read:
 
 @example
 (make-music 'SequentialMusic
@@ -959,10 +1083,18 @@ containing a @code{NoteEvent} object (storing the duration and
 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}.
 
@@ -1084,7 +1216,7 @@ Now we examine the input,
 @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}.
 
@@ -1276,14 +1408,13 @@ We may verify that this music function works correctly,
 
 
 
-
 @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
@@ -1303,7 +1434,7 @@ TODO Find a simple example
 @lilypond[quote,verbatim,ragged-right]
 padText = #(define-music-function (parser location padding) (number?)
 #{
-  \once \override TextScript #'padding = #$padding
+  \once \override TextScript #'padding = #padding
 #})
 
 \relative c''' {
@@ -1328,7 +1459,7 @@ tempoPadded = #(define-music-function (parser location padding tempotext)
   (number? string?)
 #{
   \once \override Score.MetronomeMark #'padding = $padding
-  \tempo \markup { \bold $tempotext }
+  \tempo \markup { \bold #tempotext }
 #})
 
 \relative c'' {