# Create an array of variables with string keys

I'd like to have a macro where I can insert a key as argument and get a value which I have defined before. This should be similar to Create an array of variables but with strings/text instead of numbers.

The usage should look like:

\setprefix{foaf}{http://xmlns.com/foaf/0.1/}


and later

\getprefix{foaf}


which should return http://xmlns.com/foaf/0.1/. When I try to use the code from the before mentioned question I get ! Illegal parameter number in definition of.

-
This is more or less exactly what LaTeX's \@namedef and \@nameuse do. Or etoolbox' \csdef and \csuse. –  clemens May 16 '13 at 17:47
What will your definitions contain? URLs only? –  Werner May 16 '13 at 18:26
@Werner yes only URIs. I just realized, after checking all these answers, that it didn't work for me because I had a hash # in one URI which resulted in the ! Illegal parameter number in definition of. –  white_gecko May 16 '13 at 20:31
@white_gecko: Then you can include the url package and change #2 in David's answer to \url{#2}. –  Werner May 16 '13 at 20:44
Thank you David Carlisle, egreg and Steve B. Segletes all your answer work for me :-) My final result is here: gist.github.com/white-gecko/5595112 –  white_gecko May 16 '13 at 21:10

\def\setprefix#1#2{\expandafter\def\csname MY@#1\endcsname{#2}}

\def\getprefix#1{\csname MY@#1\endcsname}


Should be all you need. The MY@ internal prefix is arbitrary and just needs to be distinct from other prefixes (so don't use LT@ unless you want to break longtable). By using different strings there you can have different arrays of macros.

-

You can use \csname...\endcsname:

\documentclass{article}

\makeatletter
\newcommand\setprefix[2]{\global\@namedef{gecko@\detokenize{#1}}{#2}}
\newcommand{\getprefix}[1]{%
\@ifundefined{gecko@\detokenize{#1}}
{\@latex@warning{No prefix \detokenize{#1}' defined}UNKNOWN}%
{\@nameuse{gecko@\detokenize{#1}}}%
}
\makeatother

\setprefix{foaf}{http://xmlns.com/foaf/0.1/}
\setprefix{\just#stupid@input}{http://xmlns.com/foaf/0.1/}

\begin{document}

\getprefix{foaf}

\getprefix{fuaf}

\getprefix{\just#stupid@input}

\end{document}


In the first argument of \setprefix you're basically limited in using only balanced braces.

-
\documentclass{article}
\newcommand\setprefix[2]{\expandafter\def\csname#1\endcsname{#2}}
\newcommand\getprefix[1]{\csname#1\endcsname}
\begin{document}
\setprefix{foaf}{http://xmlns.com/foaf/0.1/}
\getprefix{foaf}
\end{document}


Note also that you can recall the prefix with \key, in the example \foaf (only as long as the key is alphabetic).

ROLLBACK to original answer, removing caveat.

-
The keys do not have to be alphabetic but can be anything: \setprefix{?.3$a}{foo}\useprefix{?.3$a} will work just fine –  clemens May 16 '13 at 17:53
Why the edit? \expandafter\def\csname ?.3$a\endcsname{foo} and then \csname ?.3$a\endcsname` does work without problems! Your initial solution did suffice just fine! (I'd had upvoted but I'm out of votes for today...) –  clemens May 16 '13 at 18:17
@cgnieder I did not know that I could put strange characters inside a csname. Now if I only knew how to undo an edit... –  Steven B. Segletes May 16 '13 at 18:19
There should be a rollback button if you look at the edit history –  clemens May 16 '13 at 18:20