Могут ли keyval и pgfkeys давать одинаковые результаты?

Могут ли keyval и pgfkeys давать одинаковые результаты?

Я потратил около пяти часов (!) на изучениеКак создать команду с ключевыми значениями?(и другие ресурсы) и пытаюсь понять, как реализовать ключевые значения, и это крайне запутанно. Я написал по сути тривиальный (для большинства людей здесь, во всяком случае) тестовый случай, и в нем есть некоторые несоответствия, которые я не могу объяснить.

Вот MWE с использованием keyval.

% !TEX TS-program = lualatexmk
% !TEX encoding = UTF-8 Unicode

\documentclass{article}
\usepackage{keyval}

\makeatletter
% Key definitions
\define@key{sayhello}{towhom}{\def\sh@towhom{#1}}
% Key defaults
\setkeys{sayhello}{towhom=Michael}
% Define the command that uses the key
\newcommand{\sayhello}[2][]{%
  %\begingroup% localizes the new settings w/o calling the defaults
  \setkeys{sayhello}{towhom=Michael} % Reset defaults w/o localizing
  \setkeys{sayhello}{#1} % Set new keys
  Say hello to \sh@towhom\ #2.
  %\endgroup%
}%
\makeatother
\begin{document}
\sayhello{tomorrow}

%\sayhello[towhom]{today} % throws no value specified for towhom

\sayhello[towhom=Jill]{tomorrow}

%\sayhello[towhom]{today} % throws no value specified for towhom

\sayhello[towhom=Joe]{tomorrow}

%\sayhello[towhom]{tomorrow} % throws no value specified for towhom

\sayhello{today}
\end{document}

А вот MWE с использованием pgfkeys.

% !TEX TS-program = lualatexmk
% !TEX encoding = UTF-8 Unicode

\documentclass{article}
\usepackage{pgfkeys}

\pgfkeys{%
  /sayhello/.is family, /sayhello,
  towhom/.default=Michael,
  towhom/.store in=\sayto
}%

\newcommand*{\sayhello}[2][]{%
  \pgfkeys{/sayhello,#1}
  Say hello to \sayto\ #2.
}%
\begin{document}
%\sayhello{tomorrow} % throws undefined control sequence

\sayhello[towhom]{today}

\sayhello[towhom=Jill]{tomorrow}

\sayhello[towhom]{today}

\sayhello[towhom=Joe]{tomorrow}

\sayhello[towhom]{tomorrow}

\sayhello{today} % works perfectly
\end{document}

Я надеялся, что обе реализации дадут одинаковые результаты. Они этого не делают. keyvalпохоже, не любит указывать ключ без значения. pgfkeysведет себя непоследовательно, когда вообще не указано никаких параметров, но ведет себя идеально в случаях, когда keyvalих нет. Мои примеры неправильно закодированы? Являются ли несоответствия ожидаемым поведением? Я совершенно запутался.

решение1

Вы путаете начальное значение и значение по умолчанию. Второе используется, если вы используете ключ без указания значения. Кроме того, если вы используете команду для сохранения значения ключа, хорошей практикой будет сначала определить его с помощью \newcommand, так как это позволит избежать перезаписи существующих команд.

Лично я нахожуpgfkeys более запутанным, так как в этом случае используется одна и та же команда для определения и установки ключей, а понимание поведения некоторых обработчиков не всегда легко, см., например,Что делают обработчики ключей pgfkeys .get и .store?.

\documentclass{article}
\usepackage{keyval}

\makeatletter
\newcommand\sh@towhom{}
\define@key{sayhello}{towhom}[Default]{\def\sh@towhom{#1}}
\setkeys{sayhello}{towhom=Initial}
\newcommand{\sayhello}[2][]{%
  \begingroup  
  \setkeys{sayhello}{#1} % Set new keys
   keyval, say hello to \sh@towhom\ #2.
  \endgroup%
}%
\makeatother

\usepackage{pgfkeys}

\newcommand\sayto{}
\pgfkeys{%
  /sayhello/.is family, /sayhello,
  towhom/.store in=\sayto,
  towhom/.default=Default,
  towhom = Initial,
}%

\newcommand*{\sayhellopgf}[2][]{%
  \begingroup
  \pgfkeys{/sayhello,#1}%
   pgfkeys, say hello to \sayto\ #2.
  \endgroup 
}%

\ExplSyntaxOn
\tl_new:N \l_sayhello_towhom_tl
\keys_define:nn {sayhello}
 {
  towhom .tl_set:N = \l_sayhello_towhom_tl,
  towhom .initial:n = Initial,
  towhom .default:n = Default 
 }
 
\NewDocumentCommand\sayhelloexpl{O{}m}
 {
  \group_begin:
  \keys_set:nn{sayhello}{#1}
  l3keys,~say~hello~to~\l_sayhello_towhom_tl\c_space_tl#2
  \group_end:
 }
 
  
\ExplSyntaxOff
\begin{document}
\sayhello{tomorrow}

\sayhello[towhom]{today} 

\sayhello[towhom=Jill]{tomorrow}

\sayhello[towhom]{today} 

\sayhello[towhom=Joe]{tomorrow}

\sayhello[towhom]{tomorrow} 

\sayhello{today}

\sayhellopgf{tomorrow}

\sayhellopgf[towhom]{today} 

\sayhellopgf[towhom=Jill]{tomorrow}

\sayhellopgf[towhom]{today} 

\sayhellopgf[towhom=Joe]{tomorrow}

\sayhellopgf[towhom]{tomorrow} 

\sayhellopgf{today}


\sayhelloexpl{tomorrow}

\sayhelloexpl[towhom]{today} 

\sayhelloexpl[towhom=Jill]{tomorrow}

\sayhelloexpl[towhom]{today} 

\sayhelloexpl[towhom=Joe]{tomorrow}

\sayhelloexpl[towhom]{tomorrow} 

\sayhelloexpl{today}
\end{document}

введите описание изображения здесь

Связанный контент