Expl3 para simplificar los problemas de expansión con contenido Tabularray creado en bucle

Expl3 para simplificar los problemas de expansión con contenido Tabularray creado en bucle

Un seguimiento demi pregunta anteriorRespondido gracias a @egreg. (Quizás el Prof. Gregorio también pueda ayudarme en esto).

Situación

Estoy creando una macro de tabla de preguntas (ToQ) para crear una tabla de calificaciones en la portada de un examen o tarea. Estaba funcionando bien, tabularpero cambié a Tabularray tblr, del cual me estoy enamorando. Desafortunadamente, debido a que suelo totcountcrear contadores para las calificaciones en cada nueva pregunta a medida que se van encontrando, me encuentro con problemas de expansión que me han dejado perplejo hoy.

Problema

Los bucles no se pueden poner dentro de un tblrentorno (ver§3.2.3del manual), como es el caso de los tabulares ordinarios. Pero las soluciones que parecen funcionar para tablas ordinarias:

  • usando bucles primitivos de LaTeX,
  • construir el cuerpo fuera de la mesa como un \gdef hecho de \edefs, y
  • construir el cuerpo como un registro simbólico,

no he trabajado para tblr. Además, tblrpermite especificar una expandopción para especificar tokens para la expansión antes de procesar el cuerpo. (Mostraré esto en el MWE posterior).

lo que me gustaria

Inspirado por la respuesta de @frougonaquí, Me gustaría adoptar un enfoque completamente expl3, ya que de todos modos estoy tratando de aprender expl3. Pero estoy perdido y agradecería un poco de ayuda. No es simplemente una solución, si pudiera ser tan amable, me gustaría un breve resumen para poder estudiar la solución rastreando los documentos.

MWE

\documentclass{article}
\usepackage{tabularray}
\usepackage{xcolor}

\usepackage{totcount}

% Stuff for keeping account of questions and their scores
% ........................................................<<<
\newcounter{questioncount}
\setcounter{questioncount}{0}
\regtotcounter{questioncount}%
\newcounter{scoretotal}
\setcounter{scoretotal}{0}
\regtotcounter{scoretotal}%

