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.

I am trying to make macro with variadic arguments, iterating over them. The final result is supposed to be:

\foreach[x]((var = \x )){foo}{bar}{baz}\null

evals to

var = foo var = bar var = baz

My naive guess is this one:

\def\Macro#1{\if \null#1 . \else ,\noexpand\Macro \fi}
\Macro foogg\null

I expected it to eval to ,,,,,., but it evals to ,oogg. Am I understanding \noexpand behavior wrong?

share|improve this question
3  
Can you please clarify your aim? However, the test \if\null#1 will always evaluate to false, because \if expands tokens and the expansion of \null is \hbox{}, so \if is comparing \hbox to {. –  egreg Mar 2 '13 at 16:54
2  
Many list parsers (like pgffor and etoolbox) would be able to assist in your task. See Cunning (La)TeX tricks, for example. –  Werner Mar 2 '13 at 17:26

2 Answers 2

up vote 7 down vote accepted

Change \noexpand to \expandafter, that's what you need to "skip" that \fi. As well, as egreg points out, \if\null won't work. Either use \ifx, or change \null to \relax and hope it is not contained in your text. The reason why \relax will work is that it is unexpandable and \if takes it, instead of expanding. For the reason that \relax or \null might be used by someone else, a much safer option is to use a command that doesn't exist, like \thisIStoheczSdelimiter:

\def\Macro#1{\ifx\thisIStoheczSdelimiter#1 . \else ,\expandafter\Macro \fi}
\Macro foogg\thisIStoheczSdelimiter

As for working foreach cycles, look into pgffor package. Your code, IIRC, could be rewritten as

\foreach \x in {foo, bar, baz}{ var = \x, }
share|improve this answer
    
It's not sufficient; see my other comment. –  egreg Mar 2 '13 at 16:56
    
I know, I missed that it's not \ifx. I'll correct. –  tohecz Mar 2 '13 at 16:57
\def\Macro#1{\if \null#1 . \else ,\noexpand\Macro \fi}
\Macro foogg\null

\def\xnull{\null}
\def\Macro#1{\def\tmp{#1}\ifx\tmp\xnull\else ,#1\expandafter\Macro \fi}
\Macro foogg\null

\bye

produces ,foogg from your original then ,f,o,o,g,g from the modified version, in your original the \noexpand makes \Macro act like \relax and so do nothing after the first call, so only f is ever taken as an argument.

The above is plain TeX, but if you are intending this for LaTeX you should really use a different syntax, one of the main aims of LaTeX is to give a unifying syntactic structure, and LaTeX commands never take a variable number of {} arguments. The LaTeX syntax would be a comma separated list within a single {} argument.

share|improve this answer

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.