Subject: Fonction substitution Scheme

From: joel brassart <[email-masked]>
Date: Mon, 27 Sep 2021 14:36:16 +0200

Bonjour à tous,
Je commence à chipoter avec Scheme et voudrais me doter de quelques outils
pour me simplifier la vie.
Je voudrais créer une fonction de substitution pour un Header, mais le code
qui suit me retourne l'erreur suivante :

Erreur : La fonction music ne peut retourner ##<module 7fb7290743e0>

pour la ligne '*\hh " titre gras"*' alors que si j'insère directement
l'instruction Lilypond '*Header ...',* cela fonctionne ...
alors que

code :

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\version "2.20.0"
\language "italiano"

hh =
#(define-music-function
     ( text )
     ( string? )
   #{
    \header { piece = \markup {  \fontsize #2 \bold #text }  }
   #})

\hh " titre gras" % <--- erreur
%\header { piece = \markup {  \fontsize #2 \bold "titre gras" }  } %<--- OK

\relative do' {
  do re mi }

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Qu'ai-je mal fait ?

D'avance merci,

Joël Brassart

Lilypond 2.20

Linux Ubuntu 20.4

---

From: Jean Abou Samra <[email-masked]>
Date: Mon, 27 Sep 2021 21:29:52 +0200

Bonjour,

Le 27/09/2021 à 14:36, joel brassart a écrit :
> Bonjour à tous,
> Je commence à chipoter avec Scheme et voudrais me doter de quelques 
> outils pour me simplifier la vie.

Excellente idée, vous verrez que LilyPond devient sans
limites avec Scheme. À tout hasard, si ce n'est pas ce
que vous lisez déjà, sachez qu'il existe ce tutoriel :

https://tutoriel-scheme.readthedocs.io

(Il y en a d'autres, et de meilleurs, mais celui-ci est
spécifiquement tourné vers LilyPond, et en français.)

> Je voudrais créer une fonction de substitution pour un Header, mais le 
> code qui suit me retourne l'erreur suivante :
>
> pour la ligne '/\hh " titre gras"/'alors que si j'insère directement 
> l'instruction Lilypond '/Header ...',/ cela fonctionne ... alors que
>
> code :
>
> \version "2.20.0" \language "italiano" hh = #(define-music-function   
>    ( text )      ( string? )    #{     \header { piece = \markup { 
>  \fontsize #2 \bold #text }  }    #}) \hh " titre gras" % <--- erreur 
> %\header { piece = \markup {  \fontsize #2 \bold "titre gras" }  } 
> %<--- OK \relative do' {   do re mi }
>

La macro define-music-function crée des fonctions musicales,
qui doivent impérativement renvoyer de la musique, par exemple
{ c' d' }, ou encore \new Lyrics \lyricmode { Frère Jacques }.
Ce n'est pas le cas de votre fonction, puisqu'un bloc \header
n'est pas une expression musicale (mais en fait un module Guile,
d'où le message d'erreur). Il faut donc déclarer cette fonction
avec define-scheme-function, qui n'impose aucune restriction.

\version "2.22.1"

\language français

hh =
#(define-scheme-function (text) (string?)
    #{
       \header { piece = \markup { \fontsize #2 \bold #text } }
    #})

\hh "titre gras"
\relative do' { do re mi }

Dans la documentation, vous pouvez lire
https://lilypond.org/doc/v2.22/Documentation/extending/music-function-usage

Vous vous demandez sûrement l'intérêt de define-music-function
si define-scheme-function est plus flexible. Pour faire simple
et ne pas dire de bêtises sur un domaine que je connais mal,
l'analyse syntaxique d'un fichier LilyPond est beaucoup plus
compliquée qu'il n'y paraît, et define-music-function permet dans
certains cas d'accepter une expression grâce à la certitude qu'elle
donnera de la musique et pas autre chose, avant même d'avoir à
exécuter vraiment la fonction. Voici un exemple où define-music-function
fonctionne mieux que define-scheme-function :

\version "2.22.1"

\language français

fonctionScheme =
#(define-scheme-function (music) (ly:music?)
    #{ \stemUp #music \stemNeutral #})

fonctionMusicale =
#(define-music-function (music) (ly:music?)
    #{ \stemUp #music \stemNeutral #})

\new Staff \fonctionScheme { do re mi } % erreur
%\new Staff \fonctionMusicale { do re mi } % accepté

Donc, si votre fonction renvoie de la musique, utilisez 
define-music-function,
et sinon, define-scheme-function.

Notez que la dernière version stable est 2.22 et il est recommandé
de faire la mise à jour. Cependant, les exemples de ce message
sont valides en 2.20.

Cordialement,
Jean