\newcommand{\setquestionpoints}[2]{%
  \expanded{\noexpand\newtotcounter{qpoints#1}}%
  \expanded{\noexpand\setcounter{qpoints#1}}{#2}%
}
\newcommand{\getquestionpoints}[1]{%
  \ifnum\value{qpoints#1}>0
    \arabic{qpoints#1}%
  \else
    0%
  \fi
}

\newcommand{\TOTAL}[1]{%
  \ifcsname c@#1@totc\endcsname
    \total{#1}%
  \else
    ??%
  \fi
}
% ........................................................>>>

% Typesetting questions
% ........................................................<<<
\newcommand{\nquestion}[1]{%
  \stepcounter{questioncount}%
  \setquestionpoints{\arabic{questioncount}}{#1}%
  \addtocounter{scoretotal}{#1}%
  Question~\thequestioncount (#1 marks.)%
}
% ........................................................>>>

\ExplSyntaxOn

\cs_new_protected:Npn \my_typeset_table_generic:nn #1#2
  {
    \group_begin:
      \cs_set_protected:Npn \__my_typeset_table_generic_tmp_func:n ##1 {#1}
      \__my_typeset_table_generic_tmp_func:n {#2}
    \group_end:
  }

\cs_generate_variant:Nn \my_typeset_table_generic:nn { nV }

\ExplSyntaxOff

\begin{document}

\ExplSyntaxOn

% This works, but I would like to know how expl3 can help me build this
%  list automatically, looping for
%      q ∈ [1, \totvalue{questioncount}]
%  to obtain \TOTAL{qpoints\theq} in each cell of the middle column.
\tl_set:Nn \l_my_tabular_tl {%
    1 & \TOTAL{qpoints1} & \null \\ \hline
    2 & \TOTAL{qpoints2} & \null \\ \hline
    3 & \TOTAL{qpoints3} & \null \\ \hline
}
\my_typeset_table_generic:nV
  {
    \SetTblrInner{rowsep=1ex}%
    \begin{tblr}{colspec={|ccX[c]|}, width=0.35\linewidth}
      \SetRow{black, rowsep=0.25ex}
      \color{white}\textit{Q}\textnumero & \color{white}Marks & \color{white}Grade \\ \hline
      #1
    \SetCell[c=2]{c}~TOTAL:~&~\null\\\cline[r]{3-3}
           && {\TOTAL{scoretotal}}\\\hline
    \end{tblr}
  }
  \l_my_tabular_tl
\ExplSyntaxOff

%%% Make some questions:
\vspace{2cm}
\noindent
\nquestion{10}\\
\nquestion{12}\\
\nquestion{15}\\


\end{document}

Produce:

Respuesta1

El último \\después \nquestion{15}provocó un Badbox por lo que se eliminó.

El tblrentorno se puede poner fuera del código expl3. Se utiliza la opción expanden el entorno. tblrEntonces \my_typeset_table_generic:nnya no es necesario.

En el tblrentorno, la opción rowsep=1exse coloca en la lista de opciones, la configuración para la primera fila se determina con la tecla row{1}. Entonces no es necesario escribir \color{white}tres veces.

\nullSe elimina la macro .

\TOTAL{scoretotal}Se eliminan los tirantes alrededor .

En el comando \nquestion, {}se agrega después \thequestioncountpara que los paréntesis no sigan inmediatamente después del número.

La macro \l_my_tabular_tlno se inicializó con \tl_new:N. Esto ya está hecho con \tl_new:N \tblrbody.

El contenido se recopila con \tl_build_put_right:Nn. Este proceso se inicia \tl_build_begin:Ny finaliza con \tl_build_end:N.

No es necesario ponerlo \setcounter{questioncount}{0}después \newcounter{questioncount}porque el valor inicial ya es 0.

En lugar de utilizar \newcountery , se puede utilizar \regtotcounterla taquigrafía .\newtotcounter

No es necesario definir el comando \TOTAL. Esto se reemplaza por \total.

El mando \setquestionpointsestá integrado en el mando \nquestion. Aquí, \arabic{questioncount}se reemplaza por \thequestioncount. Para \setcountery \expandedson \noexpandinnecesarios.

Después \SetCell, &se agrega an porque al usar \SetCell, las celdas omitidas no deben eliminarse.

ingrese la descripción de la imagen aquí

\documentclass{article}
\usepackage{xcolor}
\usepackage{tabularray}

\usepackage{totcount}

% Stuff for keeping account of questions and their scores
% ........................................................<<<
\newtotcounter{questioncount}
\newtotcounter{scoretotal}

\newcommand{\getquestionpoints}[1]{%
  \ifnum\value{qpoints#1}>0
    \arabic{qpoints#1}%
  \else
    0%
  \fi
}

% ........................................................>>>

% Typesetting questions
% ........................................................<<<
\newcommand{\nquestion}[1]{%
  \stepcounter{questioncount}%
  \expanded{\noexpand\newtotcounter{qpoints\thequestioncount}}%
  \setcounter{qpoints\thequestioncount}{#1}%
  \addtocounter{scoretotal}{#1}%
  Question~\thequestioncount{} (#1 marks.)%
}
% ........................................................>>>


\begin{document}
\ExplSyntaxOn
\tl_new:N \tblrbody
\tl_build_begin:N \tblrbody
\int_step_inline:nn { \totvalue { questioncount } }
  {
    \tl_build_put_right:Nn \tblrbody { #1 & \total { qpoints#1 } & \\ \hline }
  }
\tl_build_end:N \tblrbody
\ExplSyntaxOff
\begin{tblr}[expand=\tblrbody]{
  colspec={|ccX[c]|},
  width=0.35\linewidth,
  rowsep=1ex,
  row{1}={bg=black,fg=white,rowsep=0.25ex}
}
\emph{Q}\textnumero & Marks & Grade\\\hline
\tblrbody
\SetCell[c=2]{c} ~TOTAL:~ & & \\\cline[r]{3-3}
 & & \total{scoretotal}\\\hline
\end{tblr}


%%% Make some questions:
\vspace{2cm}
\noindent
\nquestion{10}\\
\nquestion{12}\\
\nquestion{15}


\end{document}

Respuesta2

Encontré una solución en la que construyo las líneas de una macro en expl3. No creo que sea el más elegante, pero funciona. Estoy interesado en consejos/comentarios para mejorarlo, así que dejo esta respuesta como no aceptada para ver si alguien aporta algo hermoso.

\ExplSyntaxOn
\NewDocumentCommand{\ToQ}{}{
  \tl_set:Nn \l_tmpa_tl {
    \SetTblrInner{rowsep=1ex}%
    \begin{tblr}[b]{colspec={|ccX[c]|}, width=0.35\linewidth}
      \SetRow{black, rowsep=0.25ex}
      \color{white}\textit{Q}\textnumero
        & \color{white}Marks
          & \color{white}Grade \\ \hline
  }
  \int_step_inline:nn {\totvalue{questioncount}} {
      \tl_put_right:Nn \l_tmpa_tl { ##1 & \fromaux{qpoints##1} & \null \\ \hline }
  }
  \tl_put_right:Nn \l_tmpa_tl {
      \SetCell[c=2]{c}~TOTAL:~&~\null\\\cline[r]{3-3}
      && {\fromaux{scoretotal}}\\\hline
    \end{tblr}
  }
  \l_tmpa_tl
}
\ExplSyntaxOff

produce

ingrese la descripción de la imagen aquí

Respuesta3

La vida no tiene por qué ser tan complicada. Comience siempre especificando cómo desea que sea la entrada y cómo la salida. Eso es proporcionar una API.

  1. No necesitas los contadores LaTeX2e, usa el intmódulo.
  2. Cuando quieras almacenar valores, piensa en csname.
  3. Cree una serie de comandos \Q1... \Qnalmacenando el valor como \Q1-markssi lo desea, \Q1-questiontambién podría tener un archivo para almacenar la pregunta real.

Aquí tienes una solución rápida. He usado tabular, solo para demostrar los conceptos. Como regla general trato de minimizar los paquetes que uso. Modifique para agregar prefijos a los comandos l3, como es una buena práctica.

producción

\documentclass{article}
%------------------------------------------------------------
% INPUT : \AddQuestion{name}{marks}
% OUTPUT: PrintScoreSheet  
%------------------------------------------------------------
\ExplSyntaxOn
\int_new:N \g_questions_total_int
\clist_new:N \g_questions_clist
\prop_new:N \g_questions_marks_prop
\cs_new_protected:Npn \questions_add:nn  #1 #2
  {
    \clist_gput_right:Nn \g_questions_clist {#1}
    \prop_gput:Nnn \g_questions_marks_prop {#1} {#2}
  }

\cs_new_protected:Npn \questions_printlist:
  {
    \begin{tabular}{lrr}
      \hline
      \clist_map_inline:Nn \g_questions_clist
        {
          \prop_get:NnN \g_questions_marks_prop {##1} \l_tmpa_tl
          \int_gadd:Nn \g_questions_total_int { \l_tmpa_tl } 
           ##1  &  \use:c{##1-marks} &\\  %Row
        }
      \\\noalign{\vskip-10pt}
      \cline{2-3} 
      Total & \int_use:N\g_questions_total_int &\\ 
      \hline
    \end{tabular}
  }
\let\AddQuestion\questions_add:nn
\let\PrintScoreSheet\questions_printlist:

\ExplSyntaxOff
\begin{document}
\AddQuestion {Q1}{10}
\AddQuestion {Q2}{20}
\AddQuestion {Q3}{5}
\AddQuestion{Q4}{5}
\PrintScoreSheet
\end{document}

información relacionada