Guide, node Updating translation committishes..
@end ignore
-@c \version "2.13.36"
+@c \version "2.17.6"
@node Scheme tutorial
@chapter Scheme tutorial
-@funindex #
@cindex Scheme
@cindex GUILE
@cindex Scheme, in-line code
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}
+@code{GUILE_LOAD_PATH} to the directory @code{../usr/share/guile/1.8}
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 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>
@end lisp
-You can enter Scheme expressions at this prompt to experiment with Scheme.
+You can enter Scheme expressions at this prompt to experiment with
+Scheme. If you want to be able to use the GNU readline library for
+nicer editing of the Scheme command line, check the file
+@file{ly/scheme-sandbox.ly} for more information. If you already have
+enabled the readline library for your interactive Guile sessions outside
+of LilyPond, this should work in the sandbox as well.
@node Scheme variables
@subsection Scheme variables
@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
* LilyPond Scheme syntax::
* LilyPond variables::
* Input variables and Scheme::
+* Importing Scheme in LilyPond::
* Object properties::
* LilyPond compound variables::
* Internal music representation::
@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 the name 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. 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 $@@
+@funindex #@@
+There are also @q{list splicing} operators @code{$@@} and @code{#@@}
+that insert all elements of a list in the surrounding context.
+
+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))
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:
@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
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
@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
(make-sequential-music newLa))
-{ \twice }
+\twice
@end lilypond
@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.
+
+@node Importing Scheme in LilyPond
+@subsection Importing Scheme in LilyPond
+@funindex $
+@funindex #
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 newLa)
+@end example
+
+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}.
+
+@funindex $@@
+@funindex #@@
+A further convenience can be the @q{list splicing} operators @code{$@@}
+and @code{#@@} for inserting the elements of a list in the surrounding
+context. Using those, the last part of the example could have been
+written as
+
+@example
+...
+@{ #@@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
+Here, every element of the list stored in @code{newLa} is taken in
+sequence and inserted into the list, as if we had written
+
+@example
+@{ #(first newLa) #(second newLa) @}
+@end example
+
+Now in all of these forms, the Scheme code is evaluated while the
+input is still being consumed, either in the lexer or in the parser.
+If you need it to be executed at a later point of time, check out
+@ref{Void scheme functions}, or store it in a procedure:
@example
#(define (nopc)
@knownissues
Mixing Scheme and LilyPond variables is not possible with the
-@code{--safe} option.
+@option{--safe} option.
@node Object properties
this is:
@example
-\override Stem #'thickness = #2.6
+\override Stem.thickness = #2.6
@end example
This instruction adjusts the appearance of stems. An alist entry
@subheading Offsets
-Two-dimensional offsets (X and Y coordinates) are stored as @code{pairs}.
+Two-dimensional offsets (X and Y coordinates) are stored as @emph{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)
+\override TextScript.extra-offset = #'(1 . 2)
@end example
This assigns the pair @code{(1 . 2)} to the @code{extra-offset}
Procedures for working with offsets are found in @file{scm/lily-library.scm}.
+@subheading Fractions
+
+Fractions as used by LilyPond are again stored as @emph{pairs}, this
+time of unsigned integers. While Scheme can represent rational numbers
+as a native type, musically @samp{2/4} and @samp{1/2} are not the same,
+and we need to be able to distinguish between them. Similarly there are
+no negative @q{fractions} in LilyPond's mind. So @code{2/4} in LilyPond
+means @code{(2 . 4)} in Scheme, and @code{#2/4} in LilyPond means
+@code{1/2} in Scheme.
+
@subheading Extents
Pairs are also used to store intervals, which represent a range of numbers
'SequentialMusic
'elements
(list (make-music
- 'EventChord
- 'elements
+ 'NoteEvent
+ 'articulations
(list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch 0 0 0))
- (make-music
'AbsoluteDynamicEvent
'text
- "f")))))
+ "f"))
+ 'duration
+ (ly:make-duration 2 0 1 1)
+ 'pitch
+ (ly:make-pitch 0 0 0))))
@end example
By default, LilyPond will print these messages to the console along
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 magic, 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
- 'elements (list (make-music 'EventChord
- 'elements (list (make-music 'NoteEvent
- 'duration (ly:make-duration 2 0 1 1)
- 'pitch (ly:make-pitch 0 0 0))
- (make-music 'AbsoluteDynamicEvent
- 'text "f")))))
+ 'elements (list
+ (make-music 'NoteEvent
+ 'articulations (list
+ (make-music 'AbsoluteDynamicEvent
+ 'text
+ "f"))
+ 'duration (ly:make-duration 2 0 1 1)
+ 'pitch (ly:make-pitch 0 0 0))))
@end example
A @code{@{ ... @}} music sequence has the name @code{SequentialMusic},
and its inner expressions are stored as a list in its @code{'elements}
-property. A note is represented as an @code{EventChord} expression,
-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.
+property. A note is represented as a @code{NoteEvent} object (storing
+the duration and pitch properties) with attached information (in this
+case, an @code{AbsoluteDynamicEvent} with a @code{"f"} text property)
+stored in its @code{articulations} 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
@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}.
+Let's look at an example:
@example
someNote = c'
\displayMusic \someNote
===>
+(make-music
+ 'NoteEvent
+ 'duration
+ (ly:make-duration 2 0 1 1)
+ 'pitch
+ (ly:make-pitch 0 0 0))
+@end example
+
+The @code{NoteEvent} object is the representation of @code{someNote}.
+Straightforward. How about putting c' in a chord?
+
+@example
+someNote = <c'>
+\displayMusic \someNote
+===>
(make-music
'EventChord
'elements
(ly:make-pitch 0 0 0))))
@end example
+Now the @code{NoteEvent} object is the first object of the
+@code{'elements} property of @code{someNote}.
+
The @code{display-scheme-music} function is the function used by
@code{\displayMusic} to display the Scheme representation of a music
expression.
@subsection Doubling a note with slurs (example)
Suppose we want to create a function that translates input like
-@code{a} into @code{a( a)}. We begin by examining the internal
+@code{a} into @code{@{ a( a) @}}. We begin by examining the internal
representation of the desired result.
@example
'SequentialMusic
'elements
(list (make-music
- 'EventChord
- 'elements
+ 'NoteEvent
+ 'articulations
(list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch 0 5 0))
- (make-music
'SlurEvent
'span-direction
- -1)))
+ -1))
+ 'duration
+ (ly:make-duration 2 0 1 1)
+ 'pitch
+ (ly:make-pitch 0 5 0))
(make-music
- 'EventChord
- 'elements
+ 'NoteEvent
+ 'articulations
(list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch 0 5 0))
- (make-music
'SlurEvent
'span-direction
- 1)))))
+ 1))
+ 'duration
+ (ly:make-duration 2 0 1 1)
+ 'pitch
+ (ly:make-pitch 0 5 0))))
@end example
The bad news is that the @code{SlurEvent} expressions
-must be added @q{inside} the note (or more precisely,
-inside the @code{EventChord} expression).
+must be added @q{inside} the note (in its @code{articulations}
+property).
Now we examine the input,
@example
+\displayMusic a'
+===>
(make-music
- 'SequentialMusic
- 'elements
- (list (make-music
- 'EventChord
- 'elements
- (list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch 0 5 0))))))
+ 'NoteEvent
+ 'duration
+ (ly:make-duration 2 0 1 1)
+ 'pitch
+ (ly:make-pitch 0 5 0))))
@end example
-So in our function, we need to clone this expression (so that we
-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}.
+So in our function, we need to clone this expression (so that we have
+two notes to build the sequence), add a @code{SlurEvent} to the
+@code{'articulations} property of each one, and finally make a
+@code{SequentialMusic} with the two @code{EventChords}. For adding to a
+property, it is useful to know that an unset property is read out as
+@code{'()}, the empty list, so no special checks are required before we
+put another element at the front of the @code{articulations} property.
@example
doubleSlur = #(define-music-function (parser location note) (ly:music?)
"Return: @{ note ( note ) @}.
- `note' is supposed to be an EventChord."
+ `note' is supposed to be a single note."
(let ((note2 (ly:music-deep-copy note)))
- (set! (ly:music-property note 'elements)
+ (set! (ly:music-property note 'articulations)
(cons (make-music 'SlurEvent 'span-direction -1)
- (ly:music-property note 'elements)))
- (set! (ly:music-property note2 'elements)
+ (ly:music-property note 'articulations)))
+ (set! (ly:music-property note2 'articulations)
(cons (make-music 'SlurEvent 'span-direction 1)
- (ly:music-property note2 'elements)))
+ (ly:music-property note2 'articulations)))
(make-music 'SequentialMusic 'elements (list note note2))))
@end example
@subsection Adding articulation to notes (example)
The easy way to add articulation to notes is to merge two music
-expressions into one context, as explained in
-@ruser{Creating contexts}. However, suppose that we want to write
-a music function that does this.
+expressions into one context, as explained in @ruser{Creating contexts}.
+However, suppose that we want to write a music function that does this.
+This will have the additional advantage that we can use that music
+function to add an articulation (like a fingering instruction) to a
+single note inside of a chord which is not possible if we just merge
+independent music.
A @code{$variable} inside the @code{#@{...#@}} notation is like
a regular @code{\variable} in classical LilyPond notation. We
@noindent
will not work in LilyPond. We could avoid this problem by attaching
-the articulation to a fake note,
+the articulation to an empty chord,
@example
-@{ << \music s1*0-.-> @}
+@{ << \music <> -. -> >> @}
@end example
@noindent
\displayMusic c4
===>
(make-music
- 'EventChord
- 'elements
- (list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch -1 0 0))))
+ 'NoteEvent
+ 'duration
+ (ly:make-duration 2 0 1 1)
+ 'pitch
+ (ly:make-pitch -1 0 0))))
=====
% desired output
\displayMusic c4->
===>
(make-music
- 'EventChord
- 'elements
+ 'NoteEvent
+ 'articulations
(list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch -1 0 0))
- (make-music
'ArticulationEvent
'articulation-type
- "marcato")))
+ "accent"))
+ 'duration
+ (ly:make-duration 2 0 1 1)
+ 'pitch
+ (ly:make-pitch -1 0 0))
@end example
-We see that a note (@code{c4}) is represented as an @code{EventChord}
-expression, with a @code{NoteEvent} expression in its elements list. To
-add a marcato articulation, an @code{ArticulationEvent} expression must
-be added to the elements property of the @code{EventChord}
-expression.
+We see that a note (@code{c4}) is represented as an @code{NoteEvent}
+expression. To add an accent articulation, an @code{ArticulationEvent}
+expression must be added to the @code{articulations} property of the
+@code{NoteEvent} expression.
To build this function, we begin with
@example
-(define (add-marcato event-chord)
- "Add a marcato ArticulationEvent to the elements of `event-chord',
- which is supposed to be an EventChord expression."
- (let ((result-event-chord (ly:music-deep-copy event-chord)))
- (set! (ly:music-property result-event-chord 'elements)
- (cons (make-music 'ArticulationEvent
- 'articulation-type "marcato")
- (ly:music-property result-event-chord 'elements)))
- result-event-chord))
+(define (add-accent note-event)
+ "Add an accent ArticulationEvent to the articulations of `note-event',
+ which is supposed to be a NoteEvent expression."
+ (set! (ly:music-property note-event 'articulations)
+ (cons (make-music 'ArticulationEvent
+ 'articulation-type "accent")
+ (ly:music-property note-event 'articulations)))
+ note-event)
@end example
The first line is the way to define a function in Scheme: the function
-name is @code{add-marcato}, and has one variable called
-@code{event-chord}. In Scheme, the type of variable is often clear
+name is @code{add-accent}, and has one variable called
+@code{note-event}. In Scheme, the type of variable is often clear
from its name. (this is good practice in other programming languages,
too!)
@example
-"Add a marcato..."
+"Add an accent..."
@end example
@noindent
is a description of what the function does. This is not strictly
necessary, but just like clear variable names, it is good practice.
-@example
-(let ((result-event-chord (ly:music-deep-copy event-chord)))
-@end example
-
-@code{let} is used to declare local variables. Here we use one local
-variable, named @code{result-event-chord}, to which we give the value
-@code{(ly:music-deep-copy event-chord)}. @code{ly:music-deep-copy} is
-a function specific to LilyPond, like all functions prefixed by
-@code{ly:}. It is use to make a copy of a music
-expression. Here we copy @code{event-chord} (the parameter of the
-function). Recall that our purpose is to add a marcato to an
-@code{EventChord} expression. It is better to not modify the
-@code{EventChord} which was given as an argument, because it may be
-used elsewhere.
-
-Now we have a @code{result-event-chord}, which is a
-@code{NoteEventChord} expression and is a copy of
-@code{event-chord}. We add the marcato to its @code{'elements}
-list property.
+You may wonder why we modify the note event directly instead of working
+on a copy (@code{ly:music-deep-copy} can be used for that). The reason
+is a silent contract: music functions are allowed to modify their
+arguments: they are either generated from scratch (like user input) or
+are already copied (referencing a music variable with @samp{\name} or
+music from immediate Scheme expressions @samp{$(@dots{})} provides a
+copy). Since it would be inefficient to create unnecessary copies, the
+return value from a music function is @emph{not} copied. So to heed
+that contract, you must not use any arguments more than once, and
+returning it counts as one use.
+
+In an earlier example, we constructed music by repeating a given music
+argument. In that case, at least one repetition had to be a copy of its
+own. If it weren't, strange things may happen. For example, if you use
+@code{\relative} or @code{\transpose} on the resulting music containing
+the same elements multiple times, those will be subjected to
+relativation or transposition multiple times. If you assign them to a
+music variable, the curse is broken since referencing @samp{\name} will
+again create a copy which does not retain the identity of the repeated
+elements.
+
+Now while the above function is not a music function, it will normally
+be used within music functions. So it makes sense to heed the same
+contract we use for music functions: the input may be modified for
+producing the output, and the caller is responsible for creating copies
+if it still needs the unchanged argument itself. If you take a look at
+LilyPond's own functions like @code{music-map}, you'll find that they
+stick with the same principles.
+
+Where were we? Now we have a @code{note-event} we may modify, not
+because of using @code{ly:music-deep-copy} but because of a long-winded
+explanation. We add the accent to its @code{'articulations} list
+property.
@example
(set! place new-value)
@end example
-Here, what we want to set (the @q{place}) is the @code{'elements}
-property of @code{result-event-chord} expression.
+Here, what we want to set (the @q{place}) is the @code{'articulations}
+property of @code{note-event} expression.
@example
-(ly:music-property result-event-chord 'elements)
+(ly:music-property note-event 'articulations)
@end example
@code{ly:music-property} is the function used to access music properties
-(the @code{'elements}, @code{'duration}, @code{'pitch}, etc, that we
+(the @code{'articulations}, @code{'duration}, @code{'pitch}, etc, that we
see in the @code{\displayMusic} output above). The new value is the
-former @code{'elements} property, with an extra item: the
+former @code{'articulations} property, with an extra item: the
@code{ArticulationEvent} expression, which we copy from the
@code{\displayMusic} output,
@example
(cons (make-music 'ArticulationEvent
- 'articulation-type "marcato")
- (ly:music-property result-event-chord 'elements))
+ 'articulation-type "accent")
+ (ly:music-property result-event-chord 'articulations))
@end example
-@code{cons} is used to add an element to a list without modifying
-the original list. This is what we want: the same list as before,
-plus the new @code{ArticulationEvent} expression. The order
-inside the @code{'elements} property is not important here.
+@code{cons} is used to add an element to the front of a list without
+modifying the original list. This is what we want: the same list as
+before, plus the new @code{ArticulationEvent} expression. The order
+inside the @code{'articulations} property is not important here.
-Finally, once we have added the marcato articulation to its @code{elements}
-property, we can return @code{result-event-chord}, hence the last line of
-the function.
+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.
-Now we transform the @code{add-marcato} function into a music
-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).
@example
-addMarcato = #(define-music-function (parser location event-chord)
+addAccent = #(define-music-function (parser location note-event)
(ly:music?)
- "Add a marcato ArticulationEvent to the elements of `event-chord',
- which is supposed to be an EventChord expression."
- (let ((result-event-chord (ly:music-deep-copy event-chord)))
- (set! (ly:music-property result-event-chord 'elements)
- (cons (make-music 'ArticulationEvent
- 'articulation-type "marcato")
- (ly:music-property result-event-chord 'elements)))
- result-event-chord))
+ "Add an accent ArticulationEvent to the articulations of `note-event',
+ which is supposed to be a NoteEvent expression."
+ (set! (ly:music-property note-event 'articulations)
+ (cons (make-music 'ArticulationEvent
+ 'articulation-type "accent")
+ (ly:music-property note-event 'articulations)))
+ note-event)
@end example
We may verify that this music function works correctly,
@example
-\displayMusic \addMarcato c4
+\displayMusic \addAccent c4
@end example
We have seen how LilyPond output can be heavily modified using
commands like
-@code{\override TextScript #'extra-offset = ( 1 . -1)}. But
+@code{\override TextScript.extra-offset = ( 1 . -1)}. But
we have even more power if we use Scheme. For a full explanation
of this, see the @ref{Scheme tutorial}, and
@ref{Interfaces for programmers}.
@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''' {
@lilypond[quote,verbatim,ragged-right]
tempoPadded = #(define-music-function (parser location padding tempotext)
- (number? string?)
+ (number? markup?)
#{
- \once \override Score.MetronomeMark #'padding = $padding
- \tempo \markup { \bold $tempotext }
+ \once \override Score.MetronomeMark.padding = #padding
+ \tempo \markup { \bold #tempotext }
#})
\relative c'' {
\tempo \markup { "Low tempo" }
c4 d e f g1
- \tempoPadded #4.0 #"High tempo"
+ \tempoPadded #4.0 "High tempo"
g4 f e d c1
}
@end lilypond
@lilypond[quote,verbatim,ragged-right]
pattern = #(define-music-function (parser location x y) (ly:music? ly:music?)
#{
- $x e8 a b $y b a e
+ #x e8 a b #y b a e
#})
\relative c''{