In the process of answering expl3 switch for booleans: Is there a \bool_case:Nnn?, I tried to make sense of the various \xx_case: functions Expl3 provides. Here, for example, is \tl_case:Npn:
\cs_new:Npn \tl_case:Nnn #1#2#3 { \tex_romannumeral:D \__tl_case:Nw #1 #2 #1 {#3} \q_recursion_stop } \cs_new:Npn \__tl_case:Nw #1#2#3 { \tl_if_eq:NNTF #1 #2 { \__tl_case_end:nw {#3} } { \__tl_case:Nw #1 } } \cs_new_eq:NN \__tl_case_end:nw \__prg_case_end:nw Working from the inside-out, I’ve figured out this much:
The command \__prg_case_end:nw {<code>} <tokens> \q_recursion_stop consumes all ⟨tokens⟩ until \q_recursion_stop, leaving ⟨code⟩ behind.
Within the internal function \__tl_case:Nw, we test for equality of the ⟨test token-list variable⟩ to the particular ⟨token-list variable case⟩: if they’re equal, the function terminates returning the associated ⟨code case⟩; otherwise the function yields itself, which then applies to the next {<token-list variable case>} {<code case>} pair.
What I’m having trouble understanding is how \tl_case:Nnn sets up this recursion. In particular, I know \tex_romannumeral:D (\romannumeral) does something funny related to expansion, but what’s it doing in this context?
(Would it be easier to explain or implement this sort of function in terms of the recursion functionality documented in l3quark §§ 4 & 6?)