LATEX-L Archives

Mailing list for the LaTeX3 project

LATEX-L@LISTSERV.UNI-HEIDELBERG.DE

Options: Use Forum View

Use Monospaced Font
Show Text Part by Default
Show All Mail Headers

Message: [<< First] [< Prev] [Next >] [Last >>]
Topic: [<< First] [< Prev] [Next >] [Last >>]
Author: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
Subject:
From:
Joseph Wright <[log in to unmask]>
Reply To:
Mailing list for the LaTeX3 project <[log in to unmask]>
Date:
Thu, 6 Aug 2009 07:20:26 +0100
Content-Type:
text/plain
Parts/Attachments:
text/plain (117 lines)
Hello Lars,

I've answered a lot of things as follow-ons from Will's comments.  Some
that make most sense here.

>> As promised yesterday, I'd like to discuss finalising xparse. 
> [snip]
>> Several questions have come up about xparse.  At the most basic level,
>> the idea of using something like xparse rather than \def 
> 
> Well, it's more a replacement for \newcommand and friends than for \def...

True: in which case the syntax needs to be explainable to normal users.
(My point about \def was that xparse does things \newcommand can't, and
that all functions are \protected).

>> The idea here is that it makes LaTeX syntax
>> more "regular", useful for translation to other formats.  I think he's
>> right, but wonder how others see it.  The current xparse allows both
>> space-skipping and non-space-skipping tests.  I'd certainly say we
>> should go with only one: either spaces are allowed or they are not.
> 
> Since TeX always skips spaces (i) after control sequences whose names
> consist of letters and (ii) in front of a mandatory argument, the only
> possibility if you want to make it more "regular" for non-TeX parsers is
> to skip spaces in front of all kinds of argument. I think that is the
> wrong way to go however, as it increases the risk of LaTeX grabbing text
> that isn't arguments.

Yes, the space-skipping of TeX does limit us. My take is to go the other
way: don't skip any spaces we can avoid skipping (so it's only the first
argument where the issue arises).

>> Finally, the question about expandability of \IfNoValue has been asked
>> before.  As \DeclareDocumentCommand only ever makes \protected
>> functions, I don't think we need to worry.  The idea is that the NoValue
>> test should be done "early":
>>
>> \DeclareDocumentCommand \foo { o m } {
>>   \IfNoValueTF {#1} {
>>     \int_function_one:n {#2}
>>   }{
>>     \int_function_two:nn {#1} {#2}
>>   }
>> }
>>
>> and not in the internal functions.  So the test can never be expanded,
>> and there is not an issue (I hope).
> 
> There's quite a lot which is wrong with that. First, you presume that
> optional arguments are mostly a method of combining two
> implementation-level commands into one user-level command; in that
> particular case, it would probably be easier to just expose
> \int_function_one:n and \int_function_two:nn separately. Second, you
> assume that the \IfNoValueTF test will happen close to the command which
> takes an optional argument (otherwise protection status becomes
> irrelevant), but a great advantage of \NoValue is that it can be passed
> around without syntactic difficulties, so the actual test might happen
> in a distant helper macro or even completely separate from the \foo
> command (if the argument is stored away in a token list). Finally,
> you're thinking too imperatively about the whole thing, thus discarding
> the possibility of performing such tests at expand-only time.
> 
> The following is a short extract from some code I've been using for
> years, and which occurs entirely within a \[log in to unmask] Here, I'd
> like to switch the idiom "\ifx\NoValue#1\@empty" to ”\IfNoValueTF{#1}":
> 
>       \LevelSorted{%
>          #4 \ifx \NoValue#1\@empty
>             \TD@namespace
>          \else
>             \TD@convert@colons #1::\relax
>          \fi
>       }{%
>          \texttt{#3}%
>          \ifx \NoValue#5\@empty \else\space(#5)\fi, %
>          \ifx \NoValue#1\@empty
>             \texttt{\TD@namespace} %
>          \else\ifx $#1$%
>             global %
>          \else
>             \texttt{\TD@convert@colons #1::\relax} %
>          \fi\fi \namespacephrase
>       }%
> 
> Good luck rewriting that in imperative style, as a non-expandable
> \IfNoValueTF would require (and you seem to prefer!!). Mind you, this is
> maybe a third of the full thing being \edef'ed...

The reason I said this was that my reading of the xparse
documentation/idea is that it is supposed to be used only to make
"wrapper" macro.  Everything else is meant to be handed off to
well-defined internals. As I understand it, you are no supposed to hand
\NoValue "along": it is not meant to escape from the code you define
directly using xparse. So if you want to send an marker value or
something through, you do it explicitly:

\IfNoValueTF {#1} {
  \int_function:n { \q_no_value } % use \quark_if_no_value:n test later
}{
  \in_function:n {#1}
}

(If we could risk using a quark directly, this would not be an issue,
but it is pretty clear we can't.)

That said, in xparse-alt I've used an alternative implementation that
makes \IfNoValueTF expandable with newer engines (it uses \(pdf)strcmp).
The test is not as clever at the current one, but does have this
distinct advantage. (I'd much prefer an expandable test, as it leaves
the programmer freedom to do what they feel is best.)

I guess we need to be clear on what is supposed to happen with \NoValue.
 I'd be keen to know how other people see this.
-- 
Joseph Wright

ATOM RSS1 RSS2