Respuesta a la pregunta actualizada

Respuesta a la pregunta actualizada

Quiero definir dinámicamente algunas macros que esencialmente crean una lista de \refs. Parece que puedo definir estas macros pero luego no puedo imprimirlas.

Aquí está mi M(no)NOSOTROS:

\documentclass{article}
\makeatletter
\def\Assign#1{% if \DP@#1 is defined append to it otherwise create it
  \ifcsname DP@#1\endcsname\def\DP@tmp{\csname DP@#1\endcsname,\@currentlabel}
  \else\def\DP@tmp{\@currentlabel}
  \fi
  \expandafter\edef\csname DP@#1\endcsname{\DP@tmp}
  \typeout{ASSIGN: \csname DP@#1\endcsname}
}
\def\Assigned#1{#1: \csname DP@#1\endcsname}
                \typeout{ASSIGNED: \csname DP@#1\endcsname}
}
\makeatother

\begin{document}

\begin{enumerate}
  \item Apples \Assign{fred}
  \item Oranges \Assign{julie}
  \item Bananas \Assign{fred}
  \item Mangos \Assign{julie}
  \item Strawberries \Assign{julie}
\end{enumerate}

\Assigned{fred}   % should print 1,3
\Assigned{julie}  % should print 2,4,5

\end{document}

Quiero que la \Assigned{}macro imprima los números de artículo "asignados" a esa persona. Es decir, después del itemiseentorno anterior debería obtener:

fred: 1,3
julie: 2,4,5

Desafortunadamente, me faltan los números de artículo y solo aparece:

fred:
julie:

El látex M(non)WE no tiene problemas pero, por razones que no entiendo, las \Assignedmacros no se expanden. He probado muchas variaciones usando \expandafter1 o más veces, \edef... pero nada parece funcionar.

En el archivo de registro, las \typeout{}llamadas anteriores producen:

ASSIGN: 1
ASSIGN: 2
ASSIGN: 1,3
ASSIGN: 2,4
ASSIGN: 2,4,5
ASSIGNED: `\DP@fred`
ASSIGNED: `\DP@julie`

Entonces parece que los \DP@#1archivos están creados correctamente y son las \Assigned{}macros las que no funcionan, lo que probablemente sea un problema de expansión. Usar \edefno funciona... pero el hecho de que el problema de expansión ocurra DENTRO \typeoutme sugiere que estoy haciendo algo fundamentalmente incorrecto.

¿Alguien puede decirme cómo solucionar este problema?

Lo siguiente en mi lista de deseos sería imprimir "1,3-6,8" en lugar de "1,3,4,5,6,8", por ejemplo. ¡Pero primero lo primero!

Respuesta1

El entorno enumerateagrega un grupo, por lo que los cambios \DP@#1son locales y se pierden después de que se cierra el entorno. Así, el ejemplo hace que la definición sea global:

\documentclass{article}

