# Define and set length in one command

Sorry this might be a very simple question, I am trying to cleanup a style file, and would like to write a command that basically runs the following code:

\newlength{<name>}\setlength{<name>}{<value>}


Based on another command that runs a \def, I though I'd be able to use expandafter and csname easily; here is what I tried:

\newcommand{\deflen}[2]{%
\expandafter\newlength{%
\csname #1\endcsname}\setlength{%
\csname #1\endcsname}{#2}
}


Unfortunately, this seems to generate an error related to csname being already defined. I think it means that I can't use csname twice in the same expand, but I don't know how to define the name first, and then use it twice... Help? :)

-

You need to assemble the control sequence name before defining with \newcommand, and before using it. This can be achieved using \expandafter twice.

\newcommand{\deflen}[2]{%
\expandafter\newlength\csname #1\endcsname
\expandafter\setlength\csname #1\endcsname{#2}%
}

\deflen{mylength}{12pt}

\showthe\mylength

-
Thank you very much, that works of course :) – Sh3ljohn Apr 18 '14 at 16:54

Ian Thompson's code is good, but you could add the check whether you can define a new length in the first place; calling, say,

\deflen{textwidth}{6pt}


would issue an error message at \newlength, but it would set \textwidth nonetheless. Since you are in a style file you don't need \makeatletter for @ commands, so you can do

\newcommand{\deflen}[2]{%
\expandafter\@ifdefinable\csname #1\endcsname{\prefix@deflen{#1}{#2}}%
}
\newcommand{\prefix@deflen}[2]{%
\expandafter\newlength\csname #1\endcsname
\expandafter\setlength\csname #1\endcsname{#2}%
}


The code given as second argument to \@ifdefinable is executed only if the control sequence given as first argument is undefined; otherwise an error is raised and the code is ignored.

Note that prefix stands for the prefix used in the style file for not clobbering other packages' macros.

A LaTeX3 version could be

\RequirePackage{xparse}
\ExplSyntaxOn

\NewDocumentCommand{\deflen}{ s m m }
{
\IfBooleanTF { #1 }
{ \prefix_deflen:nnn { dim }  { #2 } { #3 } }
{ \prefix_deflen:nnn { skip } { #2 } { #3 } }
}

\cs_new_protected:Npn \prefix_deflen:nnn #1 #2 #3
{
\cs_if_exist:cTF { #2 }
{
\msg_error:nnn { package } { already~defined } { #2 }
}
{
\__prefix_deflen:nnn { #1 } { #2 } { #3 }
}
}
\cs_new_protected:Npn \__prefix_deflen:nnn #1 #2 #3
{
\use:c { #1_new:c } { l_prefix_#2_#1 }
\use:c { #1_set:cn } { l_prefix_#2_#1 } { #3 }
\cs_set_eq:cc { #2 } { l_prefix_#2_#1 } % user level name
}

\msg_new:nnnn { package } { already~defined }
{
}
{
}

\ExplSyntaxOff


Note that \deflen{foo}{6pt} will define \l_prefix_foo_skip as the internal name of the register, but also \foo at the user level. The *-version would allocate a rigid length register (a \dimen, in TeXspeak).

Test code:

\deflen{foo}{3pt}
\showthe\foo
\show\foo

\deflen*{baz}{3pt}
\showthe\baz
\show\baz

\deflen{textwidth}{3pt}


Here's the terminal output:

> 3.0pt.
l.40 \showthe\foo

?
> \foo=\skip47.
l.41 \show\foo

?
> 3.0pt.
l.44 \showthe\baz

?
> \baz=\dimen133.
l.45 \show\baz

?

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
!
! Control sequence \textwidth already defined.
!
! See the package documentation for further information.
!
! For immediate help type H <return>.
!...............................................

l.46 \deflen{textwidth}{3pt}

? h
|'''''''''''''''''''''''''''''''''''''''''''''''
| The control sequence \textwidth already exists. Please use a new name; the
| command will not be executed.
|...............................................
?

-
Your answer is incredible, I didn't even know there was a LaTeX3.. Thank you very much! – Sh3ljohn Apr 18 '14 at 20:53
@Sh3ljohn There's not yet a LaTeX3, but its programming layer is already usable along with current LaTeX. As you see, there's no visible \expandafter. Once one gets the hang of it, programming is really easier. – egreg Apr 18 '14 at 20:55