Guide, node Updating translation committishes..
@end ignore
-@c \version "2.17.6"
+@c \version "2.19.22"
@node Scheme tutorial
@chapter Scheme tutorial
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
@lisp
guile> (define mypair (cons 123 "hello there")
-... )
+@dots{} )
guile> (car mypair)
123
guile> (cdr mypair)
@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:
@lisp
guile> (let ((x 2) (y 3) (z 4)) (display (+ x y)) (display (- z 4))
-... (+ (* x y) (/ z x)))
+@dots{} (+ (* x y) (/ z x)))
508
@end lisp
@example
(cond (test-expression-1 result-expression-sequence-1)
(test-expression-2 result-expression-sequence-2)
- ...
+ @dots{}
(test-expression-n result-expression-sequence-n))
@end example
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}
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
-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
-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 $@@
@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
-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
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}.
+The usual way to refer to LilyPond variables is to call them using a
+backslash, i.e., @code{\twentyFour} (see @ref{LilyPond Scheme syntax}).
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
is internally converted to a Scheme definition:
@example
-(define traLaLa @var{Scheme value of `@code{... }'})
+(define traLaLa @var{Scheme value of `@code{@dots{}}'})
@end example
This means that LilyPond variables and Scheme variables may be freely
been written as
@example
-...
+@dots{}
$(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.
+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
written as
@example
-...
+@dots{}
@{ #@@newLa @}
@end example
#(define (nopc)
(ly:set-option 'point-and-click #f))
-...
+@dots{}
#(nopc)
@{ c'4 @}
@end example
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
@{
'text
"f"))
'duration
- (ly:make-duration 2 0 1 1)
+ (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
with all the other messages. To split up these messages and save
-the results of @code{\display@{STUFF@}}, redirect the output to
-a file.
+the results of @code{\display@{STUFF@}}, you can specify an optional
+output port to use:
@example
-lilypond file.ly >display.txt
+@{
+ \displayMusic #(open-output-file "display.txt") @{ c'4\f @}
+@}
@end example
-With a combined bit of Lilypond and Scheme magic, you can actually
-let Lilypond direct just this output to a file of its own:
-
+This will overwrite a previous output file whenever it is called; if you
+need to write more than one expression, you would use a variable for
+your port and reuse it:
@example
@{
- #(with-output-to-file "display.txt"
- (lambda () #@{ \displayMusic @{ c'4\f @} #@}))
+ port = #(open-output-file "display.txt")
+ \displayMusic \port @{ c'4\f @}
+ \displayMusic \port @{ d'4 @}
+ #(close-output-port port)
@}
@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
+the first example, we did not bother to do so.
A bit of reformatting makes the above information easier to read:
@example
(make-music 'SequentialMusic
'elements (list
- (make-music 'NoteEvent
+ (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))))
+ (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 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.
+A @code{@{ @dots{} @}} 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 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
@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.
+@end ignore
Let's look at an example:
(make-music
'NoteEvent
'duration
- (ly:make-duration 2 0 1 1)
+ (ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch 0 0 0))
@end example
(list (make-music
'NoteEvent
'duration
- (ly:make-duration 2 0 1 1)
+ (ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch 0 0 0))))
@end example
(make-music
'NoteEvent
'duration
- (ly:make-duration 2 0 1 1)
+ (ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch 0 0 0))
@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
(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
(ly:make-pitch 0 1 0)) ;; set the pitch to d'.
\displayLilyMusic \someNote
===>
-d'
+d'4
@end example
'span-direction
-1))
'duration
- (ly:make-duration 2 0 1 1)
+ (ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch 0 5 0))
(make-music
'span-direction
1))
'duration
- (ly:make-duration 2 0 1 1)
+ (ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch 0 5 0))))
@end example
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'
(make-music
'NoteEvent
'duration
- (ly:make-duration 2 0 1 1)
+ (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{'articulations} property of each one, and finally make a
-@code{SequentialMusic} with the two @code{EventChords}. For adding to a
+@code{SequentialMusic} with the two @code{NoteEvent} elements. 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?)
+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)))
@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}.
+expressions into one context.
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 @code{$variable} inside the @code{#@{@dots{}#@}} notation is like
a regular @code{\variable} in classical LilyPond notation. We
know that
@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
(make-music
'NoteEvent
'duration
- (ly:make-duration 2 0 1 1)
+ (ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch -1 0 0))))
=====
'articulation-type
"accent"))
'duration
- (ly:make-duration 2 0 1 1)
+ (ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch -1 0 0))
@end example
too!)
@example
-"Add an accent..."
+"Add an accent@dots{}"
@end example
@noindent
of its sole @q{real} argument).
@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."
note-event)
@end example
-We may verify that this music function works correctly,
+We may verify that this music function works correctly:
@example
\displayMusic \addAccent c4
@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
#})
-\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
@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 }
#})
-\relative c'' {
+\relative {
\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
}
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
#})