\makeatletter
\def\Assign#1{% if \DP@#1 is defined append to it otherwise create it
  \ifcsname DP@#1\endcsname
    \edef\DP@tmp{\csname DP@#1\endcsname,\@currentlabel}%
  \else
    \edef\DP@tmp{\@currentlabel}%
  \fi
  \global\expandafter\let\csname DP@#1\endcsname\DP@tmp
  \typeout{ASSIGN: \csname DP@#1\endcsname}
}
\def\Assigned#1{%
  % \expandafter\def\csname Assigned#1\endcsname{\csname DP@#1\endcsname}
  \typeout{ASSIGNED: \csname DP@#1\endcsname}
}
\makeatother

\begin{document}

\begin{enumerate}
  \item Apples \Assign{fred}  
  \item Oranges \Assign{julie}
  \item Bananas \Assign{fred}
  \item Mangos \Assign{julie}
  \item Strawberries \Assign{julie}
\end{enumerate}

\Assigned{fred}   % should print 1,3  
\Assigned{julie}  % should print 2,4,5

\end{document}

Resultado:

ASSIGN: 1
ASSIGN: 2
ASSIGN: 1,3
ASSIGN: 2,4
ASSIGN: 2,4,5
ASSIGNED: 1,3
ASSIGNED: 2,4,5

Actualización para compresión de rango

El ejemplo analiza la lista de comas \DP@#1y define \Assign#1con rangos comprimidos para entradas consecutivas:

\documentclass{article}

\usepackage{kvoptions}

\makeatletter
\def\Assign#1{% if \DP@#1 is defined append to it otherwise create it
  \ifcsname DP@#1\endcsname
    \edef\DPx@tmp{\csname DP@#1\endcsname,\@currentlabel}%
  \else
    \edef\DPx@tmp{\@currentlabel}%
  \fi
  \global\expandafter\let\csname DP@#1\endcsname\DPx@tmp
  \typeout{ASSIGN: \csname DP@#1\endcsname}
}
\def\Assigned#1{%
  \begingroup
    \let\DPx@curr\@empty
    \let\DPx@tmp\@empty
    \expandafter\expandafter\expandafter\comma@parse
    \expandafter\expandafter\expandafter{\csname DP@#1\endcsname}%
    \AssignedAux
    \ifx\DPx@curr\@empty
    \else
      \edef\DPx@tmp{\DPx@tmp-\DPx@curr}%
    \fi
    \global\expandafter\let\csname Assigned#1\endcsname\DPx@tmp
  \endgroup
  \typeout{ASSIGNED: \csname Assigned#1\endcsname}
}
\def\AssignedAux#1{%
  \ifx\DPx@tmp\@empty
    \def\DPx@tmp{#1}%
    \count@=#1\relax
  \else
    \advance\count@\@ne
    \ifnum#1=\count@
      \def\DPx@curr{#1}%
    \else
      \count@=#1\relax
      \ifx\DPx@curr\@empty
        \edef\DPx@tmp{\DPx@tmp,#1}%
      \else
        \edef\DPx@tmp{\DPx@tmp-\DPx@curr,#1}%
        \let\DPx@curr\@empty
      \fi
    \fi
  \fi
}
\makeatother

\begin{document}

\begin{enumerate}
  \item Apples \Assign{fred}
  \item Oranges \Assign{julie}
  \item Bananas \Assign{fred}
  \item Mangos \Assign{julie}\Assign{fred}
  \item Strawberries \Assign{julie}
  \item Pears \Assign{julie}
  \item Lemons \Assign{fred}
\end{enumerate}

\Assigned{fred}   % should print 1,3
\Assigned{julie}  % should print 2,4,5

\end{document}

Resultado:

ASSIGN: 1
ASSIGN: 2
ASSIGN: 1,3
ASSIGN: 2,4
ASSIGN: 1,3,4
ASSIGN: 2,4,5
ASSIGN: 2,4,5,6
ASSIGN: 1,3,4,7
ASSIGNED: 1,3-4,7
ASSIGNED: 2,4-6

Respuesta2

La sintaxis \def\Assigned#1{}es incorrecta. La forma correcta es \expandafter\def\csname Assigned#1\endcsname{}. Eso permite que su código se compile. Además, \edefestá localizado y no se puede acceder a él en un nivel superior. Cambiarlo para \xdefsolucionar eso.

\documentclass{article}
\makeatletter
\def\Assign#1{% if \DP@#1 is defined append to it otherwise create it
  \ifcsname DP@#1\endcsname\def\DP@tmp{\csname DP@#1\endcsname,\@currentlabel}
  \else\def\DP@tmp{\@currentlabel}
  \fi
  \expandafter\xdef\csname DP@#1\endcsname{\DP@tmp}
  \typeout{ASSIGN: \csname DP@#1\endcsname}
}
\def\Assigned#1{\expandafter\def\csname Assigned#1\endcsname{\csname DP@#1\endcsname}
                \typeout{ASSIGNED: \csname DP@#1\endcsname}
}
\makeatother

\begin{document}

\begin{enumerate}
  \item Apples \Assign{fred}
  \item Oranges \Assign{julie}
  \item Bananas \Assign{fred}
  \item Mangos \Assign{julie}
  \item Strawberries \Assign{julie}
\end{enumerate}

\Assigned{fred}   % should print 1,3
\Assigned{julie}  % should print 2,4,5

\end{document}

El archivo de registro contiene:

ASSIGN: 1
ASSIGN: 2
ASSIGN: 1,3
ASSIGN: 2,4
ASSIGN: 2,4,5
ASSIGNED: 1,3
ASSIGNED: 2,4,5

Respuesta3

\documentclass{article}
\makeatletter
\def\Assign#1{% if \DP@#1 is defined append to it otherwise create it
  \ifcsname DP@#1\endcsname\def\DP@tmp{\csname DP@#1\endcsname,\@currentlabel}
  \else\def\DP@tmp{\@currentlabel}
  \fi
  \expandafter\xdef\csname DP@#1\endcsname{\DP@tmp}
  \typeout{ASSIGN: \csname DP@#1\endcsname}
}
\def\Assigned#1{%
  \csname DP@#1\endcsname
                \typeout{ASSIGNED: \csname DP@#1\endcsname}
}
\makeatother

\begin{document}

\begin{enumerate}
  \item Apples \Assign{fred}
  \item Oranges \Assign{julie}
  \item Bananas \Assign{fred}
  \item Mangos \Assign{julie}
  \item Strawberries \Assign{julie}
\end{enumerate}

\Assigned{fred}   % should print 1,3
\Assigned{julie}  % should print 2,4,5

\end{document}

Asignaciones

Respuesta a la pregunta actualizada

Para obtener los nombres y los números de artículo:

\documentclass{article}
\makeatletter
\def\Assign#1{% if \DP@#1 is defined append to it otherwise create it
  \ifcsname DP@#1\endcsname\def\DP@tmp{\csname DP@#1\endcsname,\@currentlabel}
  \else\def\DP@tmp{\@currentlabel}
  \fi
  \expandafter\xdef\csname DP@#1\endcsname{\DP@tmp}
  \typeout{ASSIGN: \csname DP@#1\endcsname}
}
\def\Assigned#1{%
  #1: \csname DP@#1\endcsname
                \typeout{ASSIGNED: \csname DP@#1\endcsname}
}
\makeatother

\begin{document}

\begin{enumerate}
  \item Apples \Assign{fred}
  \item Oranges \Assign{julie}
  \item Bananas \Assign{fred}
  \item Mangos \Assign{julie}
  \item Strawberries \Assign{julie}
\end{enumerate}

\Assigned{fred}   % should print 1,3
\Assigned{julie}  % should print 2,4,5

\end{document}

Tareas por nombre

Respuesta4

Quizás aprecies una versión LaTeX3;

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\Assign}{m}
 {
  \andrew_assign:n { #1 }
 }
\NewDocumentCommand{\Assigned}{m}
 {
  \andrew_assigned:n { #2 }
 }

% syntactic sugar for shortening code
\cs_new:Npn \__andrew_seq:n #1
 {
  g_andrew_assignee_#1_seq
 }

\cs_new_protected:Npn \andrew_assign:n #1
 {% if the assignee is not yet defined, create a sequence
  \seq_if_exist:cF { \__andrew_seq:n { #1 } }
   {
    \seq_new:c { \__andrew_seq:n { #1 } }
   }
  % globally add the item to the assignee's sequence
  \seq_gput_right:cv { \__andrew_seq:n { #1 } } { @currentlabel }
 }

\cs_new:Npn \andrew_assigned:n #1
 {% print the assignee's items separated by a comma
  \seq_use:cn { \__andrew_seq:n { #1 } } { ,~ }
 }

\cs_generate_variant:Nn \seq_gput_right:Nn { cv }
\cs_generate_variant:Nn \seq_use:Nn { c }

\ExplSyntaxOff

\begin{document}
\begin{enumerate}
  \item Apples \Assign{fred}
  \item Oranges \Assign{julie}
  \item Bananas \Assign{fred}
  \item Mangos \Assign{julie}
  \item Strawberries \Assign{julie}
\end{enumerate}

Fred has \Assigned{fred}   % should print 1,3

Julie has \Assigned{julie}  % should print 2,4,5

\end{document}

información relacionada