[risolto] plain – confronto condizionale fra stringhe

  • Creatore
    Topic
  • #58839
    Up
    0
    Down
    ::


    L’esempio minimo è il seguente:`\def\param{moebius}

    \def\test#1#2#3#4{%
    \if#4\param%
    Well done job!%
    \else%
    Ah no! Il quarto parametro deve %
    contenere la stringa `\param'%
    \fi}

    \test{pianoforte}{betelgeuse}{Zen}{moebius}

    \bye`

    Ovviamente restituisce il risultato sbagliato.
    Perchè non vuole capire che il quarto parametro contiene davvero la stringa ‘moebius’?

    Grazie, ciao.

    Sam Qasbah

Visualizzazione 4 filoni di risposte
  • Autore
    Risposte
    • #58840
      Up
      0
      Down
      ::

      L’esempio minimo è il seguente:`\def\param{moebius}

      \def\test#1#2#3#4{%
      \if#4\param%
      Well done job!%
      \else%
      Ah no! Il quarto parametro deve %
      contenere la stringa `\param'%
      \fi}

      \test{pianoforte}{betelgeuse}{Zen}{moebius}

      \bye`

      Ovviamente restituisce il risultato sbagliato.
      Perchè non vuole capire che il quarto parametro contiene davvero la stringa ‘moebius’?

      Grazie, ciao.

      Sam Qasbah

      Perché \if confronta solo due token. Nel tuo caso confronta la “m” con la “o” e ovviamente decide che sono diversi. 🙂

      Occorre parecchia attenzione con \if, perché questo condizionale opera con espansione; la risposta corretta è
      `\def\param{moebius}
      \def\test#1#2#3#4{%
      \def\next{#4}%
      \ifx\next\param
      Well done job!%
      \else
      Ah no! Il quarto parametro deve %
      contenere la stringa `\param'%
      \fi}`
      Il condizionale \ifx non espande i due token che seguono e ne confronta i significati.

      In alternativa
      `\usepackage{etoolbox}
      \def\test#1#2#3#4{%
      \ifstrequal{#4}{moebius}
      {Well done job!}
      {Ah no! Il quarto parametro deve %
      contenere la stringa `\param'}}`
      Ciao
      Enrico

    • #58841
      Up
      0
      Down
      ::

      … la risposta corretta è
      `\def\param{moebius}
      \def\test#1#2#3#4{%
      \def\next{#4}%
      \ifx\next\param
      Well done job!%
      \else
      Ah no! Il quarto parametro deve %
      contenere la stringa `\param'%
      \fi}`
      Il condizionale \ifx non espande i due token che seguono e ne confronta i significati.

      In alternativa …

      Ogni tua correzione è una illuminazione. Non ho parole per ringraziarti.

      Ciao.

      Sam Qasbah

    • #58842
      Up
      0
      Down
      ::

      … la risposta corretta è
      `\def\param{moebius}
      \def\test#1#2#3#4{%
      \def\next{#4}%
      \ifx\next\param
      Well done job!%
      \else
      Ah no! Il quarto parametro deve %
      contenere la stringa `\param'%
      \fi}`

      In alternativa

      `\usepackage{etoolbox}
      \def\test#1#2#3#4{%
      \ifstrequal{#4}{moebius}
      {Well done job!}
      {Ah no! Il quarto parametro deve %
      contenere la stringa `\param'}}`
      Ciao
      Enrico

      … \ifstrequal ha un comportamento molto simile a quello suggerito da te:

      `\newrobustcmd{\ifstrequal}[2]{%
      \begingroup
      \edef\etb@tempa{\detokenize{#1}}%
      \edef\etb@tempb{\detokenize{#2}}%
      \ifx\etb@tempa\etb@tempb
      \aftergroup\@firstoftwo
      \else
      \aftergroup\@secondoftwo
      \fi
      \endgroup}`

      non capisco però una cosa: \ifx, se ha in input delle macro, le consdera uguali se tali sono a seguito di una “top-level expansion” [TB pg. 210]. Nel caso di sopra, a seguito di una top-level expansion, \etb@tempa restituisce ancora una macro (cioè \detokenize{#1}) e, nel caso specifico, il risultato della comparazione dovrebbe essere sempre false.

      O forse mi sfugge il significato di top-level expansion…

      Hai il tempo di scrivere due righe di chiarimento?

      Grazie, ciao.

      Sam Qasbah (che, a letto con un infezione virale, trova il tempo di approfondre le cose)

    • #58843
      OldClaudio
      Partecipante
        Up
        0
        Down
        ::


        No, \edef esegue l\espansione del contenuto della definzione, quindi \etb@tempa non contiene più \detokenize{#1} ma contiene il parametro #1 detokenizzato, cioè come una stringa di caratteri a ciascuno dei quali è stato tolto il codice di categoria iniziale; e lo stesso succede per l’altra variabile\etb@tempb.

        Quindi il test è vero quando le due stringhe sono identiche indipendentemente dai codici di categoria che ogni carattere poteva avere prima di essere detokenizzato. Se non ci fosse il comando \detokenise, l’espansione delle due stringhe andrebbe fino in fondo e non si fermerebbe al primo livello.

      • #58844
        Up
        0
        Down
        ::

        No, \edef esegue l\espansione del contenuto della definzione, quindi \etb@tempa non contiene più \detokenize{#1} ma contiene il parametro #1 detokenizzato, cioè come una stringa di caratteri a ciascuno dei quali è stato tolto il codice di categoria iniziale; e lo stesso succede per l’altra variabile\etb@tempb.

        Quindi il test è vero quando le due stringhe sono identiche indipendentemente dai codici di categoria che ogni carattere poteva avere prima di essere detokenizzato. Se non ci fosse il comando \detokenise, l’espansione delle due stringhe andrebbe fino in fondo e non si fermerebbe al primo livello.

        Ti ringrazio infinitamente.

        Sam Qasbah

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

    Go to top