lilypond-user-fr
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Version 2.23.80 : define vs ly:parser-defined


From: Jean Abou Samra
Subject: Re: Version 2.23.80 : define vs ly:parser-defined
Date: Wed, 26 Oct 2022 16:49:49 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.3.1

Bonjour Gilles,


Le 26/10/2022 à 15:30, Gilles Thibault a écrit :
Bonjour tout le monde.
Question en court :
  Peut-on employer indifféremment, pour définir une variable scheme simple,
      define (fournit par guile)
   et ly:parser-define! (fonction scheme fournit par Lilypond) ?

Explications :
J'avais défini dans mes fichiers de config des variables par exemple de la manière suivante :
#(if (not (defined? 'textSize))
     (define textSize -1))

J'ajustais tous les objets Lilypond ayant une propriété font-size en fonction de cette variable :
   \override TextScript.font-size = #textSize
   \override MetronomeMark.font-size = #textSize
   \override BarNumber.font-size = #(1- textSize)  % 1 point de moins
   etc...
Si pour une musique donnée, je trouvais la taille des textes encore trop grosse, je n'avais qu'à rajouter juste avant mon fichier config à inclure
  textSize = #-2
  \include "mon_fichier_config.ly"
et tous les font-size étaient ajustées en prenant en compte cette nouvelle valeur

La version 2 de Guile vient avec des restrictions pour la fonction define
  (voir le message de Jean ABOU



Enchanté, moi c'est Jean ABOU SAMRA :-)



https://lists.gnu.org/archive/html/lilypond-user-fr/2022-10/msg00051.html )
La solution devrait être
  #(define textSize (if (defined? 'textSize)
                        textSize
                        -1))

Pour éviter de redéfinir textSize à la valeur qu'il a déjà, je voudrais garder la syntaxe que j'avais avant, mais en utilisant ly:parser-defined!

#(if (not (defined? 'textSize))
     (ly:parser-define! 'textSize -1))

... ce qui semble fonctionner.

Comme j'ai un très grand nombre de fichiers à modifier, je voudrais être sûr que cette solution est pérenne. Il n'y a pas de projet de restriction de syntaxe pour ly:parser-define! ?



Ton message soulève plusieurs questions.

Est-ce qu'on peut utiliser define et ly:parser-define! de
manière interchangeable ? En général, non, dans ce cas
précis, oui. define est une syntaxe prédéfinie par Guile
qui sert à créer des variables aussi bien globales que
locales. Par exemple, on peut écrire


#(define (f x)
   (define y (1+ x))
   (* 3 y))


qui est équivalent à


#(define (f x)
   (let ((y (1+ x)))
     (* 3 y)))



Tu peux aussi écrire


#(define (f x)
   (ly:parser-define! 'y (1+ x))
   (* 3 y))


mais c'est complètement différent : la variable y n'est
plus locale à la fonction, mais globale, donc visible
en dehors de la fonction, comme si tu avais fait


#(define y #f)
#(define (f x)
   (set! y (1+ x))
   (* 3 y))


En somme, au contraire de define, ly:parser-define! ne crée
jamais que des variables globales. Dans ton cas, la variable
est globale, donc les deux sont effectivement équivalents.


Ensuite, est-ce que des restrictions similaires à define risquent
d'arriver à ly:parser-define! ? Absolument pas, les deux
sont séparés. ly:parser-define! n'est pas pour autant figée
pour l'éternité, mais elle n'a pas plus de raison d'évoluer
que les autres fonctions de LilyPond, en tous cas pas à cause
de define. Les règles sur le placement de define sont purement
syntaxiques et imposées par Guile, or ly:parser-define! est
une bête fonction, pas une « syntaxe spéciale » comme define
(en termes techniques, une « macro »), donc aucun problème
de ce côté-là.


Pour finir, est-ce que je recommande personnellement d'utiliser ce
style de codage ? À vrai dire, non, pas vraiment,  pour deux raisons.
D'une part, en utilisant defined?, tu mets quand même les mains dans
le cambouis de Guile et de son interaction de bas niveau avec LilyPond.
Pourquoi pas, mais il faut savoir que defined? te réserve des surprises
si tu n'as pas étudié la manière dont ça fonctionne. Exemples :


\version "2.23.80"

#(define variable-globale 'toto)
#(display (defined? 'variable-globale)) % => #t
#(newline)

#(let ((variable-locale 'toto))
   (display (defined? 'variable-locale)) ; => #f
   (newline))

\layout {
  variable-layout = #'toto
}

\score {
  { c' }
  \layout {
    #(display (defined? 'variable-layout)) % => #t
    #(newline)
  }
}



La deuxième raison est qu'avec ce système, le réglage est global.
Tu ne peux pas inclure ton fichier de config et régler une taille
plus petite pour une partition seulement à l'intérieur d'un \book,
ou un seul \book parmi plusieurs, etc.

Somme toute, je ferais plutôt :


\version "2.23.80"

setTextSize =
#(define-music-function (textSize) (number?)
   #{
     \override TextScript.font-size = #textSize
     \override Score.MetronomeMark.font-size = #textSize
     \override Score.BarNumber.font-size = #(- textSize 1)
   #})

\layout {
  \setTextSize -1
}



En incluant cela, tu as une taille par défaut, et si tu veux la changer,
il suffit de faire

\include "mon_fichier_config.ly"
\layout {
  \setTextSize -2
}


ou bien

\include "mon_fichier_config.ly"

\book {
  \score { ... }
  \score {
    ...
    \layout {
      \setTextSize -2
    }
  }
}


Bien sûr, la transition est plus compliquée que de changer un
define en ly:parser-define!, donc si tu as vraiment beaucoup
de fichiers, pourquoi pas rester à ly:parser-define! .


Cordialement,
Jean




reply via email to

[Prev in Thread] Current Thread [Next in Thread]