Define function inside \score in LilyPond - scope

I compile a large song book, and for that I would like to have many local definitions of functions, that will, in the end, be in an \include d file, but that makes no difference here. For this, I need to define the functions inside \score{ ... } scope. However, LilyPond keeps throwing errors.
The non-working example:
\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"
}
}
}
Throws an error:
test.ly:10:17: error: unrecognized string, not in text script or \lyricmode
xyz = { a' b' c'' }
The following works, however, I have to give the functions unique names, which is frowned upon.
\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"
}
}
}

Unfortunatey, it's not possible to stick assignments in a score. You can only put assignments in the following places:
the top level,
inside \display, \header, and \midi blocks
The LilyPond grammar makes this quite clear, even if the rest of the manual is a bit evasive about it. (Look at http://lilypond.org/doc/v2.17/Documentation/contributor/lilypond-grammar , and look for where the assignment rule gets used).
Assuming your assignments are not appropriate for the blocks listed above (which is definitely the case in this example), and assuming that you don't want to do something exotic like go and define your own Scheme modules and figure out how to use them in your LilyPond file, you have two choices:
Define xyz and abc, then define the music that will go into the first score. Then redefine xyz and abc before defining the music for the next score. This works because assignments overwrite whatever was previously there, and because LilyPond defines are generally processed in order. However, if you want some of your defines to be used in both scores and to be the same, you may get confused.
Settle for your approach, though I would pick a prefix or a suffix that makes it clearer which score the define goes with.
The first option would look something like this:
\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" }
}
}
This also works if the music-defining parts are refactored out into separate LilyPond source files.

It is possible!
But you have to define a command to define the variable or command:
parserDefine =
#(define-void-function (parser location name val)(symbol? scheme?)
(ly:parser-define! parser name val))
This is a void-function and can be called almost anywhere:
\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'
}
}
If the command is defined, you can call inside your music expressions. After you have done so, the parser needs a little lookahead, so that the variable really is available - here its the c''. You can optionally wrap the expression in another pair of curly braces.

Related

Why can't you modify closure parameters of inline methods?

I've got this section of code:
class Main {
static inline function difference(a:Int, b:Int, ?f:(Int, Int) -> Int):Int {
if (f == null) {
f = (a, b) -> a - b;
}
return f(a, b);
}
static function main() {
trace(difference(42, 37));
trace(difference(42, 37, (a, b) -> a - b));
}
}
Which, when I compile using haxe --main Main, fails with this error:
Main.hx:11: characters 15-50 : Cannot modify a closure parameter inside inline method
Main.hx:11: characters 15-50 : For function argument 'v'
If I change Main.difference to not be inline, this error doesn't come up and everything compiles fine.
Why does this error occur?
Edit: I've found out I can also assign the argument to a variable first, and then pass the variable to Main.difference, like this:
static function main() {
var f = (a, b) -> a - b;
trace(difference(42, 37, f));
}
Which works fine with Main.difference being inlined. How does assigning the function to a variable first change things though?
This is related to how inline functions are unwrapped by the compiler. Let us take a simpler variant of your code:
class HelloWorld {
static inline function difference(a:Int, b:Int, ?f:(Int, Int) -> Int):Int {
return f(a, b);
}
static function main() {
trace(difference(42, 37, (a, b) -> a - b));
}
}
When disabling optimizations, this will yield the following JavaScript:
HelloWorld.main = function() {
console.log("HelloWorld.hx:14:",(function(a,b) {
return a - b;
})(42,37));
};
So the body of difference has been incorporated into main using a JavaScript closure. My best guess for what is happnening in your exact case is something like this:
HelloWorld.main = function() {
var v = function(a,b) {
return a - b;
}
console.log("HelloWorld.hx:14:", (function(a,b) {
if (v == null) {
v = function(a, b) {
return a - b;
}
}
return v(a, b);
})(42, 37));
};
This alters the value of v, which exists outside of difference, which has been automatically placed there as a binding for the anonymous lambda. This is what the compiler is trying to avoid. This would not be the end of the world in your case, but in general this is bad and would lead to issues in many programs.
There is a way to inline this code perfectly by hand without this, but I think that there is some weirdness surrounding how annonymous lambdas are currently handled. The situation may improve in the future.
When you explicitly defined f in main, the compiler is intelligent enough to rename the nested f as f1, which is why the issue does not occur:
HelloWorld.main = function() {
var f = function(a,b) {
return a - b;
};
var f1 = f;
if(f1 == null) {
f1 = function(a,b) {
return a - b;
};
}
console.log("HelloWorld.hx:14:",f1(42,37));
};
But this would also work if the inline part of this function is important to you:
class HelloWorld {
static inline function difference(a:Int, b:Int, ?f:(Int, Int) -> Int):Int {
var h = f;
if (h == null) {
h = (a, b) -> a - b;
}
return h(a, b);
}
static function main() {
trace(difference(42, 37, (a, b) -> a - b));
}
}

How can I know that I can call a Perl 6 method that with a particular signature?

