From: Andreas Leitgeb on
Andreas Leitgeb <avl(a)gamma.logic.tuwien.ac.at> wrote:
> Uwe Klein <uwe_klein_habertwedt(a)t-online.de> wrote:
>>>>>>set newpath [eval [linsert $components 0 file join]]
>>>> you can have it faster even:
>>>> set newpath [if true [linsert $components 0 file join]]]
>>> As I understand it, both invocations cause an evaluation of the same
>>> body. So, how come that the latter is faster?
>> [eval] is supposed to shimmer to string to list tokens
>> while [if] takes the list without further ado.
>> at least that is the explanation that was given some years ago.
>
> Also some years ago there was a statement, that eval recognizes list
> Tcl_Obj's (internally) and avoids the string/script detour then.

I did an experiment now:

proc f1 {l} {eval [linsert $l 0 list]}
proc f2 {l} {if 1 [linsert $l 0 list]}
set l [lrepeat 1000 x]; llength $l
time {f1 $l} 10000;# 116.3 µs
time {f2 $l} 10000;# 1146.115 µs

So, "if" in this case is ten times slower!

PS: the timings were taken on a netbook with atom processor, so
on normal PC's the timings are (probably proportionally) much
smaller.

From: Erik Leunissen on
Andreas Leitgeb wrote:
> ...
> proc f1 {l} {eval [linsert $l 0 list]}
> proc f2 {l} {if 1 [linsert $l 0 list]}
> set l [lrepeat 1000 x]; llength $l
> time {f1 $l} 10000;# 116.3 µs
> time {f2 $l} 10000;# 1146.115 µs
>
> So, "if" in this case is ten times slower!
>
> PS: the timings were taken on a netbook with atom processor, so
> on normal PC's the timings are (probably proportionally) much
> smaller.
>

Yes, but surprisingly, the relative timings are also different. Yours
differ by a factor 10 (roughly), mine by a factor of 3. Maybe we are
using different Tcl versions.

% time {f1 $l} 10000
15.7694 microseconds per iteration
% time {f2 $l} 10000
49.0552 microseconds per iteration
% parray tcl_platform
tcl_platform(byteOrder) = littleEndian
tcl_platform(machine) = x86_64
tcl_platform(os) = Linux
tcl_platform(osVersion) = 2.6.25.20-0.5-default
tcl_platform(platform) = unix
tcl_platform(pointerSize) = 8
tcl_platform(user) = erik
tcl_platform(wordSize) = 8
% set tcl_version
8.5

Erik.
--
leunissen@ nl | Merge the left part of these two lines into one,
e. hccnet. | respecting a character's position in a line.
From: Arndt Roger Schneider on
Uwe Klein schrieb:
> Jonathan Bromley wrote:
>
>> On 11 Sep 2009 10:09:48 GMT, Andreas Leitgeb wrote:
>>
>>
>>> I'd most suggest trying to get unstuck and upgrade to 8.5
>>
>>
>>
>> When Tcl is embedded in a commercial tool, I don't have
>> that luxury :-(
>>
>>
>>> treat the arguments to eval such, that it will be safe and
>>> not all that slow:
>>>
>>> set newpath [eval [linsert $components 0 file join]]
>>
>>
>>
>> ah, yes, that's nicer. Every Script Is A List.
>
>
> you can have it faster even:
>
> set newpath [if true [linsert $components 0 file join]]]
>
> uwe

Very nice indeed!

Tcl 8.4 PPC:

set komponents [list a b c]

% time {::eval [linsert $komponents 0 file join]}
173868 microseconds per iteration
% time {::eval [linsert $komponents 0 file join]}
60 microseconds per iteration
% time {::eval [concat [list file join] $komponents]}
102590 microseconds per iteration
% time {::eval [concat [list file join] $komponents]}
69 microseconds per iteration
% ::eval [concat [list file join] $komponents]
a/b/c
% time { if 1 [linsert $komponents 0 file join]}
58558 microseconds per iteration
% time { if 1 [concat [list file join] $komponents] }
106 microseconds per iteration


.... so whatever these time numbers mean.

On concat: concat takes two forms one working on
strings the other on lists, If the first argument
is a list, then the list form is being aplied.

It seems to be faster than linsert, too.
And is better readable than linsert.

-roger

From: Jonathan Bromley on
On 12 Sep 2009 03:02:22 GMT, Joe English wrote:

>> Joe English wrote:
>>>What you can say is: "A canonical-form list, when parsed as a script,
>>>will be interpreted as a single command whose words are the elements
>>>of the list." That's about the only relationship between lists
>>>and scripts I can think of...
>>
>> I'm not sure about "single command":
>>
>> % set L {puts a ; puts b}
>> % llength $L
>> => 5
>> % eval $L
>> => a
>> b
>
>Ah, but that's not a *canonical-form* list.
>
> % set L {puts a ; puts b}
> % lrange $L 0 end
> ==> "puts a {;} puts b"
> ............^^^ note quoting

oooooh, that's embarrassing. Two fundamental goofs
in one thread. Thanks for the kindly correction.

How many times have I told people "never create a list
except by using the list commands..."? And then I
go and say something stupid like that.

>That's why the [eval [linsert ...]] idiom is recommended for
>callbacks: [linsert] returns a canonical-form list, so
>you don't need to worry about quoting Tcl syntax characters.

Indeed.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley(a)MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
From: Andreas Leitgeb on
Arndt Roger Schneider <arndt.roger(a)web.de> wrote:
> On concat: concat takes two forms one working on
> strings the other on lists, If the first argument
> is a list, then the list form is being aplied.

No, only if *all* the arguments are pure lists, then the
result also will be one, otherwise not.

e.g:
concat [list foo bar] \;

> It seems to be faster than linsert, too.
> And is better readable than linsert.

never trust "time" about microseconds when you don't specify
a larger number of iterations (like 1000).