Le samedi 01 juillet 2023 à 16:42 +0200, Volodymyr Prokopyuk a écrit :

> I'm trying to define a music function as below, however I've faced 
> difficulties with parameter predicates, visibility of the Staff object, and 
> flexibility of the solution ideally without code duplication
> 
> **Desired music function** (the code is not working)
> 
> ```
>   momentBeat = #(define-music-function (moment beat scope)  
>     (fraction? list? (what? Staff))  
>     #{  
>       \set #scope.beamExceptions = #'()  
>       \set #scope.baseMoment = #(ly:make-moment moment)  
>       \set #scope.beatStructure = #beat  
>     #})
> ```
>
> **Usage**
>
> ``` 
> \momentBeat 1/2 #'(1)
> \momentBeat 1/4 1,1,1,1 Voice
> ```
>
> **Questions**
> 
> 
> - It seems that Staff is not available to Guile at that moment. I tried to 
> use "Staff" string and 'Staff symbol for the scope parameter with a cond 
> expression and code replication for Staff and Voice, but I did not manage to 
> get it to work due to incorrect predicates errors
> 
> - How would it look like an idiomatic and working implementation of the above 
> music function?



There are a couple problems here.

- The `#` character introduces a Scheme expression. In Scheme, dots are allowed 
in identifiers. As such, `\set #scope.beamExceptions` is trying to look up a 
variable literally called "scope.beamExceptions". You need a space after 
`#scope` to terminate the Scheme expression.
- A `fraction?` is not a rational number but a (numerator . denominator) pair. 
The reason is that `fraction?` is the predicate for music functions like 
`\time`, and `\time 4/4` needs to be distinguished from `\time 2/2` (for 
example). The `ly:make-moment` function, on the other hand, expects a rational 
number.
- If you want an optional argument to actually be optional, it must not be the 
last argument. Otherwise, you can't actually omit it, you can only replace it 
with `\default`. See 
[here](https://extending-lilypond.gitlab.io/en/extending/music.html#optional-arguments)
 for more details.

Here is a working version of your function:

```
\version "2.24.1"

momentBeat =
#(define-music-function (scope moment beat) ((symbol? 'Staff) fraction? list?)
   #{
     \set #scope .beamExceptions = #'()
     \set #scope .baseMoment = #(ly:make-moment (/ (car moment) (cdr moment)))
     \set #scope .beatStructure = #beat
   #})

{
  \momentBeat Voice 1/8 3,3,2
  c'8 8 8 8 8 8 8 8
}
```

Best,

Jean

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to