]> git.donarmstrong.com Git - lilypond.git/blobdiff - Documentation/extending/scheme-tutorial.itely
Remove unnecessary std
[lilypond.git] / Documentation / extending / scheme-tutorial.itely
index 58a20421346f0aefa1542d934dc36c318b27baa4..24865121692f8eb705d2d670cebbb71897b72823 100644 (file)
@@ -8,12 +8,11 @@
     Guide, node Updating translation committishes..
 @end ignore
 
-@c \version "2.13.36"
+@c \version "2.15.20"
 
 @node Scheme tutorial
 @chapter Scheme tutorial
 
-@funindex #
 @cindex Scheme
 @cindex GUILE
 @cindex Scheme, in-line code
@@ -73,7 +72,14 @@ 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 receive 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>
@@ -148,7 +154,7 @@ 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
@@ -607,17 +613,59 @@ guile> (cond ((< a b) "a is less than b")
 
 @node LilyPond Scheme syntax
 @subsection LilyPond Scheme syntax
+@funindex $
+@funindex #
 
 The Guile interpreter is part of LilyPond, which means that
-Scheme can be included in LilyPond input files.  The hash mark @code{#}
-is used to tell the LilyPond parser that the next value is a Scheme
-value.
+Scheme can be included in LilyPond input files.  There are several
+methods for including Scheme in LilyPond.
 
-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.
+The simplest way is to use a hash mark@tie{}@code{#} before a Scheme
+expression.
 
-Scheme procedures can be defined in LilyPond input files:
+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
 #(define (average a b c) (/ (+ a b c) 3))
@@ -625,7 +673,7 @@ Scheme procedures can be defined in LilyPond input files:
 
 Note that LilyPond comments (@code{%} and @code{%@{ %@}}) cannot
 be used within Scheme code, even in a LilyPond input file, because
-the Guile interpreter, not the LilyPond parser, is interpreting
+the Guile interpreter, not the LilyPond lexer, is reading
 the Scheme expression.  Comments in Guile Scheme are entered
 as follows:
 
@@ -640,7 +688,7 @@ as follows:
 @end example
 
 For the rest of this section, we will assume that the data is entered
-in a music file, so we add @code{#}s at the beginning of each Scheme
+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
@@ -682,6 +730,15 @@ twentyFour = #(* 2 twelve)
 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
 
@@ -733,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
@@ -746,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)
@@ -780,7 +846,7 @@ 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
@@ -987,7 +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
@@ -1006,6 +1083,10 @@ 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
@@ -1353,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''' {
@@ -1378,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'' {