我编译了一本大的歌曲书,为此我希望有许多函数的本地定义,这些定义最终将在include
d文件中,但这在这里没有什么区别。为此,我需要定义score{ ... }
范围内的函数。然而,LilyPond不断抛出错误。
不起作用的例子:
version "2.17.26"
book {
header {
title = "This is a book"
}
score {
xyz = { a' b' c'' }
abc = #(define-music-function
( parser location musicnotes )
( ly:music? )
#{
c' $musicnotes e'
#}
)
{ abc { d' } f' xyz }
header {
piece = "First piece"
opus = "op. 1024"
}
}
score {
xyz = { a' a' a' }
abc = #(define-music-function
( parser location musicnotes )
( ly:music? )
#{
e' $musicnotes c'
#}
)
{ abc { d' } f' xyz }
header {
piece = "Second piece"
opus = "op. 1025"
}
}
}
抛出错误:
test.ly:10:17: error: unrecognized string, not in text script or lyricmode xyz = { a' b' c'' }
然而,下面的工作,我必须给函数赋予唯一的名称,这是令人不快的
version "2.17.26"
xyz = { a' b' c'' }
abc = #(define-music-function
( parser location musicnotes )
( ly:music? )
#{
c' $musicnotes e'
#}
)
xxyz = { a' a' a' }
aabc = #(define-music-function
( parser location musicnotes )
( ly:music? )
#{
e' $musicnotes c'
#}
)
book {
header {
title = "This is a book"
}
score {
{ abc { d' } f' xyz }
header {
piece = "First piece"
opus = "op. 1024"
}
}
score {
{ aabc { d' } f' xxyz }
header {
piece = "Second piece"
opus = "op. 1025"
}
}
}
不幸的是,不可能把作业粘在分数里。您只能将作业放在以下位置:
- 顶级
display
、header
和midi
块内部
LilyPond语法使这一点非常清楚,即使手册的其余部分对此有点回避http://lilypond.org/doc/v2.17/Documentation/contributor/lilypond-grammar,并查找assignment
规则的使用位置)。
假设你的任务不适合上面列出的块(本例中肯定是这样),并且假设你不想做一些奇怪的事情,比如去定义你自己的Scheme模块并找出如何在LilyPond文件中使用它们,你有两个选择:
- 定义
xyz
和abc
,然后定义将进入第一个乐谱的音乐。然后重新定义xyz
和abc
,然后再定义下一个乐谱的音乐。这是因为赋值覆盖了以前存在的内容,并且LilyPond定义通常按顺序处理。然而,如果你希望你的一些定义在两个分数中使用,并且相同,你可能会感到困惑 - 接受你的方法,尽管我会选择一个前缀或后缀,让定义的分数更清楚
第一个选项看起来像这样:
version "2.18.0"
xyz = { a' b' c'' }
abc = #(define-music-function (parser location musicnotes)
(ly:music?)
#{ c' $musicnotes e' #})
smus_a = { abc { d' } f' xyz }
xyz = { a' a' a' }
abc = #(define-music-function (parser location musicnotes)
(ly:music?)
#{ e' $musicnotes c' #})
smus_b = { abc { d' } f' xyz }
book {
header {
title = "A Book!"
}
score {
smus_a
header { piece = "First piece" }
}
score {
smus_b
header { piece = "Second piece" }
}
}
如果音乐定义部分被重构到单独的LilyPond源文件中,这也会起作用。
这是可能的!但是您必须定义一个命令来定义变量或命令:
parserDefine =
#(define-void-function (parser location name val)(symbol? scheme?)
(ly:parser-define! parser name val))
这是一个void函数,几乎可以在任何地方调用:
score {
{
% you have to be in your music-expression
parserDefine xyz { a' a' a' }
% There must be something between parserDefine and the call!
c'' xyz
parserDefine abc #(define-music-function
( parser location musicnotes )
( ly:music? )
#{
c' $musicnotes e'
#}
)
a' abc d'
}
}
如果该命令已定义,则可以在音乐表达式内部调用。完成后,解析器需要进行一点前瞻,这样变量才真正可用——这里是c。您可以选择将表达式包装在另一对大括号中。