引数を \ref{..} とするマクロの定義

引数を \ref{..} とするマクロの定義

- 匿 名 の投稿
返信数: 2
こんにちは

山下と申します.コマンドの利用法で分からない点が出てきました.対応策をご存じの方,ご教示お願い致します.

やりたいことは,
1)OTF の \ajMaru コマンド使う.ただし,数字はカウンターを用いて定義する.
2)カウンターにラベルを付け,そのラベルで番号を参照できるようにする.

ということです.以下のようなファイルを作ってみましたが,うまくいきません.

\documentclass[a4j,10pt]{jsarticle}
\usepackage{otf}
\newcounter{suji}
\setcounter{suji}{0}
\def\maru#1{\refstepcounter{suji}\ajMaru{\value{suji}}\label{#1}}
\begin{document}

\maru{hoge1}
\maru{hoge2}

\ajMaru{\ref{hoge2}}

\end{document}

最後の方の「\ajMaru{\ref{hoge2}}」がなければうまく行きますので,ここがおかしいのだと思います.

少し調べたところでは expandafter を使うのではないかと見当をつけたのですが,どうにもうまくいきません.

お手数ですが,対応策がお分かりの方,ご教示お願い致します.

匿 名 への返信

Re: 引数を \ref{..} とするマクロの定義

- 匿 名 の投稿
単に \ajMaru による丸数字で番号付けした項目を
参照できるようにしたいという話なら,
\ajLabel を使って済ませるのもよいでしょう.

e.g.
\documentclass{jarticle}
\usepackage{otf}
\newcounter{suji}
\renewcommand*{\thesuji}{\ajLabel\ajMaru{suji}}
\DeclareRobustCommand*{\maru}[1]{%
  \refstepcounter{suji}%
  \thesuji
  \label{#1}}
\begin{document}
\maru{patapata}ぱたぱた

\maru{oyoyo}およよ

項目\ref{patapata}と\ref{oyoyo}には意味はありません.
\end{document}

そういう(otf パッケージに特化した)話ではなく,
「\ref で取得できる情報をさらに加工して使う」という話であれば,
「LaTeX 自体が \label/\ref によって何をしているのか」を調べたほうが
よいでしょう.
# 「\ref で取得できる情報をさらに加工して使う」ことを支援する
# パッケージ類の有無は存じません.

とりあえず,次の点には注意が必要です.
・\ref で参照したラベルが設定されていないとき(「LaTeX Warning: Reference
  `<ラベル文字列>'」云々という警告がなされる場合)には,
  \ref を用いてもその後の処理に使えるデータはまず得られないでしょう.
・参照するラベルが設定されていたとしても,\ref は参照するもの「だけ」を
  与えるわけではありません(\relax や \null が追加されています).
  したがって,\ref での参照結果をそのまま他のマクロに渡しても
  うまくいくとは限りません.
  例えば,「(非負)整数を 10 進表記した文字列」が与えられることを
  前提としたマクロには,(\expandafter を使ってあらかじめ展開したとしても)
  \ref での参照結果を与えることはできません.

とりあえず,次のようなことは可能です.
# ただし,「LaTeX の相互参照処理に手を加えるようなパッケージ」
# (e.g. hyperref パッケージ)を用いた場合,この例にあるような
# LaTeX の内部処理を「単純に」借用した処理はうまくいかなくなることがあります.

\documentclass{jarticle}
\usepackage{otf}
\newcounter{suji}
\DeclareRobustCommand*{\maru}[1]{%
  \refstepcounter{suji}%
  \ajMaru{\arabic{suji}}%
  \label{#1}}
\makeatletter
\def\maruref#1{%%% #1: <label>
  \expandafter\ifx\csname r@#1\endcsname\relax
      %%% ラベル <label> に関する相互参照情報がない場合
      \ref{#1}%%% \ref 自体を用いて「未定義のラベル」に関する警告処理等を行う
  \else
      %%% ・\label{<foo>} は aux ファイルに
      %%%  \newlabel{<foo>}{{<\ref{foo}で参照されるもの>}{<\label{foo}の位置のページ番号>}}
      %%%  を書き出す(ただし,\label が書き出させる内容を変更するパッケージはある).
      %%% ・\newlabel{<foo>}{{<ref>}{<page>}} は \r@<foo> を
      %%%  \gdef\r@<foo>{{<ref>}{<page>}}%%% (*)
      %%%  のごとく定義する(ラベルの重複に関する検査も行う).
      %%%  (つまり,\ref{<foo>} で参照されるもの「のみ」が要るときには,
      %%%  (*) における <ref> の部分を取り出せばよい.)
      \protected@edef\@maruref@temp{%
        \expandafter\expandafter\expandafter
        \@firstoftwo\csname r@#1\endcsname\empty\empty}%
%      \protected@edef\@maruref@temp{%
%        \expandafter\expandafter\expandafter
%        \@car\csname r@#1\endcsname\empty\@nil}%
      \ajMaru{\@maruref@temp}%
  \fi}
\makeatother
\begin{document}
\maru{patapata}ぱたぱた

\maru{oyoyo}およよ

項目\maruref{patapata}と\maruref{oyoyo}には意味はありません.
\end{document}
匿 名 への返信

Re: 引数を \ref{..} とするマクロの定義

- 匿 名 の投稿
匿名様

山下です.ご回答ありがとうございました.うまくいきました.

\ajLabel の存在は知りませんでした.


> 参照するラベルが設定されていたとしても,\ref は参照するもの「だけ」を 与えるわけではありません(\relax や \null が追加されています).
したがって,\ref での参照結果をそのまま他のマクロに渡してもうまくいくとは限りません.
例えば,「(非負)整数を 10 進表記した文字列」が与えられることを前提としたマクロには,(\expandafter を使ってあらかじめ展開したとしても)\ref での参照結果を与えることはできません.

これも知りませんでした.\ref{} で出力したら「1」や「2」とだけ出ていたので,あとは expandafter をどう使うかの問題だと思っていました.

勉強になりました.