4

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?

  • 1
    Wouldn't a usual \docvar_key_defined:nTF be much easier? – user31729 Mar 20 '17 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.) – Bruno Le Floch Mar 20 '17 at 22:41
  • @BrunoLeFloch: Thanks ;-) I also think (although a little bit slower, perhaps) that a \prop variable could be more useful here – user31729 Mar 20 '17 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 Mar 21 '17 at 9:03
  • 1
    Ah, in your version 2 you're missing braces around #1 as an argument of \prop_if_in:NnTF. – Bruno Le Floch Mar 22 '17 at 9:32
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.