Sebastian Bia?y <
he...@poczta.onet.pl> wrote:
> Hello.
>
> There is simple loop executed under TCL8.5 (8.6 is out of question now
> since I do not have working port of my application):
>
> proc ifact1loop count {
> for {set i 0} {$i < $count} {incr i} {
> set x 1.0
> for {set j 1} {$j <= 100} {incr j} {
> set x [expr $x * $j]
> }
> }
> }
>
> Why this simple script converts doubles to string *all* the time
> wasting cpu?
Because you wrote it to always convert to string then perform a concat.
This: [expr $x * $j], as documented by expr (emphasis added):
man expr:
**Concatenates args** (adding separator spaces between them),
evaluates the result as a Tcl expression, and returns the value.
Expr, when it is finally called, see's three arguments on its argv, and
so it calls concatenate internally on the three args to get a single
string. In order to "concatenate" the string representation of $x and
$j are needed, so concatenate obtains the string version of $x and $j,
performs a concat with those two strings, and the star, then returns
the result to expr to be interpreted as a math expression. That is the
source of your "converts doubles to string *all* the time" question.
> I was almost sure that whole idea of Obj in tcl was about not
> converting to string.
It is, but in order to prevent the conversion to string, you have to
give expr a single argument that is itself an unsubstituted string.
That is why it is always recommended to "brace your expressions" [1].
When you give expr this: [expr {$x * $j}] what expr receives is the
string "$x * $j". Since it is one arg, it does no 'concat', and it
(expr) performs the variable accesses, so it asks $x for a numeric rep
(preventing conversion to string if $x already has a numeric rep cached
and the numeric rep is current). Same for $j. Then expr performs a
multiply on values that are already numeric, returning a tclobj that is
itself numeric.
[1]
https://wiki.tcl-lang.org/page/Brace+your+expr-essions