In Perl 6, a multi-dispatch language, you can find out if there is a method that matches a name. If there is, you get a list of Method objects that match that name:
class ParentClass {
multi method foo (Str $s) { ... }
}
class ChildClass is ParentClass {
multi method foo (Int $n) { ... }
multi method foo (Rat $r) { ... }
}
my $object = ChildClass.new;
for $object.can( 'foo' )
.flatmap( *.candidates )
.unique -> $candidate {
put join "\t",
$candidate.package.^name,
$candidate.name,
$candidate.signature.perl;
};
ParentClass foo :(ParentClass $: Str $s, *%_)
ChildClass foo :(ChildClass $: Int $n, *%_)
ChildClass foo :(ChildClass $: Rat $r, *%_)
That's fine, but it's a lot of work. I'd much rather have something simpler, such as:
$object.can( 'foo', $signature );
I can probably do a lot of work to make that possible, but am I missing something that's already there?
As I hit submit on that question I had this idea, which still seems like too much work. The cando method can test a Capture (the inverse of a signature). I can grep those that match:
class ParentClass {
multi method foo (Str $s) { ... }
}
class ChildClass is ParentClass {
multi method foo (Int $n) { ... }
multi method foo (Rat $r) { ... }
}
my $object = ChildClass.new;
# invocant is the first thing for method captures
my $capture = \( ChildClass, Str );
for $object.can( 'foo' )
.flatmap( *.candidates )
.grep( *.cando: $capture )
-> $candidate {
put join "\t",
$candidate.package.^name,
$candidate.name,
$candidate.signature.perl;
};
I'm not sure I like this answer though.

Groovy paradigm for conditional with find

This code works, but the duplicate find seems less than optimal. Is it possible to implement the same functionality without the duplication?
def pattern = ~'some_regex'
def inFile = new File('in')
inFile.eachLine { String line ->
if (line.find(pattern)) {
line.find(pattern) { match ->
... // do something
}
}
else {
... // do something (else)
}
}
I'd suggest to use eachMatch()
inFile.eachLine { String line ->
String matched
line.eachMatch( pattern ){
matched = it[ 0 ]
doSomethingWithMatch matched
}
if( !matched ) doNoMatch()
}

Nested `each` loops in Groovy

Need guidance on the syntax of nested looping in groovy. How to use iterator to print values of (value of a.name, value of b.name) here?
List a
a.each {
print(it.name)
List b = something
b.each {
print(value of a.name, value of b.name)
}
}
List a
a.each { x ->
println(x.name)
List b = something
b.each { y ->
println(x.name + y.name)
}
}

Specify order of alternatives in happy parser

I am working on a Happy parser for a language with the following types, and many more.
type :: { ... }
type :
'void' { ... }
| type '*' { ... } {- pointer -}
| type '(' types ')' { ... } {- function -}
| ... {- many more! -}
types :: { ... }
{- empty -} { ... }
| types ',' type { ... }
The language has apparently ambiguous syntax for calls.
callable :: { ... }
callable :
type operand { ... } {- return type -}
| type '(' types ')' '*' operand { ... } {- return and argument types -}
The second rule does not have the same meaning as the first when type takes on the type of a function pointer.
The ambiguity can be removed by adding a special rule for a type that isn't a function pointer. Barring doing so and duplicating all of the type definitions to produce something like
callable :: { ... }
callable :
typeThatIsNotAFunctionPointer operand { ... }
| type '(' types ')' '*' operand { ... }
How can I specify that the alternative type operand is only legal when the type '(' types ')' '*' operand alternative fails?
There are many questions on stack overflow about why a grammar has ambiguities (I found at least 7), and some about how to remove an ambiguity, but none about how to specify how to resolve an ambiguity.
Undesirable Solution
I'm aware that I can refactor the grammar for types to a giant convoluted mess.
neverConstrainedType :: { ... }
neverConstrainedType :
'int' { ... }
| ... {- many more! -}
voidType :: { ... }
voidType :
'void'
pointerType :: { ... }
pointerType :
type '*' { ... } {- pointer -}
functionType :: { ... }
type '(' types ')' { ... } {- function -}
type :: { ... }
type :
neverConstrainedType { ... }
| voidType { ... }
| pointerType { ... }
| functionType { ... }
typeNonVoid :: { ... } {- this already exists -}
typeNonVoid :
neverConstrainedType { ... }
| pointerType { ... }
| functionType { ... }
typeNonPointer :: { ... }
typeNonPointer :
neverConstrainedType { ... }
| voidType { ... }
| functionType { ... }
typeNonFunction :: { ... }
typeNonFunction :
neverConstrainedType { ... }
| voidType { ... }
| functionType { ... }
typeNonFunctionPointer :: { ... }
typeNonFunctionPointer :
typeNonPointer { ... }
| typeNonFunction '*' { ... }
And then define callable as
callable :: { ... }
callable :
typeNonFunctionPointer operand { ... }
| type '(' types ')' '*' operand { ... }
Basically you have what's called a shift/reduce conflict. You can google "resolve shift/reduce conflict" for more info and resources.
The basic idea in resolving shift/reduce conflicts is to refactor the grammar. For instance, this grammar is ambiguous:
%token id comma int
A : B comma int
B : id
| id comma B
The shift/reduce conflict can be eliminated by refactoring it as:
A : B int
B : id comma
| id comma B
In your case you could try something like this:
type : simple {0}
| func {0}
| funcptr {0}
simple : 'void' {0}
| simple '*' {0}
| funcptr '*' {0}
func : type '(' type ')' {0}
funcptr : func '*' {0}
The idea is this:
simple matches any type that is not a function or function pointer
func matches any function type
funcptr matches any function pointer type
That said, many of the things I've attempted to do in grammars I've found are better accomplished by analyzing the parse tree after it's been created.

Resources