FM TIP 759 is a proposition whose goal is to facilitate arithmetic calculations with Tcl. The prototype can be found at its dedicated branch
The features offered fall into three categories:
You can refer to the text of the TIP to see more details.
It came out during a very long discussion whith AMB in the page [L1 ]. I have to thank Eric Taylor also (ET), who gave me great insights on the Tcl core code style.
<News> (2026/09/25) : After the discussion with NR (see below), I added the possibility to call some commands from expr. The implementation can be found in the tip-759b_tcl90 branch . A command is called using command syntax. But it must be closed by a semi-colon.
Example of usage :
proc matrixProduct {A B} {(
foreach Arow $A Brow $B \
aMap {{a00 a01 a02} {a10 a11 a12} {a20 a21 a22}}\
bMap {{b00 b01 b02} {b10 b11 b12} {b20 b21 b22}} {
foreach valA $Arow valB $Brow varA $aMap varB $bMap {( $varA = $valA; $varB = $valB )}
};
# Return the product of matrixes, using formula.
# First row :
(($a00*$b00 + $a01*$b10 + $a02*$b20),
($a00*$b01 + $a01*$b11 + $a02*$b21),
($a00*$b02 + $a01*$b12 + $a02*$b22)),
# Second row :
(($a10*$b00 + $a11*$b10 + $a12*$b20),
($a10*$b01 + $a11*$b11 + $a12*$b21),
($a10*$b02 + $a11*$b12 + $a12*$b22)),
# Third row :
(($a20*$b00 + $a21*$b10 + $a22*$b20),
($a20*$b01 + $a21*$b11 + $a22*$b21),
($a20*$b02 + $a21*$b12 + $a22*$b22))
)}proc test {} {(
s=0
;
foreach i {1 2 3} {(s=$s+$i)}
foreach j {4 5 6} {(s=$s+$j)}
;
return $s;
)}
if 0 {
% test
21
}NR - 2026-09-18 17:55:12
Hello Florent, I think the idea is interesting, especially for numerical and mathematical code. My main concern is more about readability.
Looking at the complete 3D polyhedra with simple tk canvas example, I find that there is quite a lot of Tcl and mathematical syntax mixed together. With (...), [(...)], [foreach {()}], substitutions and regular Tcl scripts appearing within the same procedures, it can sometimes be difficult to tell at a glance where Tcl ends and the mathematical syntax begins.
I actually have a math package myself, so I know the problem you are trying to address. There are places in my own code where expressing mathematical operations in Tcl becomes quite cumbersome. For example, I have this line in one of my quaternion tests:
set q29 [[[[[[[[$q2 * $q2] * $q2] * $q2] * $q2] * $q2] * $q2] * $q2] * $q2]
This is quite extreme just to express repeated multiplication, and it is a good example of why I understand the motivation behind TIP 759.
Interestingly, I already have a ^ operator in my Quaternion package, so this particular example could simply be written as:
set q29 [$q2 ^ 9]
At the same time, I don’t really have a better solution myself, and I certainly wouldn’t have been able to come up with something like your approach.
I wonder if the concept might also work well as a separate package, perhaps with something like a ‘math::proc’ construct. This could provide a clearer boundary between regular Tcl code and the mathematical part, while still offering the benefits of the new syntax.
For example:
math::proc CrossProduct {x1 y1 z1 x2 y2 z2} {(
$y1*$z2 - $y2*$z1,
$z1*$x2 - $z2*$x1,
$x1*$y2 - $x2*$y1
)}In a function like this, I actually wouldn’t want to have other Tcl commands mixed into the mathematical expression. I would prefer the whole body to clearly be “the mathematical part”, with the boundary to regular Tcl being explicit.
Of course, my opinion is just one perspective here. I can clearly see how enthusiastic you are about the idea, especially from the amount of existing Tcl code you have already transformed using the concept. That’s actually what made me look more closely at the result and think about how it feels in a larger, real-world example.
For me, the interesting question is perhaps less about whether the mathematical syntax is useful, and more about how clearly we can separate the two worlds. In the current examples, I feel there is quite a lot of mixing between Tcl and math.
And of course, I may simply have misunderstood the intent of the TIP. If so, I apologize in advance!
Hi NR. You understood pretty well the intent of the TIP. What you are explaining is true. We can mix command syntax in arithmetic syntax, and arithmetic syntax in command syntax. So we may shift from one syntax to another frequently. It can be disturbing. But Subscripts must be recognized in arithmetic syntax. If they were not, something as simple as retrieving an element of a list would become impossible.
# Arithmetic Syntax : ... v = [lindex $L 0]; ...
We have not choice : we must allow to cross the bounderies... So, if the TIP is accepted, there should be a "good practice" guideline. The number of nested levels should be minimized.
Something I found displeasant is when I have to use the arithmetic substitution again in a nested command script
# Arithmetic Syntax : ... v = [lindex $L [($i*2)] ]; ...
Maybe a solution would be to have a special mode of command parsing, when this command is parsed from a arithmetic script. Let's say, in this situation, ) will be taken as a word terminator, and then a word like (...) would be parsed as an expression :
# Arithmetic Syntax : ... v = [lindex $L ($i*2)]; ...
A variant would be to shift to another kind of delimiters, to create a better contrast.
# Arithmetic Syntax : ... v = [lindex $L <$i*2>]; v = [lindex $L \\$i*2\\]; v = [lindex $L `$i*2`]; ...
But what is working now, is to use variables to communicate between these two worlds.
# Arithmetic Syntax : ... j = $i*2; v = [lindex $L $j]; ...
About the abondance of symboles like in [foreach ... {()}];
First idea was to create a Foreach mathfunc, with a body in arithmetic syntax, we then would write : Foreach("i",$L,{ ... });
But this is slow (uplevel). We have to use comas, we to quote the arguments... There is no gain, finally.
So A new idea came to me : it should be possible to define "COMMAND" leaf lexem type and make expr to call Tcl_ParseCommand (but not nested ..), which would then make a parse... in command syntax till the next newline or semi-colon. Then we can write :
proc test {} {(
A = (1,2,3);
foreach i $A {(
...
)};
B = (4,5,6);
...
)}It would be a lot more clear !
Of course the set of commands to be recognized like this should be in a limited number, mainly restricted to commands that control the flow (for, while, switch, if, foreach, lmap).
Would you prefer it like this ?
NR - 2026-09-19 08:12:20
Thanks, I think I understand the idea better now.
If I understand correctly, with your new approach the mathematical syntax remains the main context, and when the parser encounters one of the recognized Tcl commands, such as foreach, it switches temporarily to Tcl command syntax, then returns to the mathematical syntax afterwards.
So your example:
proc test {} {(
A = (1,2,3);
foreach i $A {(
...
)};
)}would roughly mean:
Is that the intended interpretation?
There is one thing about the ; that I am still wondering about. In Tcl, ; already has a very specific meaning: it terminates a Tcl command, for example:
set x 1; set y 2
So if ; is also used as the marker telling the math parser to resume after a Tcl command, what happens with multiple Tcl commands on the same line?
For example, would something like this be possible?
foreach i $A {( ... )}; set x 10; set y 20<FM> Tcl_parseCommand will return at the terminator, which is ;. So expr will get a TCL_TOKEN_SCRIPT containing "foreach i $A {( ... )};". After the semi-colon, we are back to expr syntax, so there will be an error like "invalid barewords set". You'll have to write :
foreach i $A {( ... )}; x=10; y=20</FM>
And more generally, would a sequence of mathematical statements be allowed on the same line, or does the parser require a newline after each one?
<FM> TIP 759 introduce ";" as a separator. So you must separate instructions by ";". On the other end, newline has no meaning at all in expr.</FM>
I am also wondering about comments. Would normal Tcl comments still work in the Tcl parts, for example:
foreach i $A {(
# some Tcl comment
...
)};Or would comments need special handling once the parser is inside the mathematical syntax?
<FM> comments were already implemented in expr. All they need is to be followed by a newline. So you can add coments, as the examples are showing it.</FM>
I ask because one thing I really like about Tcl is that newlines and semicolons are generally interchangeable as command separators, and comments can appear naturally in the code. I am curious how those existing Tcl rules would interact with this parser-switching mechanism.
One other thing I was wondering about with your new COMMAND lexeme idea: once we are already inside the arithmetic syntax, could the body of a recognized Tcl command use just parentheses instead of {( and )}?
For example:
proc test {} {(
A = (1,2,3);
foreach i $A (
...
);
)}Would the parser be able to determine from the context that the ( after foreach i $A starts the command body, while the parentheses in something like:
A = (1,2,3)
are part of the mathematical expression?
Or is there a parsing reason why the {( and )} would still be necessary?
<FM> the reason lay in the logic of the implementation. To compile it's body, the foreach command is calling the function Tcl_CompileScript. In this function, I made things so that if a script begins by ( and finish by ), then it will be compiled as an arithmetic expression. So we always have :
foreach i $L {
# command syntax
}
foreach i $L {(
# arithmetic syntax
)}To implement what you ask (use only parentheses to signal an arithmetic body) :
proc test {} {(
A = (1,2,3);
foreach i $A (
...
);
)}I would have to signal to Tcl_ParseCommand that it is parsing a command from expr. That should be possible with the nested parameter of this procedure. Then Tcl_ParseCommand would have to treat parentheses as braces, producing a simple word.
In the expr configuration, the expr parser will detect a SCRIPT TOKEN and store it as a TCL_TOKEN_COMMAND (Here I add to create a new Token type TCL_TOKEN_CMD_IN_EXPR because the "inlined command" is not enclosed in brackets). Later, the expr compiler Tcl_CompileExpr will call Tcl_CompileTokens on that Token. Tcl_CompileTokens will then call Tcl_CompileScript. Tcl_CompileScript will call Tcl_ParseCommand.
Sadly, Tcl_CompileScript only consider a string, the one pointed by the Token. No extra-flag can be passed to it. Therefore, we have no simple way to signal to Tcl_ParseCommand that it is called from expr. The only possibility to make this modulation would be to set a field in the CompileEnv structure. That could be coherent, since this TIP introduce two contexts of compilation (command / arithmetics). </FM>
NR - 2026-09-19 13:57:09
Thanks again for the detailed explanations. I understand the implementation much better now.
There is one more thing I would like to clarify. Outside of a proc body or another command body, would the following forms also work with the current implementation?
set value [(1 + 2)]
With the opening parenthesis on the following line:
set value [(
1 + 2
)]<FM> this works. ParseExpr will parse till the closing paren., followed by the bracket. Newlines don't matter in expr </FM>
And, since ; can be used to chain several arithmetic instructions, would this also work?
set value [(A = 1; B = 2; $A + $B)]
<FM> this works and returns $A+$B
What you should know here : a trailling ; will mute the expression. If you write :
set value [(A = 1; B = 2; $A + $B;)]
value is set to ""
</FM>
And, in particular, would this multiline form work as well?
set value [
(
A = 1;
B = 2;
$A + $B
)
]<FM> this won't work. The opening parenthesis must immediately follow an open bracket, and the closing parenthesis must be immediately followed by a close bracket.
You will get an error "unknown command '('"
</FM>
I am asking because I have seen similar expression-block constructs in other languages, where a parenthesized block can contain several statements and the value of the block is the value of its final expression.
I am mainly curious whether the last form is already possible with the current implementation, or whether the arithmetic parser requires the opening ( to be immediately after the [ in an arithmetic substitution.
<FM> Must be immediately after. The other way is doable, just have to add a loop on spaces to skip it. But i didn't want : If someone has a proc '(', he can shift it one space away from the bracket to use it</FM>
I also noticed that you use {(...)} for arithmetic bodies in cases such as foreach and proc, for example:
foreach i $A {(
...
)}and:
proc test {} {(
...
)}So I was wondering why the same idea is not used for a direct arithmetic block, for example:
set value {(
A = 1;
B = 2;
$A + $B
)}I assume this may be related to the fact that braces have an established meaning in Tcl, particularly with respect to substitutions. Is that the reason you use [(...)] for arithmetic substitution instead?
<FM> i have to speak about the internals of Tcl to answer... There is the parser, and there is the compiler.
The parser split a commands in words. Each word is the site of a set of substitutions (eventually empty) to produce one Tcl_Obj, collected in arrays which are then transmitted to commands. As the Tcl Parser takes words in braces like simple words, it doesn't make any substitution in it.
There is the compiler. It works only on already parsed strings. Some commands, like foreach, proc, if...etc are compiling some of there arguments (their body). I made in sure that, if this argument to be compiled is enclosed by parentheses, then it will be compiled as an expression, with arithmetic syntax (-> arithmetic compilation)
It turns out that the command set doesn't compile it's second argument. So the variable 'value' will get exactly the string that was written between the braces. To get this string substituted, you must use arithmetic substitution, aka : [(...)], so that the parser knows what it has to do. </FM>
NR - 2026-09-19 15:58:27
Thanks for the clarifications. I understand the TIP much better now, as well as the way you rewrote the 3D polyhedra with simple tk canvas example.