5

I made a macro that just puts an item in a sequence. Now I want to check if the item is in the sequence. I tried to create a predicate with the \prg_new_conditional:Npnn function but I run into a Missing number error.

EDIT:

I changed to use a property list, to have expandable macros. The error still appears either for \if_predicate:w and \docvar_key_defined:nTF.

VERSION 2:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\prop_new:N \g_docvar_defined_prop
\DeclareDocumentCommand \definedocvar {o m} {
  \prop_gput_if_new:Nnn \g_docvar_defined_prop {#2} {}
  }

\prg_new_conditional:Npnn \docvar_key_defined:n #1 {p, T, F, TF}
  {
    \prop_if_in:NnTF \g_docvar_defined_prop #1 {\prg_return_true:} {\prg_return_false:}
  }
\ExplSyntaxOff



\begin{document}
\definedocvar{title}
\ExplSyntaxOn
    \if_predicate:w \docvar_key_defined_p:n { title }
    Title exists
    \else:
    Title doesn't exist.
    \fi:
%\docvar_key_defined:nTF {title} {Title exist} {Title doesn't exist}
\ExplSyntaxOff
\end{document}

Someone can explain a bit how the boolean logic is working in expl3?

6
  • 1
    Wouldn't a usual \docvar_key_defined:nTF be much easier?
    – user31729
    Commented Mar 20, 2017 at 22:41
  • 2
    Short answer: the problem is that you use the non-expandable \seq_if_in:NnTF in the definition of \docvar_key_defined:n and that is not possible if you want a predicate (predicates must be expandable). Depending on details you may be able to use a property list instead of a sequence to store the data. (EDIT: Christian Hupfer is right.) Commented Mar 20, 2017 at 22:41
  • @BrunoLeFloch: Thanks ;-) I also think (although a little bit slower, perhaps) that a \prop variable could be more useful here
    – user31729
    Commented Mar 20, 2017 at 22:48
  • @BrunoLeFloch I changed to use the prop. It seems that every function used is expandable, but I still have the problem, even using \docvar_key_defined:nTF.
    – TeXtnik
    Commented Mar 21, 2017 at 9:03
  • 1
    Ah, in your version 2 you're missing braces around #1 as an argument of \prop_if_in:NnTF. Commented Mar 22, 2017 at 9:32

1 Answer 1

4

Since they can be used after \if_predicate:w, predicates must be expandable. This means that they cannot use any code that changes the value of any variable.

Internally, \seq_if_in:NnTF needs to perform an assignment as that is the only way to test if the item (that is looked for) precisely matches what is in the sequence (comparing tokens and not just the characters in the string representation). So \seq_if_in:NnTF cannot be used to define a predicate.

Property lists store their keys after turning them to strings of characters (ignoring category codes). This turns out to allow keys to be compared expandably, hence \prop_if_in:NnTF is expandable. This is why we advised in comments to store your "document variables" in a property list.

Then a pair of braces was missing: when writing \prop_if_in:NnTF \l_my_prop {#1} in a definition, the braces around #1 are necessary, otherwise only the first token of #1 will be taken as the key to search in the property list.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .