\ pgfmathsetlengthmacro เข้ากันไม่ได้กับลูป?

Sep 06 2020

รหัสต่อไปนี้รวบรวมอย่างสมบูรณ์แบบ:

\documentclass[]{article}

\usepackage[most]{tcolorbox}

\newcommand\UseImageLeft[1]{%
\IfFileExists{#1\i.jpg}%
  {\includegraphics[scale=0.2]{#1\i.jpg}}%
    {\includegraphics[scale=0.2]{example-image.jpg}}%
}

\def\ImageLeft{\UseImageLeft{Image-}}

% Problem ===================================
% \pgfmathsetlengthmacro\LeftWidth{width("\ImageLeft")}
% =======================================

\begin{document}

\foreach \i in {1,...,2}{

% On any page (begin)
\begin{tcolorbox}[]
\begin{tcbitemize}[]
\tcbitem[] \ImageLeft
\end{tcbitemize}
\end{tcolorbox}
% On any page (end)

\newpage
}

\end{document}

ปัญหาของฉันคือฉันต้องการยกเลิกการแสดงความคิดเห็น\pgfmathsetlengthmacro\LeftWidth{width("\ImageLeft")}แต่รหัสไม่ได้รวบรวมอีกต่อไป ฉันจะแก้ไขสิ่งนี้ได้อย่างไร?

คำตอบ

2 UlrichDiez Sep 06 2020 at 14:31

ปัญหาที่ 1:

คุณสามารถใช้\pgfmathsetlengthmacro\LeftWidth{width("\ImageLeft")} นอก\foreach -loop แต่ด้วย\pgfmathsetlengthmacro\LeftWidth{width("\ImageLeft")}แมโคร\ImageLeftถูกนำมาใช้ในการใช้งานซึ่งเปิด\UseImageLeftซึ่งใช้เปิด\iในขณะที่\iมีการกำหนดให้ผลผลิตจำนวนของภาพเท่านั้นภายใน\foreach -loop

ปัญหา 2:

คุณมี\pgfmathsetlengthmacro\LeftWidth{width("\ImageLeft")}รูปแบบใด

\pgfmathsetlengthmacro\LeftWidth{⟨expression⟩}
ด้วย
⟨expression⟩ = width("\ImageLeft")
ขณะที่
width("\ImageLeft")
ในการเปิดเป็นรูปแบบ ที่มี=
width(⟨expression⟩)

⟨expression⟩"\ImageLeft"

ซึ่งหมายความว่า\ImageLeftได้รับการประเมินเป็นส่วนหนึ่งของ⟨expression⟩สองครั้ง:

ครั้งแรกเมื่อมี⟨expression⟩การ\pgfmathsetlengthmacro\LeftWidthประเมินการสร้างอาร์กิวเมนต์

ครั้งที่สองเมื่อมี⟨expression⟩การwidth(...)ประเมินการสร้างอาร์กิวเมนต์

pgfmanual.pdf ส่วน "95.2 Syntax for Mathematical Expressions: Operators" กล่าวในคำอธิบายของ-operator:"x"

... อย่างไรก็ตามเมื่อทุกนิพจน์ถูกขยายด้วย \ edef ก่อนที่จะแยกวิเคราะห์มาโคร (เช่นคำสั่งแบบอักษรเช่น \ tt หรือ \ Huge) อาจต้องได้รับการ "ป้องกัน" จากส่วนขยายนี้ (เช่น \ noexpand \ Huge) ตามหลักการแล้วคุณควรหลีกเลี่ยงมาโครดังกล่าวอยู่ดี เห็นได้ชัดว่าควรใช้ตัวดำเนินการเหล่านี้ด้วยความระมัดระวังเนื่องจากการคำนวณเพิ่มเติมไม่น่าจะเป็นไปได้กับผลลัพธ์

ข้อมูลนี้ไม่ได้เกี่ยวข้องกับ-operator เท่านั้น ข้อมูลนี้เกี่ยวข้องทุกครั้งที่ต้องประเมินไฟล์. มันเป็นกฎทั่วไปซึ่งถูกนำไปใช้ในระหว่างการประเมินผลของทุกคน ดังนั้นฉันจึงคิดว่าไม่ใช่ความคิดที่ดีที่จะถ่ายทอดข้อมูลนี้ในขณะที่อธิบายตัวดำเนินการพิเศษเท่านั้น"x"⟨expression⟩⟨expression⟩

เป็นไปอย่างนั้น:

เมื่อนำข้อมูลมารวมกันคุณจะพบว่า\ImageLeftมีการประเมิน\edefสองครั้ง ขณะที่การขยายตัวของห่วงโซ่เป็น\ImageLeft→การ\UseImageLeft→การ...\includegraphics...นี้แสดงให้เห็นว่าทั้งสองครั้งความพยายามที่จะประเมิน\includegraphicsผ่าน\edefใช้สถานที่
แต่ในกรณีที่คุณไม่ได้ใช้ TeX-distribution ล่าสุด\includegraphicsไม่สามารถใช้งานได้ใน\edefบริบทการขยายตัว เนื่องจากใน TeX-distribution รุ่นเก่า\includegraphicsไม่ได้รับการ "ป้องกัน" - "ป้องกัน" หมายถึงกลไกภายใน LaTeX สำหรับป้องกันการขยายคำสั่งในสถานการณ์ที่การขยายนั้นใช้ไม่ได้ผลและ "อาศัย" ในการมอบหมายงานชั่วคราว ในแง่ของ\defแม้ว่าการมอบหมายดังกล่าวจะไม่ได้รับการดำเนินการในขณะที่อยู่ระหว่างการ\edefประเมินราคา \edefทริกเกอร์การขยายโทเค็นที่ขยายได้ในขณะที่\defเป็นแบบดั้งเดิมที่ไม่สามารถขยายได้

ดังนั้นหากไม่ได้ใช้ TeX-distribution ล่าสุดคุณจำเป็นต้องใช้มาตรการป้องกันเพื่อป้องกันการขยาย / ประเมินคำสั่ง\ImageLeft(และป้องกันการขยาย / การประเมิน\includegraphics) ด้วยการ\edefประเมินค่าเหล่านี้ (ในการแจกแจง TeX ล่าสุดมาตรการป้องกันเหล่านี้ไม่ก่อให้เกิดความรำคาญหรือไม่จำเป็น)

คุณสามารถป้องกันการขยาย / การประเมินผลโดยนำหน้า\ImageLeftด้วย\noexpand\noexpand\noexpand.

ครั้งแรก\edef-evaluation นำไปใช้ในการ<code>\noexpand\noexpand\noexpand\ImageLeft</code>, อัตราผลตอบแทน
ที่สอง-evaluation จะถูกนำมาใช้ในที่ซึ่งอัตราผลตอบแทนในการเปิด:
<code>\noexpand\ImageLeft</code>
\edef
<code>\ImageLeft</code>

ปัญหาที่ 3:

egreg ชี้ให้เห็นว่า\iมีการกำหนดไว้แล้วใน LaTeX และคุณอาจไม่ต้องการแทนที่คำจำกัดความนั้น ดังนั้นในตัวอย่างด้านล่างฉันใช้\NiceForEachElementแทน\i.

\documentclass[]{article}

\usepackage[most]{tcolorbox}

\newcommand\UseImageLeft[1]{%
\IfFileExists{#1\NiceForEachElement.jpg}%
  {\includegraphics[scale=0.2]{#1\NiceForEachElement.jpg}}%
    {\includegraphics[scale=0.2]{example-image.jpg}}%
}

\def\ImageLeft{\UseImageLeft{Image-}}

% Problem ===================================
%\pgfmathsetlengthmacro\LeftWidth{width("\ImageLeft")}
% =======================================

\begin{document}

\foreach \NiceForEachElement in {1,...,2}{%
\pgfmathsetlengthmacro\LeftWidth{width("\noexpand\noexpand\noexpand\ImageLeft")}%
%Activate the following line in case you wish to see on screen/console what the definition of \LeftWidth looks like now:
%\show\LeftWidth
% On any page (begin)
\begin{tcolorbox}[]%
\begin{tcbitemize}[]%
\tcbitem[] \ImageLeft
\end{tcbitemize}%
\end{tcolorbox}%
% On any page (end)
\newpage
}

\end{document}

หากคุณต้องการที่จะสามารถใช้\ImageLeftนอกวงเกินไปแล้วกำหนด\ImageLeftฯลฯ เพื่อดำเนินการโต้แย้งแทนของการประมวลผล/\i ภายในลูปคุณสามารถส่งผ่าน/ เป็นอาร์กิวเมนต์ได้ นอกลูปคุณสามารถส่งผ่านหมายเลขของรูปภาพเป็นอาร์กิวเมนต์ได้โดยตรง\NiceForEachElement
\i\NiceForEachElement

\documentclass[]{article}

\usepackage[most]{tcolorbox}

% Define the command \NiceForEachElement to ensure error-message in case it is already defined.
% This way you can ensure to a certain degree that using `\niceelement` as Foreach-variable
% does not override something that alerady exists.
\newcommand\NiceForEachElement{}%

\newcommand\UseImageLeft[2]{%
% #1 preceding phrase "image-"
% #2 number of image
\IfFileExists{#1#2.jpg}%
  {\includegraphics[scale=0.2]{#1#2.jpg}}%
    {\includegraphics[scale=0.2]{example-image.jpg}}%
}

\newcommand*\ImageLeft[1]{\UseImageLeft{Image-}{#1}}

% Problem ===================================
%\pgfmathsetlengthmacro\LeftWidth{width("\ImageLeft")}
% =======================================

\begin{document}

% outside the loop the width of Image-7.jpg or example-image.jpg:

\pgfmathsetlengthmacro\LeftWidth{width("\noexpand\noexpand\noexpand\ImageLeft{7}")}%
%Activate the following line in case you wish to see on screen/console what the definition of \LeftWidth looks like now:
%\show\LeftWidth

% inside the loop:

\foreach \NiceForEachElement in {1,...,2}{%
  \pgfmathsetlengthmacro\LeftWidth{width("\noexpand\noexpand\noexpand\ImageLeft{\NiceForEachElement}")}%
  %Activate the following line in case you wish to see on screen/console  what the definition of \LeftWidth looks like now:
  %\show\LeftWidth
  % On any page (begin)
  \begin{tcolorbox}[]%
  \begin{tcbitemize}[]%
  \tcbitem[] \ImageLeft{\NiceForEachElement}%
  \end{tcbitemize}%
  \end{tcolorbox}%
  % On any page (end)
  \newpage
}

\end{document}
2 UlrikeFischer Sep 06 2020 at 13:59

อย่าใช้ตัวแปรการวนซ้ำนอกลูปทั้งในโค้ดที่เรียกใช้งานหรือในคำจำกัดความ

\documentclass[]{article}

\usepackage[most]{tcolorbox}

\newcommand\UseImageLeft[1]{%
\IfFileExists{#1.jpg}%
  {\includegraphics[scale=0.2]{#1.jpg}}%
  {\includegraphics[scale=0.2]{example-image.jpg}}%
}


\begin{document}

\foreach \i in {1,...,2}{%
\pgfmathsetlengthmacro\LeftWidth{width("\UseImageLeft{image\i}")}%
% On any page (begin)
\begin{tcolorbox}[]
\begin{tcbitemize}[]
\tcbitem[] \UseImageLeft{image\i}
\end{tcbitemize}
\end{tcolorbox}
% On any page (end)

\newpage
}^

\end{document}