Latex3: определить \tl_if_integer:n

Созданный на 5 июл. 2021  ·  19Комментарии  ·  Источник: latex3/latex3

Привет,

Было бы неплохо проверить, является ли список токенов целым числом или нет, не прибегая к использованию внутреннего __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:
   }
}

Самый полезный комментарий

Я согласен, что имело бы смысл предоставить \str_if_integer:nTF , но пока не ясно, какими должны быть разрешенные целые числа. Предположительно, пробелы должны быть разрешены между знаками, но не внутри целого числа, поскольку TeX запрещает это?

Код, основанный на \romannumeral , прерывается для длинных строк цифр с ошибкой «слишком большое число». Предположительно, нам нужен более медленный процесс, который захватывает только несколько цифр за раз, но тогда становится раздражающим обнаружение пробелов между цифрами.

Альтернативой/дополнением может быть \str_to_integer:nF , который дезинфицирует строку, если она выглядит «достаточно» как целое число (мы могли бы решить быть несколько небрежным (но хорошо задокументированным)) и в противном случае оставляет свой второй аргумент во входном потоке.

Все 19 Комментарий

Лучше здесь:

\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:
      }
    }
}

Название кажется странным: на самом деле оно не проверяет целое число (например, -5 является целым числом, но возвращает false, +7 также возвращает false). Это больше похоже на тест, если присутствуют только цифры.

@zauguin Хорошо для имени, но функция полезна, и сопоставьте старую галочку в текстовой книге, чтобы проверить, является ли цифра. Я согласен, что целое число можно реализовать с помощью регулярных выражений, но это будет медленно

Улучшено с вашими комментариями:

\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 принимает несколько знаков перед числом, поэтому вашего теста обычно достаточно, но не всегда. Если это будет реализовано, это может позволить несколько таких знаков:

\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

Тест str предотвращает расширение токенов в аргументе. И моя, и ваша реализация не расширяют знак, но расширяют цифры с помощью \romannumeral . Версия tl , вероятно, должна была бы расширять все по мере необходимости.

Я согласен, что имело бы смысл предоставить \str_if_integer:nTF , но пока не ясно, какими должны быть разрешенные целые числа. Предположительно, пробелы должны быть разрешены между знаками, но не внутри целого числа, поскольку TeX запрещает это?

Код, основанный на \romannumeral , прерывается для длинных строк цифр с ошибкой «слишком большое число». Предположительно, нам нужен более медленный процесс, который захватывает только несколько цифр за раз, но тогда становится раздражающим обнаружение пробелов между цифрами.

Альтернативой/дополнением может быть \str_to_integer:nF , который дезинфицирует строку, если она выглядит «достаточно» как целое число (мы могли бы решить быть несколько небрежным (но хорошо задокументированным)) и в противном случае оставляет свой второй аргумент во входном потоке.

@blefloch Каков задокументированный предел \romannumeral ?

@bastien-roucaries Самое большое целое число, которое TeX может обработать: 2³¹−1 = 2147483647.

@PhelypeOleinik Кажется, что @blefloch означает, что +-+-+-+-+-+-+-+-+-+-+-+-+00000000000000000000000000000000000000000000000000000000000000000000 может сломаться \romannumeral ...

Итак, каков максимальный размер строки?

@bastien-roucaries \romannumeral ломается только с «Число слишком большое» для ненулевого числа. TeX может принимать произвольно длинную строку нулей, пока результирующее целое число находится в диапазоне [-2³¹-1, 2³¹-1].

@bastien-roucaries @blefloch Я бы не забыл целые числа в шестнадцатеричном или восьмеричном формате. И

