Dynamic variable name gets overwritten

You picked the question tags right: your main problem here concerns expansion. :-)

  • When you do \@nameuse{\expandafter#1}, this is... not very useful, because:

    1. You are passing \expandafter#1 to \@nameuse (with the argument substituted for #1), whereas you probably wanted to pass the result of its expansion. In this particular case, since \@nameuse is simply macro:#1->\csname #1\endcsname, its argument will be expanded anyway, due to the way \csname works.
    2. The \expandafter is not put to good use here. If you call for instance \getValue{foo}, when the \getValue control sequence token is expanded, \getValue{foo} will be replaced by the replacement text of \getValue, in which the argument foo will have been substituted for #1. In this case, this will yield:
      \@ifundefined{foo}{%  
          \PackageError{lookup}{No foo key defined}{}%
      }{%
          \@nameuse{\expandafter foo}%
      }%
      
      When TeX expands this \@nameuse, this will result in:
      \csname \expandafter foo\endcsname
      
      thus, when TeX gets to the expand the \expandafter, it will try to expand the token following f, i.e. the first character token o, which is unexpandable. So, this \expandafter doesn't serve any purpose.
  • The other \expandafter:

    \expandafter\storeValue{data@\thedataID @prio}{This is \ref{data\thedataID}}
    

    has a similar problem. It will try to expand the opening brace { following \storeValue, which again is a non-active character token and therefore is unexpandable. In this case, you want to expand the two \thedataID tokens but not \ref before \storeValue is itself expanded. Therefore, I would propose something like:

    \begingroup
    \edef\tmp{%
      \endgroup
      \noexpand\storeValue{data@\thedataID @prio}
                          {This is \noexpand\ref{data\thedataID}}%
    }%
    \tmp
    

    The \noexpand tokens prevent expansion of the next token inside the \edef. Then they disappear, so that after \tmp is expanded in the last line of this excerpt, TeX sees:

    \endgroup
    \storeValue{data@1@prio}{This is \ref{data1}}%
    

    assuming for instance that \thedataID expanded to 1. The \endgroup closes the group where \tmp was defined, and what is left in the input stream is exactly what you wanted.

  • Similarly, in \labelText, you want the argument to be recursively expanded in order to get the counter value in the replacement text of \@currentlabel, as opposed to the five tokens data\thedataID (four character tokens followed by one control sequence token). Since \label recursively expands its argument anyway using \protected@write, we can do \protected@edef\@currentlabel{#1} for consistency to expand the argument (this implies that \protect will work when used inside this argument in case you need it). Actually, \def also works here, because \label does \protected@write\@auxout{}{ ... \@currentlabel ...}, so it recursively expands both its argument and the \@currentlabel.

Other things:

  • There is no need to wrap the \label call within braces (and make it look like an argument to \def!).

  • hyperref should be loaded last, except in very special cases such as when cleveref is used (cleveref must be loaded after hyperref).

  • Minor nit: you don't need \csname ... \endcsname to form the \phantomsection control sequence token (all letters p, h, a, ..., i, o, n have category code 11 in normal circumstances, i.e. are letters for TeX).

Note: I left your @ as is because it works, but there is a trap, so beware. Indeed, the @ in the replacement text of your \data macro has category code 11 (letter), whereas the ones in your document body have category code 12 (other). These are not the same character tokens. This works because in the end, they are only used inside \csname ... \endcsname, and there it doesn't matter whether they have catcode 11 or 12 (they become part of a control sequence name, which is just a sequence of characters in the ordinary sense, without any catcode attached). If unsure, you can always use another character, such as . or -.

All in all, I propose the following:

\documentclass{article}
\usepackage{hyperref}

\makeatletter
\newcommand{\getValue}[1]{%
  \@ifundefined{#1}{%
      \PackageError{lookup}{No '#1' key defined}{}%
  }{%
      \@nameuse{#1}%
  }%
}

\newcommand{\storeValue}[2]{%
  \@namedef{#1}{#2}%
}

\newcommand{\labelText}[1]{%
  \@bsphack
  \phantomsection % for hyperrred usage
  % \def also works here (see above)
  \protected@edef\@currentlabel{#1}%
  \label{#1}%
  \@esphack
}

\newcounter{dataID}
\newcommand{\data}{%
    \refstepcounter{dataID}%
    \labelText{data\thedataID}
    data\thedataID

    \quad dataID value = \thedataID
    \begingroup
    \edef\tmp{%
      \endgroup
      \noexpand\storeValue{data@\thedataID @prio}
                          {This is \noexpand\ref{data\thedataID}}%
    }%
    \tmp
}
\makeatother

\begin{document}

\data   % data1

\verb|data@1@prio|
$\rightarrow$ \getValue{data@1@prio}

---

\data   % data2

\verb|data@\thedataID@prio|
$\rightarrow$ \getValue{data@\thedataID @prio} (because dataID=2)

---

\verb|data@1@prio| $\rightarrow$ \getValue{data@1@prio}

\verb|data@2@prio| $\rightarrow$ \getValue{data@2@prio}

\end{document}

screenshot


As @frougon says in their nice breakdown of your code, for which he deserves the green tick, the main problem in terms of the output is that you are storing the unexpanded \ref{data\thedataID} so what \getValue returns depends on the current the value of \thedataID.

Rather than using \@nameuse and friends I recommend using the corresponding commands from the etoolbox package as, at least for me, this results in more readable code:

\documentclass[a4paper]{article}
\usepackage{hyperref}
\usepackage{xcolor}
\usepackage{etoolbox}

\newcommand{\getValue}[1]{
    \ifcsdef{#1}{\csuse{#1}}%
                {\PackageError{lookup}{No #1 key defined}{}}%
}
\newcommand{\storeValue}[2]{\csxdef{#1}{#2}}

\makeatletter
\newcommand{\labelText}[1]{\typeout{label=#1.}%
    \@bsphack
    \phantomsection % for hyperrredf usage
    \def\@currentlabel{#1}{\label{#1}}%
    \@esphack
}
\makeatother

\newcounter{dataID}
\newcommand{\data}{%
    \refstepcounter{dataID}%
    \labelText{data\thedataID}
    data\thedataID

    \quad dataID value = \thedataID
    \storeValue{data@\thedataID @prio}{This is \noexpand\ref{data\thedataID}}
}

\begin{document}
    \data   % data1

    \texttt{data@1@prio} $\rightarrow$ \getValue{data@1@prio} \quad\textcolor{blue}{1st Definition of \texttt{data@1@prio} !}

    ---

    \data   % data2

    \texttt{data@thedataID@prio} $\rightarrow$ \getValue{data@\thedataID @prio} (because dataID=2)

    ---

    \texttt{data@1@prio} $\rightarrow$ \getValue{data@1@prio} \quad\textcolor{red}{Redefinition of \texttt{data@1@prio} !}

    \texttt{data@2@prio} $\rightarrow$ \getValue{data@2@prio}

\end{document}

The output is the same as above:

enter image description here


I propose a different implementation using property lists of expl3:

\documentclass[a4paper]{article}
\usepackage{xcolor,xparse}
\usepackage{hyperref}

\ExplSyntaxOn

\prop_new:N \g_eisenheim_values_prop
\cs_generate_variant:Nn \prop_item:Nn { Ne }
\cs_generate_variant:Nn \prop_gput:Nnn { Nxx }
\prg_generate_conditional_variant:Nnn \prop_if_in:Nn { Ne } { T,F,TF,p }
\cs_generate_variant:Nn \msg_expandable_error:nnn { nne }

\NewExpandableDocumentCommand{\getValue}{m}
 {
  \prop_if_in:NeTF \g_eisenheim_values_prop { #1 }
   {
    \prop_item:Ne \g_eisenheim_values_prop { #1 }
   }
   {
    \msg_expandable_error:nne { lookup } { missing } { #1 }
   }
 }

\NewDocumentCommand{\storeValue}{mm}
 {
  \prop_gput:Nxx \g_eisenheim_values_prop { #1 } { #2 }
 }

\msg_new:nnn { lookup } { missing } { The~value~#1~is~missing }

\ExplSyntaxOff

\makeatletter
\newcommand{\labelText}[1]{%
    \@bsphack
    \csname phantomsection\endcsname % for hyperref usage
    \def\@currentlabel{#1}{\label{#1}}%
    \@esphack
}
\makeatother

\newcounter{dataID}

\newcommand{\data}{%
    \refstepcounter{dataID}%
    \labelText{data\thedataID}%
    data\thedataID
    \quad dataID value = \thedataID
    \storeValue{data@\thedataID @prio}{This is \noexpand\ref{data\thedataID}}
}


\begin{document}

\data   % data1

\texttt{data@1@prio} $\rightarrow$ \getValue{data@1@prio}

---

\data   % data2

\texttt{data@thedataID@prio} $\rightarrow$ \getValue{data@\thedataID @prio} (because dataID=2)

---

\texttt{data@1@prio} $\rightarrow$ \getValue{data@1@prio} 

\texttt{data@2@prio} $\rightarrow$ \getValue{data@2@prio}

\getValue{x}

\end{document}

enter image description here

The advantage is that \getValue is fully expandable.