<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE TIP SYSTEM "http://www.tcl.tk/cgi-bin/tct/tip/tipxml.dtd">
<!-- Converted at Wed May 22 04:00:57 GMT 2013 -->
<!-- TIP AutoGenerator - written by Donal K. Fellows -->

<TIP number='225'>
<header><title>Arithmetic Series with Optimized Space Complexity</title><author address="mailto:antirez@invece.org">Salvatore Sanfilippo</author><author address="mailto:msofer@users.sf.net">Miguel Sofer</author><status type='project' state='draft' tclversion="8.7" vote='prior'>$Revision: 1.10 $</status><history></history><created day='25' month='oct' year='2004' /></header>
<abstract>This TIP proposes to add a new command to generate arithmetic sequences as Tcl lists that may be stored in constant space in many practical situations. The only change from the point of view of the Tcl programmer is the addition of a new command named <emph style="bold">range</emph>.</abstract>
<body><section title="Rationale">
<para>An idiomatic way to assign successive elements of an arithmetic series to a variable is to use the <emph style="bold">for</emph> command. Usually the loop variable is initialized to the first element of the sequence, and incremented at every iteration of a given step using <emph style="bold">incr</emph>. The <emph style="bold">for</emph> test condition is used to limit the sequence generation to a given element, like in the following example:</para>
<verbatim><vline encoding='base64'>Zm9yIHtzZXQgaSAwfSB7JGkgPCAxMH0ge2luY3IgaX0gew==</vline><vline encoding='base64'>ICAgIHB1dHMgJGk=</vline><vline encoding='base64'>fQ==</vline></verbatim>
<para>The Tcl programming language is at higher level than the C language, where this idiom firstly appeared, so it may be desiderable to be able to generate arithmetic sequences of integer numbers in a more comfortable way. Being the Tcl list a central data structure of the Tcl language, it apperas natural to generate a Tcl list of integers, and possibly use the <emph style="bold">foreach</emph> command to loop over every element, so that the above <emph style="bold">for</emph> loop can be translated into the following fragment of code:</para>
<verbatim><vline encoding='base64'>Zm9yZWFjaCBpIFtyYW5nZSAwIDEwXSB7</vline><vline encoding='base64'>ICAgIHB1dHMgJGk=</vline><vline encoding='base64'>fQ==</vline></verbatim>
<para>The <emph style="bold">range</emph> command can be also conveniently used in different contexts. The following code generates a list of squares of 0, 1, 2, 3, ... 9.</para>
<verbatim><vline encoding='base64'>cHJvYyBtYXAge3Zhcm5hbWUgc2NyaXB0IG15bGlzdH0gew==</vline><vline encoding='base64'>ICAgIHVwdmFyICR2YXJuYW1lIHZhcg==</vline><vline encoding='base64'>ICAgIHNldCByZXMge30=</vline><vline encoding='base64'>ICAgIGZvcmVhY2ggdmFyICRteWxpc3Qgew==</vline><vline encoding='base64'>ICAgICAgICBsYXBwZW5kIHJlcyBbdXBsZXZlbCAxICRzY3JpcHRd</vline><vline encoding='base64'>ICAgIH0=</vline><vline encoding='base64'>ICAgIHJldHVybiAkcmVz</vline><vline encoding='base64'>fQ==</vline><vline encoding='base64'></vline><vline encoding='base64'>cHV0cyBbbWFwIHgge2V4cHIgeyR4KiR4fX0gW3JhbmdlIDAgMTBdXQ==</vline><vline encoding='base64'></vline><vline encoding='base64'>IyBXaWxsIG91dHB1dCAiMCAxIDQgOSAxNiAyNSAzNiA0OSA2NCA4MSI=</vline></verbatim>
<para>The <emph style="bold">range</emph> command can be implemented in a way that makes it possible to internally store the arithmetic sequences genereated in constant space if they are only accessed using <emph style="bold">foreach</emph>, <emph style="bold">llength</emph> and <emph style="bold">lindex</emph> commands (<emph style="bold">lrange</emph> may also be handled in a special way). When needed, the object will be converted into a List object automatically. From the Tcl programmer point of view this optimization is transparent.</para>
</section>
<section title="Specification of the Behaviour">
<para>The <emph style="bold">range</emph> command takes three arguments in the complete format, named <emph style="italic">start</emph>, <emph style="italic">end</emph> and <emph style="italic">step</emph>, and generates a sequence of integers accordingly to the following algorithm in pseudo code:</para>
<verbatim><vline encoding='base64'>UmFuZ2VMZW4oc3RhcnQsIGVuZCwgc3RlcCk=</vline><vline encoding='base64'>MS4gaWYgc3RlcCA9IDA=</vline><vline encoding='base64'>Mi4gICAgIHRoZW4gRVJST1I=</vline><vline encoding='base64'>My4gaWYgc3RhcnQgPSBlbmQ=</vline><vline encoding='base64'>NC4gICAgIHRoZW4gcmV0dXJuIDA=</vline><vline encoding='base64'>NS4gaWYgc3RlcCA+IDAgQU5EIHN0YXJ0ID4gZW5k</vline><vline encoding='base64'>Ni4gICAgIHRoZW4gRVJST1I=</vline><vline encoding='base64'>Ny4gaWYgc2V0cCA8IDAgQU5EIGVuZCA+IHN0YXJ0</vline><vline encoding='base64'>OC4gICAgIHRoZW4gRVJST1I=</vline><vline encoding='base64'>OS4gcmV0dXJuIDErKChBQlMoZW5kLXN0YXJ0KS0xKS9BQlMoc3RlcCkp</vline><vline encoding='base64'></vline><vline encoding='base64'>UmFuZ2Uoc3RhcnQsIGVuZCwgc3RlcCk=</vline><vline encoding='base64'>MS4gcmVzdWx0IDwtIEVNUFRZIExJU1Q=</vline><vline encoding='base64'>Mi4gbGVuIDwtIFJhbmdlTGVuKHN0YXJ0LCBlbmQsIHN0ZXAp</vline><vline encoding='base64'>My4gZm9yIGkgPC0gMCB0byBsZW4gLSAx</vline><vline encoding='base64'>NC4gICAgIHJlc3VsdC5hcHBlbmQoc3RhcnQrKGkqc3RlcCkp</vline><vline encoding='base64'>Ni4gcmV0dXJuIHJlc3VsdA==</vline></verbatim>
<para>The <emph style="italic">step</emph> argument can be omitted, and default to the value of 1, so [<emph style="bold">range</emph> 0 10 1] is the same as [<emph style="bold">range</emph> 0 10]. It&apos;s also possible to call the <emph style="bold">range</emph> command with a single argument, omitting both the <emph style="italic">start</emph> and <emph style="italic">step</emph> argument that will default respectively to 0 and 1, so that the following three commands will generate the same sequence of integers:</para>
<verbatim><vline encoding='base64'>cmFuZ2UgMCAxMCAx</vline><vline encoding='base64'>cmFuZ2UgMCAxMA==</vline><vline encoding='base64'>cmFuZ2UgMTA=</vline></verbatim>
<para>The following are examples of outputs.</para>
<verbatim><vline encoding='base64'>W3JhbmdlIDAgMTAgMV0gPT4gMCAxIDIgMyA0IDUgNiA3IDggOQ==</vline><vline encoding='base64'>W3JhbmdlIDEwIDAgLTJdID0+IDEwIDggNiA0IDI=</vline><vline encoding='base64'>W3JhbmdlIDEwIDEwXSA9PiBlbXB0eSBsaXN0</vline><vline encoding='base64'>W3JhbmdlIDEwIDIwIC0zXSA9PiBFUlJPUg==</vline><vline encoding='base64'>W3JhbmdlIDVdIC0+IDAgMSAyIDMgNA==</vline></verbatim>
<para>Infinite series and series resulting in lists bigger than the maximum list length that the Tcl code can handle are detected and reported as an error. <emph style="italic">start</emph>, <emph style="italic">end</emph>, and <emph style="italic">step</emph> can be anything can fit into a Tcl wide integer.</para>
<para>Note that there is a practical justification for the fact that the elements generated never reach the value of the End argument, with the effect of [<emph style="bold">range</emph> 0 10 1] generating the sequence 0, 1, 2, ..., 9 and a range with the same value of <emph style="italic">start</emph> and <emph style="italic">end</emph> always generating an emtpy list. This is needed in order to make it comfortable to use <emph style="bold">range</emph> and <emph style="bold">foreach</emph> instead of <emph style="bold">for</emph> loops like in the following example:</para>
<verbatim><vline encoding='base64'>Zm9yZWFjaCBpIFtyYW5nZSBbbGxlbmd0aCAkbXlsaXN0XV0gew==</vline><vline encoding='base64'>ICAgIGZvb2JhciBbbGluZGV4ICRteWxpc3QgJGld</vline><vline encoding='base64'>fQ==</vline></verbatim>
<para>Because Tcl indexes are mostly zero-based, and it is often useful to access every element of a sequence given it&apos;s length, this appears to be the more sensible behaviour (this semantic is very similar to the range() function of the Python programming language, where range() is fully used to replace C-like <emph style="italic">for</emph> loops.)</para>
<para>Unfortunately this behaviour is not as comfortable to run the indexes in reverse order:</para>
<verbatim><vline encoding='base64'>Zm9yZWFjaCBpIFtyYW5nZSBbZXhwciB7W2xsZW5ndGggJG15bGlzdF0tMX1dIC0xIC0xXSB7</vline><vline encoding='base64'>ICAgIGZvb2JhciBbbGluZGV4ICRteWxpc3QgJGld</vline><vline encoding='base64'>fQ==</vline></verbatim>
<para>But the access from the first to the last element is far more common in programs, and the range command needs to be consistent when the step is negative.</para>
<para>An alternative syntax for reverse-indexing is:</para>
<verbatim><vline encoding='base64'>Zm9yZWFjaCBpIFtyYW5nZSBbbGxlbmd0aCAkbXlsaXN0XV0gew==</vline><vline encoding='base64'>ICAgZm9vYmFyIFtsaW5kZXggJG15bGlzdCBlbmQtJGld</vline><vline encoding='base64'>fQ==</vline></verbatim>
</section>
<section title="Proposed Change">
<para>The change proposed is to modify the Tcl core in order to handle a new object type called ArithSeries, that is recongnized and handled as a special case by at least the <emph style="bold">llength</emph>, <emph style="bold">lindex</emph> and <emph style="bold">foreach</emph> commands. Syntactically, the ArithSeries object will have the string representation that is exactly that that would be produced by creating a list with the elements that would be iterated over by <emph style="bold">foreach</emph> as previously described. This TIP also proposes to add logic into <emph style="italic">SetListFromAny</emph> method of the List type in order to convert an Arithmetic Series object into a List directly without to pass from the string representation.</para>
<para>This TIP proposes to add a <emph style="bold">range</emph> command to the Tcl core having the semantics specified above, and returning an Arithmetic Series object. Formally, the syntax is:</para>
<quote><emph style="bold">range</emph> ?<emph style="italic">start</emph>? <emph style="italic">end</emph> ?<emph style="italic">step</emph>?</quote>
<para>The proposed changes are available as a Patch against HEAD that can be found in the SourceForge Tcl patch 1052584 [<url ref="http://sf.net/tracker/?func=detail&amp;aid=1052584&amp;group_id=10894&amp;atid=310894"/>]</para>
</section>
<section title="Copyright">
<para>This document has been placed in the public domain.</para>
<rule/>
</section>
<section title="Appendix: Reference Pure-Tcl Implementation">
<para>It may be useful to test the behaviour of the <emph style="bold">range</emph> command without having to apply the Patch, so the following is a pure Tcl implementation that should be exactly equivalent in the semantic to the specification in this TIP, but of course not able to store ranges in O(1) space.</para>
<verbatim><vline encoding='base64'>IyBSYW5nZUxlbihzdGFydCwgZW5kLCBzdGVwKQ==</vline><vline encoding='base64'>IyAxLiBpZiBzdGVwID0gMA==</vline><vline encoding='base64'>IyAyLiAgICAgdGhlbiBFUlJPUg==</vline><vline encoding='base64'>IyAzLiBpZiBzdGFydCA9IGVuZA==</vline><vline encoding='base64'>IyA0LiAgICAgdGhlbiByZXR1cm4gMA==</vline><vline encoding='base64'>IyA1LiBpZiBzdGVwID4gMCBBTkQgc3RhcnQgPiBlbmQ=</vline><vline encoding='base64'>IyA2LiAgICAgdGhlbiBFUlJPUg==</vline><vline encoding='base64'>IyA3LiBpZiBzZXRwIDwgMCBBTkQgZW5kID4gc3RhcnQ=</vline><vline encoding='base64'>IyA4LiAgICAgdGhlbiBFUlJPUg==</vline><vline encoding='base64'>IyA5LiByZXR1cm4gMSsoKEFCUyhlbmQtc3RhcnQpLTEpL0FCUyhzdGVwKSk=</vline><vline encoding='base64'>cHJvYyByYW5nZUxlbiB7c3RhcnQgZW5kIHN0ZXB9IHs=</vline><vline encoding='base64'>ICAgIGlmIHskc3RlcCA9PSAwfSB7cmV0dXJuIC0xfQ==</vline><vline encoding='base64'>ICAgIGlmIHskc3RhcnQgPT0gJGVuZH0ge3JldHVybiAwfQ==</vline><vline encoding='base64'>ICAgIGlmIHskc3RlcCA+IDAgJiYgJHN0YXJ0ID4gJGVuZH0ge3JldHVybiAtMX0=</vline><vline encoding='base64'>ICAgIGlmIHskc3RlcCA8IDAgJiYgJGVuZCA+ICRzdGFydH0ge3JldHVybiAtMX0=</vline><vline encoding='base64'>ICAgIGV4cHIgezErKChhYnMoJGVuZC0kc3RhcnQpLTEpL2Ficygkc3RlcCkpfQ==</vline><vline encoding='base64'>fQ==</vline><vline encoding='base64'></vline><vline encoding='base64'>IyBSYW5nZShzdGFydCwgZW5kLCBzdGVwKQ==</vline><vline encoding='base64'>IyAxLiByZXN1bHQgPC0gRU1QVFkgTElTVA==</vline><vline encoding='base64'>IyAyLiBsZW4gPC0gUmFuZ2VMZW4oc3RhcnQsIGVuZCwgc3RlcCk=</vline><vline encoding='base64'>IyAzLiBmb3IgaSA8LSAwIHRvIGxlbiAtIDE=</vline><vline encoding='base64'>IyA0LiAgICAgcmVzdWx0LmFwcGVuZChzdGFydCsoaSpzdGVwKSk=</vline><vline encoding='base64'>IyA2LiByZXR1cm4gcmVzdWx0</vline><vline encoding='base64'>cHJvYyByYW5nZSBhcmdzIHs=</vline><vline encoding='base64'>ICAgICMgQ2hlY2sgYXJpdHk=</vline><vline encoding='base64'>ICAgIHNldCBsIFtsbGVuZ3RoICRhcmdzXQ==</vline><vline encoding='base64'>ICAgIGlmIHskbCA9PSAxfSB7</vline><vline encoding='base64'>ICAgICAgICBzZXQgc3RhcnQgMA==</vline><vline encoding='base64'>ICAgICAgICBzZXQgc3RlcCAx</vline><vline encoding='base64'>ICAgICAgICBzZXQgZW5kIFtsaW5kZXggJGFyZ3MgMF0=</vline><vline encoding='base64'>ICAgIH0gZWxzZWlmIHskbCA9PSAyfSB7</vline><vline encoding='base64'>ICAgICAgICBzZXQgc3RlcCAx</vline><vline encoding='base64'>ICAgICAgICBmb3JlYWNoIHtzdGFydCBlbmR9ICRhcmdzIGJyZWFr</vline><vline encoding='base64'>ICAgIH0gZWxzZWlmIHskbCA9PSAzfSB7</vline><vline encoding='base64'>ICAgICAgICBmb3JlYWNoIHtzdGFydCBlbmQgc3RlcH0gJGFyZ3MgYnJlYWs=</vline><vline encoding='base64'>ICAgIH0gZWxzZSB7</vline><vline encoding='base64'>ICAgICAgICBlcnJvciB7d3JvbmcgIyBvZiBhcmdzOiBzaG91bGQgYmUgInJhbmdlID9zdGFydD8gZW5kID9zdGVwPyJ9</vline><vline encoding='base64'>ICAgIH0=</vline><vline encoding='base64'></vline><vline encoding='base64'>ICAgICMgR2VuZXJhdGUgdGhlIHJhbmdl</vline><vline encoding='base64'>ICAgIHNldCBybGVuIFtyYW5nZUxlbiAkc3RhcnQgJGVuZCAkc3RlcF0=</vline><vline encoding='base64'>ICAgIGlmIHskcmxlbiA9PSAtMX0gew==</vline><vline encoding='base64'>ICAgICAgICBlcnJvciB7aW52YWxpZCAoaW5maW5pdGU/KSByYW5nZSBzcGVjaWZpZWR9</vline><vline encoding='base64'>ICAgIH0=</vline><vline encoding='base64'>ICAgIHNldCByZXN1bHQge30=</vline><vline encoding='base64'>ICAgIGZvciB7c2V0IGkgMH0geyRpIDwgJHJsZW59IHtpbmNyIGl9IHs=</vline><vline encoding='base64'>ICAgICAgICBsYXBwZW5kIHJlc3VsdCBbZXhwciB7JHN0YXJ0KygkaSokc3RlcCl9XQ==</vline><vline encoding='base64'>ICAgIH0=</vline><vline encoding='base64'>ICAgIHJldHVybiAkcmVzdWx0</vline><vline encoding='base64'>fQ==</vline></verbatim>
<rule/>
</section>
<section title="Discussion">
<para>Does the TIP include a C-level api to ranges, or are they transparent also in C - in the sense that they are addressable with any of the list-oriented functions of the Tcl api? What if any changes and caveats are necessary in the documentation of Tcl&apos;s C api? <emph style="italic">Miguel</emph></para>
<para>Ranges are transparent to C level too, in the proposed patch, because the logic is put inside the commands, so directly in the code implementing lindex, foreach, ... In all the other cases, when a SetListFromAny() call occurs the range is converted into a normal Tcl list object. <emph style="italic">Salvatore</emph></para>
</section>
</body></TIP>
