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 } Mar 1 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. Mar 1 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. Mar 1 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. Mar 1 at 12:13
  • I wonder whether on should group the \keys_set:nn { mymodule } { #1 } command as { \keys_set:nn { mymodule } { #1 } } or not.
    – Ragonese
    Mar 1 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.
    – Ragonese
    Mar 1 at 13:58
  • Is it a common occurrence to have a command to set the keys as is done by \setmymodulekeys ?
    – Ragonese
    Mar 1 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 Mar 1 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. Mar 1 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 ?
    – Ragonese
    Mar 1 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.
    – egreg
    Mar 1 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 ?
    – Ragonese
    Mar 1 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.
    – egreg
    Mar 1 at 22:02
  • That is right, it is the same as your strategy 2.
    – Ragonese
    Mar 1 at 22:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .