8

我编写了一本大型歌曲集,为此我希望有许多函数的本地定义,最终将在一个\included 文件中,但这在这里没有区别。为此,我需要在\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"
        }
    }

}
4

2 回答 2

6

不幸的是,不可能将作业粘贴在乐谱中。您只能将作业放置在以下位置:

  • 顶层,
  • 内部\display, \header, 和\midi

LilyPond 语法很清楚地说明了这一点,即使手册的其余部分对此有点回避。(查看http://lilypond.org/doc/v2.17/Documentation/contributor/lilypond-grammar并查找使用该assignment规则的位置)。

假设你的分配不适合上面列出的块(在这个例子中肯定是这种情况),并假设你不想做一些奇特的事情,比如去定义你自己的 Scheme 模块并弄清楚如何在你的 LilyPond 文件,你有两个选择:

  1. 定义xyzabc,然后定义将进入第一乐谱的音乐。然后重新定义 xyz,然后abc再定义下一个乐谱的音乐。这是有效的,因为分配会覆盖以前存在的任何内容,并且因为 LilyPond 定义通常是按顺序处理的。但是,如果您希望您的某些定义在两个乐谱中都使用并且相同,您可能会感到困惑。
  2. 接受您的方法,尽管我会选择一个前缀或后缀,以便更清楚地说明定义的分数。

第一个选项看起来像这样:

\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 源文件,这也有效。

于 2014-01-11T09:13:41.233 回答
4

有可能的! 但是你必须定义一个命令来定义变量或命令:

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''。您可以选择将表达式包装在另一对花括号中。

于 2014-03-07T13:53:03.977 回答