Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Is it okay to put commands from xparse inside functions created by \cs_new:Npn instead of \NewDocumentCommand? Would that be a confusion of programming levels?

The example below works but I was wondering if it conforms to LaTeX3 conventions.

It tests #1 for -NoValue-; but #1 is an optional argument to public \create not to private \__mypkg_create.

mypkg.sty:

\RequirePackage{expl3}
\ProvidesExplPackage{mypkg}{2013/01/20}{0.01}{My Package}
\RequirePackage{xparse}

\NewDocumentCommand \foo {om}
 {
    \__mypkg_foo:nn {#1} {#2}
 }

\cs_new:Npn \__mypkg_foo:nn #1#2
 {
    \IfNoValueTF {#1} {true} {false}
 }
\endinput

sample.tex:

\documentclass{article}
\usepackage{mypkg}
\begin{document}
\foo{bar}
\end{document}

Edit:

mypkg.sty:

\RequirePackage{expl3}
\ProvidesExplPackage{mypkg}{2013/01/20}{0.01}{My Package}
\RequirePackage{xparse}

\NewDocumentCommand \foo {om}
 {
    \mypkg_foo:nn {#1} {#2}
 }

\cs_new:Npn \mypkg_foo:nn #1#2
 {
    \IfNoValueTF {#1} {true} {false}
 }
\endinput
share|improve this question
    
Yes and no; the example seems quite contorted. –  egreg Jan 22 '13 at 7:41
    
I edited the example. Thanks! –  eduardo.tex Jan 22 '13 at 8:09
add comment

1 Answer

up vote 7 down vote accepted

As it stands, you are making the error of using an internal command from a document command: that's not the approach the team is aiming for. One problem with LaTeX2e is that many document commands directly use internals, and that makes it very difficult to alter interfaces, internal commands, etc. safely. The LaTeX3 approach is therefore that each document command should be a simple 'translation' layer, taking a user syntax and turning into the input for a documented code-level interface

\NewDocumentCommand \foo {om}
  { \mypkg_foo:nn {#1} {#2} }

If you need to test for \NoValue, this would currently normally be done as part of this interface conversion

\NewDocumentCommand { \foo } {om}
  {
    \IfNoValueTF {#1} 
      { \mypkg_foo:nn { } {#2} }
      { \mypkg_foo:nn {#1} {#2} }
  }

(The exact detail of dealing with this 'special' token is still something that perhaps needs work.)

An alternative formulation would be

\NewDocumentCommand { \foo } { O { } m }
  { \mypkg_foo:nn {#1} {#2} }

where as we don't care if #1 is present or not we simply set an empty default.

The reason for taking this approach is that it's then possible to redefine \foo while retaining access to the functionality of \mypkg_foo:nn (as it's documented). If you use an internal function inside \foo then you effectively tie the two together. (Note that getting this right is tricky, and parts of for example my own code need revision to get this correct. It's very much a work in progress.)

share|improve this answer
    
Thank you so much! Now I understand. There are at least 2 mistakes: (i) calling \__mypkg_foo:nn directly from within \foo; and (ii) calling \IfNoValueTF from within either \mypkg_foo:nn or \__mypkg_foo:nn. –  eduardo.tex Jan 22 '13 at 8:35
    
@EduardoLima The first one is a definite mistake, the second is not quite the same as we've not tied down quite how that should work :-) –  Joseph Wright Jan 22 '13 at 8:37
    
I think to have already said this, but I'll repeat anyway: an "internal" test for "NoValue" would be welcome. In your code you basically defer it to \tl_if_empty:nTF {#1}, but this is not general as one would like it to be. –  egreg Jan 22 '13 at 9:01
    
@egreg I can see the argument for that, and indeed on of the reasons for having an expandable \IfNoValue is to allow use in c- and x-type contexts. I guess this needs raising (again) on LaTeX-L: I'll prod the team first and see what people think. –  Joseph Wright Jan 22 '13 at 9:45
1  
Joseph, I think you are not quite right here to call the same internal function when the document command has and doesn't have the optional argument. I would find \NewDocumentCommand{\foo}{om}{\IfNoValueTF{#1}{\mypkg_foo:n {#2}}{\mypkg_foo:nn {#1}{#2}}} better. This circumvents what @egreg says about the need of an internal test for -NoValue-. –  Bruno Le Floch Jan 22 '13 at 13:51
show 4 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.