Is there a command/macro in latex
to generate python
-like dictionaries, i.e.
var = {a:1, b:2, c:3}
which then return for \var{b}
2
?
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It only takes a minute to sign up.
Sign up to join this communityYou can emulate it with a property list:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\DefineDictionary}{mm}
{
\arclupus_dict_def:nn { #1 } { #2 }
}
\seq_new:N \l__arclupus_dict_temp_seq
\cs_new_protected:Nn \arclupus_dict_def:nn
{
\prop_gclear_new:c { g_arclupus_#1_dict_prop }
\clist_map_inline:nn { #2 }
{
\__arclupus_dict_add:nn { #1 } { ##1 }
}
\cs_new:cpn { #1 } ##1 { \prop_item:cn { g_arclupus_#1_dict_prop } { ##1 } }
}
\cs_new_protected:Nn \__arclupus_dict_add:nn
{
\seq_set_split:Nnn \l__arclupus_dict_temp_seq { / } { #2 }
\prop_gput:cxx { g_arclupus_#1_dict_prop }
{
\seq_item:Nn \l__arclupus_dict_temp_seq { 1 }
}
{
\seq_item:Nn \l__arclupus_dict_temp_seq { 2 }
}
}
\cs_generate_variant:Nn \prop_gput:Nnn { cxx }
\ExplSyntaxOff
\DefineDictionary{var}{a/1, b/2, c/3}
\begin{document}
\var{a}
\var{c}
\var{b}
\end{document}
The \DefineDictionary
takes as argument the dictionary name and the data. A new property list is created (or an existing one is cleared); then each item in the second argument is split at /
to become an item in the property list. Finally, a macro with the name of the dictionary is created to retrieve the data.
The version with the colon is slightly trickier, because we can't use a literal :
for the split operation.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\DefineDictionary}{mm}
{
\arclupus_dict_def:nn { #1 } { #2 }
}
\seq_new:N \l__arclupus_dict_temp_seq
\cs_new_protected:Nn \arclupus_dict_def:nn
{
\prop_gclear_new:c { g_arclupus_#1_dict_prop }
\clist_map_inline:nn { #2 }
{
\__arclupus_dict_add:nn { #1 } { ##1 }
}
\cs_new:cpn { #1 } ##1 { \prop_item:cn { g_arclupus_#1_dict_prop } { ##1 } }
}
\cs_new_protected:Nn \__arclupus_dict_add:nn
{
\seq_set_split:NVn \l__arclupus_dict_temp_seq \c_colon_str { #2 }
\prop_gput:cxx { g_arclupus_#1_dict_prop }
{
\seq_item:Nn \l__arclupus_dict_temp_seq { 1 }
}
{
\seq_item:Nn \l__arclupus_dict_temp_seq { 2 }
}
}
\cs_generate_variant:Nn \seq_set_split:Nnn { NV }
\cs_generate_variant:Nn \prop_gput:Nnn { cxx }
\ExplSyntaxOff
\DefineDictionary{var}{a:1, b:2, c:3}
\begin{document}
\var{a}
\var{c}
\var{b}
\end{document}
If you also need to pass macros to \var
, then change the line
\cs_new:cpn { #1 } ##1 { \prop_item:cn { g_arclupus_#1_dict_prop } { ##1 } }
into
\cs_new:cpn { #1 } ##1 { \prop_item:cf { g_arclupus_#1_dict_prop } { ##1 } }
and add, just before \ExplSyntaxOff
, the magic line
\cs_generate_variant:Nn \prop_item:Nn { cf }
that defines the required variant.
Macros that expand to strings are then welcome in the argument of the newly created macro (\var
in the example). Note that \var
is still fully expandable.
{a:1, b:2}
version. With the recent (or not so recent) \char_generate:nn
and a \seq_set_split:Nfn
it's relatively simple.
\var{\mysinglelettermacro}
working? Right now it just prints nothing. (Assuming the \var
from the above MWE).
FWIW, ConTeXt has built-in data-structure that is equivalent to a dictionary. In particular,
\setvariables
[var]
[
a=1,
b=2,
c=3,
]
Then you can access the variables using \getvariable{var}{a}
, etc.
Using \def\abc{a} \getvariable{var}{\abc}
also works.