[L3] Comando { o m o }

  • Creatore
    Topic
  • #80981
    robitex
    Amministratore del forum
      Up
      0
      Down
      ::


      Ciao,
      guardate come è semplice in LaTeX3 definire un comando con un primo argomento opzionale, un secondo argomento obbligatorio ed un terzo argomento ancora opzionale.

      `\NewDocumentCommand { \numx } { o m o }
      {
      \tl_set:Nx \l_tmpa_tl { #2 }
      \IfValueTF { #3 }
      {
      \IfValueTF { #1 }
      {
      \SI[#1]{ \tl_use:N \l_tmpa_tl }{ #3 }
      }
      {
      \SI{ \tl_use:N \l_tmpa_tl }{ #3 }
      }
      }
      {
      \IfValueTF { #1 }
      {
      \num[#1]{ \tl_use:N \l_tmpa_tl }
      }
      {
      \num{ \tl_use:N \l_tmpa_tl }
      }
      }
      }`

      Lo scopo è quello di riunire in un unico comando \num e \SI entrambe del pacchetto siunitx.
      Posso quindi scrivere:
      `un numero \numx{120.12}
      un numero con opzioni \numx[round-precision=2]{120.123}
      un numero con unità di misura \numx{12.23}[\percent]
      un numero con unità di misura ed opzioni \numx[round-precision=3]{12.123}[\percent]
      `

      Ciao.
      R.

    Visualizzazione 9 filoni di risposte
    • Autore
      Risposte
      • #80982
        franen
        Partecipante
          Up
          0
          Down
          ::


          Come mai il #2 lo assegni a [tt]\l_tmpa_tl[/tt] anziché usarlo direttamente come fai con #1 e #3? Serve?
          Fran

        • #80983
          Up
          0
          Down
          ::

          robitex” post=80214Ciao,
          guardate come è semplice in LaTeX3 definire un comando con un primo argomento opzionale, un secondo argomento obbligatorio ed un terzo argomento ancora opzionale.

          `\NewDocumentCommand { \numx } { o m o }
          {
          \tl_set:Nx \l_tmpa_tl { #2 }
          \IfValueTF { #3 }
          {
          \IfValueTF { #1 }
          {
          \SI[#1]{ \tl_use:N \l_tmpa_tl }{ #3 }
          }
          {
          \SI{ \tl_use:N \l_tmpa_tl }{ #3 }
          }
          }
          {
          \IfValueTF { #1 }
          {
          \num[#1]{ \tl_use:N \l_tmpa_tl }
          }
          {
          \num{ \tl_use:N \l_tmpa_tl }
          }
          }
          }`

          Lo scopo è quello di riunire in un unico comando \num e \SI entrambe del pacchetto siunitx.
          Posso quindi scrivere:
          `un numero \numx{120.12}
          un numero con opzioni \numx[round-precision=2]{120.123}
          un numero con unità di misura \numx{12.23}[\percent]
          un numero con unità di misura ed opzioni \numx[round-precision=3]{12.123}[\percent]
          `

          Ciao.
          R.

          Può essere ancora più semplice. Non vedo la necessità di espandere il secondo argomento, ma si può discuterne.
          `\ExplSyntaxOn
          \NewDocumentCommand{\numx}{ O{} m o }
          {
          \IfValueTF{#3}
          {
          \SI[#1]{#2}{#3}
          }
          {
          \num[#1]{#2}
          }
          }
          \ExplSyntaxOff`
          Se proprio vuoi l’espansione completa del secondo argomento, meglio fare così:
          `\ExplSyntaxOn
          \NewDocumentCommand{\numx}{ O{} m o }
          {
          \IfNoValueTF{#3}
          { \robitex_numx:nx { #1 } { #2 } }
          { \robitex_numx:nxn { #1 } { #2 } { #3 } }
          }
          \cs_new_protected:Npn \robitex_numx:nn { \num[#1]{#2} }
          \cs_new_protected:Npn \robitex_numx:nnn { \SI[#1]{#2}{#3} }
          \cs_generate_variant:Nn \robitex_numx:nn { nx }
          \cs_generate_variant:Nn \robitex_numx:nnn { nx }
          \ExplSyntaxOff`

          Ciao
          Enrico

        • #80984
          Up
          0
          Down
          ::


          Perché non si può usare semplicemente #2 al posto di \l_tmpa_tl?

          Ciao
          Ivan

          p.s. sarebbe molto utile avere un commento di questo codice 😉
          Sarà anche semplice (e la struttura in effetti lo è e si capisce), ma la sintassi
          per me non è per niente semplice. Mi pare un’altra lingua 🙄

          edit
          Vedo che il filone è seguito 🙂
          Giro la richiesta anche a Enrico. Qualche delucidazione
          (passo passo) al codice sarebbe utilissima 😀

        • #80985
          robitex
          Amministratore del forum
            Up
            0
            Down
            ::

            ivan” post=80218Perché non si può usare semplicemente #2 al posto di \l_tmpa_tl?

            Perché in realtà l’argomento obbligatorio è un nome di un campo di una variabili proprietà.
            Ho adattato il comando. L’argomento #2 può essere utilizzato direttamente.
            Un saluto.
            R.

          • #80986
            Up
            0
            Down
            ::

            ivan” post=80218Perché non si può usare semplicemente #2 al posto di \l_tmpa_tl?

            Ciao
            Ivan

            p.s. sarebbe molto utile avere un commento di questo codice 😉
            Sarà anche semplice (e la struttura in effetti lo è e si capisce), ma la sintassi
            per me non è per niente semplice. Mi pare un’altra lingua 🙄

            edit
            Vedo che il filone è seguito 🙂
            Giro la richiesta anche a Enrico. Qualche delucidazione
            (passo passo) al codice sarebbe utilissima 😀

            `\ExplSyntaxOn`
            Ci liberiamo dei problemi di spazi spuri (e abilitiamo l’uso delle macro di LaTeX3)
            `\NewDocumentCommand{\numx}{ O{} m o }`
            Il comando [tt]\numx[/tt] ha un argomento facoltativo (valore normale vuoto), uno obbligatorio e un altro facoltativo (senza valore normale)
            ` {
            \IfValueTF{#3}`
            Se l’argomento facoltativo [tt]#3[/tt] è espresso, [tt]\IfValueTF{#3}[/tt] risulta vero e si segue il ramo “vero”:
            ` {
            \SI[#1]{#2}{#3}
            }`
            in cui si chiama il comando [tt]\SI[/tt] con gli argomenti indicati. Altrimenti si segue il ramo “falso:
            ` {
            \num[#1]{#2}
            }`
            in cui si chiama [tt]\num[/tt]
            ` }
            \ExplSyntaxOff`
            Fine della definizione e uscita dall’ambiente speciale.

            Vediamo il secondo codice.
            `\ExplSyntaxOn
            \NewDocumentCommand{\numx}{ O{} m o }
            {`
            Tutto come prima. Ma ora, per nessun motivo particolare uso [tt]\IfNoValueTF[/tt] che fa la stessa cosa dell’altro, ma con “vero” e “falso” rovesciati.
            ` \IfNoValueTF{#3}
            { \robitex_numx:nx { #1 } { #2 } }
            { \robitex_numx:nxn { #1 } { #2 } { #3 } }
            }`
            Nei due casi chiamo due macro diverse.
            `\cs_new_protected:Npn \robitex_numx:nn { \num[#1]{#2} }
            \cs_new_protected:Npn \robitex_numx:nnn { \SI[#1]{#2}{#3} }`
            Le due macro sono definite in modo facile: chiamano [tt]\num[/tt] e [tt]\SI[/tt]. Ma si può notare che i suffissi che specificano gli argomenti sono diversi. Infatti le prossime due righe chiariscono:
            `\cs_generate_variant:Nn \robitex_numx:nn { nx }
            \cs_generate_variant:Nn \robitex_numx:nnn { nx }`
            La prima genera la macro [tt]\robitex_numx:nx[/tt] in cui il secondo argomento viene espanso completamente prima di essere passato a [tt]\robitex_numx:nn[tt]. Dunque
            `\robitex_numx:nx{}{}`
            equivale a chiamare
            `\robitex_numx:nn{}{}`

            In LaTeX (quasi) standard questo sarebbe qualcosa come:
            `\def\robitex@numx#1#2{…}
            \def\robitex@numx@expandsecond#1#2{%
            \begingroup\edef\x{\endgroup
            \unexpanded{\robitex@numx{#1}}{#2}}\x}`
            Senza usare [tt]\unexpanded[/tt] sarebbe
            `\def\robitex@numx@expandsecond#1#2{%
            \toks@={\robitex@numx{#1}}%
            \begingroup\edef\x{\endgroup
            \the\toks@{#2}}\x}`

            Direi che l’astrazione di [tt]\cs_generate_variant:Nn[/tt] è un po’ più comoda. 🙂

            Ciao
            Enrico

          • #80987
            franen
            Partecipante
              Up
              0
              Down
              ::


              Grazie Enrico.
              Però io ho sempre (un parolone… in quei 2 progetti in cui ho usto L3) usato [tt]\cs_generate_variant:Nn[/tt] per creare varianti di macro già esistenti, cioè macro di L3.
              Perché in questo caso non potrei direttamente definire`\cs_new_protected:Npn \robitex_numx:nx { \num[#1]{#2} }
              \cs_new_protected:Npn \robitex_numx:nxn { \SI[#1]{#2}{#3} }`?
              Fran

            • #80988
              Up
              0
              Down
              ::

              franen” post=80237Grazie Enrico.
              Però io ho sempre (un parolone… in quei 2 progetti in cui ho usto L3) usato [tt]\cs_generate_variant:Nn[/tt] per creare varianti di macro già esistenti, cioè macro di L3.
              Perché in questo caso non potrei direttamente definire`\cs_new_protected:Npn \robitex_numx:nx { \num[#1]{#2} }
              \cs_new_protected:Npn \robitex_numx:nxn { \SI[#1]{#2}{#3} }`?
              Fran

              Perché non farebbero quello che desideri! Il comando [tt]\cs_new_protected:Npn[/tt] è, a parte il controllo se la macro sia già definita,
              `\protected\long\gdef`
              Con [tt]\cs_new…[/tt] puoi definire solo argomenti di tipo N e n.

              Ciao
              Enrico

            • #80989
              franen
              Partecipante
                Up
                0
                Down
                ::


                Perdonami, ma non ho capito la tua risposta. Che c’entra [tt]\cs_new…[/tt]?
                Io con questo codice riesco a compilare. Non uso arogomenti espandibili, quindi non ho la certezza che tutto funzioni a dovere, Roberto ci dirà. Ho aggiunto #1#2#3 e #1#2 nella definizione date con [tt]\cs_new_protected:Npn[/tt] (Sono indispensabili vero?)`\documentclass{article}
                \usepackage{xparse,expl3}
                \usepackage{siunitx}
                \ExplSyntaxOn
                \NewDocumentCommand{\numx}{ O{} m o }
                {
                \IfNoValueTF{#3}
                { \robitex_numx:nx { #1 } { #2 } }
                { \robitex_numx:nxn { #1 } { #2 } { #3 } }
                }
                \cs_new_protected:Npn \robitex_numx:nx #1#2{ \num[#1]{#2} }
                \cs_new_protected:Npn \robitex_numx:nxn #1#2#3 { \SI[#1]{#2}{#3} }
                %\cs_generate_variant:Nn \robitex_numx:nn { nx }
                %\cs_generate_variant:Nn \robitex_numx:nnn { nx }
                \ExplSyntaxOff

                \begin{document}
                \noindent un numero \numx{120.12}\\
                un numero con opzioni \numx[output-decimal-marker = {,}]{120.123}\\
                un numero con unità di misura \numx{12.56}[km\per s]\\
                un numero con unità di misura e opzioni \numx[output-decimal-marker = {,}]{12.124}[\percent]

                \end{document}`
                Fran

              • #80990
                Up
                0
                Down
                ::

                franen” post=80241Perdonami, ma non ho capito la tua risposta. Che c’entra [tt]\cs_new…[/tt]?
                Io con questo codice riesco a compilare. Non uso arogomenti espandibili, quindi non ho la certezza che tutto funzioni a dovere, Roberto ci dirà.

                Ecco, appunto: non hai fatto alcuna prova. 🙂

                Ora provo a rispiegare. Il codice
                `\cs_new_protected:Npn \robitex_numx:nx #1#2 { \num[#1]{#2} }`
                è del tutto equivalente a
                `\protected\long\gdef\robitex_numx:nx #1#2{\num[#1]{#2}}`
                (se si eccettua il fatto che viene prima controllato che [tt]\robitex_numx:nx[/tt] non sia definita). Non è che solo per il nome succedano cose magiche; se anche usassi
                `\cs_new_protected:Nn \robitex_numx:nx { \num[#1]{#2} }`
                non avresti niente di diverso, perché questa variante si limita a contare il numero di caratteri dopo i due punti fornire la corretta lista di parametri (in questo caso [tt]#1#2[/tt]).

                Ripeto: con [tt]\cs_new:Npn[/tt] (e con le funzioni della stessa famiglia) si definiscono solo funzioni con argomenti di tipo [tt]N[/tt] o [tt]n[/tt]. Se ti occorrono varianti con argomenti di tipo diverso ([tt]cvVfxo…[/tt]) devi adoperare [tt]\cs_generate_variant:Nn[/tt].

                Ciao
                Enrico

              • #80991
                franen
                Partecipante
                  Up
                  0
                  Down
                  ::

                  egreg9″ post=80243 con [tt]\cs_new:Npn[/tt] (e con le funzioni della stessa famiglia) si definiscono solo funzioni con argomenti di tipo [tt]N[/tt] o [tt]n[/tt]. Se ti occorrono varianti con argomenti di tipo diverso ([tt]cvVfxo…[/tt]) devi adoperare [tt]\cs_generate_variant:Nn[/tt].

                  grazie, non mi era chiaro.
                  Fran

              Visualizzazione 9 filoni di risposte
              • Devi essere connesso per rispondere a questo topic.

              Go to top