1

I want to check a mutable variable against many possible values, so that a macro will behave differently based on that value.

Since there are many variables, they are stored using pgfkeys. Testing against values is done with etoolbox and plenty of braces to make it more "functional".

A minimal non-working example using pgfkeys and etoolbox:

\documentclass[12pt]{article}

\usepackage{etoolbox}
\usepackage{pgfkeys}

\begin{document}

\pgfkeys{/north/.default=a}

\pgfkeyssetvalue{/north}{h}

Current value of variable: \pgfkeysvalueof{/north}

\ifdefstring{\pgfkeysvalueof{/north}}{h}{Value is h}{Value is not h}

\end{document}

It does not work (prints "Value is not h"). I also couldn't make it work with other similar commands (like \ifstrequal, \ifcsstrequal, etc.).

How to make it work?

4
  • 1
    Welcome to TeX.SE!
    – Mensch
    Commented Apr 24, 2023 at 17:33
  • Try \edef\mytestvariable{\pgfkeysvalueof{/north}} \ifdefstring{\mytestvariable}{h}{Value is h}{Value is not h}. Commented Apr 24, 2023 at 17:59
  • 1
    While you might be thinking that storing inside pgfkeys has some biggish advantage, I simply can't see that. \pgfkeysvalueof{some/long/string} is not more clear than \myvalue@some@long@string, imho, but it is slower and giving your editor a harder time (if your editor knows and autocompletes TeX syntax).
    – Skillmon
    Commented Apr 24, 2023 at 18:00
  • 1
    @JasperHabicht that would fully expand, why not use \pgfkeysgetvalue{/north}\mytestvariable instead of \edef?
    – Skillmon
    Commented Apr 24, 2023 at 18:01

1 Answer 1

1

You could retrieve the value of your key first using \pgfkeysgetvalue. The following automatises this a bit for you inside a macro:

\documentclass{article}

\usepackage{pgfkeys}
\usepackage{etoolbox}

\providerobustcmd*\mycmpvalue[1]
  {%
    \pgfkeysgetvalue{#1}\mytmp
    \ifdefstring\mytmp
  }

\pgfkeys{/north/.initial=a}

\begin{document}
\mycmpvalue{/north}{h}{true}{false}

\pgfkeyssetvalue{/north}{h}
\mycmpvalue{/north}{h}{true}{false}
\end{document}

enter image description here

Small aside: You most likely mixed up .default and .initial (the former will not store a inside your key but will be used if you omit the value inside of \pgfkeys).

Note however that this still uses macros internally to store your value (those are just hidden by a layer of pgfkeys), instead of that indirection simply storing your values inside of macros seems not more complicated, but it will be faster and easier for you to code. Compare with the following:


\documentclass{article}

\usepackage{etoolbox}

\newcommand*\mynorth{a}

\begin{document}
\ifdefstring\mynorth{h}{true}{false}

\renewcommand*\mynorth{h}
\ifdefstring\mynorth{h}{true}{false}
\end{document}

And if you still want to use a key=value interface to set your values (that part would be understandable), you could instead use the .store in handler if you want to stick to pgfkeys, or use a different key=value interface (your code will more or less become independent of the used key=value interface):

\documentclass{article}

\usepackage{etoolbox}
\usepackage{pgfkeys}

\pgfqkeys{/my}{north/.store in=\mynorth,north=a}

\begin{document}
\ifdefstring\mynorth{h}{true}{false}

\pgfkeys{/my/north=h}
\ifdefstring\mynorth{h}{true}{false}
\end{document}

Or the same with expkv-def (of which I'm the author, so I picked that one for the example, could use almost any other key=value implementation for this):

\documentclass{article}

\usepackage{etoolbox}
\usepackage{expkv-def}

\ekvdefinekeys{my}{store north=\mynorth,initial north=a}

\begin{document}
\ifdefstring\mynorth{h}{true}{false}

\ekvset{my}{north=h}
\ifdefstring\mynorth{h}{true}{false}
\end{document}
3
  • @eduardofischermath this is what the \mycmpvalue is doing (see currying, if you just forward #2 to #4 without altering them or rearranging them, you can just leave them).
    – Skillmon
    Commented Apr 24, 2023 at 18:55
  • I cannot upvote the answer, nor can I really edit my comment which was prematurely posted. Here is the intended comment: Your answer is solid and \newcommand{\comparepgfkey}[4]{% \pgfkeysgetvalue{#1}{\mytempvariable}% \ifdefstring{\mytempvariable}{#2}{#3}{#4}% }% works fine for my purposes (I prefer a more explicit currying to ease debugging). But why is this (and is this?) workaround really necessary in LaTeX? Also, as you wrote in comment to question, pgfkeys does not appear as advantageous anymore as it gets tricked by this kind of use. Commented Apr 24, 2023 at 19:03
  • @eduardofischermath because TeX is a macro expansion language, no declarative functional programming thingy. If you want a "function" (read: macro) to see the contents of some variable you have to expand it, if you want it to see the results of some other function you have to expand it (provided it is expandable, in TeX not everything is expandable, assignments for instance aren't expandable).
    – Skillmon
    Commented Apr 24, 2023 at 19:59

You must log in to answer this question.

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