]> git.donarmstrong.com Git - lilypond.git/blobdiff - Documentation/extending/scheme-tutorial.itely
Doc: Extending - rewrite - LilyPond Variables
[lilypond.git] / Documentation / extending / scheme-tutorial.itely
index 7503306b1fa56f3e8c16b0f6d25b5f5e8d8f28a6..5984c4f038c926d962627ef67aafb5b6cf1e886f 100644 (file)
@@ -8,7 +8,7 @@
     Guide, node Updating translation committishes..
 @end ignore
 
     Guide, node Updating translation committishes..
 @end ignore
 
-@c \version "2.17.11"
+@c \version "2.19.22"
 
 @node Scheme tutorial
 @chapter Scheme tutorial
 
 @node Scheme tutorial
 @chapter Scheme tutorial
@@ -72,7 +72,7 @@ see @rlearning{Other sources of information}.  Alternatively, Windows
 users may simply choose @q{Run} from the Start menu and enter
 @q{guile}.
 
 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
 available with this command line:
 @example
 lilypond scheme-sandbox
@@ -275,9 +275,10 @@ Abelson, see
 @node Lists
 @unnumberedsubsubsec 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:
 
 There are many ways of creating lists.  Perhaps the most common is
 with the @code{list} procedure:
@@ -287,12 +288,19 @@ guile> (list 1 2 3 "abc" 17.5)
 (1 2 3 "abc" 17.5)
 @end lisp
 
 (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")
 
 @lisp
 guile> '(17 23 "foo" "bar" "bazzle")
@@ -679,7 +687,7 @@ 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
 
 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}
 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}
@@ -687,18 +695,18 @@ 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.
 
 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
 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
 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.  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
+consistent with the current LilyPond mode are accepted.
+
+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 $@@
 @code{ly:music-deep-copy} explicitly.
 
 @funindex $@@
@@ -730,11 +738,11 @@ as follows:
 @end example
 
 For the rest of this section, we will assume that the data is entered
 @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
 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
 @code{begin} statement:
 
 @example
@@ -769,17 +777,28 @@ twentyFour = #(* 2 twelve)
 @end example
 
 @noindent
 @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
 
 @node Input variables and Scheme
 @subsection Input variables and Scheme
@@ -869,7 +888,7 @@ $(make-sequential-music newLa)
 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
 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
 
 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
@@ -1104,7 +1123,7 @@ to create complicated music functions.
 
 When writing a music function it is often instructive to inspect how
 a music expression is stored internally.  This can be done with the
 
 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
 @{
 
 @example
 @{
@@ -1156,7 +1175,7 @@ your port and reuse it:
 @end example
 
 Guile's manual describes ports in detail.  Closing the port is actually
 @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
+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:
 the first example, we did not bother to do so.
 
 A bit of reformatting makes the above information easier to read:
@@ -1164,13 +1183,13 @@ A bit of reformatting makes the above information easier to read:
 @example
 (make-music 'SequentialMusic
   'elements (list
 @example
 (make-music 'SequentialMusic
   'elements (list
-            (make-music 'NoteEvent
+             (make-music 'NoteEvent
                'articulations (list
                '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{@{ @dots{} @}} music sequence has the name
 @end example
 
 A @code{@{ @dots{} @}} music sequence has the name
@@ -1188,9 +1207,11 @@ interpreted as well as displayed.  To avoid interpretation, write
 @node Music properties
 @subsection Music properties
 
 @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.
 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:
 
 
 Let's look at an example:
 
@@ -1243,7 +1264,7 @@ expression.
 @end example
 
 Then the note pitch is accessed through the @code{'pitch} property
 @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
 
 @example
 #(display-scheme-music
@@ -1253,7 +1274,7 @@ of the @code{NoteEvent} object,
 (ly:make-pitch 0 0 0)
 @end example
 
 (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
 
 
 @funindex \displayLilyMusic
 
@@ -1263,7 +1284,7 @@ The note pitch can be changed by setting this @code{'pitch} property,
        (ly:make-pitch 0 1 0)) ;; set the pitch to d'.
 \displayLilyMusic \someNote
 ===>
        (ly:make-pitch 0 1 0)) ;; set the pitch to d'.
 \displayLilyMusic \someNote
 ===>
-d'
+d'4
 @end example
 
 
 @end example
 
 
@@ -1308,7 +1329,7 @@ The bad news is that the @code{SlurEvent} expressions
 must be added @q{inside} the note (in its @code{articulations}
 property).
 
 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'
 
 @example
 \displayMusic a'
@@ -1330,7 +1351,7 @@ property, it is useful to know that an unset property is read out as
 put another element at the front of the @code{articulations} property.
 
 @example
 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)))
          "Return: @{ note ( note ) @}.
          `note' is supposed to be a single note."
          (let ((note2 (ly:music-deep-copy note)))
@@ -1373,7 +1394,7 @@ the articulation to an empty chord,
 
 @noindent
 but for the sake of this example, we will learn how to do this in
 
 @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
 
 @example
 %  input
@@ -1501,12 +1522,12 @@ Finally, once we have added the accent articulation to its
 @code{articulations} property, we can return @code{note-event}, hence
 the last line of the function.
 
 @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
 
 @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."
                                      (ly:music?)
   "Add an accent ArticulationEvent to the articulations of `note-event',
   which is supposed to be a NoteEvent expression."
@@ -1517,7 +1538,7 @@ addAccent = #(define-music-function (parser location note-event)
   note-event)
 @end example
 
   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
 
 @example
 \displayMusic \addAccent c4
@@ -1551,13 +1572,13 @@ TODO Find a simple example
 
 @ignore
 @lilypond[quote,verbatim,ragged-right]
 
 @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
   \padText #1.8
   c4^"piu mosso" d e f
   \padText #2.6
@@ -1574,16 +1595,16 @@ We can use it to create new commands:
 
 
 @lilypond[quote,verbatim,ragged-right]
 
 
 @lilypond[quote,verbatim,ragged-right]
-tempoPadded = #(define-music-function (parser location padding tempotext)
+tempoPadded = #(define-music-function (padding tempotext)
   (number? markup?)
 #{
   \once \override Score.MetronomeMark.padding = #padding
   \tempo \markup { \bold #tempotext }
 #})
 
   (number? markup?)
 #{
   \once \override Score.MetronomeMark.padding = #padding
   \tempo \markup { \bold #tempotext }
 #})
 
-\relative c'' {
+\relative {
   \tempo \markup { "Low tempo" }
   \tempo \markup { "Low tempo" }
-  c4 d e f g1
+  c''4 d e f g1
   \tempoPadded #4.0 "High tempo"
   g4 f e d c1
 }
   \tempoPadded #4.0 "High tempo"
   g4 f e d c1
 }
@@ -1593,7 +1614,7 @@ tempoPadded = #(define-music-function (parser location padding tempotext)
 Even music expressions can be passed in:
 
 @lilypond[quote,verbatim,ragged-right]
 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
 #})