Latex3: définir \tl_if_integer :n

Créé le 5 juil. 2021  ·  19Commentaires  ·  Source: latex3/latex3

Salut,

Il sera agréable de tester si une liste de jetons est un entier ou non, sans recourir à l'utilisation interne __int_to_ roman:w :

\prg_new_conditional:Npnn \tl_if_integer:n #1 { p, T, F, TF }
{
  \tl_if_blank:oTF { \__int_to_roman:w -0#1 }
   {
    \prg_return_true:
   }
   {
    \prg_return_false:
   }
}

Commentaire le plus utile

Je suis d'accord qu'il serait logique de fournir \str_if_integer:nTF , mais on ne sait pas encore quels devraient être les nombres entiers autorisés. Vraisemblablement, les espaces devraient être autorisés entre les signes, mais pas dans un entier puisque TeX l'interdit ?

Code basé sur \romannumeral sauts pour les longues chaînes de chiffres, avec une erreur "nombre trop grand". Vraisemblablement, nous avons besoin d'un processus plus lent qui ne saisit que quelques chiffres à la fois, mais il devient alors ennuyeux de détecter les espaces entre les chiffres.

Une alternative/ajout serait \str_to_integer:nF qui nettoie la chaîne si elle ressemble "assez" à un entier (nous pourrions décider d'être un peu laxiste (mais bien documenté)) et laisse sinon son deuxième argument dans le flux d'entrée.

Tous les 19 commentaires

Mieux ici :

\prg_new_conditional:Npnn \tl_if_integer:n #1 { p, T, F, TF }
{
  \tl_if_blank:nTF{#1}
    {
      \prg_return_false:
    }
    {
      \tl_if_blank:oTF { \__int_to_roman:w -0#1 }
      {
        \prg_return_true:
      }
      {
        \prg_return_false:
      }
    }
}

Le nom semble étrange : il ne vérifie pas réellement un entier (par exemple, -5 est un entier mais renvoie faux, +7 renvoie également faux). Cela ressemble plus à un test si seuls des chiffres sont présents.

@zauguin Ok pour le nom mais la fonction est utile, et faites correspondre l'ancienne coche du livre tex pour vérifier si le chiffre. Je suis d'accord que l'entier pourrait être implémenté en utilisant regex mais ce sera lent

Amélioré avec vos commentaires :

\prg_new_conditional:Npnn \tl_if_digit:n #1 { p, T, F, TF }
{
  \tl_if_blank:nTF{#1}
    {
      \prg_return_false:
    }
    {
      \tl_if_blank:oTF { \__int_to_roman:w -0#1 }
      {
        \prg_return_true:
      }
      {
        \prg_return_false:
      }
    }
  }
\prg_generate_conditional_variant:Nnn \tl_if_digit:n { o } { p, T, F, TF }
\prg_new_conditional:Npnn \__tl_if_integer:n #1 { p, T, F, TF }
{
    \exp_args:No\str_if_eq:onTF{\tl_head:n{#1}}{+}
    {
      \exp_args:No\tl_if_digit:oTF{\tl_tail:n{#1}}
      {
        \prg_return_true:
      }
      {
        \prg_return_false:
      }
    }
    {
      \exp_args:No\str_if_eq:onTF{\tl_head:n{#1}}{-}
      {
        \exp_args:No\tl_if_digit:oTF{\tl_tail:n{#1}}
        {
          \prg_return_true:
        }
        {
          \prg_return_false:
        }
      }
      {
        \prg_return_false:
      }
    }
}
\prg_new_conditional:Npnn \tl_if_integer:n #1 { p, T, F, TF }
{
  % fast path
  \tl_if_digit:nTF{#1}
  {
    \prg_return_true:
  }
  {
    % slow path
    \__tl_if_integer:nTF{#1}
    {
      \prg_return_true:
    }
    {
      \prg_return_false:
    }
  }
}

@bastien-roucaries TeX accepte plusieurs signes devant un nombre, donc votre test est généralement suffisant mais pas toujours. Si cela devait être mis en œuvre, cela pourrait autoriser plusieurs signes comme celui-ci :

\ExplSyntaxOn
\prg_new_conditional:Npnn \str_if_integer:n #1 { p, T, F, TF }
  { \exp_after:wN \__str_if_integer_sign:N \tl_to_str:n {#1} \scan_stop: }
\cs_new:Npn \__str_if_integer_sign:N #1
  {
    \if:w $
        \if_meaning:w - #1 F \fi:
        \if_meaning:w + #1 F \fi: $
      \exp_after:wN \__str_if_integer_digits:w \exp_after:wN #1
    \else:
      \exp_after:wN \__str_if_integer_sign:N
    \fi:
  }
\cs_new:Npn \__str_if_integer_digits:w #1 \scan_stop:
  {
    \tl_if_blank:nTF {#1}
      { \prg_return_false: }
      {
        \tl_if_blank:oTF { \__int_to_roman:w -0#1 }
          { \prg_return_true: }
          { \prg_return_false: }
      }
  }

\cs_new:Npn \test #1
  { \typeout { #1: \str_if_integer:nTF {#1} { INT } { NOT } } }

\test {   }
\test { ~ }
\test { 1 }
\test { - }
\test { -1 }
\test { +1 }
\test { +-+-+-1 }

\stop

Le test est str pour empêcher l'expansion des jetons dans l'argument. La mienne et votre implémentation ne développent pas le signe, mais développent les chiffres avec \romannumeral . Une version tl devrait probablement tout étendre au besoin.

Je suis d'accord qu'il serait logique de fournir \str_if_integer:nTF , mais on ne sait pas encore quels devraient être les nombres entiers autorisés. Vraisemblablement, les espaces devraient être autorisés entre les signes, mais pas dans un entier puisque TeX l'interdit ?

Code basé sur \romannumeral sauts pour les longues chaînes de chiffres, avec une erreur "nombre trop grand". Vraisemblablement, nous avons besoin d'un processus plus lent qui ne saisit que quelques chiffres à la fois, mais il devient alors ennuyeux de détecter les espaces entre les chiffres.

Une alternative/ajout serait \str_to_integer:nF qui nettoie la chaîne si elle ressemble "assez" à un entier (nous pourrions décider d'être un peu laxiste (mais bien documenté)) et laisse sinon son deuxième argument dans le flux d'entrée.

@blefloch Quelle est la limite documentée de \romannumeral ?

@bastien-roucaries Le plus grand entier que TeX peut gérer : 2³¹−1 = 2147483647.

@PhelypeOleinik Il semble que @blefloch signifie que +-+-+-+-+-+-+-+-+-+-+-+-+000000000000000000000000000000000000000000000000000000000000 pourrait casser \romannumeral ...

Alors, quelle est la taille maximale de la chaîne ?

@bastien-roucaries \romannumeral ne rompt avec "Nombre trop grand" que pour un nombre non nul. TeX peut prendre une chaîne arbitrairement longue de zéros tant que l'entier résultant est dans l'intervalle [−2³¹−1, 2³¹−1].

@bastien-roucaries @blefloch Je n'oublierais pas les entiers au format hexadécimal ou octal. Et

-`a

est aussi un entier.

il existe un test interne pour les chiffres dans l3bitset \__bitset_test_digits:nTF . Il ne gère pas les signes car cela n'était pas nécessaire, mais il devrait gérer les expressions entières.

comme @eg9 vient de le suggérer, quel est le cas d'utilisation réel ici ? Est-ce une vérification de document au niveau de l'utilisateur pour une chaîne de chiffres, ou une vérification que la chaîne est une entrée valide pour une fonction entière expl3. Ce dernier semble plus utile dans un contexte expl3, et signifie fondamentalement qu'il ne reste rien après \numexpr#1 donc la vérification lente des chaînes littérales de chiffres ne serait pas nécessaire.

@davidcarlisle Ce bogue concerne le premier cas, mais j'aimerais avoir la deuxième utilisation

Je ne pense pas être favorable à l'extension de la couche de programmation L3 avec des extensions aléatoires qui sont (éventuellement) utiles dans des situations particulières mais qui n'ont pas de cas d'utilisation clairs et régulièrement nécessaires. Pour moi, c'est un exemple. Si nous commençons par cela, où finissons-nous ? Combien de "c'est tl du X" spécial faut-il supporter alors ? Mon vote à ce sujet est non ; pas pour la langue de base.

@FrankMittelbach Sachant que nous pouvons faire des calculs ou non sur TL est utile. L'autre pourrait être fait en utilisant regex, mais avec le piège que cela ne fonctionne pas dans un contexte d'expansion (et j'ai besoin de ce test pour fonctionner dans un contexte d'expansion)

Sans doute. Mais est-il suffisamment utile pour justifier son inclusion dans le langage de base (ou uniquement pour être fourni dans le cadre d'un code de package lorsque cela est réellement nécessaire) ? C'est la question pour moi ici et jusqu'à présent, je n'ai pas vraiment vu d'arguments en faveur de son inclusion.

Vous pouvez poser la même question pour "est-ce une dimension", "est-ce que sauter", "est-ce que des lettres", "contient-il des caractères non ascii", "est-ce un format de date", et, et, et ... les possibilités sont assez ouvertes et pour la plupart d'entre elles, vous pouvez construire un cas d'utilisation ou deux. Mais 99% du temps, ils resteront assis là et prendront de la place. Et même si l'espace n'est pas une prime comme c'était le cas dans le passé, il ajoute encore à la complexité et à la maintenabilité du système central. Encore une fois, cette fonctionnalité est-elle à usage large et répété ? Si oui, et j'entends des arguments convaincants pour qu'il puisse être considéré comme un candidat à l'inclusion. Si ce n'est pas le cas, il doit être implémenté dans le cadre du code qui en a besoin.

@FrankMittelbach Le problème est spécifique à biblatex ici. Nous devons tester si un champ est un entier (pensez au nombre de pages) et ainsi faire un peu d'athmétique dessus, dans un contexte extensible.
Ok ti est spécifique mais la partie la plus délicate concerne les éléments extensibles.
Peut-être que ce genre de test devrait seulement être documenté. En lisant la doc je ne sais pas comment faire, et d'ailleurs biblatex core pense qu'il n'est pas possible de tester (développer comptabible) si un token est un entier.

Peut-être que la solution est de rendre regex extensible (je pense que ce sera bien)

Ne vous méprenez pas, je ne suis pas du tout contre le fait que nous vous aidions du côté de biblatex pour que cela fonctionne, et il se peut bien que sur le noyau il nous manque certaines fonctionnalités qui devraient être dans le noyau pour supporter cela. Mon point est que le noyau devrait se limiter aux besoins "généraux" et fournir les bases générales de base pour écrire du code spécial, mais ne pas fournir toutes sortes d'extensions qui sont utilisées très rarement, voire pas du tout (par exemple, dans ce cas, lorsque biblatex N'est pas utilisé). Sinon, nous finirons par nous retrouver avec un ensemble de commandes très chargé.

Faire fonctionner les choses de manière extensible s'accompagne généralement d'un prix élevé, soit en fonctionnalités limitées, soit en perte de vitesse, soit les deux. Je doute donc que ce soit une bonne idée d'essayer de rendre les regex extensibles, mais je laisse @blefloch commenter cela.

Mais sans connaître votre cas d'utilisation plus en détail : quelque part, vos champs sont en cours de configuration et cela ne se fait pas de manière extensible car cela nécessitera des affectations, donc à ce stade, vous pouvez déterminer si vous avez un entier ou autre chose et enregistrer ce fait qui pourrait ensuite être utilisé de manière extensible (pas sûr que cela aide ou soit faisable, mais cela éviterait de tester le champ encore et encore).

Cette page vous a été utile?
0 / 5 - 0 notes