% set ex 33/32This is perfectly normal. You are appearently not understanding how Tcl's "quoting" and evaluation works. And how expr itself works.
33/32
% expr {$ex}
33/32
% set a ttt
ttt
% expr {$a}
ttt
This happens wuth tcl8.6, tcl9.0 and jim.
Any explanation?
% set ex 33/32
33/32
% expr {$ex}
33/32
% set a ttt
ttt
% expr {$a}
ttt
This happens wuth tcl8.6, tcl9.0 and jim.
Any explanation?
On 8/12/2026 9:59 AM, Roderick wrote:
% set ex 33/32
33/32
% expr {$ex}
33/32
% set a ttt
ttt
% expr {$a}
ttt
This happens wuth tcl8.6, tcl9.0 and jim.
Any explanation?
No question? I will assume you are wondering why "expr {$ex}" did not return 1. Because doing so will require doing double substitution.
% expr {$a + 0}
can't use non-numeric string as operand of "+"
On Wed, 12 Aug 2026, saito wrote:
No question? I will assume you are wondering why "expr {$ex}" did not
return 1. Because doing so will require doing double substitution.
But it is doing a substitution of the expression, similar as
with scripts. Why it gives a string instead of an error?
% expr {$a + 0}
can't use non-numeric string as operand of "+"
As for example here?
And yes, it would be interesting if variable were substituted and then
the resulting expression evaluated, as hapenps with "".
On Wed, 12 Aug 2026, saito wrote:
% expr {$a + 0}
can't use non-numeric string as operand of "+"
As for example here?
And yes, it would be interesting if variable were substituted and then
the resulting expression evaluated, as hapenps with "".
I think the confusion may be that you see "33/32" as a value already, and not
as a string.
So when you say, "expr {$a}" at what point do you want the substitutions to stop?
On Wed, 12 Aug 2026, saito wrote:It is not. expr is not the same as a "block" as you would have with proc, or for or while. And the varable subsitution happens after expression parsing, not before.
So when you say, "expr {$a}" at what point do you want the substitutions to stop?
The problem is, that I imagined such expression as similar to
a script evaluation.
On Wed, 12 Aug 2026, saito wrote:
I think the confusion may be that you see "33/32" as a value already, and not as a string.
No, I do see it as a expression. The confussion is, what I said:
I expected an error.
... And the varable subsitution happens after expression parsing,
not before.
The currly brackets supresses subsitution.
To see why, look at the below disassemble, and then the code for that bytecode instruction tryCvtToNumeric,
note the "is acceptable" comment:
% set ex {5/4}
5/4
% expr {$ex}
5/4
% lds script {expr {$ex}}
...
Command 1: "expr {$ex}"
(0) push1 0 # "ex"
(2) loadStk
(3) tryCvtToNumeric
(4) done
case INST_TRY_CVT_TO_NUMERIC:
/*
* Try to convert the topmost stack object to numeric object. This is
* done in order to support [expr]'s policy of interpreting operands
* if at all possible as numbers first, then strings.
*/
valuePtr = OBJ_AT_TOS;
TRACE("\"%.20s\" => ", O2S(valuePtr));
if (GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) {
if (*pc == INST_UPLUS) {
/*
* ... +$NonNumeric => raise an error.
*/
TRACE_APPEND("ERROR: illegal type %s\n",
TY2S(valuePtr->typePtr));
DECACHE_STACK_INFO();
IllegalExprOperandType(interp, "", pc, valuePtr);
CACHE_STACK_INFO();
goto gotError;
}
/* ... TryConvertToNumeric($NonNumeric) is acceptable */
TRACE_APPEND("not numeric\n");
NEXT_INST_F0(1, 0);
}
-et
On Wed, 12 Aug 2026, Robert Heller wrote:Yes it is. *Expr* itself is doing the eval, not the read-eval-loop.
... And the varable subsitution happens after expression parsing,
not before.
The currly brackets supresses subsitution.
Here is not being suppressed:
% set a ttt; expr {$a}
ttt
And after parsing should follow evaluation, here should be an error.Yes. That is what does happen.
On Wed, 12 Aug 2026, et99 wrote:It requires a special build option, not normal for production builds.
To see why, look at the below disassemble, and then the code for that bytecode instruction tryCvtToNumeric,
note the "is acceptable" comment:
Thanks! From where you have the command lds?
It does not exist in my tclsh
R.
% set ex {5/4}
5/4
% expr {$ex}
5/4
% lds script {expr {$ex}}
...
Command 1: "expr {$ex}"
(0) push1 0 # "ex"
(2) loadStk
(3) tryCvtToNumeric
(4) done
case INST_TRY_CVT_TO_NUMERIC:
/*
* Try to convert the topmost stack object to numeric object. This is
* done in order to support [expr]'s policy of interpreting operands
* if at all possible as numbers first, then strings.
*/
valuePtr = OBJ_AT_TOS;
TRACE("\"%.20s\" => ", O2S(valuePtr));
if (GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) {
if (*pc == INST_UPLUS) {
/*
* ... +$NonNumeric => raise an error.
*/
TRACE_APPEND("ERROR: illegal type %s\n",
TY2S(valuePtr->typePtr));
DECACHE_STACK_INFO();
IllegalExprOperandType(interp, "", pc, valuePtr);
CACHE_STACK_INFO();
goto gotError;
}
/* ... TryConvertToNumeric($NonNumeric) is acceptable */
TRACE_APPEND("not numeric\n");
NEXT_INST_F0(1, 0);
}
-et
At Thu, 13 Aug 2026 06:55:58 +0000 Roderick <hruodr@gmail.com> wrote:
On Wed, 12 Aug 2026, Robert Heller wrote:
... And the varable subsitution happens after expression parsing,
not before.
The currly brackets supresses subsitution.
Here is not being suppressed:
% set a ttt; expr {$a}
ttt
Yes it is. *Expr* itself is doing the eval, not the read-eval-loop.
Compare to this:
% set a ttt; expr $a
invalid bareword "ttt"
in expression "ttt";
should be "$ttt" or "{ttt}" or "ttt(...)" or ...
And after parsing should follow evaluation, here should be an error.
Yes. That is what does happen.
You are still confused bt what the currly brackets (braces) are doing.
On Wed, 12 Aug 2026, Robert Heller wrote:
... And the varable subsitution happens after expression parsing,
not before.
The currly brackets supresses subsitution.
Here is not being suppressed:
% set a ttt; expr {$a}
ttt
And after parsing should follow evaluation, here should be an error.
I think part of what is confusing you is this fact:h
Tcl *DOES NOT* have a [sematic] parser, This is something Tcl shares wit=
LISP. Almost all other programming languages have a [sematic] parser: FORTRAN, BASIC, COBOL, Algol / Pascal, C / C++, Java, rust, and many othe=rs.
For these languages an "if" statement (for example) is something defined =in a
standard somewhere and is something programmers can count on to have a we=ll
documented structure.a
Tcl, like LISP, does not have a set of "statements", each with a specific "syntax". *Everything* [that does anything] in Tcl (like LISP) is a just=
"function". Period. Tcl does not have "if" *statements* (in the sense t=hat C
has "if" statements). Tcl just has a *function* (coded in C) named "if".=The
sematics is implemented in the if *function*, there is no specific parse =logic
for "if" or really ANY other "control flow" operation. One can easily de=fine
a proc that completely redefines what "if" looks like, or define complete=ly
new "control flow" functions.are
In LISP there are two main types of functions: those where the arguments =
evaluated before being passed and those that are NOT evaluated before bei=ng
passed. LISP's "control flow" functions (like cond) are functions where =the
argument evaluation is "supressed" and these functions call evel internal=ly.
With Tcl, all arguments are evaluated (subsituted) before being passed. Always. The currly brackets (braces) suppress evaluation (subsitutation) before passing. Really, what is happening is the braces are a kind of quo=ting,
which happens to work across newlines, so they "look" like and seem to be=have
like braces in C. But they are not really anything like braces in C. Even=when
that is what it *looks* like.xpr
Something similar is happening with expr. The braces in the argument to e=
are not a syntacic "feature" of expr, but a way of "quoting" the argument=to
expr to prevent pre-mature "evaluation" (subsitutation) of the argument(s=) to
expr. This is done to "defer" evaluation (subsitutation) until *after* ex=pr
parses the expression, becaue expr itself will perform the evaluation (subsitutation) itself (eg it calls Tcl_Eval).
At Thu, 13 Aug 2026 06:55:58 +0000 Roderick <hruodr@gmail.com> wrote:
On Wed, 12 Aug 2026, Robert Heller wrote:
... And the varable subsitution happens after expression parsing,
not before.
The currly brackets supresses subsitution.
Here is not being suppressed:
% set a ttt; expr {$a}
ttt
And after parsing should follow evaluation, here should be an error.
--
Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
Deepwoods Software -- Custom Software Services http://www.deepsoft.com/ -- Linux Administration Services heller@deepsoft.com -- Webhosting Services
To make this discussion more objective, I fed claud with the post bellowerred=20
and asked:
"Is this guy answering what at the end is quoted? Please, short answer."
Answer from Claude:
"No =E2=80=94 he restates his general theory about braces/quoting and def=
substitution, but doesn't actually address Roderick's specific example (e=xpr=20
{$a} returning ttt instead of erroring)."
Rod.
On Thu, 13 Aug 2026, Robert Heller wrote:th
I think part of what is confusing you is this fact:
=20
Tcl *DOES NOT* have a [sematic] parser, This is something Tcl shares wi=
in=20LISP. Almost all other programming languages have a [sematic] parser:
FORTRAN, BASIC, COBOL, Algol / Pascal, C / C++, Java, rust, and many=20
others.
For these languages an "if" statement (for example) is something defined=
ca
standard somewhere and is something programmers can count on to have a w= ell
documented structure.
=20
Tcl, like LISP, does not have a set of "statements", each with a specifi=
t a"syntax". *Everything* [that does anything] in Tcl (like LISP) is a jus=
=20"function". Period. Tcl does not have "if" *statements* (in the sense=
=20that C
has "if" statements). Tcl just has a *function* (coded in C) named "if"= =2E=20
The
sematics is implemented in the if *function*, there is no specific parse= =20
logic
for "if" or really ANY other "control flow" operation. One can easily=
=20define
a proc that completely redefines what "if" looks like, or define complet= ely
new "control flow" functions.
=20
In LISP there are two main types of functions: those where the arguments= =20
are
evaluated before being passed and those that are NOT evaluated before be= ing
passed. LISP's "control flow" functions (like cond) are functions where= =20
the
argument evaluation is "supressed" and these functions call evel=20
internally.
=20
With Tcl, all arguments are evaluated (subsituted) before being passed.
Always. The currly brackets (braces) suppress evaluation (subsitutation)
before passing. Really, what is happening is the braces are a kind of=20
quoting,
which happens to work across newlines, so they "look" like and seem to=
=20behave
like braces in C. But they are not really anything like braces in C. Eve= n=20
when
that is what it *looks* like.
=20
Something similar is happening with expr. The braces in the argument to=
expr
are not a syntacic "feature" of expr, but a way of "quoting" the argumen= t=20
to
expr to prevent pre-mature "evaluation" (subsitutation) of the argument(= s)=20
to
expr. This is done to "defer" evaluation (subsitutation) until *after* e= xpr
parses the expression, becaue expr itself will perform the evaluation
(subsitutation) itself (eg it calls Tcl_Eval).
=20
=20
At Thu, 13 Aug 2026 06:55:58 +0000 Roderick <hruodr@gmail.com> wrote:
=20
=20=20
=20
On Wed, 12 Aug 2026, Robert Heller wrote:
=20
... And the varable subsitution happens after expression parsing,=20
not before.
=20
The currly brackets supresses subsitution.
Here is not being suppressed:
=20
% set a ttt; expr {$a}
ttt
=20
And after parsing should follow evaluation, here should be an error.
=20
=20
=20
--
Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
Deepwoods Software -- Custom Software Services
http://www.deepsoft.com/ -- Linux Administration Services
heller@deepsoft.com -- Webhosting Services
To make this discussion more objective, I fed claud with the post bellow
and asked:
"Is this guy answering what at the end is quoted? Please, short answer."
Answer from Claude:
"No |o-C-o he restates his general theory about braces/quoting and deferred substitution, but doesn't actually address Roderick's specific example
(expr {$a} returning ttt instead of erroring)."
Rod.
On Thu, 13 Aug 2026, Robert Heller wrote:
I think part of what is confusing you is this fact:
Tcl *DOES NOT* have a [sematic] parser, This is something Tcl shares with LISP. Almost all other programming languages have a [sematic] parser: FORTRAN, BASIC, COBOL, Algol / Pascal, C / C++, Java, rust, and many others.
For these languages an "if" statement (for example) is something defined in a
standard somewhere and is something programmers can count on to have a well documented structure.
Tcl, like LISP, does not have a set of "statements", each with a specific "syntax". *Everything* [that does anything] in Tcl (like LISP) is a just a "function". Period. Tcl does not have "if" *statements* (in the sense that C
has "if" statements). Tcl just has a *function* (coded in C) named "if". The
sematics is implemented in the if *function*, there is no specific parse logic
for "if" or really ANY other "control flow" operation. One can easily define
a proc that completely redefines what "if" looks like, or define completely new "control flow" functions.
In LISP there are two main types of functions: those where the arguments are
evaluated before being passed and those that are NOT evaluated before being passed. LISP's "control flow" functions (like cond) are functions where the
argument evaluation is "supressed" and these functions call evel internally.
With Tcl, all arguments are evaluated (subsituted) before being passed. Always. The currly brackets (braces) suppress evaluation (subsitutation) before passing. Really, what is happening is the braces are a kind of quoting,
which happens to work across newlines, so they "look" like and seem to behave
like braces in C. But they are not really anything like braces in C. Even when
that is what it *looks* like.
Something similar is happening with expr. The braces in the argument to expr
are not a syntacic "feature" of expr, but a way of "quoting" the argument to
expr to prevent pre-mature "evaluation" (subsitutation) of the argument(s) to
expr. This is done to "defer" evaluation (subsitutation) until *after* expr parses the expression, becaue expr itself will perform the evaluation (subsitutation) itself (eg it calls Tcl_Eval).
At Thu, 13 Aug 2026 06:55:58 +0000 Roderick <hruodr@gmail.com> wrote:
On Wed, 12 Aug 2026, Robert Heller wrote:
... And the varable subsitution happens after expression parsing,
not before.
The currly brackets supresses subsitution.
Here is not being suppressed:
% set a ttt; expr {$a}
ttt
And after parsing should follow evaluation, here should be an error.
--
Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
Deepwoods Software -- Custom Software Services http://www.deepsoft.com/ -- Linux Administration Services heller@deepsoft.com -- Webhosting Services
Why do you think
set a "ttt";expr {$a}
should return an error?
An expression containing a single variable reference is a perfectly valid expression and results in the variable's value, nothing more. What error message did you expect?
If you are expecting an error complaining that "ttt" is
an invalid expression, that is what you get when you leave off the braces:
I think this is what originally confused you.
The confusion is understandable if one does not *fully* understand just
what the braces are doing.
So I tried to explained what the braces are doing.
It is enirely possible to code successfully in Tcl without fully understanding
what the braces really are and still be supprised when something "unexpected" happens.
In my case I learned LISP *before* Tcl,
And Claude, like all LLMs are total idiots, Don't expect it to give you any really good in-depth answers. Especially for this sort of question.
On Thu, 13 Aug 2026, Robert Heller wrote:"computer algebra"? What is that? I'm guessing English is not your first language?
Why do you think
set a "ttt";expr {$a}
should return an error?
An expression containing a single variable reference is a perfectly valid expression and results in the variable's value, nothing more. What error message did you expect?
An analogue expresion that do bring an error:
% set a "ttt";expr {$a+0}
can't use non-numeric string as operand of "+"
"expr {$a+0}" does not do cumpter algebra, but "expr {$a}" does.
If you are expecting an error complaining that "ttt" is
an invalid expression, that is what you get when you leave off the braces:
The question is not about writing an expression that brings an error.
I told you that before.
Exactly what "inconsistent behavior"? You have never really explained what that was. I don't see anything inconsistent.I think this is what originally confused you.
What "confused" me was incosistent behavior. et99 showed from where it
comes: it is artificially introduced in the source code with an if.
The only question that remains: why tcl and jim are doing it.
The confusion is understandable if one does not *fully* understand just what the braces are doing.
If you do not undertand what is the problem I was pointing to, you cannot
say "the confusion is understandable".
So I tried to explained what the braces are doing.
Please, never try to explain things you do not understand.
It is enirely possible to code successfully in Tcl without fully understanding
what the braces really are and still be supprised when something "unexpected"
happens.
The issue is not about the braces.
In my case I learned LISP *before* Tcl,
I also.
And Claude, like all LLMs are total idiots, Don't expect it to give you any
really good in-depth answers. Especially for this sort of question.
Claude just confirmed what I told you: et99 answered my question, you did not. I really cannot call Claude under this circumstances "total idiot".
"computer algebra"? What is that? I'm guessing English is not your first language?
inconsistant here. Expr is not required to return a numercial value.
Consider:
marchhare% tclsh
% set a 4
4
% expr {$a % 2 = 1 ? "$a is odd" : "$a is even"}
4 is even
On Thu, 13 Aug 2026, Robert Heller wrote:Right. Expr has no requirement that expression terms be numerical and is not presumed to return a numerical result. Remember the Tcl mantra: "everything is a string". So there is nothing inconsistant about expr returning a string and not complaining when given an expression that evaluates to a string, even when the expression is a simple term. This might be unique to Tcl, but such is the nature of things.
"computer algebra"? What is that? I'm guessing English is not your first language?
Never heard of maxima/macsyma and reduce, very old LISP programs?
https://en.wikipedia.org/wiki/Computer_algebra
inconsistant here. Expr is not required to return a numercial value.
Consider:
marchhare% tclsh
% set a 4
4
% expr {$a % 2 = 1 ? "$a is odd" : "$a is even"}
4 is even
New to me. That means, there are more acceptable non numeric expressions.
And then, I fed Claude with et99's posting and asked:
"And-a et99's posting?"
Answer from Claude:
"Yes rCo et99 directly addresses Roderick's point (expecting an error for expr {$ex}) by showing the actual bytecode disassembly, demonstrating
that expr tries to convert to numeric but falls back to treating it as a string ("not numeric") rather than erroring rCo which explains why no
error occurs, unlike Heller's more general/evasive answer."
Claude just confirmed what I told you: et99 answered my question,you did
not. I really cannot call Claude under this circumstances "total idiot".
It did. But since it has no operators, it simply returns
whatever it has so far.
% expr {$a + 0}
can't use non-numeric string as operand of "+"
"Also, Tcl expressions support non-numeric operands and string
comparisons, as well as some additional operators not found in C."
One, please be respectful, especially to people trying to help you.
Second, perhaps you could also ask Claude whether I answered your implicit question on day one,
and what you needed to learn that you hadn't since 2000.
On Thu, 13 Aug 2026, saito wrote:
One, please be respectful, especially to people trying to help you.
Well, I was a little disgusted that the thema turned insistent to be
my "confussion" followed by long confuse explanations. I just wanted to
stop the trend.
I think, now is all clear.
Thanks! From where you have the command lds?
It does not exist in my tclsh
* Roderick <hruodr@gmail.com>
| I used expr a lot, but always as a numerical calculator, so that
| I was never confronted with this issue. I never needed expr to
| do something with strings.
Whenever you code something like
if {$a ne $b} ... (note: "ne", not "!=")
you're using the "string expr".
NB. All of the discussion in this thread holds for 'if' as well.
You can brace the conditional expression for 'if', or you can double
quote it, with the same consequences as for 'expr'.
On Fri, 14 Aug 2026, Ralf Fassel wrote:
NB. All of the discussion in this thread holds for 'if' as well.
You can brace the conditional expression for 'if', or you can double
quote it, with the same consequences as for 'expr'.
Look:
% set a test
test
% expr {$a}
test
% if {$a} {return 1} else {return 0}
expected boolean value but got "test"
* Roderick <hruodr@gmail.com>
| On Fri, 14 Aug 2026, Ralf Fassel wrote:
| > NB. All of the discussion in this thread holds for 'if' as well.
| > You can brace the conditional expression for 'if', or you can double
| > quote it, with the same consequences as for 'expr'.
| Look:
| % set a test
| test
| % expr {$a}
| test
| % if {$a} {return 1} else {return 0}
| expected boolean value but got "test"
To be expected (pun intended :-).
'expr' is just looking for any expression, but 'if' requires a boolean.
The equivalent for the 'if' would be
expr {$a ? 1 : 0}
which yields the exact same error as 'if', since a boolean value is
expected at the position of $a.
On Fri, 14 Aug 2026, Ralf Fassel wrote:Yes. The mapping of "numbers" to boolean is a tradional artefact of C that Tcl "inheirited". The mapping of yes, no, true, false as boolean is a "feature" of Tcl, mostly because Tcl can't do this C idiom:
* Roderick <hruodr@gmail.com>
| On Fri, 14 Aug 2026, Ralf Fassel wrote:
| > NB. All of the discussion in this thread holds for 'if' as well.
| > You can brace the conditional expression for 'if', or you can double
| > quote it, with the same consequences as for 'expr'.
| Look:
| % set a test
| test
| % expr {$a}
| test
| % if {$a} {return 1} else {return 0}
| expected boolean value but got "test"
To be expected (pun intended :-).
'expr' is just looking for any expression, but 'if' requires a boolean.
The equivalent for the 'if' would be
expr {$a ? 1 : 0}
which yields the exact same error as 'if', since a boolean value is expected at the position of $a.
The set of all integers is mapped to booleans, the set of all floating
point numbers also, but not the set of all strings (but a small
subset containing yes, no, true, false).
* Roderick <hruodr@gmail.com>
| The set of all integers is mapped to booleans, the set of all floating
| point numbers also, but not the set of all strings (but a small
| subset containing yes, no, true, false).
Exactly.
https://www.tcl-lang.org/man/tcl8.6.17/TclLib/GetInt.htm
states:
[...]
Tcl_GetBoolean expects src to specify a boolean value.
If src is any of 0, false, no, or off, then Tcl_GetBoolean stores a
zero value at *intPtr.
If src is any of 1, true, yes, or on, then 1 is stored at *intPtr.
Any of these values may be abbreviated, and upper-case spellings are
also acceptable.
On Fri, 14 Aug 2026, Ralf Fassel wrote:
* Roderick <hruodr@gmail.com>
| The set of all integers is mapped to booleans, the set of all floating
| point numbers also, but not the set of all strings (but a small
| subset containing yes, no, true, false).
Exactly.
https://www.tcl-lang.org/man/tcl8.6.17/TclLib/GetInt.htm
states:
[...]
Tcl_GetBoolean expects src to specify a boolean value.
If src is any of 0, false, no, or off, then Tcl_GetBoolean stores a
zero value at *intPtr.
If src is any of 1, true, yes, or on, then 1 is stored at *intPtr.
Any of these values may be abbreviated, and upper-case spellings are
also acceptable.
Look:
% if {0.1} {return 1} else {return 0}
1
% if {-5} {return 1} else {return 0}
1
Sure innherited from C, as Robert Heller said, but is this an
undocumented feature?
I use it continuously ...
R.
| Sysop: | Amessyroom |
|---|---|
| Location: | Fayetteville, NC |
| Users: | 74 |
| Nodes: | 6 (0 / 6) |
| Uptime: | 53:38:02 |
| Calls: | 1,101 |
| Calls today: | 1 |
| Files: | 1,339 |
| Messages: | 276,196 |