\const
不适用于当前定义。它被定义为在 TeX 和 PostScript 范围内易于声明的常量。例如,如果我想定义一个Speed
值的const 300000000
,我可以使用在 PS 和 TeX 范围内已知的单个调用来声明它\const{Speed}{300000000}
。另一个例子,如果我想NumberOfElements
在 PS 和 TeX 范围内创建一个 const,我可以调用\const{NumberOfElements}{\length{\list}}
where \length
(定义如 MWE 中所示)和\def\list{a,b,c}
。
问题是我不懂创作\const{\length{\list}}
作品时保持\const
作品的初衷。这是 MWE。
\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pstricks-add,fp}
% user defined data
\def\listX{1,2,3,4,5,6}
\def\listY{1,2,3}
% to determine the number of elements in a list
\newcounter{x}
\def\length#1{\setcounter{x}{0}\psforeach{\i}{#1}{\stepcounter{x}}\thex}
% to create constants in both TeX and PS scopes
\def\const#1#2{%
\expandafter\FPeval\csname#1\endcsname{#2}%
\pstVerb{/#1 \csname#1\endcsname\space def}%
}
\const{Nx}{\length{\listX}}
\const{Ny}{\length{\listY}}
\const{CellW}{1}
\const{CellH}{2}
\const{CanvasWidth}{Nx*CellW}
\const{CanvasHeight}{Ny*CellH}
\begin{document}
\begin{pspicture}[showgrid=bottom](\CanvasWidth,\CanvasHeight)
% use other PS constants here
\end{pspicture}
\end{document}
附加问题:有没有更聪明的方法来了解列表中元素的数量?
答案1
让我们总体上看一下这个问题,尽管深入的讨论需要写很多页书。
您关心的是命令的定义,而不仅仅是嵌套宏调用。“工作”定义
\def\const#1#2{\expandafter\def\csname#1\endcsname{#2}}
通过电话
\const{Count}{\length{\list}}
相当于
\def\Count{\length{\list}}
如果你也有\def\list{1,2,3}
,那么
\const{Count}{\length{\list}}\Count
会打印 3。但是,如果你说
\def\list{1,2,3}
\const{Count}{\length{\list}}
\Count
\def\list{a,b,c,d}
\Count
你会得到
3
4
为什么?因为宏\Count
是根据 定义的\list
,它将使用 的当前含义\list
,而不是定义时的含义:\list
只是一个指向标记列表(当前替换文本)的指针。
\Count
你的问题是将当前的的长度\list
,与可能的后续重新定义无关。并且您希望它作为纯数字,因为您必须将其\pstVerb
作为 PostScript 标记的替换文本传递给。
解决这个问题的方法是执行计算,将数字结果存储在临时控制序列中,然后使用\edef
。
这里有一种方法:
\makeatletter
\newcount\const@count
\def\length#1{%
\const@count=\z@
\@for\next:=#1\do{\advance\const@count\@ne}%
\edef\@tempa{\number\const@count}%
}
\def\const#1#2{%
#2%
\expandafter\let\csname #1\endcsname\@tempa
\begingroup\edef\x{\endgroup
\noexpand\pstVerb{/#1 \@tempa\space def}}\x
}
\makeatother
称之为
\const{Count}{\length{\list}}
重要的是执行计算前定义\Count
并执行\pstVerb
。
这与您在其他地方所做的事情类似\FPeval
。
首先\length{\list}
计算并将结果存储在中\@tempa
,\edef
因此实际数字是替换文本。然后\let
将使\Count
具有当前含义,\@tempa
然后\pstVerb
以间接方式发出,以避免在替换文本中引用\@tempa
,这要归功于\edef
再次。
让我们尝试概括这一点;我建议使用三个参数的宏:
\makeatletter
\def\const#1#2#3{% #1=name, #2=method, #3=data
#2{#1}{#3}%
\begingroup\edef\x{\endgroup
\noexpand\pstVerb{/#1 \csname#1\endcsname\space def}}\x
}
\newcount\const@count
\def\length#1#2{%
\const@count=\z@
\@for\next:=#2\do{\advance\const@count\@ne}%
\expandafter\edef\csname#1\endcsname{\number\const@count}%
}
\makeatother
现在\const{Count}{\length}{\list}
或\const{ABC}{\FPeval}{2*3}
将会起作用。
如果\FPeval
是默认方法,则可以简化语法:
\documentclass{article}
\usepackage{pstricks-add,fp}
% user defined data
\def\list{1,2,3,4,5,6}
\makeatletter
\newcommand\const[3][\FPeval]{% #1=method, #2=name, #3=data
\expandafter#1\csname#2\endcsname{#3}%
\begingroup\edef\x{\endgroup
\noexpand\pstVerb{/#2 \csname#2\endcsname\space def}}\x
}
\newcount\const@count
\def\length#1#2{%
\const@count=\z@
\@for\next:=#2\do{\advance\const@count\@ne}%
\edef#1{\number\const@count}%
}
\makeatother
\begin{document}
\const[\length]{Count}{\list}
\Count
\const{ABC}{2*2}
\ABC
\end{document}
答案2
如果仅通过扩展进行工作,则最简单,那么 TeX 和 PS 构造的行为更相似。我稍微更改了\
产品表达式中的语法,以节省解析标记的时间。
\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pstricks-add,fp}
% user defined data
\def\listX{1,2,3,4,5,6}
\def\listY{1,2,3}
% to determine the number of elements in a list
\makeatletter
\long\def\length#1{%
\expandafter\xlength\expandafter0#1,\relax,}
\long\def\xlength#1#2,{%
\ifx\relax#2%
\the\numexpr#1\relax
\expandafter\@gobblefour
\fi
\expandafter\xlength\expandafter{\the\numexpr#1+1\relax}}
\makeatother
% to create constants in both TeX and PS scopes
\def\const#1#2{%
\expandafter\edef\csname#1\endcsname{\the\numexpr#2\relax}%
\pstVerb{/#1 \csname#1\endcsname\space def}%
}
\const{Nx}{\length{\listX}}
\const{Ny}{\length{\listY}}
\const{CellW}{1}
\const{CellH}{2}
\const{CanvasWidth}{\Nx*\CellW}
\const{CanvasHeight}{\Ny*\CellH}
\begin{document}
\begin{pspicture}[showgrid=bottom](\CanvasWidth,\CanvasHeight)
% use other PS constants here
\end{pspicture}
\end{document}