Having syntactic sugar for ranges can be useful in programming languages. For example in Ruby, one can use a range by

(2..10).map {|elem| elem + 1}

to get an array consisting of each element in the range added by one ([3, 4, ..., 11]).

I've found it helpful to take a look at how things are done in other languages which use Alonzo Church's lambda logic, in this case, Scheme:

(define (range low high)
    [(> low high) null]
    [else (cons low (range (+ low 1) high))]))

(I'm assuming that [...]-syntax is specific to PLT Scheme. The above is taken from this webpage.)

So, recursion, eh? Sure, why not:

\def\range#1#2{\ifnum#1>#2\else#1, \range{\the\numexpr#1+1\relax}{#2}\fi}

Well OK, I get the range (with a surplus comma at the end), but it starts to choke on larger ranges. Why? Looking at the log-file might give a clue with \tracingmacros=2:

\range #1#2-><macro definition>
#1<-\the \numexpr \the \numexpr \the \numexpr \the \numexpr ...

OK, I get the idea.

So I'd need to throw in some \expandafters, right?:


\def\R@nge#1#2{\number#1 \ifnum#1<#2, \expandafter\R@nge


Now it doesn't choke.

I've fallen in love with Alan Jeffrey's lambda.sty for lists in TeX's mouth, and so my instinct was to try and make that range into a list:

\input lambda.sty
\def\R@nge#1#2{\number#1 \ifnum#1<#2, \expandafter\R@nge

\Unlistize{\Listize[\R@nge{2}{10}]} % works, but getting back to the ruby example,


\Unlistize{\Map\Succ{\Listize[\R@nge{2}{10}]}} % doesn't work
% (expected result: [3, 4, 5, 6, 7, 8, 9, 10, 11],
% instead of: [2, 3, 4, 5, 6, 7, 8, 9, 10+1].)

Maybe those \expandafters are getting back to haunt me at this stage?

So next I tried to follow more strictly the Scheme version:

\input lambda.sty


Looks about the same as the Scheme version, doesn't it? Alas, it returns an empty list!

The Question

How can I make a range-macro which would output a list (in the lambda.sty-sense) so I can use \Map and such with it?

I have an inkling that the command should somehow resemble the \Listize-macro from lambda.sty:


But I haven't been able to figure out what to change and how.

  • Sorry, but I can't follow all the code snippets; please try and make them full compilable examples.
    – egreg
    Jun 24 '12 at 9:56
  • @egreg: OK, done.
    – morbusg
    Jun 24 '12 at 10:10

Beware (not) terminating numbers!

\input lambda.sty
\def\Range[#1..#2]{\TeXif{\ifnum#1>#2 }{\Nil}%



I added a space after #2 and a \relax after the \numexpr

$ pdftex ltest2
This is pdfTeX, Version 3.1415926-2.3-1.40.12 (TeX Live 2011/Cygwin)
 restricted \write18 enabled.
entering extended mode
(./ltest2.tex (./lambda.sty)
[2, 3, 4, 5, 6, 7, 8, 9, 10]
No pages of output.
Transcript written on ltest2.log.
  • Awesome! Yes, that was IT! Thank you thank you thank you! :-D
    – morbusg
    Jun 25 '12 at 10:53
  • Ooh, just a short comment for the reader who is wondering about the \expandafter-connection on the "choking-effect": Just put a \expandafter before the recursive \Range call, and another after it. Makes all the difference. :-)
    – morbusg
    Jun 26 '12 at 15:13
  • oops sorry should have noticed that: feel free to edit my answer to your final tested version:-) Jun 26 '12 at 15:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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