2

When the initial values are not set and the arguments are empty, the current values in the variables are used, not necessarily the .initial:n ones.

.initial:n only sets the values once at point of use, without adding any way to reset those values later.

Is the situation described considered defective ? Should one actually disallow the use of the current values and reset every time a command gets called ?

\documentclass{article}

\ExplSyntaxOn

% Define a new key-value family
\keys_define:nn { mymodule }
{
  width  .dim_set:N = \l_mymodule_width_dim,
  %%width .initial:n = 34pt,
  width .default:n = 10pt,
  
  height .dim_set:N = \l_mymodule_height_dim,
  %%height .initial:n = 34pt,
  height .default:n = 10pt,
  
  margin .dim_set:N = \l_mymodule_margin_dim,
  %%margin .initial:n = 34pt,
  margin .default:n = 10pt,
}

% Command to use the keys
\NewDocumentCommand{\setdimensions} { O{} }
{
  % Use the dimensions in your document or perform other actions
  \fbox
  {
    \keys_set:nn { mymodule } { #1 }
    \begin{tabular}{ll}
      Width: & \dim_use:N \l_mymodule_width_dim \\
      Height: & \dim_use:N \l_mymodule_height_dim \\
      Margin: & \dim_use:N \l_mymodule_margin_dim
    \end{tabular}
  }
}

\ExplSyntaxOff

\begin{document}

% Example usage
With custom values:

\setdimensions[%
  width = 8cm,
  height = 4cm,
  margin = 1.5cm,
]

With initial values:

\setdimensions

With default values:

\setdimensions[width,height,margin]

\end{document}
7
  • 2
    we can't tell you want you want to do whether you want to allow document defaults or force a reset every time, You can do either., If you want every use to start from normalised settings do \keys_set:nn { mymodule } { width = 8cm, height = 4cm, margin = 1.5cm} \keys_set:nn { mymodule } { #1 } Commented Mar 1, 2024 at 11:53
  • without adding any way to reset those values later. is of course incorrect you can set them at any time using \keys_set:nn that is exactly what that command does. Commented Mar 1, 2024 at 11:54
  • 1
    Your prefix With initial values: is misleading, it would be better to say: With current values: as the initial values are not reset, your default version will just use whatever the current values of the keys are. Commented Mar 1, 2024 at 11:56
  • there is nothing special about an empty argument here, each key is considered separately the issue iher you set a key or not, the argument is only empty as you set no keys. Commented Mar 1, 2024 at 12:13
  • I wonder whether on should group the \keys_set:nn { mymodule } { #1 } command as { \keys_set:nn { mymodule } { #1 } } or not. Commented Mar 1, 2024 at 20:03

2 Answers 2

2

I modified your example to show two variants A (your version) which picks up the current setttings for any key you don't set, and B which normalises all keys so the current settings are not used.

enter image description here

\documentclass{article}

\ExplSyntaxOn

% Define a new key-value family
\keys_define:nn { mymodule }
{
  width  .dim_set:N = \l_mymodule_width_dim,
  %%width .initial:n = 34pt,
  width .default:n = 10pt,
  
  height .dim_set:N = \l_mymodule_height_dim,
  height .initial:n = 34pt,
  height .default:n = 10pt,
  
  margin .dim_set:N = \l_mymodule_margin_dim,
  %%margin .initial:n = 34pt,
  margin .default:n = 10pt,
}

% Command to use the keys
\NewDocumentCommand{\setdimensionsA} { O{} }
{
  % Use the dimensions in your document or perform other actions
  \fbox
  {
    \keys_set:nn { mymodule } { #1 }
    \begin{tabular}{ll}AAA\\
      Width: & \dim_use:N \l_mymodule_width_dim \\
      Height: & \dim_use:N \l_mymodule_height_dim \\
      Margin: & \dim_use:N \l_mymodule_margin_dim
    \end{tabular}
  }
}

\NewDocumentCommand{\setdimensionsB} { O{} }
{
  % Use the dimensions in your document or perform other actions
  \fbox
  {
    \keys_set:nn {mymodule} {
      width = 100pt,
      height = 200pt,
      margin = 300pt,
      }
    \keys_set:nn { mymodule } { #1 }
    \begin{tabular}{ll}BBB\\
      Width: & \dim_use:N \l_mymodule_width_dim \\
      Height: & \dim_use:N \l_mymodule_height_dim \\
      Margin: & \dim_use:N \l_mymodule_margin_dim
    \end{tabular}
  }
}

\NewDocumentCommand\setmymodulekeys{m}{ \keys_set:nn { mymodule } { #1 }}

\ExplSyntaxOff

\begin{document}

% Example usage
With custom values:

\setdimensionsA[%
  width = 8cm,
  height = 4cm,
  margin = 1.5cm,
]

\setdimensionsB[%
  width = 8cm,
  height = 4cm,
  margin = 1.5cm,
]

With current values:

\setdimensionsA

\setdimensionsB

With default values:

\setdimensionsA[width,height,margin]

\setdimensionsB[width,height,margin]

Change current values in the current document scope


\setmymodulekeys{width=5pt,height=5pt,margin=5pt}


With new current values:

\setdimensionsA

\setdimensionsB


\end{document}

You can use both styles in a single command. for example in \includegraphics it rarely makes sense to pick up a current value for the file name, it needs to be specified each time but people often globally set width to some fraction of \textwidth if they want all images the same width.

4
  • In essence, there exist circumstances where implementations A and B are appropriate. There is no reason to always favour one over the other. Commented Mar 1, 2024 at 13:58
  • Is it a common occurrence to have a command to set the keys as is done by \setmymodulekeys ? Commented Mar 1, 2024 at 14:04
  • yes. \hypersetup in hyperref, \sisetup in siunitx, ... in graphicx I don't as global settings less commn but I document \setkeys{Gin}{...} which is the same thing. @Ragonese Commented Mar 1, 2024 at 14:10
  • @Ragonese yes and you can choose per key, in B I reset all three but I could just have reset margin and then margin would act like B and be set per call but height and width would be set like A and pick up current document setting. Commented Mar 1, 2024 at 14:12
2

Default and initial values are different animals.

With .default:n you specify what value is supplied if the key is called without any value.

With .initial:n you specify the value that the key has, well, initially.

A common way to work with key-value items is to set the keys in a group, so when the group is closed, the initial value will be reset, but this is not always possible.

Your analysis is flawed by the fact that you set the keys inside an \fbox, which makes an implicit group.

Let's see the two possible strategies to keep initial values.

Strategy 1 – Grouping

\documentclass{article}

\ExplSyntaxOn

% Define a new key-value family
\keys_define:nn { mymodule }
{
  width  .dim_set:N = \l_mymodule_width_dim,
  width .initial:n = 34pt,
  width .default:n = 10pt,
  
  height .dim_set:N = \l_mymodule_height_dim,
  height .initial:n = 34pt,
  height .default:n = 10pt,
  
  margin .dim_set:N = \l_mymodule_margin_dim,
  margin .initial:n = 34pt,
  margin .default:n = 10pt,
}

% Command to use the keys
\NewDocumentCommand{\setdimensions} { O{} }
{
  % Use the dimensions in your document or perform other actions
    \group_begin:
    \keys_set:nn { mymodule } { #1 }
    \begin{tabular}[t]{ll}
      Width: & \dim_use:N \l_mymodule_width_dim \\
      Height: & \dim_use:N \l_mymodule_height_dim \\
      Margin: & \dim_use:N \l_mymodule_margin_dim
    \end{tabular}
    \group_end:
}

\ExplSyntaxOff

\begin{document}

% Example usage
With custom values:

\setdimensions[
  width = 80pt,
  height = 40pt,
  margin = 20pt,
]

\bigskip

With initial values:

\setdimensions

\bigskip

With default values:

\setdimensions[width,height,margin]

\end{document}

enter image description here

You see that in the second call the initial values are used.

Strategy 2 – Without grouping

If grouping is not possible or not convenient, you can precompile the initial values and use them before setting the new values.

\documentclass{article}

\ExplSyntaxOn

% Define a new key-value family
\keys_define:nn { mymodule }
{
  width  .dim_set:N = \l_mymodule_width_dim,
  width .default:n = 10pt,
  
  height .dim_set:N = \l_mymodule_height_dim,
  height .default:n = 10pt,
  
  margin .dim_set:N = \l_mymodule_margin_dim,
  margin .default:n = 10pt,
}

\tl_new:N \l_mymodule_initial_tl
\keys_precompile:nnN { mymodule } { width=34pt, height=34pt, margin=34pt } \l_mymodule_initial_tl

% Command to use the keys
\NewDocumentCommand{\setdimensions} { O{} }
{
  % Use the dimensions in your document or perform other actions
    \tl_use:N \l_mymodule_initial_tl
    \keys_set:nn { mymodule } { #1 }
    \begin{tabular}[t]{ll}
      Width: & \dim_use:N \l_mymodule_width_dim \\
      Height: & \dim_use:N \l_mymodule_height_dim \\
      Margin: & \dim_use:N \l_mymodule_margin_dim
    \end{tabular}
}

\ExplSyntaxOff

\begin{document}

% Example usage
With custom values:

\setdimensions[
  width = 80pt,
  height = 40pt,
  margin = 20pt,
]

\bigskip

With initial values:

\setdimensions

\bigskip

With default values:

\setdimensions[width,height,margin]

\end{document}

The output is the same as before.

8
  • Thusly, for the sake of clarity, would one recommend not to set the keys inside the \fbox ? Commented Mar 1, 2024 at 15:17
  • @Ragonese Not at all. I suggest to use one of those two strategies. The \fbox in your example just makes things unclear. Commented Mar 1, 2024 at 15:44
  • You recommend to group the call \keys_set:nn { mymodule } { #1 }. Seen the possibility suggested by @David to use normalised settings \keys_set:nn { mymodule } { width = 8cm, height = 4cm, margin = 1.5cm} \keys_set:nn { mymodule } { #1 }. The latter seems a superior solution. @egreg Would you agree ? Commented Mar 1, 2024 at 21:51
  • @Ragonese David's suggestion is the same as strategy 2, only less efficient. Whether using strategy 1 or 2 depends on the application. Commented Mar 1, 2024 at 22:02
  • That is right, it is the same as your strategy 2. Commented Mar 1, 2024 at 22:13

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.