From: Arndt Roger Schneider on
Andreas Leitgeb schrieb:
> Arndt Roger Schneider <arndt.roger(a)web.de> wrote:
>
>>eval versus if 1 has no effect on the
>>evaluation time.
>
>
> This is not supported by the experiment I posted recently.

In Tcl 8.5 tclCmdIL:

241 }
clause = TclGetString(objv[i]);
if ((i < objc) && (strcmp(clause, "then") == 0)) {
i++;
}
246 if (i >= objc) {
....

/*

* The expression evaluated to false.
* Skip the command, then see if
* there is an "else" or "elseif" clause.

257 */

i++;
if (i >= objc) {
if (thenScriptIndex) {
262 /*

* TIP #280. Make invoking context available to branch.

*/

return TclEvalObjEx(interp, objv[thenScriptIndex], 0,
267 iPtr->cmdFramePtr, thenScriptIndex);
}
return TCL_OK;
}


Tcl searches for the "then" after the
expression...

"if expression command" has a linear complexity with the
length of the command immediate following
the expression --not just 10 times
slower than eval...

Every Tcl-Script is affect, when then is
being ommited.


Which is why we have different results for our two
testcases Andreas.



-roger
From: Arndt Roger Schneider on
Andreas Leitgeb schrieb:
> Hai Vu <wuhrrr(a)gmail.com> wrote:
>
>>Another way to skin the cat:
>>eval [concat file join $components]
>
>
> For the record: this is exactly as slow and potentially unsafe as
> eval file join $components
>
> concat doesn't "sanitize" lists the way linsert,lrange,... do.
> (and it's not a bug: concat isn't supposed to do that)
>
> I can't think of any situation, where using explicit [concat ...]
> directly for eval arguments makes any difference to letting eval do
> the concatting itself.
>

I suppose you meant:
eval {file join} $components;

Lets sum it up:

what ever is throw to eval would better
be a list.
Do concat, eval, linsert alter the argument
from file split into a string ?

Tcl 8.4 PPC:

# Make sure file split returns a
# single argument:
set term [file split "alpha beta gaam"]
{alpha beta gaam}

eval {file join} $term
--> alpha beta gaam


eval file join $term
--> alpha beta gaam


eval [concat {file join} $term]
--> alpha beta gaam


eval [concat file join $term]
--> alpha beta gaam


eval [linsert $term 0 file join]
--> alpha beta gaam


Apparently file split always returns
a list. So every concat operation is
valid.

Now Performance:
linsert is the fastest method.
concat and "eval" are equal to each other,
but ~50% slower than linsert.

Ergo, linsert has received a lot of
performance optimization over 20 years
whereas the rest did not.

The performance comparision should
come out as:

set components [file split a/b/c]

eval {file join} [file split a/b/c]
; # concatination of two unshared lists inside eval.

eval [lconcat {file join} [file split a/b/c]]
; # Note: there is no lconcat in Tcl
; # lconcat is an optimzed version of the
; # pulled list-version of concat in
; # tclUtil.c Line 1178 to 1212 (Tcl 8.5).

eval [concat {file join} [file split a/b/c]]
;# calls lconcat, but contains some overhead
# to determine if the parameters contains strings.


# concatination of one unshared and one shared list:
eval {file join} $components
eval [lconcat {file join} $components] ; # see above note!
eval [concat {file join} $components]

# Today the fastest approach:
eval [linsert [file split a/b/c] 0 file join]
eval [linsert $components 0 file join]


-roger