Definire un condizionale come alias di un altro

  • Creatore
    Topic
  • #90745
    Up
    0
    Down
    ::


    Questo il codice:
    `\documentclass{article}

    \def\ifciao{\iftrue}

    \begin{document}
    \ifciao
    \typeout{Ciao!}
    \fi
    \iffalse
    \ifciao
    Ciao!!
    \fi
    \fi
    \end{document}`

    Il primo [tt]\ifciao[/tt] non dà alcun problema. Il secondo, invece, viene completamente saltato e conduce all’errore:
    `! Extra \fi.
    l.14 \fi

    ? `

    Il primo [tt]\ifciao[/tt] viene valutato sempre, in quanto esterno, mentre il secondo, che è annidato dentro un altro condizionale falso, sembra essere sbrigativamente saltato da TeX. Perché avviene ciò? Se ci metto un qualsiasi condizionale dichiarato con [tt]\newif[/tt] funziona correttamente.

    Secondo quale regola TeX salta il corpo di un condizionale falso? O meglio (ci sono sul fatto che pensa solo a bilanciare i condizionali annidati): secondo quale criterio TeX determina se una sequenza di controllo incontrata è un condizionale? Flag interni (praticamente una valutazione a livello di stomaco)? Credevo che il tutto avvenisse a un livello piuttosto superficiale, già sulle “labbra” (per esempio che venissero saltate le macro che iniziano con [tt]\if[/tt]).

    Il mio obiettivo originario era definire un condizionale come alias di un altro, da qui l’uso del [tt]\def[/tt]. Mi sembra di aver visto altri esempi di definizione di condizionali in questo modo: devo dedurre che in tutti quei casi si suppone di non annidare i condizionali?

    Grazie,
    Antonio

