An implementation with expl3
An implementation with expl3
; note that it's easier to use a name instead of a control sequence for the storage bin.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\storedata}{mm}
{
\bcp_store_data:nn { #1 } { #2 }
}
\DeclareExpandableDocumentCommand{\getdata}{O{1}m}
{
\bcp_get_data:nn { #1 } { #2 }
}
\cs_new_protected:Npn \bcp_store_data:nn #1 #2
{
% create the sequence if it doesn't exist
\seq_if_exist:cF { l_bcp_data_#1_seq } { \seq_new:c { l_bcp_data_#1_seq } }
% populate the sequence
\seq_set_split:cnn { l_bcp_data_#1_seq } { } { #2 }
}
\cs_generate_variant:Nn \seq_set_split:Nnn { c }
\cs_new:Npn \bcp_get_data:nn #1 #2
{
% retrieve the requested item
\seq_item:cn { l_bcp_data_#2_seq } { #1 }
}
\ExplSyntaxOff
\begin{document}
\storedata{mydata}{{one}{two}{three}}
\getdata[1]{mydata}
\getdata[2]{mydata}
\getdata[3]{mydata}
\end{document}

You can even use \getdata[1+1+1]{mydata}
or use a counter, say
\newcounter{acounter} % in the preamble
\setcounter{acounter}{2} % somewhere in the document
\getdata[\value{acounter}]{mydata}
The second argument to \storedata
should be braced, because otherwise it would be impossible to tell where it ends.
An extended implementation with expl3
A straightforward extension for also allowing appending to the list, counting the items and removing the last item (optionally storing it in a macro).
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\storedata}{mm}
{
\bcp_store_data:nn { #1 } { #2 }
}
\NewDocumentCommand{\appenddata}{mm}
{
\bcp_append_data:nn { #1 } { #2 }
}
\NewExpandableDocumentCommand{\getdata}{O{1}m}
{
\bcp_get_data:nn { #1 } { #2 }
}
\NewExpandableDocumentCommand{\getlength}{m}
{
\seq_count:c { l_bcp_data_#1_seq }
}
\NewDocumentCommand{\removelast}{om}
{
\IfNoValueTF { #1 }
{
\bcp_remove_last:Nn \l_tmpa_tl { #2 }
}
{
\bcp_remove_last:Nn #1 { #2 }
}
}
\cs_new_protected:Npn \bcp_store_data:nn #1 #2
{
% create the sequence if it doesn't exist or clear it if it exists
\seq_clear_new:c { l_bcp_data_#1_seq }
% append the items
\__bcp_append_data:nn { #1 } { #2 }
}
\cs_new_protected:Npn \bcp_append_data:nn #1 #2
{
% create the sequence if it doesn't exist, do nothing if it exists
\seq_if_exist:cF { l_bcp_data_#1_seq }
{ \seq_new:c { l_bcp_data_#1_seq } }
% append the items
\__bcp_append_data:nn { #1 } { #2 }
}
\cs_new_protected:Npn \__bcp_append_data:nn #1 #2
{
% append items one at a time
\tl_map_inline:nn { #2 }
{
\seq_put_right:cn { l_bcp_data_#1_seq } { ##1 }
}
}
\cs_new:Npn \bcp_get_data:nn #1 #2
{
% retrieve the requested item
\seq_item:cn { l_bcp_data_#2_seq } { #1 }
}
\cs_new_protected:Nn \bcp_remove_last:Nn
{
\seq_pop_right:cN { l_bcp_data_#2_seq } #1
}
\ExplSyntaxOff
\begin{document}
\storedata{mydata}{{one}{two}}
Length is: \getlength{mydata}
\appenddata{mydata}{{three}{four}}
Length is: \getlength{mydata}
\getdata[1]{mydata}
\getdata[2]{mydata}
\getdata[3]{mydata}
\getdata[4]{mydata}
\removelast{mydata}
Length is: \getlength{mydata}
\removelast[\test]{mydata}
\test % should be 'three'
\end{document}

With both solutions, one can also say
\getdata[-1]{mydata}
to retrieve the last item; with -2
the last but one and so on. So
\getdata[-1]{mydata}\par
\getdata[-2]{mydata}\par
\getdata[-3]{mydata}\par
\getdata[-4]{mydata}
would print
four
three
two
one
A simpler (but less flexible) solution with expl3
Of course there's a much less flexible solution, that I wouldn't recommend, because data in a sequence is better retrievable than in a token list. However, this is the shortest in all presented solutions that have \getdata
expandable.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\storedata}{mm}{\tl_set:Nn#1{#2}}
\DeclareExpandableDocumentCommand{\getdata}{O{1}m}{\tl_item:Nn#2{#1}}
\ExplSyntaxOff
\begin{document}
\storedata\mydata{{one}{two}{three}}
\getdata[1]\mydata
\getdata[2]\mydata
\getdata[3]\mydata
\getdata[-1]\mydata
\getdata[-2]\mydata
\getdata[-3]\mydata
\end{document}
A “classical” implementation
This assumes you just have three items to store.
\documentclass{article}
\newcommand\storedata[4]{\def#1{{#2}{#3}{#4}}}
\makeatletter
\providecommand\@firstofthree[3]{#1}
\providecommand\@secondofthree[3]{#2}
\providecommand\@thirdofthree[3]{#3}
\def\getdata[#1]#2{%
\ifcase#1 \ERROR\or
\expandafter\@firstofthree#2\or
\expandafter\@secondofthree#2\or
\expandafter\@thirdofthree#2\else
\ERROR\fi}
\makeatother
\begin{document}
\storedata\mydata{one}{two}{three}
\getdata[1]\mydata\par % returns one
\getdata[2]\mydata\par % returns two
\getdata[3]\mydata\par % returns three
\end{document}
The \getdata
macro is expandable, which isn't in an \ifthenelse
based approach.
\getdata
to be optional as the LaTeX syntax for[]
would suggest?