# Why is \tl_if_in:VnTF giving a different answer depending on where it is?

I'm trying to build a simple replacements dictionary using a prop structure of replacements old=new. When I'm mapping through the prop, I don't find any replacements. When I'm not (i.e., hardcoding), I do. What's going on here?

### MWE

\nonstopmode
\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\prop_put:Nnn \l_tmpa_prop {sean} {patrick}
\msg_term:n {resolving}

\tl_set:Nn \l_tmpa_tl {hello,~sean}
\prop_map_inline:Nn \l_tmpa_prop
{
\tl_show:N \l_tmpa_tl
\tl_show:n {#1}
\tl_if_in:VnTF \l_tmpa_tl {#1}
{ \msg_term:n {#1'~found~in~\l_tmpa_tl'} }
{ \msg_term:n {#1'~not~found~in~\l_tmpa_tl'} }
}

\msg_term:n {contrived}
\tl_show:N \l_tmpa_tl
\tl_show:n {sean}
\tl_if_in:VnTF \l_tmpa_tl {sean}
{ \msg_term:n {oh,~yes~it~is!} }
{ \msg_term:n {nope} }

\ExplSyntaxOff

\begin{document}
hello
\end{document}


### Output

* resolving
*************************************************
> \l_tmpa_tl=hello, sean.

l.18     }

> sean.

l.18     }

*************************************************
* sean' not found in hello, sean'
*************************************************
*************************************************
* contrived
*************************************************
> \l_tmpa_tl=hello, sean.

l.21     \tl_show:N \l_tmpa_tl

> sean.

l.22     \tl_show:n {sean}

*************************************************
* oh, yes it is!

• Are you sure that \l_tmpa_tl is still the same you expect it to be? And shouldn't it be \tl_if_in:VnTF {#2} ...? – user31729 Jan 7 '17 at 16:31
• @ChristianHupfer See the contrived example; it certainly looks to me like each piece of state is the same. – Sean Allred Jan 7 '17 at 16:33
• @ChristianHupfer concerning #2 vs {#2}: no, I don't think so (though I did try that). It's my understanding that capital-letter arguments are given without braces (e.g. \tl_new:N \l_my_tl). – Sean Allred Jan 7 '17 at 16:42
• Yes, I forgot about that convention – user31729 Jan 7 '17 at 16:43

What you are forgetting here is category codes: yes, the two token lists contain the same characters, but if you use \tl_show_analysis:N you can see that they have different catcodes. This is because keys are detokenized: as the documentation says

The ⟨keys⟩ are compared on a string basis, using the same method as \str_if_eq:nn.

(We could perhaps make it explicit that they are detokenized.)

If you want to replace the value in a prop by a new one, the correct approach is to use \prop_put:Nnn, which will as-described replace the stored value with a new one when the key is the same.

• Note I'm not trying to replace values in a property list – I'm trying to replace values in a token list based on a property list. For example, a prop list of {{sean}={patrick}} will turn \l_tmpa_tl={hello,~sean} into {hello,~patrick}. I'll look into the catcode stuff :-) – Sean Allred Jan 7 '17 at 16:56
• It sounds like a \str_if_in_p:nn fits the bill exactly, but sadly it does not exist (yet?) :-( – Sean Allred Jan 7 '17 at 16:58