Visualizzazione 5 filoni di risposte
  • Autore
    Risposte
    • #90746
      Up
      0
      Down
      ::

      antonio.macrì” post=90295Credevo che il tutto avvenisse a un livello piuttosto superficiale, già sulle “labbra” (per esempio che venissero saltate le macro che iniziano con [tt]\if[/tt]).

      In effetti se fosse così non funzionerebbe questo codice (e sarebbe un po’ strano):
      `\documentclass{article}

      \newif\ciccio

      \begin{document}
      \ciccio
      \typeout{Hola!}
      \fi
      \iffalse
      \ciccio
      Hola!
      \fi
      \fi
      \end{document}`
      Invece funziona! (Anche se è strano comunque… senza contare un eventuale [tt]\cciotrue[/tt]…) 🙂

    • #90747
      OldClaudio
      Partecipante
        Up
        0
        Down
        ::


        Mmmm

        Non vedo la necessità di definire degli alias, specialmente perché ogni definizione di condizionale [tt]\newif\ifpippo[/tt] definisce in realtà tre control sequence [tt]\ifpippo, \pippotrue, \pippofalse[/tt] quindi i condizionali sono particolarmente fragili se non li manipoli correttamente.

        È vero i condizionali vengono gestiti nella bocca (o negli occhi?) e i rami falsi vengono eliminati subito, in modo che eliminato input tokens direttamente all’origine; così dice il TeXbook in modo molto più elaborato. Invece di definire alias di condizionali, io ho trovato molto comodo gestire e testare l’esistenza di certi condizionali mediante i test definiti da etoolbox, in particolare quelli che fanno rifermento non alla macro ma al nome della macro( in sostanza non a \ifpippo, ma a ifpippo) le cose si gestiscono molto meglio e i comandi sono robusti, molto più robusti di quelli che si hanno con il pacchetto ifthen (ammesso che esista un grado di robustezza; in realtà un comando o è robusto o non lo è; ma è incerto sapere quando si rompe e quando rimane integro. Le regole ci sono, evidentemente, ma le circostanze le oscurano spesso e volentieri).

      • #90748
        Up
        0
        Down
        ::


        Ciao Claudio, grazie della risposta.

        OldClaudio” post=90299Mmmm

        Non vedo la necessità di definire degli alias, specialmente perché ogni definizione di condizionale [tt]\newif\ifpippo[/tt] definisce in realtà tre control sequence [tt]\ifpippo, \pippotrue, \pippofalse[/tt] quindi i condizionali sono particolarmente fragili se non li manipoli correttamente.

        Sì, son d’accordo con te: infatti poi ho risolto diversamente. Però la curiosità mi è rimasta. 🙂

        OldClaudio” post=90299È vero i condizionali vengono gestiti nella bocca (o negli occhi?) e i rami falsi vengono eliminati subito, in modo che eliminato input tokens direttamente all’origine; così dice il TeXbook in modo molto più elaborato.

        Il fatto è che mi sembra di aver già visto definizioni di condizionali in quel modo, ne ho ritrovato uno sul TeXByTopic all’inizio del paragrafo 13.8.7 (pagina 149):
        `\def\ifEqString#1#2%
        {\def\csa{#1}\def\csb{#2}\ifx\csa\csb }`
        Poco dopo lo ridefinisce ma perché “dal momento che usa [tt]\def[/tt], non è espandibile” (e non perché può creare problemi se annidato in un condizionale falso).

        OldClaudio” post=90299Invece di definire alias di condizionali, io ho trovato molto comodo gestire e testare l’esistenza di certi condizionali mediante i test definiti da etoolbox, in particolare quelli che fanno rifermento non alla macro ma al nome della macro( in sostanza non a \ifpippo, ma a ifpippo) le cose si gestiscono molto meglio e i comandi sono robusti, molto più robusti di quelli che si hanno con il pacchetto ifthen (ammesso che esista un grado di robustezza; in realtà un comando o è robusto o non lo è; ma è incerto sapere quando si rompe e quando rimane integro. Le regole ci sono, evidentemente, ma le circostanze le oscurano spesso e volentieri).

        Ti riferisci a [tt]\ifbool[/tt] e simili? La sintassi di ifthen non mi è mai piaciuta, quella di etoolbox sembra simile. Se posso evito i condizionali con graffe, che poi possono richiedere anche di metterci i [tt]%[/tt]… Trovo molto più elegante e leggibile la sintassi nativa di TeX.

      • #90749
        OldClaudio
        Partecipante
          Up
          0
          Down
          ::

          Ti riferisci a \ifbool e simili? La sintassi di ifthen non mi è mai piaciuta, quella di etoolbox sembra simile. Se posso evito i condizionali con graffe, che poi possono richiedere anche di metterci i %… Trovo molto più elegante e leggibile la sintassi nativa di TeX.

          Secondo me la sintassi originale di TeX è fragile, perché è facile dimenticarsi di usare un numero sufficiente di \expandafter er non lasciare delle espressioni condizionali aperte.

          Invece i comandi del tipo \ifcsdef, sono decisamente robusti anche se le due frasi vanno messe dentro due gruppi; garantiscono la robusezza, perché prima viene valutata la verità di qualcosa, poi con di debiti \expandafter viene eseguito con \@firstoftwo e \@secondoftwo solo il contenuto di no dei due gruppi; ciascuno di questi gruppi può contenere altri condizionali. Non dico che si debbano sempre usare quei condizionali lì e le espressioni logiche loro collegate, che rischiano di diventare complesse, ma quello è anche il principio dei condizionali di LaTeX (simili a quello del tuo esempio, ma robusti) come \@ifpackageloaded e simili. Sia quelli di LaTeX sia quello dell’esempio che riporti, pur cominciando con \if, non sono definiti come condizionali, ma come normali macro che, evidentemente, contengono almeno un condizionale al loro interno e, tranne l’esempio che riporti, i fatidici \@firstoftwo e \@secondoftwo. In certi casi ho visto usare il \@firstofone, e in hyperref ci osno anche i 5 \@firstoffive,…,\@fiftoffive.

          Trucchi che dovremmo usare più spesso quando scriviamo pacchetti. Forse rendono più oscuro il codice, ma certamente lo rendo più robusto. Il codice del tuo esempio riportato da TeXbyTopic dovrebbe quindi essere con etoolbox`\def\ifEqString#1#2{\ifstrequal{#1}{#2}{vero}{falso}}` decisamente più semplice; se poi si mettono due semplici commenti è ancora più chiaro:`
          \def\ifEqString#1#2{% confronta due stringhe
          \ifstrequal{#1}{#2}{% vero
          vero
          }{% falso
          falso
          }}`

          Non parliamo dei test di babel come [tt]\bbl@afterfi[/tt] e [tt]\bbl@afteresle[/tt] che dovrebbero essere robusti, ma non lo sono, proprio per la mancanza di gruppi.

        • #90750
          Up
          0
          Down
          ::

          antonio.macrì” post=90295Questo il codice:
          `\documentclass{article}

          \def\ifciao{\iftrue}

          \begin{document}
          \ifciao
          \typeout{Ciao!}
          \fi
          \iffalse
          \ifciao
          Ciao!!
          \fi
          \fi
          \end{document}`

          Il primo [tt]\ifciao[/tt] non dà alcun problema. Il secondo, invece, viene completamente saltato e conduce all’errore:
          `! Extra \fi.
          l.14 \fi

          ? `

          Il primo [tt]\ifciao[/tt] viene valutato sempre, in quanto esterno, mentre il secondo, che è annidato dentro un altro condizionale falso, sembra essere sbrigativamente saltato da TeX. Perché avviene ciò? Se ci metto un qualsiasi condizionale dichiarato con [tt]\newif[/tt] funziona correttamente.

          Secondo quale regola TeX salta il corpo di un condizionale falso? O meglio (ci sono sul fatto che pensa solo a bilanciare i condizionali annidati): secondo quale criterio TeX determina se una sequenza di controllo incontrata è un condizionale? Flag interni (praticamente una valutazione a livello di stomaco)? Credevo che il tutto avvenisse a un livello piuttosto superficiale, già sulle “labbra” (per esempio che venissero saltate le macro che iniziano con [tt]\if[/tt]).

          Il mio obiettivo originario era definire un condizionale come alias di un altro, da qui l’uso del [tt]\def[/tt]. Mi sembra di aver visto altri esempi di definizione di condizionali in questo modo: devo dedurre che in tutti quei casi si suppone di non annidare i condizionali?

          Occorre ricordare che quando TeX scarta i token corrispondenti a un ramo di un condizionale non esegue alcuna espansione, ma si limita a tenere conto dei condizionali che incontra. Nel primo esempio, [tt]\ifciao[/tt] viene espanso e quindi TeX trova
          `\iftrue\typeout{Ciao!}\fi`
          che sa bene come gestire.

          Nel secondo caso
          `\iffalse\ifciao Ciao!!\fi\fi`
          il condizionale è falso, quindi il ramo vero è tutto ciò che va fino al primo [tt]\else[/tt] o, se mancante, al primo [tt]\fi[/tt]. Perciò il passo successivo dell’espansione lascia
          `\fi\fi`
          Il primo sparisce perché TeX sa di aver espanso il condizionale [tt]\iffalse[/tt]; il secondo è di troppo. Se invece fosse
          `\iftrue\ifciao Ciao!!\fi\fi`
          TeX terrebbe tutto e, eliminato [tt]\iftrue[/tt] troverebbe [tt]\ifciao[/tt] che espanderebbe prima di aver “visto” [tt]\fi[/tt].

          Solo con
          `\let\ifciao\iftrue`
          daresti a [tt]\ifciao[/tt] lo stato di vero condizionale. E infatti, quando esegui [tt]\newif\ifpippo[/tt], le macro definiscono
          `\let\ifpippo\iffalse
          \def\pippotrue{\let\ifpippo\iftrue}
          \def\pippofalse{\let\ifpippo\iffalse}`

          Ciao
          Enrico

        • #90751
          Up
          0
          Down
          ::


          Grazie delle risposte.

          OldClaudio” post=90301Invece i comandi del tipo \ifcsdef, sono decisamente robusti anche se le due frasi vanno messe dentro due gruppi; garantiscono la robusezza, perché prima viene valutata la verità di qualcosa, poi con di debiti \expandafter viene eseguito con \@firstoftwo e \@secondoftwo solo il contenuto di no dei due gruppi; ciascuno di questi gruppi può contenere altri condizionali. Non dico che si debbano sempre usare quei condizionali lì e le espressioni logiche loro collegate, che rischiano di diventare complesse, ma quello è anche il principio dei condizionali di LaTeX (simili a quello del tuo esempio, ma robusti) come \@ifpackageloaded e simili. […]

          Trucchi che dovremmo usare più spesso quando scriviamo pacchetti. Forse rendono più oscuro il codice, ma certamente lo rendo più robusto.

          Ottimi argomenti!

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

      Go to top