Saving arguments of commands to be used later











up vote
6
down vote

favorite
1












I'd like to create a command to print some contacts inserted with same 3 commands: name{},work{},email{}.



Every time we use those 3 commands, a new contact is collected and then all of them is printed as below.



I suspect that I need some kind of array of list, to save the contacts, but I have no idea how to search for this.



MWE



documentclass{article}

makeatletter
deflistcontacts{%
noindenttextbf{@name}par
noindenttextit{@work}par
noindenttexttt{@email}par

vskip 1in % to start a new block of contact
}

newcommand{name}[1]{def@name{#1}}
newcommand{work}[1]{def@work{#1}}
newcommand{email}[1]{def@email{#1}}

newcommand{information}[3]{%
name{#1}
work{#2}
email{#3}
}
makeatother

information{Faa Foo}{Univ. Blah}{goo@goo.com}


%% I'd like to insert a new one with same commands
%name{Faa Foo}
%work{Univ. Blah}
%email{goo@goo.com}


% and repeat the process with different number of blocks,
%that is, could be any finite number of contacts.

begin{document}
listcontacts
end{document}









share|improve this question


























    up vote
    6
    down vote

    favorite
    1












    I'd like to create a command to print some contacts inserted with same 3 commands: name{},work{},email{}.



    Every time we use those 3 commands, a new contact is collected and then all of them is printed as below.



    I suspect that I need some kind of array of list, to save the contacts, but I have no idea how to search for this.



    MWE



    documentclass{article}

    makeatletter
    deflistcontacts{%
    noindenttextbf{@name}par
    noindenttextit{@work}par
    noindenttexttt{@email}par

    vskip 1in % to start a new block of contact
    }

    newcommand{name}[1]{def@name{#1}}
    newcommand{work}[1]{def@work{#1}}
    newcommand{email}[1]{def@email{#1}}

    newcommand{information}[3]{%
    name{#1}
    work{#2}
    email{#3}
    }
    makeatother

    information{Faa Foo}{Univ. Blah}{goo@goo.com}


    %% I'd like to insert a new one with same commands
    %name{Faa Foo}
    %work{Univ. Blah}
    %email{goo@goo.com}


    % and repeat the process with different number of blocks,
    %that is, could be any finite number of contacts.

    begin{document}
    listcontacts
    end{document}









    share|improve this question
























      up vote
      6
      down vote

      favorite
      1









      up vote
      6
      down vote

      favorite
      1






      1





      I'd like to create a command to print some contacts inserted with same 3 commands: name{},work{},email{}.



      Every time we use those 3 commands, a new contact is collected and then all of them is printed as below.



      I suspect that I need some kind of array of list, to save the contacts, but I have no idea how to search for this.



      MWE



      documentclass{article}

      makeatletter
      deflistcontacts{%
      noindenttextbf{@name}par
      noindenttextit{@work}par
      noindenttexttt{@email}par

      vskip 1in % to start a new block of contact
      }

      newcommand{name}[1]{def@name{#1}}
      newcommand{work}[1]{def@work{#1}}
      newcommand{email}[1]{def@email{#1}}

      newcommand{information}[3]{%
      name{#1}
      work{#2}
      email{#3}
      }
      makeatother

      information{Faa Foo}{Univ. Blah}{goo@goo.com}


      %% I'd like to insert a new one with same commands
      %name{Faa Foo}
      %work{Univ. Blah}
      %email{goo@goo.com}


      % and repeat the process with different number of blocks,
      %that is, could be any finite number of contacts.

      begin{document}
      listcontacts
      end{document}









      share|improve this question













      I'd like to create a command to print some contacts inserted with same 3 commands: name{},work{},email{}.



      Every time we use those 3 commands, a new contact is collected and then all of them is printed as below.



      I suspect that I need some kind of array of list, to save the contacts, but I have no idea how to search for this.



      MWE



      documentclass{article}

      makeatletter
      deflistcontacts{%
      noindenttextbf{@name}par
      noindenttextit{@work}par
      noindenttexttt{@email}par

      vskip 1in % to start a new block of contact
      }

      newcommand{name}[1]{def@name{#1}}
      newcommand{work}[1]{def@work{#1}}
      newcommand{email}[1]{def@email{#1}}

      newcommand{information}[3]{%
      name{#1}
      work{#2}
      email{#3}
      }
      makeatother

      information{Faa Foo}{Univ. Blah}{goo@goo.com}


      %% I'd like to insert a new one with same commands
      %name{Faa Foo}
      %work{Univ. Blah}
      %email{goo@goo.com}


      % and repeat the process with different number of blocks,
      %that is, could be any finite number of contacts.

      begin{document}
      listcontacts
      end{document}






      macros






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 15 at 18:00









      Sigur

      23.3k353135




      23.3k353135






















          4 Answers
          4






          active

          oldest

          votes

















          up vote
          3
          down vote



          accepted










          This is similar to Steven Seglets solution with slightly different packaging. You can show a single contact with ShowContact{} or list all the contact with listcontacts



          enter image description here



          Notes:




          • The values are stored based on #1 which is used as the key to access the contacts. An attempt to reuse the same key is now flagged as an error.

          • This has now been updated to add a medskip between entries when the entire list is printed. The medskip is not added before the first entry, nor after the last as shown in the figure.


          Code:



          documentclass{article}
          usepackage{etoolbox}

          makeatletter

          newtoggle{@IsFirstEntryInList}

          newcommand*{@ShowContact}[1]{%
          iftoggle{@IsFirstEntryInList}{%
          globaltogglefalse{@IsFirstEntryInList}%
          }{%
          medskip% <-- separator between entries
          }%
          ShowContact{#1}%
          }
          newcommand*{ShowContact}[1]{%
          parnoindenttextbf{csuse{name #1}}%
          parnoindenttextit{csuse{work #1}}%
          parnoindenttexttt{csuse{email #1}}%
          }%

          %% https://tex.stackexchange.com/a/14394/4301
          newcommand*{listcontacts}{% Initialize
          globaltoggletrue{@IsFirstEntryInList}%
          }
          newcommand{AddToListOfContacts}[1]{%
          g@addto@macrolistcontacts{{#1}}%
          }


          newcommand{information}[3]{%
          ifcsdef{name #1}{%
          PackageError{jobname}{Multiple uses of the key: '#1'}{}%
          }{%
          csdef{name #1}{#1}%
          csdef{work #1}{#2}%
          csdef{email #1}{#3}%
          AddToListOfContacts{unexpanded{@ShowContact{#1}}}%
          }%
          }
          makeatother

          information{Faa Foo}{Univ. Blah}{goo@goo.com}
          information{Harvard}{Harvard University}{me@harvard.com}
          %information{Harvard}{xxx University}{me@harvard.com}% <-- Triggers an error

          begin{document}
          noindent
          To show one contact:

          ShowContact{Harvard}

          medskipnoindent
          To show all contacts:

          listcontacts
          parnoindent
          Text following to check that there is no extra space at end...
          end{document}





          share|improve this answer























          • Interesting. In this case, the contacts are accessed via argument value, not via a number, right?
            – Sigur
            Nov 15 at 18:28










          • @Sigur: Yes, the first parameter is used as the key to access the information. This is really helpful if you have a large number of contacts.
            – Peter Grill
            Nov 15 at 18:30










          • Since I'm going to share this file, do you know if etoolbox comes with a basic installation? Because I know that tikz does not.
            – Sigur
            Nov 15 at 18:30










          • Yes, etoolbox is in the standard distribution. But, so is tikz so not sure why you think otherwise. Also, have added error checking in the updated version.
            – Peter Grill
            Nov 15 at 18:34








          • 1




            @Sigur: As requested, I have updated it inserts a medskip only between entries. You can replace the medskip with the symbol you desire.
            – Peter Grill
            Nov 16 at 6:39


















          up vote
          4
          down vote













          I have made it so that @name[<index>] @work[<index>], and @email[<index>] are arrays, where the index is stepped with every call to information{}{}{}.



          listcontact{<index>} will provide the contact info for the one specified index. In the MWE, I loop through all indices.



          documentclass{article}
          usepackage{pgffor}
          makeatletter
          newcounter{infocnt}
          newcommand{name}[1]{%
          expandafterdefcsname @name[theinfocnt]endcsname{#1}}
          newcommand{work}[1]{%
          expandafterdefcsname @work[theinfocnt]endcsname{#1}}
          newcommand{email}[1]{%
          expandafterdefcsname @email[theinfocnt]endcsname{#1}}
          newcommand{information}[3]{%
          stepcounter{infocnt}%
          name{#1}%
          work{#2}%
          email{#3}%
          }
          newcommandlistcontact[1]{noindent%
          NAME: textbf{csname @name[#1]endcsname}\
          WORK: textbf{csname @work[#1]endcsname}\
          EMAIL: textbf{csname @email[#1]endcsname}par
          vskip 1in
          }
          makeatother
          information{Faa Foo}{Univ. Blah}{goo@goo.com}
          information{XXX}{YYY}{ZZZ@goo.com}
          begin{document}
          foreachx in {1,2,...,theinfocnt}{listcontact{x}}
          end{document}


          enter image description here



          If I had my 'druthers, though, I would input the list all at once, quite simply, with the same output. The listofitems package immediately stores the list as an accessible array:



          documentclass{article}
          usepackage{listofitems}
          newcommandlistcontact[1]{noindent%
          NAME: textbf{contacts[#1,1]}\
          WORK: textbf{contacts[#1,2]}\
          EMAIL: textbf{contacts[#1,3]}par
          vskip 1in
          }
          setsepchar{\/&}
          begin{document}
          readlist*contacts{
          Faa Foo & Univ. Blah & goo@goo.com\
          XXX & YYY & ZZZ@goo.com}
          foreachitemxincontacts{listcontact{xcnt}}

          Here is the email of contact 2: contacts[2,3].
          end{document}


          enter image description here



          With a small supplement from the readarray package, the list of contacts could even be stored in an external file.






          share|improve this answer























          • Very nice, specially since tikz is needed only for the loop.
            – Sigur
            Nov 15 at 18:18










          • @Sigur Oops. I redefined it (didn't see it defined earlier).
            – Steven B. Segletes
            Nov 15 at 18:20












          • No problem, I observed that. Thanks a lot
            – Sigur
            Nov 15 at 18:21










          • Do you know another way to print all without using tikz? Maybe using the value of the counter only? I'm going to share the file and tikz could be not available.
            – Sigur
            Nov 15 at 18:31






          • 1




            @Sigur I changed it to pgffor. However, I also added technique #2, which is far simpler, if you can add all names at once.
            – Steven B. Segletes
            Nov 15 at 18:33


















          up vote
          3
          down vote













          This is “property lists” playground. Here I define newcontact for defining a contact with a key-value interface.



          With newcontactscheme one defines different ways to print the data; default is used by listcontact if no optional argument is supplied. In the definition, use getcontact{<key>}{#1} to print the value corresponding to <key> for the current contact, represented by #1.



          documentclass{article}
          usepackage{xparse}

          ExplSyntaxOn

          NewDocumentCommand{newcontact}{mm}
          {% #1 = contact label, #2 = data
          prop_new:c { g_sigur_contact_#1_prop }
          prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
          }
          NewDocumentCommand{listcontact}{O{default}m}
          {
          cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
          __sigur_contact_list:n { #2 }
          }
          NewDocumentCommand{getcontact}{mm}
          {
          sigur_contact_print:nn { #1 } { #2 }
          }
          NewDocumentCommand{newcontactscheme}{m+m}
          {% #1 = scheme name, #2 = definition
          cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
          }
          cs_new_protected:Nn sigur_contact_print:nn
          {
          prop_item:cn { g_sigur_contact_#2_prop } { #1 }
          }
          ExplSyntaxOff

          newcontactscheme{default}{%
          parnoindent
          getcontact{name}{#1}\
          getcontact{work}{#1}\
          getcontact{email}{#1}par
          }
          newcontactscheme{short}{%
          getcontact{name}{#1}, getcontact{email}{#1}%
          }
          newcontactscheme{alternate}{%
          begin{tabular}[t]{@{}l@{ }l@{}}
          Name: & getcontact{name}{#1} \
          Work: & getcontact{work}{#1} \
          Email: & texttt{getcontact{email}{#1}}
          end{tabular}%
          }

          newcontact{foo}{
          name=Faa Foo,
          work=Univ. Blah,
          email=goo@goo.com
          }
          newcontact{xxx}{
          name=XXX,
          work=YYY,
          email=ZZZ@goo.com
          }

          begin{document}

          listcontact{foo}

          medskip

          listcontact{xxx}

          medskip

          Short: listcontact[short]{xxx}

          medskip

          Alternate: listcontact[alternate]{foo}

          end{document}


          enter image description here



          A version that also defines listallcontacts (the optional argument is one of the defined schemes).



          documentclass{article}
          usepackage{xparse}

          ExplSyntaxOn

          NewDocumentCommand{newcontact}{mm}
          {% #1 = contact label, #2 = data
          prop_new:c { g_sigur_contact_#1_prop }
          prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
          seq_gput_right:Nn g_sigur_contact_seq { #1 }
          }
          NewDocumentCommand{listcontact}{O{default}m}
          {
          cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
          __sigur_contact_list:n { #2 }
          }
          NewDocumentCommand{listallcontacts}{O{default}}
          {
          cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
          seq_map_inline:Nn g_sigur_contact_seq
          {
          __sigur_contact_list:n { ##1 } par
          }
          }
          NewDocumentCommand{getcontact}{mm}
          {
          sigur_contact_print:nn { #1 } { #2 }
          }
          NewDocumentCommand{newcontactscheme}{m+m}
          {% #1 = scheme name, #2 = definition
          cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
          }

          seq_new:N g_sigur_contact_seq

          cs_new_protected:Nn sigur_contact_print:nn
          {
          prop_item:cn { g_sigur_contact_#2_prop } { #1 }
          }
          ExplSyntaxOff

          newcontactscheme{default}{%
          parnoindent
          getcontact{name}{#1}\
          getcontact{work}{#1}\
          getcontact{email}{#1}par
          }
          newcontactscheme{short}{%
          getcontact{name}{#1}, getcontact{email}{#1}%
          }
          newcontactscheme{alternate}{%
          begin{tabular}[t]{@{}l@{ }l@{}}
          Name: & getcontact{name}{#1} \
          Work: & getcontact{work}{#1} \
          Email: & texttt{getcontact{email}{#1}}
          end{tabular}%
          }

          newcontact{foo}{
          name=Faa Foo,
          work=Univ. Blah,
          email=goo@goo.com
          }
          newcontact{xxx}{
          name=XXX,
          work=YYY,
          email=ZZZ@goo.com
          }

          begin{document}

          listcontact{foo}

          medskip

          listcontact{xxx}

          medskip

          Short: listcontact[short]{xxx}

          medskip

          Alternate: listcontact[alternate]{foo}

          medskip

          listallcontacts

          medskip

          listallcontacts[short]

          end{document}





          share|improve this answer























          • I never studied or tried to learn xparse. The result is amazing. Nice!
            – Sigur
            Nov 15 at 21:04


















          up vote
          0
          down vote













          This "answer" does not answer your question.



          A few remarks about the pitfalls of database-management in LaTeX



          A few remarks about database-management in general:



          Usually data is organized in so-called data-bases.



          A data-base could, e.g., be a list of contact-details.



          Each person or organization that you wish to contact might within the data-base be connected to a data-record which holds all the contact-details related to that person/organization.



          Therefore a data-record itself could be organized by means of data-fields whereby each field serves for storing/providing information that belongs to a specific category.



          Thus the logical structure of a data-base could be something like:



          Data-base: contact-details
          ==========================

          Data-record 001:
          ----------------
          Value of data-field "Name":=John Doe
          Value of data-field "Work":=whistle blower
          Value of data-field "E-Mail":=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Name":=Jane Smith
          Value of data-field "Work":=employée at department of alternative facts
          Value of data-field "E-Mail":=AltFacts@fake.email.address

          ...


          You need means




          • both for identifying each record that belongs to a data-base

          • and for keeping the single records that belong to a data-base distinguishable from each other.


          The data-fields "Name" or "Work" or "E-Mail" are not suitable for this purpose.



          E.g., some day there might be records about two different people in the data-base that have the same name.



          Thus in data-base-management, it is common practise to indroduce in the structure of data-records a data-field which for each data-record holds a piece of information which does not occur within the corresponding data-field of any other data-record.



          Usually this data-field is called a "primary key".



          Often this primary-key is just some item of continuous numeration which is obtained by continuously numerating data-records.



          When introducing a primary-key, the data-base "contact details" could look like this:



          Data-base: contact-details
          ==========================

          Data-record 001:
          ----------------
          Value of data-field "Primary Key":=001
          Value of data-field "Name":=John Doe
          Value of data-field "Work":=whistle blower
          Value of data-field "E-Mail":=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Primary Key":=002
          Value of data-field "Name":=Jane Smith
          Value of data-field "Work":=employée at department of alternative facts
          Value of data-field "E-Mail":=AltFacts@fake.email.address


          When doing this, you can - besides the single data-records - also maintain




          • a list of primary-keys belonging to the data-base an

          • a counter denoting the amount of records belonging to the data-base:


           



          Data-base: contact-details
          ==========================

          Amount of data-records: 2
          List of primary-keys: {001}, {002}

          Data-record 001:
          ----------------
          Value of data-field "Primary Key":=001
          Value of data-field "Name":=John Doe
          Value of data-field "Work":=whistle blower
          Value of data-field "E-Mail":=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Primary Key":=002
          Value of data-field "Name":=Jane Smith
          Value of data-field "Work":=employée at department of alternative facts
          Value of data-field "E-Mail":=AltFacts@fake.email.address


          The list of primary-keys would be of special interest for sorting out specific data-records:



          Assume you wish to retrieve the e-mail-address of Jane Smith:



          In terms of pseudo-code, you would do this via a directive like:



          Iterate on that list of primary-keys that belongs to
          the data-base "contact-details" as follows:

          In each iteration "look" at the value of the data-field "Name"
          of that data-record whose data-field "Primary Key" equals the
          current list element.
          If that value equals "Jane Smith", print out the value of the
          data-field "E-Mail" of that data-record.


          Pitfalls related to (La)TeX:



          When implementing such things in terms of (La)TeX, you will encounter a few problems which have to do with the fact that (La)TeX is a macro-language which does some pre-processing of input in terms of reading and tokenizing input:



          For example, curly braces ({ and }) have a specific meaning in LaTeX and usually each opening-brace must habe a matching closing-brace and vice versa.



          For example, the percent-character (%) has a specific meaning in LaTeX.



          But according to RFC 2822 e-mail-adresses may contain unbalanced curly braces and percent-characters.



          Therefore maintaining such entries via a data-base that is provided in terms of (La)TeX-input might be related to circumstances which the not-so experienced user might see as problems.



          E.g., Alt}Fa%c#1ts@fake.email.address would be a nice e-mail-address.



          But how to get the value Alt}Fa%c#1ts@fake.email.address into a data-record's data-field "E-Mail" in case the data-base in question is maintained in (La)TeX?



          At first glimpse you could do it by means of macros that deliver the desired symbols in question:



          Something like:



          Value of data-field "E-Mail":=Altleftbrace Fatextpercent chash1ts@fake.email.address


          Also the names of people/organizations might contain characters/symbols which the input-encoding in which the (La)TeX-file is written does not contain.



          Assume one of the persons whose contact-details are to be maintained has the name Alaïa Maëlys Gambolpütty while the data-base is written in a (La)TeX-input-file that is encoded in ASCII.

          In such a case you must do it in terms of control-sequence-tokens whose names are formed by characters within the range of the input-encoding.



          But such control-sequences make sorting out specific data-records difficult.



          Therefore it might be a good idea to maintain each piece of data twice:



          Once written only by means of characters of the input-encoding in question.

          Once written in a way where also LaTeX-control-sequences that deliver the desired characters/symbols may occur:



          Data-base: contact-details
          ==========================

          Amount of data-records: 3
          List of primary-keys: {001}, {002}, {003}

          Data-record 001:
          ----------------
          Value of data-field "Primary Key":=001
          Value of data-field "Name" in input-encoding-representation:=John Doe
          Value of data-field "Name" in LaTeX-representation:=John Doe
          Value of data-field "Work" in input-encoding-representation:=whistle blower
          Value of data-field "Work" in LaTeX-representation:=whistle blower
          Value of data-field "E-Mail" in input-encoding-representation:=Whistle@fake.email.address
          Value of data-field "E-Mail" in LaTeX-representation:=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Primary Key":=002
          Value of data-field "Name" in input-encoding-representation:=Jane Smith
          Value of data-field "Name" in LaTeX-representation:=Jane Smith
          Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
          Value of data-field "Work" in LaTeX-representation:=employ'ee at department of alternative facts
          Value of data-field "E-Mail" in input-encoding-representation:=AltFacts@fake.email.address
          Value of data-field "E-Mail" in LaTeX-representation:=AltFacts@fake.email.address

          Data-record 003:
          ----------------
          Value of data-field "Primary Key":=003
          Value of data-field "Name" in input-encoding-representation:=Alaia Maelys Gambolpuetty
          Value of data-field "Name" in LaTeX-representation:=Ala"{i}a Ma"{e}lys Gambolp"{u}tty
          Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
          Value of data-field "Work" in LaTeX-representation:=employée at department of alternative facts
          Value of data-field "E-Mail" in input-encoding-representation:=Alt}Fa%c#1ts@fake.email.address
          Value of data-field "E-Mail" in LaTeX-representation:=Altleftbrace Fatextpercent chash1ts@fake.email.address

          ...


          With such an approach you could implement an interface where searching and sorting out takes place in terms of input-encoding-representation and delivers data in terms of LaTeX-representation.



          With such an interface, one stage would always include reading and tokenizing the input-encoding-representations under verbatim-catcode-régime.



          This is feasible but makes using the macros that form the interface




          • within pure-expansion-contexts impossible.

          • within the definition-texts of other macros cumbersome.


          With such an interface, it would also be a good idea to have everything that denotes names of databases or names of data-fields or values in input-encoding-representation evaluate to characters of the input-encoding.



          Therefore for proper error-checking a routine would be useful which does fully evaluate/expand arguments and then does check whether the expansion-result does hold character-tokens obeying the verbatim-catcode-régime only.



          Full evaluation/expansion of an argument that might hold arbitrary tokens is already a nice problem.



          An easy approach would be using edef.

          For one thing this also would break expandability of the interface.

          For another thing edef is not totally safe with arbitrary tokens.

          E.g., look at



          edeftest{%
          Where does the definition text
          stop?iffalse{fi Here?} Or Here?{iffalse}fi
          }


          I think a minimalist interface for some sort of database-management is feasible in LaTeX – with things like:



          NewInitializedDataRecord{<Primary Key>}%
          {<Name>}%
          {<Work>}%
          {<EMail>}%


          NewEmptyDataRecord{<Primary Key>}
          AddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}{<Value>}%
          VerbatimizedAddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}|<Value>|% <- verbatim-arg
          (extraction of verbatimized values of data-fields via scantokens...)

          PrintFieldValueFromDataRecord{<Primary Key>}{<Name of data-field>}

          PrintDataRecord{<Primary Key>}

          PrintAllDataRecords

          PrintAllDataRecordsWithSpecificDatFieldValue{<Name of data-field>}{<Specific Value>}


          But before going into details, specification about the tokens that might form values of data-fields and about their treatment when comparing values of data-fields is needed.






          share|improve this answer























          • I am not sure if I understood your comments. Anyway, thanks for attention. Let me inform that the contacts come from authors of a paper, so I think that two exactly equal names could happen rarely.
            – Sigur
            Nov 16 at 18:13










          • Your question actually is about some sort of whatsoever minimalist database-management. :-) I extended my answer in the hope of pointing out some of the pitfalls related to whatsoever minimalist database-management in terms of a macro language. :-)
            – Ulrich Diez
            Nov 16 at 21:29










          • Well, thanks for your work. But I confess that I have no idea how to understand it... lol
            – Sigur
            Nov 16 at 21:33










          • I think you want to say “From relational algebra we know that it is not a good idea to assign to each data-record its own unique primary-key as a data-field of its own of that data-record.”.
            – egreg
            Nov 16 at 21:48










          • @UlrichDiez The formulation is way better now. For the same reason I assigned a label to each contact.
            – egreg
            Nov 16 at 22:31











          Your Answer








          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "85"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














           

          draft saved


          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f460175%2fsaving-arguments-of-commands-to-be-used-later%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          4 Answers
          4






          active

          oldest

          votes








          4 Answers
          4






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          3
          down vote



          accepted










          This is similar to Steven Seglets solution with slightly different packaging. You can show a single contact with ShowContact{} or list all the contact with listcontacts



          enter image description here



          Notes:




          • The values are stored based on #1 which is used as the key to access the contacts. An attempt to reuse the same key is now flagged as an error.

          • This has now been updated to add a medskip between entries when the entire list is printed. The medskip is not added before the first entry, nor after the last as shown in the figure.


          Code:



          documentclass{article}
          usepackage{etoolbox}

          makeatletter

          newtoggle{@IsFirstEntryInList}

          newcommand*{@ShowContact}[1]{%
          iftoggle{@IsFirstEntryInList}{%
          globaltogglefalse{@IsFirstEntryInList}%
          }{%
          medskip% <-- separator between entries
          }%
          ShowContact{#1}%
          }
          newcommand*{ShowContact}[1]{%
          parnoindenttextbf{csuse{name #1}}%
          parnoindenttextit{csuse{work #1}}%
          parnoindenttexttt{csuse{email #1}}%
          }%

          %% https://tex.stackexchange.com/a/14394/4301
          newcommand*{listcontacts}{% Initialize
          globaltoggletrue{@IsFirstEntryInList}%
          }
          newcommand{AddToListOfContacts}[1]{%
          g@addto@macrolistcontacts{{#1}}%
          }


          newcommand{information}[3]{%
          ifcsdef{name #1}{%
          PackageError{jobname}{Multiple uses of the key: '#1'}{}%
          }{%
          csdef{name #1}{#1}%
          csdef{work #1}{#2}%
          csdef{email #1}{#3}%
          AddToListOfContacts{unexpanded{@ShowContact{#1}}}%
          }%
          }
          makeatother

          information{Faa Foo}{Univ. Blah}{goo@goo.com}
          information{Harvard}{Harvard University}{me@harvard.com}
          %information{Harvard}{xxx University}{me@harvard.com}% <-- Triggers an error

          begin{document}
          noindent
          To show one contact:

          ShowContact{Harvard}

          medskipnoindent
          To show all contacts:

          listcontacts
          parnoindent
          Text following to check that there is no extra space at end...
          end{document}





          share|improve this answer























          • Interesting. In this case, the contacts are accessed via argument value, not via a number, right?
            – Sigur
            Nov 15 at 18:28










          • @Sigur: Yes, the first parameter is used as the key to access the information. This is really helpful if you have a large number of contacts.
            – Peter Grill
            Nov 15 at 18:30










          • Since I'm going to share this file, do you know if etoolbox comes with a basic installation? Because I know that tikz does not.
            – Sigur
            Nov 15 at 18:30










          • Yes, etoolbox is in the standard distribution. But, so is tikz so not sure why you think otherwise. Also, have added error checking in the updated version.
            – Peter Grill
            Nov 15 at 18:34








          • 1




            @Sigur: As requested, I have updated it inserts a medskip only between entries. You can replace the medskip with the symbol you desire.
            – Peter Grill
            Nov 16 at 6:39















          up vote
          3
          down vote



          accepted










          This is similar to Steven Seglets solution with slightly different packaging. You can show a single contact with ShowContact{} or list all the contact with listcontacts



          enter image description here



          Notes:




          • The values are stored based on #1 which is used as the key to access the contacts. An attempt to reuse the same key is now flagged as an error.

          • This has now been updated to add a medskip between entries when the entire list is printed. The medskip is not added before the first entry, nor after the last as shown in the figure.


          Code:



          documentclass{article}
          usepackage{etoolbox}

          makeatletter

          newtoggle{@IsFirstEntryInList}

          newcommand*{@ShowContact}[1]{%
          iftoggle{@IsFirstEntryInList}{%
          globaltogglefalse{@IsFirstEntryInList}%
          }{%
          medskip% <-- separator between entries
          }%
          ShowContact{#1}%
          }
          newcommand*{ShowContact}[1]{%
          parnoindenttextbf{csuse{name #1}}%
          parnoindenttextit{csuse{work #1}}%
          parnoindenttexttt{csuse{email #1}}%
          }%

          %% https://tex.stackexchange.com/a/14394/4301
          newcommand*{listcontacts}{% Initialize
          globaltoggletrue{@IsFirstEntryInList}%
          }
          newcommand{AddToListOfContacts}[1]{%
          g@addto@macrolistcontacts{{#1}}%
          }


          newcommand{information}[3]{%
          ifcsdef{name #1}{%
          PackageError{jobname}{Multiple uses of the key: '#1'}{}%
          }{%
          csdef{name #1}{#1}%
          csdef{work #1}{#2}%
          csdef{email #1}{#3}%
          AddToListOfContacts{unexpanded{@ShowContact{#1}}}%
          }%
          }
          makeatother

          information{Faa Foo}{Univ. Blah}{goo@goo.com}
          information{Harvard}{Harvard University}{me@harvard.com}
          %information{Harvard}{xxx University}{me@harvard.com}% <-- Triggers an error

          begin{document}
          noindent
          To show one contact:

          ShowContact{Harvard}

          medskipnoindent
          To show all contacts:

          listcontacts
          parnoindent
          Text following to check that there is no extra space at end...
          end{document}





          share|improve this answer























          • Interesting. In this case, the contacts are accessed via argument value, not via a number, right?
            – Sigur
            Nov 15 at 18:28










          • @Sigur: Yes, the first parameter is used as the key to access the information. This is really helpful if you have a large number of contacts.
            – Peter Grill
            Nov 15 at 18:30










          • Since I'm going to share this file, do you know if etoolbox comes with a basic installation? Because I know that tikz does not.
            – Sigur
            Nov 15 at 18:30










          • Yes, etoolbox is in the standard distribution. But, so is tikz so not sure why you think otherwise. Also, have added error checking in the updated version.
            – Peter Grill
            Nov 15 at 18:34








          • 1




            @Sigur: As requested, I have updated it inserts a medskip only between entries. You can replace the medskip with the symbol you desire.
            – Peter Grill
            Nov 16 at 6:39













          up vote
          3
          down vote



          accepted







          up vote
          3
          down vote



          accepted






          This is similar to Steven Seglets solution with slightly different packaging. You can show a single contact with ShowContact{} or list all the contact with listcontacts



          enter image description here



          Notes:




          • The values are stored based on #1 which is used as the key to access the contacts. An attempt to reuse the same key is now flagged as an error.

          • This has now been updated to add a medskip between entries when the entire list is printed. The medskip is not added before the first entry, nor after the last as shown in the figure.


          Code:



          documentclass{article}
          usepackage{etoolbox}

          makeatletter

          newtoggle{@IsFirstEntryInList}

          newcommand*{@ShowContact}[1]{%
          iftoggle{@IsFirstEntryInList}{%
          globaltogglefalse{@IsFirstEntryInList}%
          }{%
          medskip% <-- separator between entries
          }%
          ShowContact{#1}%
          }
          newcommand*{ShowContact}[1]{%
          parnoindenttextbf{csuse{name #1}}%
          parnoindenttextit{csuse{work #1}}%
          parnoindenttexttt{csuse{email #1}}%
          }%

          %% https://tex.stackexchange.com/a/14394/4301
          newcommand*{listcontacts}{% Initialize
          globaltoggletrue{@IsFirstEntryInList}%
          }
          newcommand{AddToListOfContacts}[1]{%
          g@addto@macrolistcontacts{{#1}}%
          }


          newcommand{information}[3]{%
          ifcsdef{name #1}{%
          PackageError{jobname}{Multiple uses of the key: '#1'}{}%
          }{%
          csdef{name #1}{#1}%
          csdef{work #1}{#2}%
          csdef{email #1}{#3}%
          AddToListOfContacts{unexpanded{@ShowContact{#1}}}%
          }%
          }
          makeatother

          information{Faa Foo}{Univ. Blah}{goo@goo.com}
          information{Harvard}{Harvard University}{me@harvard.com}
          %information{Harvard}{xxx University}{me@harvard.com}% <-- Triggers an error

          begin{document}
          noindent
          To show one contact:

          ShowContact{Harvard}

          medskipnoindent
          To show all contacts:

          listcontacts
          parnoindent
          Text following to check that there is no extra space at end...
          end{document}





          share|improve this answer














          This is similar to Steven Seglets solution with slightly different packaging. You can show a single contact with ShowContact{} or list all the contact with listcontacts



          enter image description here



          Notes:




          • The values are stored based on #1 which is used as the key to access the contacts. An attempt to reuse the same key is now flagged as an error.

          • This has now been updated to add a medskip between entries when the entire list is printed. The medskip is not added before the first entry, nor after the last as shown in the figure.


          Code:



          documentclass{article}
          usepackage{etoolbox}

          makeatletter

          newtoggle{@IsFirstEntryInList}

          newcommand*{@ShowContact}[1]{%
          iftoggle{@IsFirstEntryInList}{%
          globaltogglefalse{@IsFirstEntryInList}%
          }{%
          medskip% <-- separator between entries
          }%
          ShowContact{#1}%
          }
          newcommand*{ShowContact}[1]{%
          parnoindenttextbf{csuse{name #1}}%
          parnoindenttextit{csuse{work #1}}%
          parnoindenttexttt{csuse{email #1}}%
          }%

          %% https://tex.stackexchange.com/a/14394/4301
          newcommand*{listcontacts}{% Initialize
          globaltoggletrue{@IsFirstEntryInList}%
          }
          newcommand{AddToListOfContacts}[1]{%
          g@addto@macrolistcontacts{{#1}}%
          }


          newcommand{information}[3]{%
          ifcsdef{name #1}{%
          PackageError{jobname}{Multiple uses of the key: '#1'}{}%
          }{%
          csdef{name #1}{#1}%
          csdef{work #1}{#2}%
          csdef{email #1}{#3}%
          AddToListOfContacts{unexpanded{@ShowContact{#1}}}%
          }%
          }
          makeatother

          information{Faa Foo}{Univ. Blah}{goo@goo.com}
          information{Harvard}{Harvard University}{me@harvard.com}
          %information{Harvard}{xxx University}{me@harvard.com}% <-- Triggers an error

          begin{document}
          noindent
          To show one contact:

          ShowContact{Harvard}

          medskipnoindent
          To show all contacts:

          listcontacts
          parnoindent
          Text following to check that there is no extra space at end...
          end{document}






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 16 at 6:37

























          answered Nov 15 at 18:25









          Peter Grill

          163k24432740




          163k24432740












          • Interesting. In this case, the contacts are accessed via argument value, not via a number, right?
            – Sigur
            Nov 15 at 18:28










          • @Sigur: Yes, the first parameter is used as the key to access the information. This is really helpful if you have a large number of contacts.
            – Peter Grill
            Nov 15 at 18:30










          • Since I'm going to share this file, do you know if etoolbox comes with a basic installation? Because I know that tikz does not.
            – Sigur
            Nov 15 at 18:30










          • Yes, etoolbox is in the standard distribution. But, so is tikz so not sure why you think otherwise. Also, have added error checking in the updated version.
            – Peter Grill
            Nov 15 at 18:34








          • 1




            @Sigur: As requested, I have updated it inserts a medskip only between entries. You can replace the medskip with the symbol you desire.
            – Peter Grill
            Nov 16 at 6:39


















          • Interesting. In this case, the contacts are accessed via argument value, not via a number, right?
            – Sigur
            Nov 15 at 18:28










          • @Sigur: Yes, the first parameter is used as the key to access the information. This is really helpful if you have a large number of contacts.
            – Peter Grill
            Nov 15 at 18:30










          • Since I'm going to share this file, do you know if etoolbox comes with a basic installation? Because I know that tikz does not.
            – Sigur
            Nov 15 at 18:30










          • Yes, etoolbox is in the standard distribution. But, so is tikz so not sure why you think otherwise. Also, have added error checking in the updated version.
            – Peter Grill
            Nov 15 at 18:34








          • 1




            @Sigur: As requested, I have updated it inserts a medskip only between entries. You can replace the medskip with the symbol you desire.
            – Peter Grill
            Nov 16 at 6:39
















          Interesting. In this case, the contacts are accessed via argument value, not via a number, right?
          – Sigur
          Nov 15 at 18:28




          Interesting. In this case, the contacts are accessed via argument value, not via a number, right?
          – Sigur
          Nov 15 at 18:28












          @Sigur: Yes, the first parameter is used as the key to access the information. This is really helpful if you have a large number of contacts.
          – Peter Grill
          Nov 15 at 18:30




          @Sigur: Yes, the first parameter is used as the key to access the information. This is really helpful if you have a large number of contacts.
          – Peter Grill
          Nov 15 at 18:30












          Since I'm going to share this file, do you know if etoolbox comes with a basic installation? Because I know that tikz does not.
          – Sigur
          Nov 15 at 18:30




          Since I'm going to share this file, do you know if etoolbox comes with a basic installation? Because I know that tikz does not.
          – Sigur
          Nov 15 at 18:30












          Yes, etoolbox is in the standard distribution. But, so is tikz so not sure why you think otherwise. Also, have added error checking in the updated version.
          – Peter Grill
          Nov 15 at 18:34






          Yes, etoolbox is in the standard distribution. But, so is tikz so not sure why you think otherwise. Also, have added error checking in the updated version.
          – Peter Grill
          Nov 15 at 18:34






          1




          1




          @Sigur: As requested, I have updated it inserts a medskip only between entries. You can replace the medskip with the symbol you desire.
          – Peter Grill
          Nov 16 at 6:39




          @Sigur: As requested, I have updated it inserts a medskip only between entries. You can replace the medskip with the symbol you desire.
          – Peter Grill
          Nov 16 at 6:39










          up vote
          4
          down vote













          I have made it so that @name[<index>] @work[<index>], and @email[<index>] are arrays, where the index is stepped with every call to information{}{}{}.



          listcontact{<index>} will provide the contact info for the one specified index. In the MWE, I loop through all indices.



          documentclass{article}
          usepackage{pgffor}
          makeatletter
          newcounter{infocnt}
          newcommand{name}[1]{%
          expandafterdefcsname @name[theinfocnt]endcsname{#1}}
          newcommand{work}[1]{%
          expandafterdefcsname @work[theinfocnt]endcsname{#1}}
          newcommand{email}[1]{%
          expandafterdefcsname @email[theinfocnt]endcsname{#1}}
          newcommand{information}[3]{%
          stepcounter{infocnt}%
          name{#1}%
          work{#2}%
          email{#3}%
          }
          newcommandlistcontact[1]{noindent%
          NAME: textbf{csname @name[#1]endcsname}\
          WORK: textbf{csname @work[#1]endcsname}\
          EMAIL: textbf{csname @email[#1]endcsname}par
          vskip 1in
          }
          makeatother
          information{Faa Foo}{Univ. Blah}{goo@goo.com}
          information{XXX}{YYY}{ZZZ@goo.com}
          begin{document}
          foreachx in {1,2,...,theinfocnt}{listcontact{x}}
          end{document}


          enter image description here



          If I had my 'druthers, though, I would input the list all at once, quite simply, with the same output. The listofitems package immediately stores the list as an accessible array:



          documentclass{article}
          usepackage{listofitems}
          newcommandlistcontact[1]{noindent%
          NAME: textbf{contacts[#1,1]}\
          WORK: textbf{contacts[#1,2]}\
          EMAIL: textbf{contacts[#1,3]}par
          vskip 1in
          }
          setsepchar{\/&}
          begin{document}
          readlist*contacts{
          Faa Foo & Univ. Blah & goo@goo.com\
          XXX & YYY & ZZZ@goo.com}
          foreachitemxincontacts{listcontact{xcnt}}

          Here is the email of contact 2: contacts[2,3].
          end{document}


          enter image description here



          With a small supplement from the readarray package, the list of contacts could even be stored in an external file.






          share|improve this answer























          • Very nice, specially since tikz is needed only for the loop.
            – Sigur
            Nov 15 at 18:18










          • @Sigur Oops. I redefined it (didn't see it defined earlier).
            – Steven B. Segletes
            Nov 15 at 18:20












          • No problem, I observed that. Thanks a lot
            – Sigur
            Nov 15 at 18:21










          • Do you know another way to print all without using tikz? Maybe using the value of the counter only? I'm going to share the file and tikz could be not available.
            – Sigur
            Nov 15 at 18:31






          • 1




            @Sigur I changed it to pgffor. However, I also added technique #2, which is far simpler, if you can add all names at once.
            – Steven B. Segletes
            Nov 15 at 18:33















          up vote
          4
          down vote













          I have made it so that @name[<index>] @work[<index>], and @email[<index>] are arrays, where the index is stepped with every call to information{}{}{}.



          listcontact{<index>} will provide the contact info for the one specified index. In the MWE, I loop through all indices.



          documentclass{article}
          usepackage{pgffor}
          makeatletter
          newcounter{infocnt}
          newcommand{name}[1]{%
          expandafterdefcsname @name[theinfocnt]endcsname{#1}}
          newcommand{work}[1]{%
          expandafterdefcsname @work[theinfocnt]endcsname{#1}}
          newcommand{email}[1]{%
          expandafterdefcsname @email[theinfocnt]endcsname{#1}}
          newcommand{information}[3]{%
          stepcounter{infocnt}%
          name{#1}%
          work{#2}%
          email{#3}%
          }
          newcommandlistcontact[1]{noindent%
          NAME: textbf{csname @name[#1]endcsname}\
          WORK: textbf{csname @work[#1]endcsname}\
          EMAIL: textbf{csname @email[#1]endcsname}par
          vskip 1in
          }
          makeatother
          information{Faa Foo}{Univ. Blah}{goo@goo.com}
          information{XXX}{YYY}{ZZZ@goo.com}
          begin{document}
          foreachx in {1,2,...,theinfocnt}{listcontact{x}}
          end{document}


          enter image description here



          If I had my 'druthers, though, I would input the list all at once, quite simply, with the same output. The listofitems package immediately stores the list as an accessible array:



          documentclass{article}
          usepackage{listofitems}
          newcommandlistcontact[1]{noindent%
          NAME: textbf{contacts[#1,1]}\
          WORK: textbf{contacts[#1,2]}\
          EMAIL: textbf{contacts[#1,3]}par
          vskip 1in
          }
          setsepchar{\/&}
          begin{document}
          readlist*contacts{
          Faa Foo & Univ. Blah & goo@goo.com\
          XXX & YYY & ZZZ@goo.com}
          foreachitemxincontacts{listcontact{xcnt}}

          Here is the email of contact 2: contacts[2,3].
          end{document}


          enter image description here



          With a small supplement from the readarray package, the list of contacts could even be stored in an external file.






          share|improve this answer























          • Very nice, specially since tikz is needed only for the loop.
            – Sigur
            Nov 15 at 18:18










          • @Sigur Oops. I redefined it (didn't see it defined earlier).
            – Steven B. Segletes
            Nov 15 at 18:20












          • No problem, I observed that. Thanks a lot
            – Sigur
            Nov 15 at 18:21










          • Do you know another way to print all without using tikz? Maybe using the value of the counter only? I'm going to share the file and tikz could be not available.
            – Sigur
            Nov 15 at 18:31






          • 1




            @Sigur I changed it to pgffor. However, I also added technique #2, which is far simpler, if you can add all names at once.
            – Steven B. Segletes
            Nov 15 at 18:33













          up vote
          4
          down vote










          up vote
          4
          down vote









          I have made it so that @name[<index>] @work[<index>], and @email[<index>] are arrays, where the index is stepped with every call to information{}{}{}.



          listcontact{<index>} will provide the contact info for the one specified index. In the MWE, I loop through all indices.



          documentclass{article}
          usepackage{pgffor}
          makeatletter
          newcounter{infocnt}
          newcommand{name}[1]{%
          expandafterdefcsname @name[theinfocnt]endcsname{#1}}
          newcommand{work}[1]{%
          expandafterdefcsname @work[theinfocnt]endcsname{#1}}
          newcommand{email}[1]{%
          expandafterdefcsname @email[theinfocnt]endcsname{#1}}
          newcommand{information}[3]{%
          stepcounter{infocnt}%
          name{#1}%
          work{#2}%
          email{#3}%
          }
          newcommandlistcontact[1]{noindent%
          NAME: textbf{csname @name[#1]endcsname}\
          WORK: textbf{csname @work[#1]endcsname}\
          EMAIL: textbf{csname @email[#1]endcsname}par
          vskip 1in
          }
          makeatother
          information{Faa Foo}{Univ. Blah}{goo@goo.com}
          information{XXX}{YYY}{ZZZ@goo.com}
          begin{document}
          foreachx in {1,2,...,theinfocnt}{listcontact{x}}
          end{document}


          enter image description here



          If I had my 'druthers, though, I would input the list all at once, quite simply, with the same output. The listofitems package immediately stores the list as an accessible array:



          documentclass{article}
          usepackage{listofitems}
          newcommandlistcontact[1]{noindent%
          NAME: textbf{contacts[#1,1]}\
          WORK: textbf{contacts[#1,2]}\
          EMAIL: textbf{contacts[#1,3]}par
          vskip 1in
          }
          setsepchar{\/&}
          begin{document}
          readlist*contacts{
          Faa Foo & Univ. Blah & goo@goo.com\
          XXX & YYY & ZZZ@goo.com}
          foreachitemxincontacts{listcontact{xcnt}}

          Here is the email of contact 2: contacts[2,3].
          end{document}


          enter image description here



          With a small supplement from the readarray package, the list of contacts could even be stored in an external file.






          share|improve this answer














          I have made it so that @name[<index>] @work[<index>], and @email[<index>] are arrays, where the index is stepped with every call to information{}{}{}.



          listcontact{<index>} will provide the contact info for the one specified index. In the MWE, I loop through all indices.



          documentclass{article}
          usepackage{pgffor}
          makeatletter
          newcounter{infocnt}
          newcommand{name}[1]{%
          expandafterdefcsname @name[theinfocnt]endcsname{#1}}
          newcommand{work}[1]{%
          expandafterdefcsname @work[theinfocnt]endcsname{#1}}
          newcommand{email}[1]{%
          expandafterdefcsname @email[theinfocnt]endcsname{#1}}
          newcommand{information}[3]{%
          stepcounter{infocnt}%
          name{#1}%
          work{#2}%
          email{#3}%
          }
          newcommandlistcontact[1]{noindent%
          NAME: textbf{csname @name[#1]endcsname}\
          WORK: textbf{csname @work[#1]endcsname}\
          EMAIL: textbf{csname @email[#1]endcsname}par
          vskip 1in
          }
          makeatother
          information{Faa Foo}{Univ. Blah}{goo@goo.com}
          information{XXX}{YYY}{ZZZ@goo.com}
          begin{document}
          foreachx in {1,2,...,theinfocnt}{listcontact{x}}
          end{document}


          enter image description here



          If I had my 'druthers, though, I would input the list all at once, quite simply, with the same output. The listofitems package immediately stores the list as an accessible array:



          documentclass{article}
          usepackage{listofitems}
          newcommandlistcontact[1]{noindent%
          NAME: textbf{contacts[#1,1]}\
          WORK: textbf{contacts[#1,2]}\
          EMAIL: textbf{contacts[#1,3]}par
          vskip 1in
          }
          setsepchar{\/&}
          begin{document}
          readlist*contacts{
          Faa Foo & Univ. Blah & goo@goo.com\
          XXX & YYY & ZZZ@goo.com}
          foreachitemxincontacts{listcontact{xcnt}}

          Here is the email of contact 2: contacts[2,3].
          end{document}


          enter image description here



          With a small supplement from the readarray package, the list of contacts could even be stored in an external file.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 15 at 18:42

























          answered Nov 15 at 18:12









          Steven B. Segletes

          151k9189397




          151k9189397












          • Very nice, specially since tikz is needed only for the loop.
            – Sigur
            Nov 15 at 18:18










          • @Sigur Oops. I redefined it (didn't see it defined earlier).
            – Steven B. Segletes
            Nov 15 at 18:20












          • No problem, I observed that. Thanks a lot
            – Sigur
            Nov 15 at 18:21










          • Do you know another way to print all without using tikz? Maybe using the value of the counter only? I'm going to share the file and tikz could be not available.
            – Sigur
            Nov 15 at 18:31






          • 1




            @Sigur I changed it to pgffor. However, I also added technique #2, which is far simpler, if you can add all names at once.
            – Steven B. Segletes
            Nov 15 at 18:33


















          • Very nice, specially since tikz is needed only for the loop.
            – Sigur
            Nov 15 at 18:18










          • @Sigur Oops. I redefined it (didn't see it defined earlier).
            – Steven B. Segletes
            Nov 15 at 18:20












          • No problem, I observed that. Thanks a lot
            – Sigur
            Nov 15 at 18:21










          • Do you know another way to print all without using tikz? Maybe using the value of the counter only? I'm going to share the file and tikz could be not available.
            – Sigur
            Nov 15 at 18:31






          • 1




            @Sigur I changed it to pgffor. However, I also added technique #2, which is far simpler, if you can add all names at once.
            – Steven B. Segletes
            Nov 15 at 18:33
















          Very nice, specially since tikz is needed only for the loop.
          – Sigur
          Nov 15 at 18:18




          Very nice, specially since tikz is needed only for the loop.
          – Sigur
          Nov 15 at 18:18












          @Sigur Oops. I redefined it (didn't see it defined earlier).
          – Steven B. Segletes
          Nov 15 at 18:20






          @Sigur Oops. I redefined it (didn't see it defined earlier).
          – Steven B. Segletes
          Nov 15 at 18:20














          No problem, I observed that. Thanks a lot
          – Sigur
          Nov 15 at 18:21




          No problem, I observed that. Thanks a lot
          – Sigur
          Nov 15 at 18:21












          Do you know another way to print all without using tikz? Maybe using the value of the counter only? I'm going to share the file and tikz could be not available.
          – Sigur
          Nov 15 at 18:31




          Do you know another way to print all without using tikz? Maybe using the value of the counter only? I'm going to share the file and tikz could be not available.
          – Sigur
          Nov 15 at 18:31




          1




          1




          @Sigur I changed it to pgffor. However, I also added technique #2, which is far simpler, if you can add all names at once.
          – Steven B. Segletes
          Nov 15 at 18:33




          @Sigur I changed it to pgffor. However, I also added technique #2, which is far simpler, if you can add all names at once.
          – Steven B. Segletes
          Nov 15 at 18:33










          up vote
          3
          down vote













          This is “property lists” playground. Here I define newcontact for defining a contact with a key-value interface.



          With newcontactscheme one defines different ways to print the data; default is used by listcontact if no optional argument is supplied. In the definition, use getcontact{<key>}{#1} to print the value corresponding to <key> for the current contact, represented by #1.



          documentclass{article}
          usepackage{xparse}

          ExplSyntaxOn

          NewDocumentCommand{newcontact}{mm}
          {% #1 = contact label, #2 = data
          prop_new:c { g_sigur_contact_#1_prop }
          prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
          }
          NewDocumentCommand{listcontact}{O{default}m}
          {
          cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
          __sigur_contact_list:n { #2 }
          }
          NewDocumentCommand{getcontact}{mm}
          {
          sigur_contact_print:nn { #1 } { #2 }
          }
          NewDocumentCommand{newcontactscheme}{m+m}
          {% #1 = scheme name, #2 = definition
          cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
          }
          cs_new_protected:Nn sigur_contact_print:nn
          {
          prop_item:cn { g_sigur_contact_#2_prop } { #1 }
          }
          ExplSyntaxOff

          newcontactscheme{default}{%
          parnoindent
          getcontact{name}{#1}\
          getcontact{work}{#1}\
          getcontact{email}{#1}par
          }
          newcontactscheme{short}{%
          getcontact{name}{#1}, getcontact{email}{#1}%
          }
          newcontactscheme{alternate}{%
          begin{tabular}[t]{@{}l@{ }l@{}}
          Name: & getcontact{name}{#1} \
          Work: & getcontact{work}{#1} \
          Email: & texttt{getcontact{email}{#1}}
          end{tabular}%
          }

          newcontact{foo}{
          name=Faa Foo,
          work=Univ. Blah,
          email=goo@goo.com
          }
          newcontact{xxx}{
          name=XXX,
          work=YYY,
          email=ZZZ@goo.com
          }

          begin{document}

          listcontact{foo}

          medskip

          listcontact{xxx}

          medskip

          Short: listcontact[short]{xxx}

          medskip

          Alternate: listcontact[alternate]{foo}

          end{document}


          enter image description here



          A version that also defines listallcontacts (the optional argument is one of the defined schemes).



          documentclass{article}
          usepackage{xparse}

          ExplSyntaxOn

          NewDocumentCommand{newcontact}{mm}
          {% #1 = contact label, #2 = data
          prop_new:c { g_sigur_contact_#1_prop }
          prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
          seq_gput_right:Nn g_sigur_contact_seq { #1 }
          }
          NewDocumentCommand{listcontact}{O{default}m}
          {
          cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
          __sigur_contact_list:n { #2 }
          }
          NewDocumentCommand{listallcontacts}{O{default}}
          {
          cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
          seq_map_inline:Nn g_sigur_contact_seq
          {
          __sigur_contact_list:n { ##1 } par
          }
          }
          NewDocumentCommand{getcontact}{mm}
          {
          sigur_contact_print:nn { #1 } { #2 }
          }
          NewDocumentCommand{newcontactscheme}{m+m}
          {% #1 = scheme name, #2 = definition
          cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
          }

          seq_new:N g_sigur_contact_seq

          cs_new_protected:Nn sigur_contact_print:nn
          {
          prop_item:cn { g_sigur_contact_#2_prop } { #1 }
          }
          ExplSyntaxOff

          newcontactscheme{default}{%
          parnoindent
          getcontact{name}{#1}\
          getcontact{work}{#1}\
          getcontact{email}{#1}par
          }
          newcontactscheme{short}{%
          getcontact{name}{#1}, getcontact{email}{#1}%
          }
          newcontactscheme{alternate}{%
          begin{tabular}[t]{@{}l@{ }l@{}}
          Name: & getcontact{name}{#1} \
          Work: & getcontact{work}{#1} \
          Email: & texttt{getcontact{email}{#1}}
          end{tabular}%
          }

          newcontact{foo}{
          name=Faa Foo,
          work=Univ. Blah,
          email=goo@goo.com
          }
          newcontact{xxx}{
          name=XXX,
          work=YYY,
          email=ZZZ@goo.com
          }

          begin{document}

          listcontact{foo}

          medskip

          listcontact{xxx}

          medskip

          Short: listcontact[short]{xxx}

          medskip

          Alternate: listcontact[alternate]{foo}

          medskip

          listallcontacts

          medskip

          listallcontacts[short]

          end{document}





          share|improve this answer























          • I never studied or tried to learn xparse. The result is amazing. Nice!
            – Sigur
            Nov 15 at 21:04















          up vote
          3
          down vote













          This is “property lists” playground. Here I define newcontact for defining a contact with a key-value interface.



          With newcontactscheme one defines different ways to print the data; default is used by listcontact if no optional argument is supplied. In the definition, use getcontact{<key>}{#1} to print the value corresponding to <key> for the current contact, represented by #1.



          documentclass{article}
          usepackage{xparse}

          ExplSyntaxOn

          NewDocumentCommand{newcontact}{mm}
          {% #1 = contact label, #2 = data
          prop_new:c { g_sigur_contact_#1_prop }
          prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
          }
          NewDocumentCommand{listcontact}{O{default}m}
          {
          cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
          __sigur_contact_list:n { #2 }
          }
          NewDocumentCommand{getcontact}{mm}
          {
          sigur_contact_print:nn { #1 } { #2 }
          }
          NewDocumentCommand{newcontactscheme}{m+m}
          {% #1 = scheme name, #2 = definition
          cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
          }
          cs_new_protected:Nn sigur_contact_print:nn
          {
          prop_item:cn { g_sigur_contact_#2_prop } { #1 }
          }
          ExplSyntaxOff

          newcontactscheme{default}{%
          parnoindent
          getcontact{name}{#1}\
          getcontact{work}{#1}\
          getcontact{email}{#1}par
          }
          newcontactscheme{short}{%
          getcontact{name}{#1}, getcontact{email}{#1}%
          }
          newcontactscheme{alternate}{%
          begin{tabular}[t]{@{}l@{ }l@{}}
          Name: & getcontact{name}{#1} \
          Work: & getcontact{work}{#1} \
          Email: & texttt{getcontact{email}{#1}}
          end{tabular}%
          }

          newcontact{foo}{
          name=Faa Foo,
          work=Univ. Blah,
          email=goo@goo.com
          }
          newcontact{xxx}{
          name=XXX,
          work=YYY,
          email=ZZZ@goo.com
          }

          begin{document}

          listcontact{foo}

          medskip

          listcontact{xxx}

          medskip

          Short: listcontact[short]{xxx}

          medskip

          Alternate: listcontact[alternate]{foo}

          end{document}


          enter image description here



          A version that also defines listallcontacts (the optional argument is one of the defined schemes).



          documentclass{article}
          usepackage{xparse}

          ExplSyntaxOn

          NewDocumentCommand{newcontact}{mm}
          {% #1 = contact label, #2 = data
          prop_new:c { g_sigur_contact_#1_prop }
          prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
          seq_gput_right:Nn g_sigur_contact_seq { #1 }
          }
          NewDocumentCommand{listcontact}{O{default}m}
          {
          cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
          __sigur_contact_list:n { #2 }
          }
          NewDocumentCommand{listallcontacts}{O{default}}
          {
          cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
          seq_map_inline:Nn g_sigur_contact_seq
          {
          __sigur_contact_list:n { ##1 } par
          }
          }
          NewDocumentCommand{getcontact}{mm}
          {
          sigur_contact_print:nn { #1 } { #2 }
          }
          NewDocumentCommand{newcontactscheme}{m+m}
          {% #1 = scheme name, #2 = definition
          cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
          }

          seq_new:N g_sigur_contact_seq

          cs_new_protected:Nn sigur_contact_print:nn
          {
          prop_item:cn { g_sigur_contact_#2_prop } { #1 }
          }
          ExplSyntaxOff

          newcontactscheme{default}{%
          parnoindent
          getcontact{name}{#1}\
          getcontact{work}{#1}\
          getcontact{email}{#1}par
          }
          newcontactscheme{short}{%
          getcontact{name}{#1}, getcontact{email}{#1}%
          }
          newcontactscheme{alternate}{%
          begin{tabular}[t]{@{}l@{ }l@{}}
          Name: & getcontact{name}{#1} \
          Work: & getcontact{work}{#1} \
          Email: & texttt{getcontact{email}{#1}}
          end{tabular}%
          }

          newcontact{foo}{
          name=Faa Foo,
          work=Univ. Blah,
          email=goo@goo.com
          }
          newcontact{xxx}{
          name=XXX,
          work=YYY,
          email=ZZZ@goo.com
          }

          begin{document}

          listcontact{foo}

          medskip

          listcontact{xxx}

          medskip

          Short: listcontact[short]{xxx}

          medskip

          Alternate: listcontact[alternate]{foo}

          medskip

          listallcontacts

          medskip

          listallcontacts[short]

          end{document}





          share|improve this answer























          • I never studied or tried to learn xparse. The result is amazing. Nice!
            – Sigur
            Nov 15 at 21:04













          up vote
          3
          down vote










          up vote
          3
          down vote









          This is “property lists” playground. Here I define newcontact for defining a contact with a key-value interface.



          With newcontactscheme one defines different ways to print the data; default is used by listcontact if no optional argument is supplied. In the definition, use getcontact{<key>}{#1} to print the value corresponding to <key> for the current contact, represented by #1.



          documentclass{article}
          usepackage{xparse}

          ExplSyntaxOn

          NewDocumentCommand{newcontact}{mm}
          {% #1 = contact label, #2 = data
          prop_new:c { g_sigur_contact_#1_prop }
          prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
          }
          NewDocumentCommand{listcontact}{O{default}m}
          {
          cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
          __sigur_contact_list:n { #2 }
          }
          NewDocumentCommand{getcontact}{mm}
          {
          sigur_contact_print:nn { #1 } { #2 }
          }
          NewDocumentCommand{newcontactscheme}{m+m}
          {% #1 = scheme name, #2 = definition
          cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
          }
          cs_new_protected:Nn sigur_contact_print:nn
          {
          prop_item:cn { g_sigur_contact_#2_prop } { #1 }
          }
          ExplSyntaxOff

          newcontactscheme{default}{%
          parnoindent
          getcontact{name}{#1}\
          getcontact{work}{#1}\
          getcontact{email}{#1}par
          }
          newcontactscheme{short}{%
          getcontact{name}{#1}, getcontact{email}{#1}%
          }
          newcontactscheme{alternate}{%
          begin{tabular}[t]{@{}l@{ }l@{}}
          Name: & getcontact{name}{#1} \
          Work: & getcontact{work}{#1} \
          Email: & texttt{getcontact{email}{#1}}
          end{tabular}%
          }

          newcontact{foo}{
          name=Faa Foo,
          work=Univ. Blah,
          email=goo@goo.com
          }
          newcontact{xxx}{
          name=XXX,
          work=YYY,
          email=ZZZ@goo.com
          }

          begin{document}

          listcontact{foo}

          medskip

          listcontact{xxx}

          medskip

          Short: listcontact[short]{xxx}

          medskip

          Alternate: listcontact[alternate]{foo}

          end{document}


          enter image description here



          A version that also defines listallcontacts (the optional argument is one of the defined schemes).



          documentclass{article}
          usepackage{xparse}

          ExplSyntaxOn

          NewDocumentCommand{newcontact}{mm}
          {% #1 = contact label, #2 = data
          prop_new:c { g_sigur_contact_#1_prop }
          prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
          seq_gput_right:Nn g_sigur_contact_seq { #1 }
          }
          NewDocumentCommand{listcontact}{O{default}m}
          {
          cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
          __sigur_contact_list:n { #2 }
          }
          NewDocumentCommand{listallcontacts}{O{default}}
          {
          cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
          seq_map_inline:Nn g_sigur_contact_seq
          {
          __sigur_contact_list:n { ##1 } par
          }
          }
          NewDocumentCommand{getcontact}{mm}
          {
          sigur_contact_print:nn { #1 } { #2 }
          }
          NewDocumentCommand{newcontactscheme}{m+m}
          {% #1 = scheme name, #2 = definition
          cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
          }

          seq_new:N g_sigur_contact_seq

          cs_new_protected:Nn sigur_contact_print:nn
          {
          prop_item:cn { g_sigur_contact_#2_prop } { #1 }
          }
          ExplSyntaxOff

          newcontactscheme{default}{%
          parnoindent
          getcontact{name}{#1}\
          getcontact{work}{#1}\
          getcontact{email}{#1}par
          }
          newcontactscheme{short}{%
          getcontact{name}{#1}, getcontact{email}{#1}%
          }
          newcontactscheme{alternate}{%
          begin{tabular}[t]{@{}l@{ }l@{}}
          Name: & getcontact{name}{#1} \
          Work: & getcontact{work}{#1} \
          Email: & texttt{getcontact{email}{#1}}
          end{tabular}%
          }

          newcontact{foo}{
          name=Faa Foo,
          work=Univ. Blah,
          email=goo@goo.com
          }
          newcontact{xxx}{
          name=XXX,
          work=YYY,
          email=ZZZ@goo.com
          }

          begin{document}

          listcontact{foo}

          medskip

          listcontact{xxx}

          medskip

          Short: listcontact[short]{xxx}

          medskip

          Alternate: listcontact[alternate]{foo}

          medskip

          listallcontacts

          medskip

          listallcontacts[short]

          end{document}





          share|improve this answer














          This is “property lists” playground. Here I define newcontact for defining a contact with a key-value interface.



          With newcontactscheme one defines different ways to print the data; default is used by listcontact if no optional argument is supplied. In the definition, use getcontact{<key>}{#1} to print the value corresponding to <key> for the current contact, represented by #1.



          documentclass{article}
          usepackage{xparse}

          ExplSyntaxOn

          NewDocumentCommand{newcontact}{mm}
          {% #1 = contact label, #2 = data
          prop_new:c { g_sigur_contact_#1_prop }
          prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
          }
          NewDocumentCommand{listcontact}{O{default}m}
          {
          cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
          __sigur_contact_list:n { #2 }
          }
          NewDocumentCommand{getcontact}{mm}
          {
          sigur_contact_print:nn { #1 } { #2 }
          }
          NewDocumentCommand{newcontactscheme}{m+m}
          {% #1 = scheme name, #2 = definition
          cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
          }
          cs_new_protected:Nn sigur_contact_print:nn
          {
          prop_item:cn { g_sigur_contact_#2_prop } { #1 }
          }
          ExplSyntaxOff

          newcontactscheme{default}{%
          parnoindent
          getcontact{name}{#1}\
          getcontact{work}{#1}\
          getcontact{email}{#1}par
          }
          newcontactscheme{short}{%
          getcontact{name}{#1}, getcontact{email}{#1}%
          }
          newcontactscheme{alternate}{%
          begin{tabular}[t]{@{}l@{ }l@{}}
          Name: & getcontact{name}{#1} \
          Work: & getcontact{work}{#1} \
          Email: & texttt{getcontact{email}{#1}}
          end{tabular}%
          }

          newcontact{foo}{
          name=Faa Foo,
          work=Univ. Blah,
          email=goo@goo.com
          }
          newcontact{xxx}{
          name=XXX,
          work=YYY,
          email=ZZZ@goo.com
          }

          begin{document}

          listcontact{foo}

          medskip

          listcontact{xxx}

          medskip

          Short: listcontact[short]{xxx}

          medskip

          Alternate: listcontact[alternate]{foo}

          end{document}


          enter image description here



          A version that also defines listallcontacts (the optional argument is one of the defined schemes).



          documentclass{article}
          usepackage{xparse}

          ExplSyntaxOn

          NewDocumentCommand{newcontact}{mm}
          {% #1 = contact label, #2 = data
          prop_new:c { g_sigur_contact_#1_prop }
          prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
          seq_gput_right:Nn g_sigur_contact_seq { #1 }
          }
          NewDocumentCommand{listcontact}{O{default}m}
          {
          cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
          __sigur_contact_list:n { #2 }
          }
          NewDocumentCommand{listallcontacts}{O{default}}
          {
          cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
          seq_map_inline:Nn g_sigur_contact_seq
          {
          __sigur_contact_list:n { ##1 } par
          }
          }
          NewDocumentCommand{getcontact}{mm}
          {
          sigur_contact_print:nn { #1 } { #2 }
          }
          NewDocumentCommand{newcontactscheme}{m+m}
          {% #1 = scheme name, #2 = definition
          cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
          }

          seq_new:N g_sigur_contact_seq

          cs_new_protected:Nn sigur_contact_print:nn
          {
          prop_item:cn { g_sigur_contact_#2_prop } { #1 }
          }
          ExplSyntaxOff

          newcontactscheme{default}{%
          parnoindent
          getcontact{name}{#1}\
          getcontact{work}{#1}\
          getcontact{email}{#1}par
          }
          newcontactscheme{short}{%
          getcontact{name}{#1}, getcontact{email}{#1}%
          }
          newcontactscheme{alternate}{%
          begin{tabular}[t]{@{}l@{ }l@{}}
          Name: & getcontact{name}{#1} \
          Work: & getcontact{work}{#1} \
          Email: & texttt{getcontact{email}{#1}}
          end{tabular}%
          }

          newcontact{foo}{
          name=Faa Foo,
          work=Univ. Blah,
          email=goo@goo.com
          }
          newcontact{xxx}{
          name=XXX,
          work=YYY,
          email=ZZZ@goo.com
          }

          begin{document}

          listcontact{foo}

          medskip

          listcontact{xxx}

          medskip

          Short: listcontact[short]{xxx}

          medskip

          Alternate: listcontact[alternate]{foo}

          medskip

          listallcontacts

          medskip

          listallcontacts[short]

          end{document}






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 15 at 21:43

























          answered Nov 15 at 21:01









          egreg

          698k8518573126




          698k8518573126












          • I never studied or tried to learn xparse. The result is amazing. Nice!
            – Sigur
            Nov 15 at 21:04


















          • I never studied or tried to learn xparse. The result is amazing. Nice!
            – Sigur
            Nov 15 at 21:04
















          I never studied or tried to learn xparse. The result is amazing. Nice!
          – Sigur
          Nov 15 at 21:04




          I never studied or tried to learn xparse. The result is amazing. Nice!
          – Sigur
          Nov 15 at 21:04










          up vote
          0
          down vote













          This "answer" does not answer your question.



          A few remarks about the pitfalls of database-management in LaTeX



          A few remarks about database-management in general:



          Usually data is organized in so-called data-bases.



          A data-base could, e.g., be a list of contact-details.



          Each person or organization that you wish to contact might within the data-base be connected to a data-record which holds all the contact-details related to that person/organization.



          Therefore a data-record itself could be organized by means of data-fields whereby each field serves for storing/providing information that belongs to a specific category.



          Thus the logical structure of a data-base could be something like:



          Data-base: contact-details
          ==========================

          Data-record 001:
          ----------------
          Value of data-field "Name":=John Doe
          Value of data-field "Work":=whistle blower
          Value of data-field "E-Mail":=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Name":=Jane Smith
          Value of data-field "Work":=employée at department of alternative facts
          Value of data-field "E-Mail":=AltFacts@fake.email.address

          ...


          You need means




          • both for identifying each record that belongs to a data-base

          • and for keeping the single records that belong to a data-base distinguishable from each other.


          The data-fields "Name" or "Work" or "E-Mail" are not suitable for this purpose.



          E.g., some day there might be records about two different people in the data-base that have the same name.



          Thus in data-base-management, it is common practise to indroduce in the structure of data-records a data-field which for each data-record holds a piece of information which does not occur within the corresponding data-field of any other data-record.



          Usually this data-field is called a "primary key".



          Often this primary-key is just some item of continuous numeration which is obtained by continuously numerating data-records.



          When introducing a primary-key, the data-base "contact details" could look like this:



          Data-base: contact-details
          ==========================

          Data-record 001:
          ----------------
          Value of data-field "Primary Key":=001
          Value of data-field "Name":=John Doe
          Value of data-field "Work":=whistle blower
          Value of data-field "E-Mail":=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Primary Key":=002
          Value of data-field "Name":=Jane Smith
          Value of data-field "Work":=employée at department of alternative facts
          Value of data-field "E-Mail":=AltFacts@fake.email.address


          When doing this, you can - besides the single data-records - also maintain




          • a list of primary-keys belonging to the data-base an

          • a counter denoting the amount of records belonging to the data-base:


           



          Data-base: contact-details
          ==========================

          Amount of data-records: 2
          List of primary-keys: {001}, {002}

          Data-record 001:
          ----------------
          Value of data-field "Primary Key":=001
          Value of data-field "Name":=John Doe
          Value of data-field "Work":=whistle blower
          Value of data-field "E-Mail":=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Primary Key":=002
          Value of data-field "Name":=Jane Smith
          Value of data-field "Work":=employée at department of alternative facts
          Value of data-field "E-Mail":=AltFacts@fake.email.address


          The list of primary-keys would be of special interest for sorting out specific data-records:



          Assume you wish to retrieve the e-mail-address of Jane Smith:



          In terms of pseudo-code, you would do this via a directive like:



          Iterate on that list of primary-keys that belongs to
          the data-base "contact-details" as follows:

          In each iteration "look" at the value of the data-field "Name"
          of that data-record whose data-field "Primary Key" equals the
          current list element.
          If that value equals "Jane Smith", print out the value of the
          data-field "E-Mail" of that data-record.


          Pitfalls related to (La)TeX:



          When implementing such things in terms of (La)TeX, you will encounter a few problems which have to do with the fact that (La)TeX is a macro-language which does some pre-processing of input in terms of reading and tokenizing input:



          For example, curly braces ({ and }) have a specific meaning in LaTeX and usually each opening-brace must habe a matching closing-brace and vice versa.



          For example, the percent-character (%) has a specific meaning in LaTeX.



          But according to RFC 2822 e-mail-adresses may contain unbalanced curly braces and percent-characters.



          Therefore maintaining such entries via a data-base that is provided in terms of (La)TeX-input might be related to circumstances which the not-so experienced user might see as problems.



          E.g., Alt}Fa%c#1ts@fake.email.address would be a nice e-mail-address.



          But how to get the value Alt}Fa%c#1ts@fake.email.address into a data-record's data-field "E-Mail" in case the data-base in question is maintained in (La)TeX?



          At first glimpse you could do it by means of macros that deliver the desired symbols in question:



          Something like:



          Value of data-field "E-Mail":=Altleftbrace Fatextpercent chash1ts@fake.email.address


          Also the names of people/organizations might contain characters/symbols which the input-encoding in which the (La)TeX-file is written does not contain.



          Assume one of the persons whose contact-details are to be maintained has the name Alaïa Maëlys Gambolpütty while the data-base is written in a (La)TeX-input-file that is encoded in ASCII.

          In such a case you must do it in terms of control-sequence-tokens whose names are formed by characters within the range of the input-encoding.



          But such control-sequences make sorting out specific data-records difficult.



          Therefore it might be a good idea to maintain each piece of data twice:



          Once written only by means of characters of the input-encoding in question.

          Once written in a way where also LaTeX-control-sequences that deliver the desired characters/symbols may occur:



          Data-base: contact-details
          ==========================

          Amount of data-records: 3
          List of primary-keys: {001}, {002}, {003}

          Data-record 001:
          ----------------
          Value of data-field "Primary Key":=001
          Value of data-field "Name" in input-encoding-representation:=John Doe
          Value of data-field "Name" in LaTeX-representation:=John Doe
          Value of data-field "Work" in input-encoding-representation:=whistle blower
          Value of data-field "Work" in LaTeX-representation:=whistle blower
          Value of data-field "E-Mail" in input-encoding-representation:=Whistle@fake.email.address
          Value of data-field "E-Mail" in LaTeX-representation:=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Primary Key":=002
          Value of data-field "Name" in input-encoding-representation:=Jane Smith
          Value of data-field "Name" in LaTeX-representation:=Jane Smith
          Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
          Value of data-field "Work" in LaTeX-representation:=employ'ee at department of alternative facts
          Value of data-field "E-Mail" in input-encoding-representation:=AltFacts@fake.email.address
          Value of data-field "E-Mail" in LaTeX-representation:=AltFacts@fake.email.address

          Data-record 003:
          ----------------
          Value of data-field "Primary Key":=003
          Value of data-field "Name" in input-encoding-representation:=Alaia Maelys Gambolpuetty
          Value of data-field "Name" in LaTeX-representation:=Ala"{i}a Ma"{e}lys Gambolp"{u}tty
          Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
          Value of data-field "Work" in LaTeX-representation:=employée at department of alternative facts
          Value of data-field "E-Mail" in input-encoding-representation:=Alt}Fa%c#1ts@fake.email.address
          Value of data-field "E-Mail" in LaTeX-representation:=Altleftbrace Fatextpercent chash1ts@fake.email.address

          ...


          With such an approach you could implement an interface where searching and sorting out takes place in terms of input-encoding-representation and delivers data in terms of LaTeX-representation.



          With such an interface, one stage would always include reading and tokenizing the input-encoding-representations under verbatim-catcode-régime.



          This is feasible but makes using the macros that form the interface




          • within pure-expansion-contexts impossible.

          • within the definition-texts of other macros cumbersome.


          With such an interface, it would also be a good idea to have everything that denotes names of databases or names of data-fields or values in input-encoding-representation evaluate to characters of the input-encoding.



          Therefore for proper error-checking a routine would be useful which does fully evaluate/expand arguments and then does check whether the expansion-result does hold character-tokens obeying the verbatim-catcode-régime only.



          Full evaluation/expansion of an argument that might hold arbitrary tokens is already a nice problem.



          An easy approach would be using edef.

          For one thing this also would break expandability of the interface.

          For another thing edef is not totally safe with arbitrary tokens.

          E.g., look at



          edeftest{%
          Where does the definition text
          stop?iffalse{fi Here?} Or Here?{iffalse}fi
          }


          I think a minimalist interface for some sort of database-management is feasible in LaTeX – with things like:



          NewInitializedDataRecord{<Primary Key>}%
          {<Name>}%
          {<Work>}%
          {<EMail>}%


          NewEmptyDataRecord{<Primary Key>}
          AddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}{<Value>}%
          VerbatimizedAddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}|<Value>|% <- verbatim-arg
          (extraction of verbatimized values of data-fields via scantokens...)

          PrintFieldValueFromDataRecord{<Primary Key>}{<Name of data-field>}

          PrintDataRecord{<Primary Key>}

          PrintAllDataRecords

          PrintAllDataRecordsWithSpecificDatFieldValue{<Name of data-field>}{<Specific Value>}


          But before going into details, specification about the tokens that might form values of data-fields and about their treatment when comparing values of data-fields is needed.






          share|improve this answer























          • I am not sure if I understood your comments. Anyway, thanks for attention. Let me inform that the contacts come from authors of a paper, so I think that two exactly equal names could happen rarely.
            – Sigur
            Nov 16 at 18:13










          • Your question actually is about some sort of whatsoever minimalist database-management. :-) I extended my answer in the hope of pointing out some of the pitfalls related to whatsoever minimalist database-management in terms of a macro language. :-)
            – Ulrich Diez
            Nov 16 at 21:29










          • Well, thanks for your work. But I confess that I have no idea how to understand it... lol
            – Sigur
            Nov 16 at 21:33










          • I think you want to say “From relational algebra we know that it is not a good idea to assign to each data-record its own unique primary-key as a data-field of its own of that data-record.”.
            – egreg
            Nov 16 at 21:48










          • @UlrichDiez The formulation is way better now. For the same reason I assigned a label to each contact.
            – egreg
            Nov 16 at 22:31















          up vote
          0
          down vote













          This "answer" does not answer your question.



          A few remarks about the pitfalls of database-management in LaTeX



          A few remarks about database-management in general:



          Usually data is organized in so-called data-bases.



          A data-base could, e.g., be a list of contact-details.



          Each person or organization that you wish to contact might within the data-base be connected to a data-record which holds all the contact-details related to that person/organization.



          Therefore a data-record itself could be organized by means of data-fields whereby each field serves for storing/providing information that belongs to a specific category.



          Thus the logical structure of a data-base could be something like:



          Data-base: contact-details
          ==========================

          Data-record 001:
          ----------------
          Value of data-field "Name":=John Doe
          Value of data-field "Work":=whistle blower
          Value of data-field "E-Mail":=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Name":=Jane Smith
          Value of data-field "Work":=employée at department of alternative facts
          Value of data-field "E-Mail":=AltFacts@fake.email.address

          ...


          You need means




          • both for identifying each record that belongs to a data-base

          • and for keeping the single records that belong to a data-base distinguishable from each other.


          The data-fields "Name" or "Work" or "E-Mail" are not suitable for this purpose.



          E.g., some day there might be records about two different people in the data-base that have the same name.



          Thus in data-base-management, it is common practise to indroduce in the structure of data-records a data-field which for each data-record holds a piece of information which does not occur within the corresponding data-field of any other data-record.



          Usually this data-field is called a "primary key".



          Often this primary-key is just some item of continuous numeration which is obtained by continuously numerating data-records.



          When introducing a primary-key, the data-base "contact details" could look like this:



          Data-base: contact-details
          ==========================

          Data-record 001:
          ----------------
          Value of data-field "Primary Key":=001
          Value of data-field "Name":=John Doe
          Value of data-field "Work":=whistle blower
          Value of data-field "E-Mail":=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Primary Key":=002
          Value of data-field "Name":=Jane Smith
          Value of data-field "Work":=employée at department of alternative facts
          Value of data-field "E-Mail":=AltFacts@fake.email.address


          When doing this, you can - besides the single data-records - also maintain




          • a list of primary-keys belonging to the data-base an

          • a counter denoting the amount of records belonging to the data-base:


           



          Data-base: contact-details
          ==========================

          Amount of data-records: 2
          List of primary-keys: {001}, {002}

          Data-record 001:
          ----------------
          Value of data-field "Primary Key":=001
          Value of data-field "Name":=John Doe
          Value of data-field "Work":=whistle blower
          Value of data-field "E-Mail":=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Primary Key":=002
          Value of data-field "Name":=Jane Smith
          Value of data-field "Work":=employée at department of alternative facts
          Value of data-field "E-Mail":=AltFacts@fake.email.address


          The list of primary-keys would be of special interest for sorting out specific data-records:



          Assume you wish to retrieve the e-mail-address of Jane Smith:



          In terms of pseudo-code, you would do this via a directive like:



          Iterate on that list of primary-keys that belongs to
          the data-base "contact-details" as follows:

          In each iteration "look" at the value of the data-field "Name"
          of that data-record whose data-field "Primary Key" equals the
          current list element.
          If that value equals "Jane Smith", print out the value of the
          data-field "E-Mail" of that data-record.


          Pitfalls related to (La)TeX:



          When implementing such things in terms of (La)TeX, you will encounter a few problems which have to do with the fact that (La)TeX is a macro-language which does some pre-processing of input in terms of reading and tokenizing input:



          For example, curly braces ({ and }) have a specific meaning in LaTeX and usually each opening-brace must habe a matching closing-brace and vice versa.



          For example, the percent-character (%) has a specific meaning in LaTeX.



          But according to RFC 2822 e-mail-adresses may contain unbalanced curly braces and percent-characters.



          Therefore maintaining such entries via a data-base that is provided in terms of (La)TeX-input might be related to circumstances which the not-so experienced user might see as problems.



          E.g., Alt}Fa%c#1ts@fake.email.address would be a nice e-mail-address.



          But how to get the value Alt}Fa%c#1ts@fake.email.address into a data-record's data-field "E-Mail" in case the data-base in question is maintained in (La)TeX?



          At first glimpse you could do it by means of macros that deliver the desired symbols in question:



          Something like:



          Value of data-field "E-Mail":=Altleftbrace Fatextpercent chash1ts@fake.email.address


          Also the names of people/organizations might contain characters/symbols which the input-encoding in which the (La)TeX-file is written does not contain.



          Assume one of the persons whose contact-details are to be maintained has the name Alaïa Maëlys Gambolpütty while the data-base is written in a (La)TeX-input-file that is encoded in ASCII.

          In such a case you must do it in terms of control-sequence-tokens whose names are formed by characters within the range of the input-encoding.



          But such control-sequences make sorting out specific data-records difficult.



          Therefore it might be a good idea to maintain each piece of data twice:



          Once written only by means of characters of the input-encoding in question.

          Once written in a way where also LaTeX-control-sequences that deliver the desired characters/symbols may occur:



          Data-base: contact-details
          ==========================

          Amount of data-records: 3
          List of primary-keys: {001}, {002}, {003}

          Data-record 001:
          ----------------
          Value of data-field "Primary Key":=001
          Value of data-field "Name" in input-encoding-representation:=John Doe
          Value of data-field "Name" in LaTeX-representation:=John Doe
          Value of data-field "Work" in input-encoding-representation:=whistle blower
          Value of data-field "Work" in LaTeX-representation:=whistle blower
          Value of data-field "E-Mail" in input-encoding-representation:=Whistle@fake.email.address
          Value of data-field "E-Mail" in LaTeX-representation:=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Primary Key":=002
          Value of data-field "Name" in input-encoding-representation:=Jane Smith
          Value of data-field "Name" in LaTeX-representation:=Jane Smith
          Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
          Value of data-field "Work" in LaTeX-representation:=employ'ee at department of alternative facts
          Value of data-field "E-Mail" in input-encoding-representation:=AltFacts@fake.email.address
          Value of data-field "E-Mail" in LaTeX-representation:=AltFacts@fake.email.address

          Data-record 003:
          ----------------
          Value of data-field "Primary Key":=003
          Value of data-field "Name" in input-encoding-representation:=Alaia Maelys Gambolpuetty
          Value of data-field "Name" in LaTeX-representation:=Ala"{i}a Ma"{e}lys Gambolp"{u}tty
          Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
          Value of data-field "Work" in LaTeX-representation:=employée at department of alternative facts
          Value of data-field "E-Mail" in input-encoding-representation:=Alt}Fa%c#1ts@fake.email.address
          Value of data-field "E-Mail" in LaTeX-representation:=Altleftbrace Fatextpercent chash1ts@fake.email.address

          ...


          With such an approach you could implement an interface where searching and sorting out takes place in terms of input-encoding-representation and delivers data in terms of LaTeX-representation.



          With such an interface, one stage would always include reading and tokenizing the input-encoding-representations under verbatim-catcode-régime.



          This is feasible but makes using the macros that form the interface




          • within pure-expansion-contexts impossible.

          • within the definition-texts of other macros cumbersome.


          With such an interface, it would also be a good idea to have everything that denotes names of databases or names of data-fields or values in input-encoding-representation evaluate to characters of the input-encoding.



          Therefore for proper error-checking a routine would be useful which does fully evaluate/expand arguments and then does check whether the expansion-result does hold character-tokens obeying the verbatim-catcode-régime only.



          Full evaluation/expansion of an argument that might hold arbitrary tokens is already a nice problem.



          An easy approach would be using edef.

          For one thing this also would break expandability of the interface.

          For another thing edef is not totally safe with arbitrary tokens.

          E.g., look at



          edeftest{%
          Where does the definition text
          stop?iffalse{fi Here?} Or Here?{iffalse}fi
          }


          I think a minimalist interface for some sort of database-management is feasible in LaTeX – with things like:



          NewInitializedDataRecord{<Primary Key>}%
          {<Name>}%
          {<Work>}%
          {<EMail>}%


          NewEmptyDataRecord{<Primary Key>}
          AddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}{<Value>}%
          VerbatimizedAddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}|<Value>|% <- verbatim-arg
          (extraction of verbatimized values of data-fields via scantokens...)

          PrintFieldValueFromDataRecord{<Primary Key>}{<Name of data-field>}

          PrintDataRecord{<Primary Key>}

          PrintAllDataRecords

          PrintAllDataRecordsWithSpecificDatFieldValue{<Name of data-field>}{<Specific Value>}


          But before going into details, specification about the tokens that might form values of data-fields and about their treatment when comparing values of data-fields is needed.






          share|improve this answer























          • I am not sure if I understood your comments. Anyway, thanks for attention. Let me inform that the contacts come from authors of a paper, so I think that two exactly equal names could happen rarely.
            – Sigur
            Nov 16 at 18:13










          • Your question actually is about some sort of whatsoever minimalist database-management. :-) I extended my answer in the hope of pointing out some of the pitfalls related to whatsoever minimalist database-management in terms of a macro language. :-)
            – Ulrich Diez
            Nov 16 at 21:29










          • Well, thanks for your work. But I confess that I have no idea how to understand it... lol
            – Sigur
            Nov 16 at 21:33










          • I think you want to say “From relational algebra we know that it is not a good idea to assign to each data-record its own unique primary-key as a data-field of its own of that data-record.”.
            – egreg
            Nov 16 at 21:48










          • @UlrichDiez The formulation is way better now. For the same reason I assigned a label to each contact.
            – egreg
            Nov 16 at 22:31













          up vote
          0
          down vote










          up vote
          0
          down vote









          This "answer" does not answer your question.



          A few remarks about the pitfalls of database-management in LaTeX



          A few remarks about database-management in general:



          Usually data is organized in so-called data-bases.



          A data-base could, e.g., be a list of contact-details.



          Each person or organization that you wish to contact might within the data-base be connected to a data-record which holds all the contact-details related to that person/organization.



          Therefore a data-record itself could be organized by means of data-fields whereby each field serves for storing/providing information that belongs to a specific category.



          Thus the logical structure of a data-base could be something like:



          Data-base: contact-details
          ==========================

          Data-record 001:
          ----------------
          Value of data-field "Name":=John Doe
          Value of data-field "Work":=whistle blower
          Value of data-field "E-Mail":=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Name":=Jane Smith
          Value of data-field "Work":=employée at department of alternative facts
          Value of data-field "E-Mail":=AltFacts@fake.email.address

          ...


          You need means




          • both for identifying each record that belongs to a data-base

          • and for keeping the single records that belong to a data-base distinguishable from each other.


          The data-fields "Name" or "Work" or "E-Mail" are not suitable for this purpose.



          E.g., some day there might be records about two different people in the data-base that have the same name.



          Thus in data-base-management, it is common practise to indroduce in the structure of data-records a data-field which for each data-record holds a piece of information which does not occur within the corresponding data-field of any other data-record.



          Usually this data-field is called a "primary key".



          Often this primary-key is just some item of continuous numeration which is obtained by continuously numerating data-records.



          When introducing a primary-key, the data-base "contact details" could look like this:



          Data-base: contact-details
          ==========================

          Data-record 001:
          ----------------
          Value of data-field "Primary Key":=001
          Value of data-field "Name":=John Doe
          Value of data-field "Work":=whistle blower
          Value of data-field "E-Mail":=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Primary Key":=002
          Value of data-field "Name":=Jane Smith
          Value of data-field "Work":=employée at department of alternative facts
          Value of data-field "E-Mail":=AltFacts@fake.email.address


          When doing this, you can - besides the single data-records - also maintain




          • a list of primary-keys belonging to the data-base an

          • a counter denoting the amount of records belonging to the data-base:


           



          Data-base: contact-details
          ==========================

          Amount of data-records: 2
          List of primary-keys: {001}, {002}

          Data-record 001:
          ----------------
          Value of data-field "Primary Key":=001
          Value of data-field "Name":=John Doe
          Value of data-field "Work":=whistle blower
          Value of data-field "E-Mail":=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Primary Key":=002
          Value of data-field "Name":=Jane Smith
          Value of data-field "Work":=employée at department of alternative facts
          Value of data-field "E-Mail":=AltFacts@fake.email.address


          The list of primary-keys would be of special interest for sorting out specific data-records:



          Assume you wish to retrieve the e-mail-address of Jane Smith:



          In terms of pseudo-code, you would do this via a directive like:



          Iterate on that list of primary-keys that belongs to
          the data-base "contact-details" as follows:

          In each iteration "look" at the value of the data-field "Name"
          of that data-record whose data-field "Primary Key" equals the
          current list element.
          If that value equals "Jane Smith", print out the value of the
          data-field "E-Mail" of that data-record.


          Pitfalls related to (La)TeX:



          When implementing such things in terms of (La)TeX, you will encounter a few problems which have to do with the fact that (La)TeX is a macro-language which does some pre-processing of input in terms of reading and tokenizing input:



          For example, curly braces ({ and }) have a specific meaning in LaTeX and usually each opening-brace must habe a matching closing-brace and vice versa.



          For example, the percent-character (%) has a specific meaning in LaTeX.



          But according to RFC 2822 e-mail-adresses may contain unbalanced curly braces and percent-characters.



          Therefore maintaining such entries via a data-base that is provided in terms of (La)TeX-input might be related to circumstances which the not-so experienced user might see as problems.



          E.g., Alt}Fa%c#1ts@fake.email.address would be a nice e-mail-address.



          But how to get the value Alt}Fa%c#1ts@fake.email.address into a data-record's data-field "E-Mail" in case the data-base in question is maintained in (La)TeX?



          At first glimpse you could do it by means of macros that deliver the desired symbols in question:



          Something like:



          Value of data-field "E-Mail":=Altleftbrace Fatextpercent chash1ts@fake.email.address


          Also the names of people/organizations might contain characters/symbols which the input-encoding in which the (La)TeX-file is written does not contain.



          Assume one of the persons whose contact-details are to be maintained has the name Alaïa Maëlys Gambolpütty while the data-base is written in a (La)TeX-input-file that is encoded in ASCII.

          In such a case you must do it in terms of control-sequence-tokens whose names are formed by characters within the range of the input-encoding.



          But such control-sequences make sorting out specific data-records difficult.



          Therefore it might be a good idea to maintain each piece of data twice:



          Once written only by means of characters of the input-encoding in question.

          Once written in a way where also LaTeX-control-sequences that deliver the desired characters/symbols may occur:



          Data-base: contact-details
          ==========================

          Amount of data-records: 3
          List of primary-keys: {001}, {002}, {003}

          Data-record 001:
          ----------------
          Value of data-field "Primary Key":=001
          Value of data-field "Name" in input-encoding-representation:=John Doe
          Value of data-field "Name" in LaTeX-representation:=John Doe
          Value of data-field "Work" in input-encoding-representation:=whistle blower
          Value of data-field "Work" in LaTeX-representation:=whistle blower
          Value of data-field "E-Mail" in input-encoding-representation:=Whistle@fake.email.address
          Value of data-field "E-Mail" in LaTeX-representation:=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Primary Key":=002
          Value of data-field "Name" in input-encoding-representation:=Jane Smith
          Value of data-field "Name" in LaTeX-representation:=Jane Smith
          Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
          Value of data-field "Work" in LaTeX-representation:=employ'ee at department of alternative facts
          Value of data-field "E-Mail" in input-encoding-representation:=AltFacts@fake.email.address
          Value of data-field "E-Mail" in LaTeX-representation:=AltFacts@fake.email.address

          Data-record 003:
          ----------------
          Value of data-field "Primary Key":=003
          Value of data-field "Name" in input-encoding-representation:=Alaia Maelys Gambolpuetty
          Value of data-field "Name" in LaTeX-representation:=Ala"{i}a Ma"{e}lys Gambolp"{u}tty
          Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
          Value of data-field "Work" in LaTeX-representation:=employée at department of alternative facts
          Value of data-field "E-Mail" in input-encoding-representation:=Alt}Fa%c#1ts@fake.email.address
          Value of data-field "E-Mail" in LaTeX-representation:=Altleftbrace Fatextpercent chash1ts@fake.email.address

          ...


          With such an approach you could implement an interface where searching and sorting out takes place in terms of input-encoding-representation and delivers data in terms of LaTeX-representation.



          With such an interface, one stage would always include reading and tokenizing the input-encoding-representations under verbatim-catcode-régime.



          This is feasible but makes using the macros that form the interface




          • within pure-expansion-contexts impossible.

          • within the definition-texts of other macros cumbersome.


          With such an interface, it would also be a good idea to have everything that denotes names of databases or names of data-fields or values in input-encoding-representation evaluate to characters of the input-encoding.



          Therefore for proper error-checking a routine would be useful which does fully evaluate/expand arguments and then does check whether the expansion-result does hold character-tokens obeying the verbatim-catcode-régime only.



          Full evaluation/expansion of an argument that might hold arbitrary tokens is already a nice problem.



          An easy approach would be using edef.

          For one thing this also would break expandability of the interface.

          For another thing edef is not totally safe with arbitrary tokens.

          E.g., look at



          edeftest{%
          Where does the definition text
          stop?iffalse{fi Here?} Or Here?{iffalse}fi
          }


          I think a minimalist interface for some sort of database-management is feasible in LaTeX – with things like:



          NewInitializedDataRecord{<Primary Key>}%
          {<Name>}%
          {<Work>}%
          {<EMail>}%


          NewEmptyDataRecord{<Primary Key>}
          AddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}{<Value>}%
          VerbatimizedAddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}|<Value>|% <- verbatim-arg
          (extraction of verbatimized values of data-fields via scantokens...)

          PrintFieldValueFromDataRecord{<Primary Key>}{<Name of data-field>}

          PrintDataRecord{<Primary Key>}

          PrintAllDataRecords

          PrintAllDataRecordsWithSpecificDatFieldValue{<Name of data-field>}{<Specific Value>}


          But before going into details, specification about the tokens that might form values of data-fields and about their treatment when comparing values of data-fields is needed.






          share|improve this answer














          This "answer" does not answer your question.



          A few remarks about the pitfalls of database-management in LaTeX



          A few remarks about database-management in general:



          Usually data is organized in so-called data-bases.



          A data-base could, e.g., be a list of contact-details.



          Each person or organization that you wish to contact might within the data-base be connected to a data-record which holds all the contact-details related to that person/organization.



          Therefore a data-record itself could be organized by means of data-fields whereby each field serves for storing/providing information that belongs to a specific category.



          Thus the logical structure of a data-base could be something like:



          Data-base: contact-details
          ==========================

          Data-record 001:
          ----------------
          Value of data-field "Name":=John Doe
          Value of data-field "Work":=whistle blower
          Value of data-field "E-Mail":=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Name":=Jane Smith
          Value of data-field "Work":=employée at department of alternative facts
          Value of data-field "E-Mail":=AltFacts@fake.email.address

          ...


          You need means




          • both for identifying each record that belongs to a data-base

          • and for keeping the single records that belong to a data-base distinguishable from each other.


          The data-fields "Name" or "Work" or "E-Mail" are not suitable for this purpose.



          E.g., some day there might be records about two different people in the data-base that have the same name.



          Thus in data-base-management, it is common practise to indroduce in the structure of data-records a data-field which for each data-record holds a piece of information which does not occur within the corresponding data-field of any other data-record.



          Usually this data-field is called a "primary key".



          Often this primary-key is just some item of continuous numeration which is obtained by continuously numerating data-records.



          When introducing a primary-key, the data-base "contact details" could look like this:



          Data-base: contact-details
          ==========================

          Data-record 001:
          ----------------
          Value of data-field "Primary Key":=001
          Value of data-field "Name":=John Doe
          Value of data-field "Work":=whistle blower
          Value of data-field "E-Mail":=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Primary Key":=002
          Value of data-field "Name":=Jane Smith
          Value of data-field "Work":=employée at department of alternative facts
          Value of data-field "E-Mail":=AltFacts@fake.email.address


          When doing this, you can - besides the single data-records - also maintain




          • a list of primary-keys belonging to the data-base an

          • a counter denoting the amount of records belonging to the data-base:


           



          Data-base: contact-details
          ==========================

          Amount of data-records: 2
          List of primary-keys: {001}, {002}

          Data-record 001:
          ----------------
          Value of data-field "Primary Key":=001
          Value of data-field "Name":=John Doe
          Value of data-field "Work":=whistle blower
          Value of data-field "E-Mail":=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Primary Key":=002
          Value of data-field "Name":=Jane Smith
          Value of data-field "Work":=employée at department of alternative facts
          Value of data-field "E-Mail":=AltFacts@fake.email.address


          The list of primary-keys would be of special interest for sorting out specific data-records:



          Assume you wish to retrieve the e-mail-address of Jane Smith:



          In terms of pseudo-code, you would do this via a directive like:



          Iterate on that list of primary-keys that belongs to
          the data-base "contact-details" as follows:

          In each iteration "look" at the value of the data-field "Name"
          of that data-record whose data-field "Primary Key" equals the
          current list element.
          If that value equals "Jane Smith", print out the value of the
          data-field "E-Mail" of that data-record.


          Pitfalls related to (La)TeX:



          When implementing such things in terms of (La)TeX, you will encounter a few problems which have to do with the fact that (La)TeX is a macro-language which does some pre-processing of input in terms of reading and tokenizing input:



          For example, curly braces ({ and }) have a specific meaning in LaTeX and usually each opening-brace must habe a matching closing-brace and vice versa.



          For example, the percent-character (%) has a specific meaning in LaTeX.



          But according to RFC 2822 e-mail-adresses may contain unbalanced curly braces and percent-characters.



          Therefore maintaining such entries via a data-base that is provided in terms of (La)TeX-input might be related to circumstances which the not-so experienced user might see as problems.



          E.g., Alt}Fa%c#1ts@fake.email.address would be a nice e-mail-address.



          But how to get the value Alt}Fa%c#1ts@fake.email.address into a data-record's data-field "E-Mail" in case the data-base in question is maintained in (La)TeX?



          At first glimpse you could do it by means of macros that deliver the desired symbols in question:



          Something like:



          Value of data-field "E-Mail":=Altleftbrace Fatextpercent chash1ts@fake.email.address


          Also the names of people/organizations might contain characters/symbols which the input-encoding in which the (La)TeX-file is written does not contain.



          Assume one of the persons whose contact-details are to be maintained has the name Alaïa Maëlys Gambolpütty while the data-base is written in a (La)TeX-input-file that is encoded in ASCII.

          In such a case you must do it in terms of control-sequence-tokens whose names are formed by characters within the range of the input-encoding.



          But such control-sequences make sorting out specific data-records difficult.



          Therefore it might be a good idea to maintain each piece of data twice:



          Once written only by means of characters of the input-encoding in question.

          Once written in a way where also LaTeX-control-sequences that deliver the desired characters/symbols may occur:



          Data-base: contact-details
          ==========================

          Amount of data-records: 3
          List of primary-keys: {001}, {002}, {003}

          Data-record 001:
          ----------------
          Value of data-field "Primary Key":=001
          Value of data-field "Name" in input-encoding-representation:=John Doe
          Value of data-field "Name" in LaTeX-representation:=John Doe
          Value of data-field "Work" in input-encoding-representation:=whistle blower
          Value of data-field "Work" in LaTeX-representation:=whistle blower
          Value of data-field "E-Mail" in input-encoding-representation:=Whistle@fake.email.address
          Value of data-field "E-Mail" in LaTeX-representation:=Whistle@fake.email.address

          Data-record 002:
          ----------------
          Value of data-field "Primary Key":=002
          Value of data-field "Name" in input-encoding-representation:=Jane Smith
          Value of data-field "Name" in LaTeX-representation:=Jane Smith
          Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
          Value of data-field "Work" in LaTeX-representation:=employ'ee at department of alternative facts
          Value of data-field "E-Mail" in input-encoding-representation:=AltFacts@fake.email.address
          Value of data-field "E-Mail" in LaTeX-representation:=AltFacts@fake.email.address

          Data-record 003:
          ----------------
          Value of data-field "Primary Key":=003
          Value of data-field "Name" in input-encoding-representation:=Alaia Maelys Gambolpuetty
          Value of data-field "Name" in LaTeX-representation:=Ala"{i}a Ma"{e}lys Gambolp"{u}tty
          Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
          Value of data-field "Work" in LaTeX-representation:=employée at department of alternative facts
          Value of data-field "E-Mail" in input-encoding-representation:=Alt}Fa%c#1ts@fake.email.address
          Value of data-field "E-Mail" in LaTeX-representation:=Altleftbrace Fatextpercent chash1ts@fake.email.address

          ...


          With such an approach you could implement an interface where searching and sorting out takes place in terms of input-encoding-representation and delivers data in terms of LaTeX-representation.



          With such an interface, one stage would always include reading and tokenizing the input-encoding-representations under verbatim-catcode-régime.



          This is feasible but makes using the macros that form the interface




          • within pure-expansion-contexts impossible.

          • within the definition-texts of other macros cumbersome.


          With such an interface, it would also be a good idea to have everything that denotes names of databases or names of data-fields or values in input-encoding-representation evaluate to characters of the input-encoding.



          Therefore for proper error-checking a routine would be useful which does fully evaluate/expand arguments and then does check whether the expansion-result does hold character-tokens obeying the verbatim-catcode-régime only.



          Full evaluation/expansion of an argument that might hold arbitrary tokens is already a nice problem.



          An easy approach would be using edef.

          For one thing this also would break expandability of the interface.

          For another thing edef is not totally safe with arbitrary tokens.

          E.g., look at



          edeftest{%
          Where does the definition text
          stop?iffalse{fi Here?} Or Here?{iffalse}fi
          }


          I think a minimalist interface for some sort of database-management is feasible in LaTeX – with things like:



          NewInitializedDataRecord{<Primary Key>}%
          {<Name>}%
          {<Work>}%
          {<EMail>}%


          NewEmptyDataRecord{<Primary Key>}
          AddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}{<Value>}%
          VerbatimizedAddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}|<Value>|% <- verbatim-arg
          (extraction of verbatimized values of data-fields via scantokens...)

          PrintFieldValueFromDataRecord{<Primary Key>}{<Name of data-field>}

          PrintDataRecord{<Primary Key>}

          PrintAllDataRecords

          PrintAllDataRecordsWithSpecificDatFieldValue{<Name of data-field>}{<Specific Value>}


          But before going into details, specification about the tokens that might form values of data-fields and about their treatment when comparing values of data-fields is needed.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 18 at 17:34

























          answered Nov 16 at 17:55









          Ulrich Diez

          3,745515




          3,745515












          • I am not sure if I understood your comments. Anyway, thanks for attention. Let me inform that the contacts come from authors of a paper, so I think that two exactly equal names could happen rarely.
            – Sigur
            Nov 16 at 18:13










          • Your question actually is about some sort of whatsoever minimalist database-management. :-) I extended my answer in the hope of pointing out some of the pitfalls related to whatsoever minimalist database-management in terms of a macro language. :-)
            – Ulrich Diez
            Nov 16 at 21:29










          • Well, thanks for your work. But I confess that I have no idea how to understand it... lol
            – Sigur
            Nov 16 at 21:33










          • I think you want to say “From relational algebra we know that it is not a good idea to assign to each data-record its own unique primary-key as a data-field of its own of that data-record.”.
            – egreg
            Nov 16 at 21:48










          • @UlrichDiez The formulation is way better now. For the same reason I assigned a label to each contact.
            – egreg
            Nov 16 at 22:31


















          • I am not sure if I understood your comments. Anyway, thanks for attention. Let me inform that the contacts come from authors of a paper, so I think that two exactly equal names could happen rarely.
            – Sigur
            Nov 16 at 18:13










          • Your question actually is about some sort of whatsoever minimalist database-management. :-) I extended my answer in the hope of pointing out some of the pitfalls related to whatsoever minimalist database-management in terms of a macro language. :-)
            – Ulrich Diez
            Nov 16 at 21:29










          • Well, thanks for your work. But I confess that I have no idea how to understand it... lol
            – Sigur
            Nov 16 at 21:33










          • I think you want to say “From relational algebra we know that it is not a good idea to assign to each data-record its own unique primary-key as a data-field of its own of that data-record.”.
            – egreg
            Nov 16 at 21:48










          • @UlrichDiez The formulation is way better now. For the same reason I assigned a label to each contact.
            – egreg
            Nov 16 at 22:31
















          I am not sure if I understood your comments. Anyway, thanks for attention. Let me inform that the contacts come from authors of a paper, so I think that two exactly equal names could happen rarely.
          – Sigur
          Nov 16 at 18:13




          I am not sure if I understood your comments. Anyway, thanks for attention. Let me inform that the contacts come from authors of a paper, so I think that two exactly equal names could happen rarely.
          – Sigur
          Nov 16 at 18:13












          Your question actually is about some sort of whatsoever minimalist database-management. :-) I extended my answer in the hope of pointing out some of the pitfalls related to whatsoever minimalist database-management in terms of a macro language. :-)
          – Ulrich Diez
          Nov 16 at 21:29




          Your question actually is about some sort of whatsoever minimalist database-management. :-) I extended my answer in the hope of pointing out some of the pitfalls related to whatsoever minimalist database-management in terms of a macro language. :-)
          – Ulrich Diez
          Nov 16 at 21:29












          Well, thanks for your work. But I confess that I have no idea how to understand it... lol
          – Sigur
          Nov 16 at 21:33




          Well, thanks for your work. But I confess that I have no idea how to understand it... lol
          – Sigur
          Nov 16 at 21:33












          I think you want to say “From relational algebra we know that it is not a good idea to assign to each data-record its own unique primary-key as a data-field of its own of that data-record.”.
          – egreg
          Nov 16 at 21:48




          I think you want to say “From relational algebra we know that it is not a good idea to assign to each data-record its own unique primary-key as a data-field of its own of that data-record.”.
          – egreg
          Nov 16 at 21:48












          @UlrichDiez The formulation is way better now. For the same reason I assigned a label to each contact.
          – egreg
          Nov 16 at 22:31




          @UlrichDiez The formulation is way better now. For the same reason I assigned a label to each contact.
          – egreg
          Nov 16 at 22:31


















           

          draft saved


          draft discarded



















































           


          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f460175%2fsaving-arguments-of-commands-to-be-used-later%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

          ComboBox Display Member on multiple fields

          Is it possible to collect Nectar points via Trainline?