# [texhax] Fragile command problem?

Toby Cubitt tsc25 at cantab.net
Sat Apr 14 10:22:35 CEST 2007

Donald Arseneau wrote:
> Toby Cubitt <tsc25 at cantab.net> writes:
>> This works fine until I try to use it inside \edef or (more
>> importantly for my purposes) inside \csname...\endcsname.
>
> Those are areas of macro expansion only, no typesetting or
> even assignments.  \@ifnextchar uses assignments, and is not
> purely expandable, so it can't work.  You should instead use
> a definitive end-marker token and consume all arguments as
> macro parameters.

I think I understand now. \let and \def are not expandable, so \edef and
\csname just leave them alone when expanding. The result is that
whatever is being \let or \def'ed gets expanded, and chaos ensues!

> Since the point of the \@ifnextchar seems to be to insert an
> empty "type" when there is none, then why not just latch on
> to the empty [] at the end...
>
>  \def\sref at type#1{%
>     \expandafter\expandafter\expandafter%
>     \sref@@type\csname r@#1\endcsname}
>
>  \def\sref@@type#1#2{\sref@@@type#1[]\delimiter}
>
>  \def\sref@@@type#1[#2]#3\delimiter{#2}

That's a really neat solution! I was in fact using the "[]" as an
end-delimeter, not being aware of the convention of using \@nil or
\delimeter or some such. I like the way your solution turns my ignorance
to use :)

Robin Fairbairns suggested (off-list) using a macro that defines a macro
in this kind of situation, which I guess is a more generally applicable
solution (i.e. the macro defines \@result to hold the "type", and
\@result *is* then expandable).

>> vaguely gather that this might be a problem with the command being fragile
>> (due to the \@ifnextchar?), therefore requiring the command definition to be
>> protected
>
> While purely expandable macros are indeed robust in all cases,
> there are also robust commands that are not expandable.  Moreover,
> no ammount of \protect will make your macro work by expansion.

Yes, I see that now. It's taking a while to get used to the fact that
macro expansion is nothing like evaluation in a normal procedural
language (it just appears similar by accident, occasionally).

Thanks a lot for taking the time to explain this,

Toby