-`a

тоже целое число.

есть внутренний тест для цифр в l3bitset \__bitset_test_digits:nTF . Он не обрабатывает знаки, так как в этом нет необходимости, но должен обрабатывать целочисленные выражения.

как только что намекнул @eg9 , каков здесь фактический вариант использования? Является ли это проверкой документа на уровне пользователя для строки цифр или проверкой того, что строка является допустимым вводом для целочисленной функции expl3. Последнее кажется более полезным в контексте expl3 и в основном означает, что после \numexpr#1 ничего не остается, поэтому медленная проверка литеральных строк цифр не требуется.

@davidcarlisle Эта ошибка относится к первому случаю, но я бы хотел использовать второй вариант.

Я не думаю, что я за расширение уровня программирования L3 случайными расширениями, которые (возможно) полезны в особых ситуациях, но не имеют четких регулярных необходимых вариантов использования. Для меня это один из таких примеров. Если мы начнем с этого, где мы закончим? Сколько специальных «это какой-то X» мы должны поддерживать тогда? Мой голос по этому поводу - нет; не для основного языка.

@FrankMittelbach Знание того, можем ли мы выполнить некоторые вычисления или нет на TL, полезно. Другой можно было бы сделать с помощью регулярного выражения, но с ошибкой, что он не работает в расширенном контексте (и мне нужно, чтобы этот тест работал в расширенном контексте)

Без сомнений. Но достаточно ли он полезен, чтобы гарантировать его включение в основной язык (или только для того, чтобы предоставлять его как часть некоторого кода пакета, когда это действительно необходимо)? Это вопрос для меня здесь, и пока я не видел действительно аргументов в пользу его включения.

Вы можете задать один и тот же вопрос для «это размер», «это как пропустить», «это просто буквы», «содержит ли он символы, отличные от ascii», «это формат даты», и, и, и ... возможности довольно открыты, и для большинства из них вы можете создать один или два варианта использования. Но в 99% случаев они просто будут сидеть и занимать место. И хотя пространство не является премией, как это было в прошлом, оно по-прежнему увеличивает сложность и ремонтопригодность базовой системы. Итак, опять же, этот функционал имеет широкое и многократное использование? Если да, и я слышу убедительные аргументы в пользу того, что его можно считать кандидатом на включение. Если нет, его следует реализовать как часть кода, который в нем нуждается.

@FrankMittelbach Проблема здесь специфична для biblatex. Нам нужно проверить, является ли какое-либо поле целым числом (подумайте о количестве страниц), а также выполнить над ним некоторые арифметические действия в расширяемом контексте.
Хорошо, это специфично, но сложная часть — это расширяемый материал.
Может быть, такой тест должен быть только задокументирован. Читая документ, я не знаю, как это сделать, и, кроме того, ядро ​​​​biblatex считает, что невозможно проверить (расширить совместимость), является ли токен целым числом.

Может быть, решение состоит в том, чтобы сделать регулярное выражение расширяемым (я думаю, это будет хорошо)

Не поймите меня неправильно, я совсем не против того, чтобы мы помогали вам со стороны biblatex, чтобы это работало, и вполне может быть, что в ядре нам не хватает некоторых функций, которые должны быть в ядре для поддержки этого. Я считаю, что ядро ​​должно ограничиваться «общими» потребностями и предоставлять базовую общую основу для написания специального кода, но не предоставлять все виды расширений, которые используются очень редко, если вообще используются (например, в этом случае, когда biblatex не используется). В противном случае мы в конечном итоге получим очень раздутый набор команд.

Заставить все работать с возможностью расширения обычно приходится дорого, либо из-за ограниченной функциональности, либо из-за потери скорости, либо из-за того и другого. Так что я сомневаюсь, что стоит пытаться сделать регулярное выражение расширяемым, но я позволил @blefloch прокомментировать это.

Но, не зная вашего варианта использования более подробно: где-то ваши поля настраиваются, и это не делается расширяемым, поскольку для этого потребуются назначения, поэтому на этом этапе вы можете определить, есть ли у вас целое число или что-то еще, и записать этот факт, который может затем можно расширить (не уверен, что это поможет или возможно, но это позволит избежать повторного тестирования поля).

Была ли эта страница полезной?
0 / 5 - 0 рейтинги