I am a beginner in Latex programming. I'm working on a small package based on arrayjobx. I have created structures to handle associative arrays as described in arrayjobx.pdf. My intention is to add some features of high level, but I've encountered the first problem by creating a macro that you exchange the values of two elements of the same array. The error message "Undefined control sequence" is showed. Any help is welcome.
The code of the package, called arrayassoc.sty, is the following:
\NeedsTeXFormat{LaTeX2e}[1994/06/01] \ProvidesPackage{arrayassoc} [2016/08/11 v1.0 of arrayassoc package] \RequirePackage{arrayjobx,multido} \makeatletter % Internally, we use three "standard" arrays to define one associative array \newarray\AssociativeArray@Names \newarray\AssociativeArray@Values \newarray\AssociativeArray@Indexes \newcount\AssociativeArrayNbValues \AssociativeArrayNbValues=\z@ \newif\ifAssociativeArray@ElementFound % To store one element \def\AssociativeArray(#1)=#2{% \expandarrayelementtrue \AssociativeArray@ElementFoundfalse \edef\@tempa{#1}% \edef\@tempb{#2}% \Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% \checkAssociativeArray@Names(\iValue)% \ifx\@tempa\cachedata % This element already exist: we replace its current value % \checkAssociativeArray@Values(\iValue)% Debug % \typeout{In #1, replace ‘\cachedata’\space by ‘#2’}% Debug \AssociativeArray@Values(\iValue)={\@tempb}% \AssociativeArray@ElementFoundtrue \multidostop \fi} \ifAssociativeArray@ElementFound \else % New element: \advance\AssociativeArrayNbValues\@ne \AssociativeArray@Names(\AssociativeArrayNbValues)={\@tempa}% \AssociativeArray@Values(\AssociativeArrayNbValues)={\@tempb}% \AssociativeArray@Indexes(\AssociativeArrayNbValues)={\the\AssociativeArrayNbValues}% \fi} % To get one element \def\checkAssociativeArray(#1){% \edef\@tempa{#1}% \edef\@tempb{999999}% \Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% \checkAssociativeArray@Names(\iValue)% \ifx\@tempa\cachedata % We have found it by name \edef\@tempb{\iValue}% \multidostop \fi} % We have now to get its value \checkAssociativeArray@Values(\@tempb)} % To get one index \def\checkiAssociativeArray(#1){% \edef\@tempa{#1}% \edef\@tempb{999999}% \Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% \checkAssociativeArray@Names(\iValue)% \ifx\@tempa\cachedata % We have found it by name \edef\@tempb{\iValue}% \multidostop \fi} % We have now to get it index \checkAssociativeArray@Indexes(\@tempb)% %same result if replace above line by: \@tempb } % Simple macro to print all the associative array \def\printAssociativeArray{% \par\noindent% Array (\newline \multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% \checkAssociativeArray@Names(\iValue)% \hphantom{Ar}\iValue: [‘\cachedata’] $=>$ ‘\AssociativeArray@Values(\iValue)’\newline}% )\par% } % A simple macro to print the array of indexes (for debugging) \def\printIndexes{% \par\noindent% Array (\newline \multido{\iIndex=\@ne+\@ne}{\AssociativeArrayNbValues}{% \checkAssociativeArray@Indexes(\iIndex)% \hphantom{Ar}index(\iIndex) $=$ ‘\cachedata’\newline}% )\par% } \def\echoAssociativeArray(#1){% \checkAssociativeArray(#1)% \ifemptydata% \null\relax% \else% \cachedata% \fi% } \def\echoiAssociativeArray(#1){% \checkiAssociativeArray(#1)% \ifemptydata% 0% index not found \else% \cachedata% \fi% } \def\firstValueAssociativeArray{% \AssociativeArray@Values(1) } \def\firstKeyAssociativeArray{% \AssociativeArray@Names(1) } \def\lastValueAssociativeArray{% \AssociativeArray@Values(\AssociativeArrayNbValues) } \def\lastKeyAssociativeArray{% \AssociativeArray@Names(\AssociativeArrayNbValues) } \def\lengthAssociativeArray{% \the\AssociativeArrayNbValues } \newif\ifAssociativeArray@FirstElementFound \newif\ifAssociativeArray@SecondElementFound \def\swapAssociativeArray(#1)(#2){% \expandarrayelementtrue% \def\@tempi{\echoAssociativeArray(#1)}% \def\@tempj{\echoAssociativeArray(#2)}% \@tempi, \@tempj% for debugging \AssociativeArray(#1)={\@tempj}% this doesn't work \AssociativeArray(#2)={\@tempi}% this doesn't work %I've replaced the two lines of code above with the following code, but it does not work. %\AssociativeArray@FirstElementFoundfalse% %\AssociativeArray@SecondElementFoundfalse% %\edef\@tempa{#1}% %\edef\@tempb{#2}% %\Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% % \checkAssociativeArray@Names(\iValue)% % \ifx\@tempa\cachedata % % First element exists: we replace its current value % \AssociativeArray@Values(\iValue)={\@tempj}% this command fails % \AssociativeArray@FirstElementFoundtrue % \else % \ifx\@tempb\cachedata % % Second element exists: we replace its current value % \AssociativeArray@Values(\iValue)={\@tempi}% this command fails % \AssociativeArray@SecondElementFoundtrue % \fi % \fi % \ifAssociativeArray@FirstElementFound % \ifAssociativeArray@SecondElementFound % \multidostop % \fi % \fi} } \makeatother \newcommand{\newAssociativeArray}[1]{% \global\expandafter\let\csname#1\endcsname\AssociativeArray% \global\expandafter\let\csname#1Check\endcsname\checkAssociativeArray% \global\expandafter\let\csname#1Checki\endcsname\checkiAssociativeArray% \global\expandafter\let\csname#1Print\endcsname\printAssociativeArray% \global\expandafter\let\csname#1Printi\endcsname\printIndexes% \global\expandafter\let\csname#1Echo\endcsname\echoAssociativeArray% \global\expandafter\let\csname#1Echoi\endcsname\echoiAssociativeArray% \global\expandafter\let\csname#1First\endcsname\firstValueAssociativeArray% \global\expandafter\let\csname#1Last\endcsname\lastValueAssociativeArray% \global\expandafter\let\csname#1FirstKey\endcsname\firstKeyAssociativeArray% \global\expandafter\let\csname#1LastKey\endcsname\lastKeyAssociativeArray% \global\expandafter\let\csname#1Length\endcsname\lengthAssociativeArray% \global\expandafter\let\csname#1Swap\endcsname\swapAssociativeArray% } \endinput %% %% End of file `arrayassoc.sty'.
The MWE is:
\documentclass{article} \usepackage{arrayassoc} \begin{document} \newAssociativeArray{word} \word(a)={a} \word(b)={b} \wordSwap(a)(b) \wordPrint \end{document}
\documentclass{article}\usepackage{arrayassoc}\begin{document}\newAssociativeArray{word}\word(a)={love}\word(c)={air}\wordSwap(a)(c)\end{document}
exhibit the same problem, while being considerably shorter?arrayjobx
; you're better to have a look atexpl3
.