1

I need a very simple associative array for my project which I am trying to implement as in the following MWE.

Two questions please:

  1. How do I need to tweak my \alistget macro to allow its result to be used in functions like \DTMdate?
  2. How should I debug this? I have been extensively round the houses with the likes of etoolbox \csdef and \csuse functions to no avail.

I don't really want solutions along the lines of "use xyz implementation of associative arrays" as this is an important learning experience for me!

\documentclass{article}
\usepackage[british]{datetime2}
\newcommand{\alistadd}[2]{
    \expandafter\def\csname alist_#1 \endcsname{#2}
}
\newcommand{\alistget}[1]{%
    \csname alist_#1 \endcsname%
}
\begin{document}
    \alistadd{Tom}{1970-12-25}
    Tom \alistget{Tom}\par
    This works: Tom \expandafter\DTMdate\csname alist_Tom \endcsname\par
    This doesn't: Tom \DTMdate{\alistget{Tom}}\par
\end{document}
0

You can avoid your hassles by using expl3 and xparse:

\documentclass{article}
\usepackage[british]{datetime2}

\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\xDTMdate}{m}
 {% use the expanding variant
  \dsla_xdtmdate:f { #1 }
 }
% syntactic sugar
\cs_new_eq:NN \dsla_xdtmdate:n \DTMdate
% create the expanding variant
\cs_generate_variant:Nn \dsla_xdtmdate:n { f }

% better management with a property list
\NewDocumentCommand{\alistadd}{mm}
 {
  \prop_gput:Nnn \g_dsla_datelist_prop { #1 } { #2 }
 }
\DeclareExpandableDocumentCommand{\alistget}{m}
 {
  \prop_item:Nn \g_dsla_datelist_prop { #1 }
 }
\prop_new:N \g_dsla_datelist_prop

\ExplSyntaxOff

\begin{document}

\alistadd{Tom}{1970-12-25}

Tom \alistget{Tom}

This works: Tom \xDTMdate{\alistget{Tom}}

\end{document}

I define a new \xDTMdate command that does “full expansion until possible” of its argument (that is, it fully expands macros until finding a single unexpandable token, which is sufficient for our purposes).

The \alistget command is made expandable by using \prop_item:Nn, which behaves well in this context. Actually, also your “hand made” property list would do, but I think it's better to stick with expl3.

enter image description here

  • Perfect, thank you. I shall get up to speed with xpl3 by reading this – dsla Oct 24 '16 at 16:33
1

The \DTMdate macro doesn't expand its argument before looking for date formats so you need to expand (two steps) before calling the macro

\documentclass{article}
\usepackage[british]{datetime2}
\newcommand{\alistadd}[2]{%dont forget
    \expandafter\def\csname alist_#1 \endcsname{#2}% these
}
\newcommand{\alistget}[1]{%
    \csname alist_#1 \endcsname% this one isn't needed
}
\begin{document}
    \alistadd{Tom}{1970-12-25}
    Tom \alistget{Tom}\par
    This works: Tom \expandafter\DTMdate\csname alist_Tom \endcsname\par
    This doesn't: Tom 
\expandafter\expandafter\expandafter\DTMdate
\expandafter\expandafter\expandafter{\alistget{Tom}}\par
\end{document}

The first step give gets from \alistget{Tom} to \alist_Tom and the second step gets to 1970-12-25

Note that your macros work by pure expansion so there is nothing really you can do to make it more likely that they "just work" in the argument of another command, but unlike in typical compiled languages, macro arguments are not expanded before the macro is called, so there is no way. in general, of making a macro always be equivalent to its replacement text, it depends on the details of the calling macro (\DTMdate here).

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.