Problème de mix Scheme-Lilypond

Bonjour,
Je rencontre un problème lors de la génération de fichiers.
J'ai une même partition que je génère pour plusieurs clefs et plusieurs instruments transpositeurs. Pour le moment, tous les instruments transpositeurs pour qui je travaille lisent en clef de Sol.
J'ai donc, en tête de fichier et pour ne pas me prendre la tête, les 3 lignes suivantes:

#(define defaultHighKey "treble")
#(define defaultLowKey "treble_8")
#(define defaultInstrumentKey "Clef_Sol")

Les 2 premières me donnent la clef que j'utiliserai pour les voix graves (\clef #defaultLowKey) et pour les les voix hautes (\clef #defaultHighKey)

La troisième ligne me donne le nom de la clef qui sera ajouté au nom du fichier dans un bloc \book (\bookOutputSuffix #(string-join (list "Fa" defaultInstrumentKey)))

J'insère une condition scheme pour ne générer les partitions pour instruments transpositeurs uniquement si defaultInstrumentKey == "Clef_Sol"

$(if (equal? defaultInstrumentKey "Clef_Sol")
   #{
    \book {
        \bookOutputSuffix #(string-join (list "Sib" defaultInstrumentKey))
         (...)
    }
#})

Mon problème est le suivant: si je répète la condition Scheme pour CHAQUE partition (aka chaque fragment \book), alors elles se génèrent sans souci.
Ex:

% 1ère condition Scheme
$(if (equal? defaultInstrumentKey "Clef_Sol")
   #{
    \book {
        \bookOutputSuffix #(string-join (list "Sib" defaultInstrumentKey))
    (...)
    }
#})

% 2ème condition Scheme
$(if (equal? defaultInstrumentKey "Clef_Sol")
   #{
    \book {
        \bookOutputSuffix #(string-join (list "Fa" defaultInstrumentKey))
    (...)
    }
#})

Si par contre je mutualise la condition, ça ne marche plus du tout:

% Condition Scheme mutualisée
$(if (equal? defaultInstrumentKey "Clef_Sol")
   #{
    \book {
        \bookOutputSuffix #(string-join (list "Sib" defaultInstrumentKey))
    (...)
    }

    \book {       % ---> Note: ceci est la ligne 287 <---
        \bookOutputSuffix #(string-join (list "Fa" defaultInstrumentKey))
    (...)
    }
#})

J'obtiens une erreur à l'instanciation du second \book:

Myfile.ly:287:5: Erreur : syntax error, unexpected \book, expecting end of input

Plus une erreur pour la ligne de la condition:

Myfile.ly:269:2: Erreur : erreur dans #{ ... #}
#(if (equal? defaultInstrumentKey "Clef_Sol")

Pourtant, quand je regarde de la documentation, p.ex. https://scheme-book.readthedocs.io/en/latest/scheme/music-function-primer.html

L'exemple montre qu'on devrait pouvoir mettre autant d'expressions Lily que l'on veut:

myMusicFunction =
#(define-music-function (color)
   (color?)
   #{
     \override NoteHead.color = #color
     \override Stem.color = #color
     \override Flag.color = #color
   #})

{
  c'4
  \myMusicFunction #red
  d'8
}

Je précise que j'ai également essayé de faire débuter la ligne Scheme de condition par "$" ou "#" (je ne sais pas trop quelle est la différence), pour le même résultat.

Est-ce que je rate quelque chose? J'imagine que l'on n'est pas bloqué dans les faits à une seule expression Scheme?

Merci, bon après-midi,
Emmanuel

Bonjour Emmanuel,

Vous ne pouvez pas utiliser deux instructions \book dans une même partition, il faut utiliser \bookpart à la place.

Au plaisir,

Ben

Bonjour Ben,

Tout d'abord merci pour votre réponse.

Je ne suis pas sûr de comprendre la réponse. Est-ce qu'on ne peut utiliser qu'un seul \book dans du code Scheme et Lilypond imbriqués?
Dans un fichier .ly, je peux mettre autant de \book que je le souhaite, ça marche parfaitement bien, je le fais pour chaque partition. C'est seulement lorsque je tente de mettre la même chose, mais encapsulé dans une condition Scheme, que ça ne fonctionne plus, alors que les mêmes instructions \book fonctionnent dans des conditions Scheme séparées.
De ce fait j'imagine que mon pb vient d'ailleurs?

Très bonne soirée,
Emmanuel

Bonjour Emmanuel,J'essayerais deux choses: enlever le scheme autour des deux book, pour voir si cela compile sans, puis remplacer les book par des bookpart dans le scheme, pour voir si c'est l'instruction book le problème.Au plaisir,Ben

Bonjour Ben,

Je n'ai pas été assez explicite dans mon message, désolé.

En fait il y a des années que je fonctionne avec plusieurs \book dans mes fichiers .ly, sans aucun problème. Donc il y a des années que "j'enlève le scheme" autour de ces éléments :wink:

J'en suis justement à l'étape où j'essaye de flexibiliser la génération des partitions, et où je commence seulement à introduire du scheme dans le code pour paramétrer la génération.

Mais, encore une fois, l'expérience que j'ai depuis longtemps déjà est qu'on peut mettre autant de \book que l'on veut.

Quant à utiliser des \bookpart, ce n'est pas adapté pour mes besoins. J'ai vraiment besoin de générer des entités séparées.

Bonne journée,
Emmanuel

Cher Emmanuel,L'idée n'était pas de le faire de manière définitive, mais seulement pour comprendre ce qui pose problème: le code scheme, le code lilypond, l'instruction book, etc.@+Ben

En fait, la syntaxe

#{
  \override NoteHead.color = #color
  \override Stem.color = #color
  \override Flag.color = #color
#}

est un raccourci pour

#{
  {
    \override NoteHead.color = #color
    \override Stem.color = #color
    \override Flag.color = #color
  }
#}

Il n'y a donc pas plusieurs éléments renvoyés mais bien un seul, qui est une expression musicale combinant les trois \override. En revanche, les \book ne peuvent pas faire partie d'expressions musicales (que voudrait dire << \book { ... } \book { ... } >> ?). Dans ce cas, il faut renvoyer une vraie liste d'éléments, et les insérer un par un en remplaçant le $ par un $@.

$@(if ...
      (list
        #{
          \book { ... }
        #}
        #{
          \book { ... }
        #}))
2 « J'aime »

(Correction : remplacer le premier # de mon exemple par $@ bien sûr…)

Bonjour Jean,

Merci beaucoup pour ta réponse. Comme d'hab, ça marche nickel ! :+1: :folded_hands:
Et ça y est, je me rappelle pourquoi je n'ai jamais refait de Scheme depuis mes années fac :smiley:

Pour ma culture, est-ce qu'il y a un endroit où je peux avoir une explication simple entre $, $@, #, etc.?

L'étape suivante d'automatisation sera d'itérer une liste de books à créer, à partir d'une liste définie en début de fichier, du type
(suffixe, transposition, (clef_aigu clef_grave))
Ex:
("Sib_Clef_Sol" "c d" ("alto" "alto_8")).

Et vu comme j'ai ramé pour un simple (if ) je pense que je vais bien m'amuser :slight_smile:

Bonne journée,
Emmanuel

Pour # vs. $, j'ai essayé d'expliquer la différence sur cette page de ce guide écrit il y a des années (le lien se trouve aussi dans la barre de gauche sur ce forum).

Ensuite, #@ et $@ sont simplement des variantes qui prennent une liste d'éléments et les insèrent chacun comme avec # ou $ respectivement.

2 « J'aime »

Bonsoir à tous,

Je reprends ce thread pour compléter ma demande: la syntaxe proposée par Jean fonctionne très bien, à partir du moment où la condition est vraie.

$@(if (equal? defaultInstrumentKey "Clef_Sol")
  (list
   #{
    \book { % Les données du premier jeu de partitions
    }
    #}
   #{
    \book { % Les données du second jeu de partitions
    }
  #}

Mais si la condition est fausse, alors on prend le message d'erreur suivant:

" Guile a signalé une erreur pour l'expression débutant ici:
$@(if (equal? defaultInstrumentKey "Clef_Sol") In procedure apply: Apply to non-list: #<unspecified>"

En clair, de ma compréhension: la partie else n'est pas correcte.

Or j'ai essaye de mettre quelques trucs (list (), '(), etc.) avant la dernière parenthèse du if, mais sans succès.

Quelqu'un sait comment on matérialise un "pas de else" alors qu'on a spécifié un $@ (qui donc travaille avec des listes)?

Merci, bonne soirée à tous,
Emmanuel

Tiens, je croyais que $@ acceptait *unspecified*, mais il semblerait que non. Cela dit, '() devrait fonctionner.

Merci beaucoup Jean! :slight_smile:

Bon je me suis bien ridiculisé, en mettant '() ça a l'air de fonctionner: plus d'erreur à la compil. J'étais pourtant persuadé l'avoir essayé. :frowning: je ne sais pas quelle boulette j'ai faite.

Le point positif est que le thread est plus complet, pour éventuellement servir à d'autres.

Bonne fin de soirée.