Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

tcl8.5 new operator in expr

22 views
Skip to first unread message

Andreas Leitgeb

unread,
Jan 17, 2006, 7:25:30 AM1/17/06
to
While it is now really easy to add new (any-adic) functions
to expr, like: (I love 8.5 :-)
interp alias {} ::tcl::mathfunc::list {} list
set xy [expr {list($r*cos($phi),$r*sin($phi))}]
or
proc ::tcl::mathfunc::like {v p} {string match $p $v}
if {like($val,"abc*")} ...

I wonder whether it will be possible someday (e.g. in final 8.5)
to also add named operators, that could then be used like "eq"
and "ne". Kevin?

Donal K. Fellows

unread,
Jan 17, 2006, 7:44:52 AM1/17/06
to
The problem with adding new operators (as opposed to new functions) is
that they require changes to the way that expressions are tokenized and
parsed. That's quite a lot harder to make work flexibly.

Donal.

Adrian Davis

unread,
Jan 18, 2006, 4:01:05 AM1/18/06
to
I do have to agree here. The "ne" and "eq" operators have made "if"
comparisons considerably less verbose - To my mind the only (widely
used) things missing now are "glob" and "regexp" string comparisons.
Some thing like:-

if {$myvar like *glob*}

...and...

if {$myvar match {^[Rr]egexp$}}

I have no idea how complex these would be to implement, but I can't
imagine any Tcl/Tk programmer who wouldn't like to see something along
these lines!!

Best Regards,
=Adrian=

suchenwi

unread,
Jan 18, 2006, 4:34:34 AM1/18/06
to

Adrian Davis schrieb:

> I have no idea how complex these would be to implement, but I can't
> imagine any Tcl/Tk programmer who wouldn't like to see something along
> these lines!!

I for one like "like" - the negated version might be "unlike" then,
just as eq/ne, in/ni ...

Uwe Klein

unread,
Jan 18, 2006, 5:32:09 AM1/18/06
to

This has been in tcl for a long time, it is called [switch]:

switch -exact|-glob|-regexp

switch -regexp -- $myvar \
{^[Rr]egexp$} {
} default {
}

It can be usefull to composite the argument like

switch -- $test1,$subtest2 \
VALUE_A,A_SUB_VALUE_1 {
} ....

which is IMHO very often the best solution to c-style if-spagetti
and clean looking too.


uwe

MartinLemburg@UGS

unread,
Jan 18, 2006, 6:00:03 AM1/18/06
to
Wow - the first time I realize, that I can extend the expr command with
our own vector procedures!

Wonderful!

But ... I don't see much need for defining own operators.
Otherwise I wanted so often additional operators for glob and regexp
matching!

Best regards,

Martin Lemburg
UGS - Transforming the Process of Innovation

Adrian Davis

unread,
Jan 18, 2006, 7:50:31 AM1/18/06
to
I'm aware of, and do use switch for this, but I still think that...

if {$myvar like *glob*}

...and...

if {$myvar match {^[Rr]egexp$}}

...are more intuative and easier to read than someting like...

switch -regexp -- $myvar \
{^[Rr]egexp$} {
} default {
}

Using "if" also allows one to mix in "and" and "or" conditions in a
natural way...

if {$myvar1 like *glob* && $myvar2 > 99}

...A personal preference I would agree - though I think many others
would agree with me.

Best Regards,
=Adrian=

Victor Wagner

unread,
Jan 18, 2006, 8:20:15 AM1/18/06
to
Adrian Davis <adr...@satisoft.com> wrote:
: I'm aware of, and do use switch for this, but I still think

that...
: if {$myvar like *glob*}
: ...and...
: if {$myvar match {^[Rr]egexp$}}


But what's wrong with

if {[string match *glob* $myvar]}
and

if {[regexp {^[Rr]egexp$} $myvar]}

?
--

Adrian Davis

unread,
Jan 18, 2006, 8:23:43 AM1/18/06
to
Just seems to me to feel like a more natual "if" type syntax - That's
all.

Regards,
=Adrian=

Uwe Klein

unread,
Jan 18, 2006, 8:27:50 AM1/18/06
to
Adrian Davis wrote:
> I'm aware of, and do use switch for this, but I still think that...
>
> if {$myvar like *glob*}
>
> ...and...
>
> if {$myvar match {^[Rr]egexp$}}
>
> ...are more intuative and easier to read than someting like...
>
> switch -regexp -- $myvar \
> {^[Rr]egexp$} {
> } default {
> }
>
> Using "if" also allows one to mix in "and" and "or" conditions in a
> natural way...
>
> if {$myvar1 like *glob* && $myvar2 > 99}

switch -glob -- $condA,$condB \
0,1 { + !A && B
} 1,1 [ # A && B
} 1,* - *,1 { # A || B
} ...

>
> ...A personal preference I would agree - though I think many others
> would agree with me.

You are certainly right, and on both counts.
But with tcl being stringier than c i have a (still) growing fondness
for [switch].

And some samples provided in the last couple of days would have gained
significantly in readability by using switch in place of repeated
if {$string eq A } {
} else if {$string eq B } {
} ....

>
> Best Regards,
> =Adrian=
>
G!
uwe

Adrian Ho

unread,
Jan 18, 2006, 5:22:44 AM1/18/06
to
On 2006-01-18, suchenwi <richard.suchenw...@siemens.com> wrote:
> I for one like "like" - the negated version might be "unlike" then,
> just as eq/ne, in/ni ...

IMO, "ni" is a *terrible* way to say "not in" -- it's far too easy to
accidentally type one when you mean the other, and it's not very distinct
visually. if/fi, case/esac et all make sense in shell programming because
[a] they're paired and [b] typo'ing them causes parse errors.

in/notin is a better choice.

Regards,
Adrian

Roy Terry

unread,
Jan 18, 2006, 10:41:57 AM1/18/06
to
"Adrian Davis" <adr...@satisoft.com> wrote in message
news:1137573896....@g43g2000cwa.googlegroups.com...

> I do have to agree here. The "ne" and "eq" operators have made "if"
> comparisons considerably less verbose - To my mind the only (widely
> used) things missing now are "glob" and "regexp" string comparisons.
> Some thing like:-
>
> if {$myvar like *glob*}
>
> ...and...
>
> if {$myvar match {^[Rr]egexp$}}
Yes! nice idea.

Andreas Leitgeb

unread,
Jan 18, 2006, 10:58:45 AM1/18/06
to
MartinLemburg@UGS <martin.le...@gmx.net> wrote:
> Wow - the first time I realize, that I can extend the expr command with
> our own vector procedures!
>
> But ... I don't see much need for defining own operators.

Just when you're talking about vektor procedures ...
Wouldn't a custom expr {$v1 dot $v2} just for your scripts
make better readable code?

> Otherwise I wanted so often additional operators for glob and regexp
> matching!

Yes, that was also the main drive behind my posting...

With "like"/"unlike" and perhaps "match" I'd be satisfied
for a while even without a user-extensible general solution.

keithv

unread,
Jan 18, 2006, 11:04:33 AM1/18/06
to
Andreas Leitgeb wrote:

> I wonder whether it will be possible someday (e.g. in
> final 8.5) to also add named operators, that could then
> be used like "eq" and "ne".

Would you then be able to override the meaning of
existing operators?

While being able to redefine "keywords" is very
tclish, I think redefining operators is going too far.

Keith

Jeff Hobbs

unread,
Jan 18, 2006, 11:38:07 AM1/18/06
to Adrian Davis

The adding of expr operators isn't that hard (but may lead to
more bytecodes). I've wanted glob/re expr operators for a
while as well. I had considered '=' based operators, like:

$a =* $b # glob
$a =~ $b # re

The =~ is obviously from Perl, but they have more elaborate
results and syntax related to it that I wanted to avoid. For
negation, you could have !* and !~.

As to the words ... I don't like the choices. I might expect
SQL syntax for like, and using glob would be only 4 chars too
(but sounds clumsy). The 'match' doesn't immediately invoke
re to me - why not use 're'? But what to negate with?

--
Jeff Hobbs, The Tcl Guy
http://www.ActiveState.com/, a division of Sophos

Donald Arseneau

unread,
Jan 18, 2006, 2:59:59 PM1/18/06
to
vi...@45.free.net (Victor Wagner) writes:

> if {[string match *glob* $myvar]}

Nothing that isn't wrong with

if {[string equal $foo $bar]}

I don't think anything is wrong with either, but "eq" was still a good
idea.


--
Donald Arseneau as...@triumf.ca

Donald Arseneau

unread,
Jan 18, 2006, 3:01:42 PM1/18/06
to
"Roy Terry" <royt...@earthlink.net> writes:

> "Adrian Davis" <adr...@satisoft.com> wrote in message
> news:1137573896....@g43g2000cwa.googlegroups.com...

> > if {$myvar like *glob*}


> > if {$myvar match {^[Rr]egexp$}}
> Yes! nice idea.

I disagree with the keyword choices. Using "match" for regexp
is confusing because [string] uses "match" for glob.


--
Donald Arseneau as...@triumf.ca

Roy Terry

unread,
Jan 18, 2006, 4:10:24 PM1/18/06
to
"Donald Arseneau" <as...@triumf.ca> wrote in message
news:yfivewh...@triumf.ca...
Yeah, good point. I do hope we stick with words or abbrevs.
instead of perl/awk style (~=, etc). Seems currently all
the expr non-match operators are alphabetic. So ....

Maybe

if {$s ma x*} ...

and

if {$s re ^x.*} ...

What's established or on its way
eq => equal
ne => not equal
in => in
ni => not in

IOW: two letters for non-negated operator,
leading 'n' negates,
single letter can stand for negated
operator and,
ops are 2 letters long.

Thus:

ma => str (glob) match (because we have [string match...]
nm => no str match

re => regexp match (because we have [regexp ...]
nr => no regexp match

This seem pretty clean so far if a bit
cryptic. OTOH, expressions are expected
to be a bit cryptic anyways :) I would vote
to go with these tidy little terms as the
point of the change would be compactness
and concision. Having all letter ops be 2
letters long could be helpful to verifying
memory and correctness for a lot of people.

Question is should the established
pattern stand, be revised, or simply
be ignored for these potential new operators.

Roy

>
>
> --
> Donald Arseneau as...@triumf.ca


MH

unread,
Jan 18, 2006, 6:06:59 PM1/18/06
to
In article <a2i1a3-...@robert.houseofmax.de>,

I'm not picking on you specifically, Uwe..

While I use switch not infrequently in C/C++, I almost NEVER use it in Tcl,
simply because it just doesn't make a lot of sense to me - I always have to
look up the exact syntax, and even afterwards, I find it awkward to read.

I can EASILY read something like:
switch(x)
{
case 1:
...
...
break;
case 2:
...
...
break;
...
default:
...
}

TCL seems to go out of its way to make switch hard to read (IMHO).

Mattias

suchenwi

unread,
Jan 18, 2006, 6:31:36 PM1/18/06
to
How is it harder to read this:
switch -- $x {
1 {...}
2 {...}
default {...}
}
?

Bryan Oakley

unread,
Jan 18, 2006, 6:48:02 PM1/18/06
to

That's a curious statement. How is that so much better than this?
Admittedly, with C you have to manually insert a break to prevent
fall-through, but claiming Tcl is "go[ing] out of its way to make switch
hard to read" is a bit far-fetched, isn't it?

switch $x {
1 {
...
...
}
2 {
...
...
}
default {
...
...
}
}

Donal K. Fellows

unread,
Jan 18, 2006, 7:08:47 PM1/18/06
to
Jeff Hobbs wrote:
> The adding of expr operators isn't that hard (but may lead to
> more bytecodes). I've wanted glob/re expr operators for a
> while as well. I had considered '=' based operators, like:

The adding of *specific* operators isn't hard (it's just a Simple Matter
of Programming, leaving aside what it takes to actually add any extra
bytecodes required) but the adding of a general mechanism for arbitrary
operators is rather more difficult. (It'd require a different kind of
expression parser to the simple LL(1) version we use now).

Donal.

Kevin Kenny

unread,
Jan 18, 2006, 9:04:56 PM1/18/06
to
Jeff Hobbs wrote:
> Adrian Davis wrote:
>
>> I do have to agree here. The "ne" and "eq" operators have made "if"
>> comparisons considerably less verbose - To my mind the only (widely
>> used) things missing now are "glob" and "regexp" string comparisons.
>> Some thing like:-
>>
>> if {$myvar like *glob*}
>>
>> ...and...
>>
>> if {$myvar match {^[Rr]egexp$}}
>>
>> I have no idea how complex these would be to implement, but I can't
>> imagine any Tcl/Tk programmer who wouldn't like to see something along
>> these lines!!

I think that I'd like to see 'lt', 'le', 'gt', and 'ge' first - 'eq'
and 'ne' seem to be missing these counterparts.

I may have time at some point to write the TIP, but I have about four
other projects going at the moment, so now is not the time.

--
73 de ke9tv/2, Kevin

MH

unread,
Jan 18, 2006, 10:34:17 PM1/18/06
to
In article <SsAzf.6073$_S7....@newssvr14.news.prodigy.com>,
Bryan Oakley <oak...@bardo.clearlight.com> wrote:
>MH wrote:

[cut]


Ok, so maybe I went a little far.. For some reason, I've never been
comfortable with switch in Tcl..

I think it's the fact that the opening brace has to be on the same line as
the pattern.. Never liked that style (still don't - wish I could change that
about Tcl).

Mattias

MH

unread,
Jan 18, 2006, 10:32:53 PM1/18/06
to
In article <1137627096....@z14g2000cwz.googlegroups.com>,

For some reason, just doesn't jive as well with my internal parser,
especially when reading other people's code..

Oh well.. Guess I'm a freak :-)

Mattias

MartinLemburg@UGS

unread,
Jan 19, 2006, 4:08:16 AM1/19/06
to
Hello Mattias,

I see switch in the opposite way, mostly!

I hate if-elseif-... chains and prevent it if possible by using switch!

It's IMHO about readability and about speed too.

The only problem I have with switch is that only text comparisons are
possible, so that non-string-type tcl objects are always converted for
this comparison. For me it would be a really good enhancement of
switch, if this command would be able to compare numerical values, with
numerical values, lists with lists ... .

That could be probably done by a new a new option like "-typerelated"
or with the lsort like options -integer and -real for numerical values.

To test for the equality of lists, is perhabs too much, but ... there
is no functionality to test a list against another list about equality
and to test it type related, not to convert every list element into a
string and to recurse into sublists. (I know, perhabs there is already
a solution to be found in the wiki. Or I can program this for my own.
But this is something I think the core is lacking. And such core lacks
are not be closed by wiki patches or selfmade packages, but to be
closed by core enhancements.)

Ok - that's about switch.

I'm very glad, that the new operators "eq", "ne", "in", and "ni" exist!
And I would be very glad to see such operators "like" and "match" or
perhabs better, because more tcl syntax like "glob" and "regexp". Ok,
"unlike" and "nomatch" are good names of the negating operators.
But what's with an operator representing "string compare"?

To overload default operators is in my eyes too dangerous, but tclish.
My stomach says "oh no, no".

Then I realized, that I can already redefine the behaviour of default
mathmatical functions. First I was really impressed, but ... my
stomache tells me again "oh no, no"!

Is this really wanted?

suchenwi

unread,
Jan 19, 2006, 4:45:10 AM1/19/06
to
> I think it's the fact that the opening brace has to be on the same line as
> the pattern.. Never liked that style (still don't - wish I could change that
> about Tcl).

Beauty lies of course in the eye of the beholder. However, if newlines
could occur between words of a command, we'd need some indication when
one is finished (e.g. mandatory ";"?) - or put parens round every
command?

But there's already too many languages like that :^)

Uwe Klein

unread,
Jan 19, 2006, 4:41:08 AM1/19/06
to
Hi Mattias,

well, it took me some time to get fond of [switch]
and for me it has grown from using case/esac with
shell-scripts and using expect -re ..
switch in tcl is quite a bit more powerfull than
switch in C/C++. ( even without missing out on (no)break.)

usage varies: in my repository of nice_and_interesting
tcl scripts from the web it is about
10 if for 1 switch and tclstuff i wrote has about
5 if for 1 switch.
so its not about replacing if ;-)

if you have a look at http://wiki.tcl.tk/14928
using switch can look orderly and make adding and
changing cases easier.

my objection to using [if] was centered on repeated
stringcompares directly ripped from C/C++.

uwe


Uwe Klein

unread,
Jan 19, 2006, 4:42:19 AM1/19/06
to
MH wrote:

> Oh well.. Guess I'm a freak :-)

wellcome to the club ;-)
>
> Mattias
uwe

Arjen Markus

unread,
Jan 19, 2006, 4:52:09 AM1/19/06
to
Well, Eiffel allows it, and it does not require a statement terminator.
It simply determines if a statement is complete or not from a
syntactical point of view ...

Regards,

Arjen

suchenwi

unread,
Jan 19, 2006, 4:53:54 AM1/19/06
to
But that would exclude commands with a variadic number of arguments...

Uwe Klein

unread,
Jan 19, 2006, 4:50:52 AM1/19/06
to
Bryan Oakley wrote:


> Admittedly, with C you have to manually insert a break to prevent

I would like to have control over (no)break in tcl as well.

switch -regexp -- $value \
<subselection of RE> {
prepare_special_value_for_general_case value
....
dontbreak
} <RE> {
process_value_for general_case $value
} ....

uwe


MartinLemburg@UGS

unread,
Jan 19, 2006, 5:18:35 AM1/19/06
to
Hhm - what's about to adopt the Tk bind mechanism?

In details - a bind script can append to an existing bind script for
the same event by using "+" as script prefix (see man page). So a chain
of bind scripts binded to the same event.

Why not doing the same for switch?

| switch -glob -- $value {
| St* {# do something}
| S* {+ # do something else}
| }

Ok - it means, that switch has to look for the next pattern and its
script, test the script to have the prefix "+" and if so to test if the
pattern matches to evaluate the related script.

No - not that good - performance related.

Another idea - the explicite usage of break and continue inside a
switch block, but continuing with the implicite break functionality!

Yes - this would break many scripts and would be an enhancement for tcl
v9.x!

An example:

| switch -glob -- $value {
| St* {
| # do something and continue checking the switch cases
| continue;
| }
| S* {
| # do something else
| }
| }

The idea to have a non-breaking switch is a quite nice one, but it is
not easy to realize not breaking old tcl scripts, right?

Donal K. Fellows

unread,
Jan 19, 2006, 5:36:11 AM1/19/06
to
Uwe Klein wrote:
> my objection to using [if] was centered on repeated
> stringcompares directly ripped from C/C++.

That's what [switch] normally does too. However, in 8.5 we now compile
some ways of writing the [switch] command into a jump table, though it
is all made a bit more complicated by the fact that we're [switch]ing on
strings and not small integers. Many other forms of [switch] are also
compiled, but just into a slightly more efficient form of [if] chain.

Donal.

Donal K. Fellows

unread,
Jan 19, 2006, 5:39:08 AM1/19/06
to
Andreas Leitgeb wrote:
> With "like"/"unlike" and perhaps "match" I'd be satisfied
> for a while even without a user-extensible general solution.

Every time I see discussion of a possible "like" operator I wonder why
we have to borrow from VALGOL... :-)
http://users.aber.ac.uk/smg/SOCIAL/valgol

Donal.

Bruce

unread,
Jan 19, 2006, 5:49:17 AM1/19/06
to

but without the open paren, the syntactical parser will always tell you
your command is complete unless it is an empty line ;)

Bruce

Arjen Markus

unread,
Jan 19, 2006, 5:52:27 AM1/19/06
to
I do not claim that the Eiffel solution is possible for Tcl. Quite on
the contrary: Eiffel is a rather strict language with a fixed syntax
and fixed semantics. I like it mostly for the way the semantics can be
defined - the books written on Eiffel are unusual in the way that the
semantics of OOP is described. It is in a sense a minimal language: it
strives for things to be done in one way (there is only one loop
construct for instance).

Regards,

Arjen

Uwe Klein

unread,
Jan 19, 2006, 6:03:11 AM1/19/06
to

Didn't know that.

The required action is
compare "single value" to list of "match_values"
execute the script for first match.

written code should show this "one of many" selection.

if .. else if ... else if
needs carefull reading if it is really the same thing every if.
uf

uwe

Bruce

unread,
Jan 19, 2006, 5:54:07 AM1/19/06
to
Jeff Hobbs wrote:
> Adrian Davis wrote:
>> I do have to agree here. The "ne" and "eq" operators have made "if"
>> comparisons considerably less verbose - To my mind the only (widely
>> used) things missing now are "glob" and "regexp" string comparisons.
>> Some thing like:-
>>
>> if {$myvar like *glob*}
>>
>> ...and...
>>
>> if {$myvar match {^[Rr]egexp$}}
>>
>> I have no idea how complex these would be to implement, but I can't
>> imagine any Tcl/Tk programmer who wouldn't like to see something along
>> these lines!!
>
> The adding of expr operators isn't that hard (but may lead to
> more bytecodes). I've wanted glob/re expr operators for a
> while as well. I had considered '=' based operators, like:
>
> $a =* $b # glob
> $a =~ $b # re
>
> The =~ is obviously from Perl, but they have more elaborate
> results and syntax related to it that I wanted to avoid. For
> negation, you could have !* and !~.
>

oh god Jeff, please please please don't do this!

> As to the words ... I don't like the choices. I might expect
> SQL syntax for like, and using glob would be only 4 chars too
> (but sounds clumsy). The 'match' doesn't immediately invoke
> re to me - why not use 're'? But what to negate with?
>

glob is good (I think)
for re you could use negreg ;)

but really why not use glob, !glob and re, !re ?


I agree that the right word/abbrev needs to be found, but again
please please no crazy messy made up operators.

Bruce

Andreas Leitgeb

unread,
Jan 19, 2006, 6:23:51 AM1/19/06
to

I've been thinking about a switch-internal(*) "reswitch"-exception,
that could be passed a value, which will be dealt with, as if
the switch was originally called with that value but only with
those branches that follow the current one. (no loops that way!)

Switch would catch this exception for each branch-body.
If no argument is given to reswitch, the original switch-
value is reused. A reswitched value can eventually run
into the default branch.
If reswitch is called from the default branch, this
consequentially exits the switch.

(*) it wouldn't be all that "internal" to switch, but probably
manifest in a new global command "reswitch" that optionally
takes an argument and does {return -code reswitch $arg}
There are some issues around the optionality of that argument,
which need to be resolved for a TIP, but not yet here and now.

Uwe Klein

unread,
Jan 19, 2006, 6:43:45 AM1/19/06
to
Andreas Leitgeb wrote:

> I've been thinking about a switch-internal(*) "reswitch"-exception,
> that could be passed a value, which will be dealt with, as if
> the switch was originally called with that value but only with
> those branches that follow the current one. (no loops that way!)
>
> Switch would catch this exception for each branch-body.
> If no argument is given to reswitch, the original switch-
> value is reused. A reswitched value can eventually run
> into the default branch.
> If reswitch is called from the default branch, this
> consequentially exits the switch.
>
> (*) it wouldn't be all that "internal" to switch, but probably
> manifest in a new global command "reswitch" that optionally
> takes an argument and does {return -code reswitch $arg}
> There are some issues around the optionality of that argument,
> which need to be resolved for a TIP, but not yet here and now.

this is a possible snakepit.
we can not use [break] as it would break loop behaviour
we can not use [continue] as see above.

creating a new command (reswitch|nobreak|more|moreswitch ..)
is intrusive and might lead to unpleasant complaints on comp.lang.tcl.

I like the style of [expect] which allows
options between the switch args. ( and placing RE submatches in variables )

switch -glob $value \
GLOB_A -cont { puts "match GLOB_A"
} GLOB_B { puts "match GLOB_B"
}


uwe


Andreas Leitgeb

unread,
Jan 19, 2006, 7:29:20 AM1/19/06
to
Uwe Klein <uwe_klein_...@t-online.de> wrote:
> this is a possible snakepit.
> we can not use [break] as it would break loop behaviour
> we can not use [continue] as see above.

100% agree that break/continue are out of question

> creating a new command (reswitch|nobreak|more|moreswitch ..)
> is intrusive and might lead to unpleasant complaints on comp.lang.tcl.

0% agree on this, though.

Andreas Leitgeb

unread,
Jan 19, 2006, 7:42:32 AM1/19/06
to
Roy Terry <royt...@earthlink.net> wrote:
> if {$s ma x*} ...
> if {$s re ^x.*} ...

By the way, even when "ma"/"re" or any other such
operators are added to expr, it most likely won't
automatically legalize barewords in expr.

if {$s ma "x*"} ...

if {$s re {^x.*y$}} ...
(of course either type of quoting can be used for any operator)

I wonder how "implementable" are operators whose
name is combined of an exclam and a word for
the negated operators (as mentioned in some
other subthread)

I think going on with two-letter ops <x><y> and
having their negation as n<x> will much too soon
leave us out of good mnemonics.

MartinLemburg@UGS

unread,
Jan 19, 2006, 8:01:36 AM1/19/06
to
> creating a new command (reswitch|nobreak|more|moreswitch ..)
> is intrusive and might lead to unpleasant complaints on comp.lang.tcl.

"unpleasant complaints" shouldn't be a problem.
But the fact, that perhabs procedures or command could exist, that
collide with this new "command", that may be problematic.

I mostly like the additional return code, that would be managed by
switch only. It should be a switch internal return code only and
perhabs should be available only as token, because as interger value it
may interfere with application defined return codes.

Andreas Leitgeb

unread,
Jan 19, 2006, 8:41:44 AM1/19/06
to
MartinLemburg@UGS <martin.le...@gmx.net> wrote:
>> creating a new command (reswitch|nobreak|more|moreswitch ..)
>> is intrusive and might lead to unpleasant complaints on comp.lang.tcl.
> "unpleasant complaints" shouldn't be a problem.
> But the fact, that perhabs procedures or command could exist, that
> collide with this new "command", that may be problematic.

In some answer to a Fredderic's posting someone explained it
(better than me) why new commands are less of a problem than
new features that would interfere with such procedure-names.

> I mostly like the additional return code, that would be managed by
> switch only. It should be a switch internal return code only

Managed? Ok, switch would likely be the only command making
any sense of it, but just like break and continue it would
at least also be caught on procedure-exit (and converted to
an error like "reswitch outside of switch").

Afterall, one might write one's own switch-like construct
and then he might like to handle a "reswitch", too.

> perhabs should be available only as token,
> because as interger value it may interfere
> with application defined return codes.

There is no such thing as a token-exception.
That "return -code ..." also accept tokens is
a feature of the return-command itself (it
translates it to the according number).
A tcl exception (behind the scenes) is not an entity, but
just the ("int" typed) return value on C-level (otoh, the
tcl return value is some entity inside the tcl interpreter
that needs to be set using some function of the tcl-api).

It's one thing to reserve a new exception, but another thing
to completely redesign the guts of exception handling.

Finally, yes, there is a remote risk that some tcl-scripts
use exception 5 for other purposes already, and depending
on the code this clash might actually trigger unintended
behaviour.
Ultimately, the TCT (TclCoreTeam, of which I'm not a member,
either) would judge whether this feature is worth the risk or not.
And for them it might depend on things I'm not even aware of :-)

Don Porter

unread,
Jan 19, 2006, 9:34:52 AM1/19/06
to
MartinLemburg@UGS wrote:
> Then I realized, that I can already redefine the behaviour of default
> mathmatical functions. First I was really impressed, but ... my
> stomache tells me again "oh no, no"!
>
> Is this really wanted?

Yes.

This has been important in my work to permit replacing some of
Tcl's built-in math functions with others that have floating point
exception handling more suitable for my needs. (Silently flatten a
value to 0.0 rather than crash the program with an underflow exception,
for example).

--
| Don Porter Mathematical and Computational Sciences Division |
| donald...@nist.gov Information Technology Laboratory |
| http://math.nist.gov/~DPorter/ NIST |
|______________________________________________________________________|

Roy Terry

unread,
Jan 19, 2006, 10:28:52 AM1/19/06
to
"Andreas Leitgeb" <a...@gamma.logic.tuwien.ac.at> wrote in message
news:slrndsv29...@gamma.logic.tuwien.ac.at...

> Roy Terry <royt...@earthlink.net> wrote:
> > if {$s ma x*} ...
> > if {$s re ^x.*} ...
>
> By the way, even when "ma"/"re" or any other such
> operators are added to expr, it most likely won't
> automatically legalize barewords in expr.
Yes. x* would be better typed "x*"

>
> if {$s ma "x*"} ...
> if {$s re {^x.*y$}} ...
> (of course either type of quoting can be used for any operator)
>
> I wonder how "implementable" are operators whose
> name is combined of an exclam and a word for
> the negated operators (as mentioned in some
> other subthread)
>
> I think going on with two-letter ops <x><y> and
> having their negation as n<x> will much too soon
> leave us out of good mnemonics.

How many other operators did you have in mind?
Kevin Kenny has already mentioned his desire for
string comparisons gt lt le ge which manage to
be 2 chars also.

So perhaps more creativity would be demanded yes.
OTOH, consistent length and negation rules
are really helpful. Or put another way, inconsitency
in forming expressions can be maddening.
So if Tcl broke the current
pattern of xy / nx, then the existing eq/ne and in/ni
should gain aliases in whatever the new format is
with the 2-letter versions left as legacy.

Roy
>


Andreas Leitgeb

unread,
Jan 19, 2006, 1:48:41 PM1/19/06
to
Roy Terry <royt...@earthlink.net> wrote:
> "Andreas Leitgeb" <a...@gamma.logic.tuwien.ac.at> wrote in message
>> I wonder how "implementable" are operators whose
>> name is combined of an exclam and a word for
>> the negated operators (as mentioned in some
>> other subthread)

>> I think going on with two-letter ops <x><y> and
>> having their negation as n<x> will much too soon
>> leave us out of good mnemonics.
>
> How many other operators did you have in mind?
> Kevin Kenny has already mentioned his desire for
> string comparisons gt lt le ge which manage to
> be 2 chars also.

Who knows? At some point in future there might be
a consensus that a new operator for "newer than"
or "nicer than" or "naughtier than" shall be added,
and then there is the problem that the leading "n"
already has some meta-meaning :-)

Another comparable story is binary scan, where
mnemonically good characters were available for
all types of conversion - back then. But the
recently added couple of conversions (though
necessary they were) really lack mnemotechnically
good letters.
Had [binary scan] been designed to allow letter groups
to describe a single conversion, We'd be much more
flexible now and the new conversions had a chance
to be actually memorizable.
Lets not repeat this design mistake.

By sticking to a n<x> style for negation, we limit
ourselves to 26 operators, and practically far less,
because not all letters "lend" themselves to a
particular useful operator-name.
(that le/gt and lt/ge are pairwise negations lifts
the limit from 26 to 28. Whether other operators
also have a cononical non-n<x> negation is pure luck)
That's not meant that we shall strictly avoid
n<x>-style negations, especially not those that are
already there, but that we don't stick too hard to it.
better consider a "!op" scheme, which doesn't consume
the valuable space too greedily.

> So perhaps more creativity would be demanded yes.
> OTOH, consistent length and negation rules
> are really helpful.

Helpful, yes, but only as long as it doesn't hinder future useful
operators just for lack of good available two-letter names.

MH

unread,
Jan 19, 2006, 2:06:42 PM1/19/06
to
In article <le34a3-...@robert.houseofmax.de>,

Hmm. I'm probably guilty of that at some point.. Mostly in little utilities
that that are run 5 times a year, but so much faster than typing it in :-)

Next time I feel like "learning", I'll spend some time playing with switch
to see if I can get a better handle on it..

Mattias

Donal K. Fellows

unread,
Jan 20, 2006, 5:14:54 AM1/20/06
to
Andreas Leitgeb wrote:
> Managed? Ok, switch would likely be the only command making
> any sense of it, but just like break and continue it would
> at least also be caught on procedure-exit (and converted to
> an error like "reswitch outside of switch").
>
> Afterall, one might write one's own switch-like construct
> and then he might like to handle a "reswitch", too.

I have no problem in principle with adding extra syntax to [switch] to
make it so that bodies run together. The devil is in the detail though
so I'd like to see a concrete proposal. Mind you, I'd be satisfied with
something like:

switch -- $val {
foo {
...
+++}
bar {
...
}
}

Putting magic syntax at the end of the arm-body that has the different
completion behaviour would be fairly cheap to implement and if it was
some character sequence that was rare, it wouldn't cause many problems.
Also, not many people write generated [switch] arm-bodies, so the risk
of a collision with the output of [list] is (thankfully) very low.

> There is no such thing as a token-exception.
> That "return -code ..." also accept tokens is
> a feature of the return-command itself (it
> translates it to the according number).
> A tcl exception (behind the scenes) is not an entity, but
> just the ("int" typed) return value on C-level (otoh, the
> tcl return value is some entity inside the tcl interpreter
> that needs to be set using some function of the tcl-api).
>
> It's one thing to reserve a new exception, but another thing
> to completely redesign the guts of exception handling.

When you say "exception" you have to take care to specify what you
really mean. For most of what people think of in terms of exceptions
(taking into account practice outside the Tcl community too) the "error"
mechanism is good enough, especially if people take advantage of the
errorCode stuff. (OK, the Tcl core isn't very good at this either. :-})
By defining a new code, you're getting something with different
semantics, perhaps more akin to a longjmp().

> Finally, yes, there is a remote risk that some tcl-scripts
> use exception 5 for other purposes already, and depending
> on the code this clash might actually trigger unintended
> behaviour.

That risk exists, but I'd ignore it. :-)

Donal.

Donal K. Fellows

unread,
Jan 20, 2006, 5:21:22 AM1/20/06
to
Andreas Leitgeb wrote:

> Roy Terry <royt...@earthlink.net> wrote:
>> So perhaps more creativity would be demanded yes.
>> OTOH, consistent length and negation rules
>> are really helpful.
>
> Helpful, yes, but only as long as it doesn't hinder future useful
> operators just for lack of good available two-letter names.

I think "ni" was chosen in part because of it's joke potential. There's
absolutely no hard-and-fast rule about operator lengths, but they
probably still ought to be short.

Donal.

Uwe Klein

unread,
Jan 20, 2006, 7:09:31 AM1/20/06
to
Hi,

a little patch to try this feature:
helper proc:
proc caryon {} {return -code 5}

and a test:
switch ABC \
ABC {
puts inABC
caryon
} AA* {
puts inAA*
}

uwe
##########################################################################

*** tcl8.4.6/generic/tcl.h 2004-02-13 02:38:00.000000000 +0100
--- tcl8.4.6-add/generic/tcl.h 2006-01-20 12:18:15.374876232 +0100
***************
*** 606,617 ****
--- 606,619 ----
* be exited; the interpreter's result is meaningless.
* TCL_CONTINUE Go on to the next iteration of the current loop;
* the interpreter's result is meaningless.
+ * TCL_CARYON continue with next script in switch
*/
#define TCL_OK 0
#define TCL_ERROR 1
#define TCL_RETURN 2
#define TCL_BREAK 3
#define TCL_CONTINUE 4
+ #define TCL_CARYON 5

#define TCL_RESULT_SIZE 200

*** tcl8.4.6/generic/tclCmdMZ.c 2004-03-01 21:18:46.000000000 +0100
--- tcl8.4.6-add/generic/tclCmdMZ.c 2006-01-20 13:03:58.003234719 +0100
***************
*** 2804,2837 ****
return TCL_ERROR;
}

! for (i = 0; i < objc; i += 2) {
/*
* See if the pattern matches the string.
*/

pattern = Tcl_GetString(objv[i]);

! matched = 0;
! if ((i == objc - 2)
! && (*pattern == 'd')
! && (strcmp(pattern, "default") == 0)) {
! matched = 1;
! } else {
! switch (mode) {
! case OPT_EXACT:
! matched = (strcmp(Tcl_GetString(stringObj), pattern) == 0);
! break;
! case OPT_GLOB:
! matched = Tcl_StringMatch(Tcl_GetString(stringObj),
! pattern);
! break;
! case OPT_REGEXP:
! matched = Tcl_RegExpMatchObj(interp, stringObj, objv[i]);
! if (matched < 0) {
! return TCL_ERROR;
! }
! break;
! }
}
if (matched == 0) {
continue;
--- 2804,2838 ----
return TCL_ERROR;
}

! for (i = 0,matched = 0; i < objc; i += 2) {
/*
* See if the pattern matches the string.
*/

pattern = Tcl_GetString(objv[i]);

! if (matched == 0) {
! if ((i == objc - 2)
! && (*pattern == 'd')
! && (strcmp(pattern, "default") == 0)) {
! matched = 1;
! } else {
! switch (mode) {
! case OPT_EXACT:
! matched = (strcmp(Tcl_GetString(stringObj), pattern) == 0);
! break;
! case OPT_GLOB:
! matched = Tcl_StringMatch(Tcl_GetString(stringObj),
! pattern);
! break;
! case OPT_REGEXP:
! matched = Tcl_RegExpMatchObj(interp, stringObj, objv[i]);
! if (matched < 0) {
! return TCL_ERROR;
! }
! break;
! }
! }
}
if (matched == 0) {
continue;
***************
*** 2862,2867 ****
--- 2863,2872 ----
interp->errorLine);
Tcl_AddObjErrorInfo(interp, msg, -1);
}
+ /* new switch_continue option suppressing the implicit break */
+ if (result == TCL_CARYON) {
+ continue;
+ }
return result;
}
return TCL_OK;

Jeff Hobbs

unread,
Jan 20, 2006, 11:25:25 AM1/20/06
to

ni!

Andreas Leitgeb

unread,
Jan 20, 2006, 12:07:41 PM1/20/06
to
When I was speaking about "exceptions", I was
really speaking about the same "thing" that break/continue
were made of. just a new numerical code.

I definitely do *not* strive for any magic syntax, but a
consistent extension, that will make switch much more
powerful than C's controllable fall-through semantics.

Donal K. Fellows <donal.k...@manchester.ac.uk> wrote:
> By defining a new code, you're getting something with different
> semantics, perhaps more akin to a longjmp().

Huh? do break&continue involve longjmp()s ?

Just for illustration, here is a (very) simplified
(It only does exact match, no "-"-fallthroughs, no "default")
procedural version of switch as I have it in mind:

# the pitcher
proc reswitch {args} { return -code 5 $args }
# the catcher
proc myswitch {val arglist} {
foreach {pat body} $arglist {
if {$val eq $pat} {
set code [catch {uplevel 1 $body} ret]
if {$code==5} {
if {[llength $ret]>0} {set val [lindex $ret 0]}
continue
}
if {$code != 0} { return -code $code $ret }
break
}
}
}

#A sample usage:
myswitch foo {
foo {puts hello; reswitch snafu}
bar {puts notreached}
snafu {
puts re-Hi!
myif {1} {reswitch foo}
}
xyz {puts notreached}
foo {puts re-re-Hi:-); reswitch}
foo {puts re-re-re-Hi:-)}
}
# "myif" could be some procedural control-structure (with
# all the bits&bytes to correctly rethrow any exceptions),
# but for now we make it easy:
interp alias {} myif {} if

This args/llength/lindex-thingie is to tell a
reswitch without arg from one with empty string.

>> Finally, yes, there is a remote risk that some tcl-scripts
>> use exception 5 for other purposes already, and depending
>> on the code this clash might actually trigger unintended
>> behaviour.
> That risk exists, but I'd ignore it. :-)

good to know :-)

Joe English

unread,
Jan 20, 2006, 4:23:41 PM1/20/06
to
Donal K. Fellows wrote:
>Andreas Leitgeb wrote:
>>
>> Finally, yes, there is a remote risk that some tcl-scripts
>> use exception 5 for other purposes already, and depending
>> on the code this clash might actually trigger unintended
>> behaviour.
>
>That risk exists, but I'd ignore it. :-)

Am I the only one who uses nonstandard completion codes
for specialized control flow?

I've used -returncode $X (where $X > 4) in the past as
an interrupt signal (to halt a long-running process),
as a way to distinguish managed failure modes from
unexpected errors, and for more conventional throw/catch-style
exception handling. It's not something I do very often,
but it does come in very handy on occasion.


--Joe English

Bryan Oakley

unread,
Jan 20, 2006, 6:11:19 PM1/20/06
to
Joe English wrote:

> Am I the only one who uses nonstandard completion codes
> for specialized control flow?

No, but you're probley one of only two or three :-)

I did it once a few years ago in a complex implementation of
try/catch/throw. I'm not a big fan, personally. Tcl's catch does pretty
much all I need for most real world tasks.

Still, it's nice knowing the capability exists to throw and catch custom
error codes, and that things like errorCode were designed to handle such
shenanigans with aplomb.

Fredderic

unread,
Jan 20, 2006, 10:10:33 PM1/20/06
to
On 20 Jan 2006 21:23:41 GMT,
jeng...@flightlab.com (Joe English) wrote:

> > > Finally, yes, there is a remote risk that some tcl-scripts
> > > use exception 5 for other purposes already

> > That risk exists, but I'd ignore it. :-)
> Am I the only one who uses nonstandard completion codes
> for specialized control flow?

No... I've used them a time or three.

Though I make it a general rule to use codes >> 4, simply since the
system uses 0-4 for itself, it kind of makes sense that there might be
a 5 some day. Or a 6, or 7...

Though I figure it's unlikely there'll be a 10 or 11 in the lifetime of
my scripts (6 wholely new concepts in core looping structure, above and
beyond those already there, is probably at least marginally unlikely),
so I generally start there. On the other hand, the last script I used
extra return codes in, started at 300, since that's the value range
used by HTTP for interesting values.


Fredderic

Andreas Leitgeb

unread,
Jan 22, 2006, 4:30:59 AM1/22/06
to
Fredderic <put_my_n...@optusnet.com.au> wrote:
>> Am I the only one who uses nonstandard completion codes
>> for specialized control flow?
>
> No... I've used them a time or three.
>
> Though I make it a general rule to use codes >> 4, simply since the
> system uses 0-4 for itself, it kind of makes sense that there might be
> a 5 some day. Or a 6, or 7...

Yes, that's what I wanted to reply, too.
I haven't yet used it at all, but I was once just before
using it, and I considered using a larger value too, for
the very same reason.

It probably had been better to mention in the docs for
catch&return, that "some range immediately above 4 should
rather be avoided for custom exceptions, in anticipation
of more standard-exceptions to be added in future."

We could remove likeliness of a clash (reswitch versus
custom exception) even further, by adding some magic into
the message, but more on that in the original reswitch-thread.

Andreas Leitgeb

unread,
Jan 22, 2006, 4:39:51 AM1/22/06
to
Some slight changes to the demo, to alleviate
possible clashes with custom exceptions
(This is because JoeE. specifically complained
about "stealing" exception 5 from user's use)

Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at> wrote:
> # the pitcher
- proc reswitch {args} { return -code 5 $args }
+ proc reswitch {args} { return -code 5 [concat reswitch $args] }

> # the catcher
> proc myswitch {val arglist} {
> foreach {pat body} $arglist {
> if {$val eq $pat} {
> set code [catch {uplevel 1 $body} ret]

- if {$code==5} {
+ if {$code==5 && [lindex $ret 0] eq "reswitch"} {
- if {[llength $ret]>0} {set val [lindex $ret 0]}
+ if {[llength $ret]>1} {set val [lindex $ret 1]}

Andreas Leitgeb

unread,
Jan 22, 2006, 4:43:16 AM1/22/06
to

O Tempora O Mores!
Who says "ni" to dear colleagues these times?
(sorry, don't know the original english wording...)

By the way, would the knights also say "!in" ?

Uwe Klein

unread,
Jan 22, 2006, 5:27:34 AM1/22/06
to
Hi,

had a look at my test implementation
posted further up?
the changes to tclCmdsMZ.c are minimal
to achieve this.

Subject: "Re: proposal: reswitch : test implementation"

uwe

Fredderic

unread,
Jan 22, 2006, 11:11:23 AM1/22/06
to
On 22 Jan 2006 09:30:59 GMT,
Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at> wrote:

> > Though I make it a general rule to use codes >> 4, simply since the
> > system uses 0-4 for itself, it kind of makes sense that there might
> > be a 5 some day. Or a 6, or 7...

> It probably had been better to mention in the docs for
> catch&return, that "some range immediately above 4 should
> rather be avoided for custom exceptions, in anticipation
> of more standard-exceptions to be added in future."

You mean they don't teach common sense in grade school anymore?
(Actually, I take that back. The last thread I had input to pretty much
proved the point already.)

You're right, though... It should have been mentioned in the
documentation when the capability was first implemented, that TCL
reserves the right to add a few extra codes every so often.


> We could remove likeliness of a clash (reswitch versus
> custom exception) even further, by adding some magic into
> the message, but more on that in the original reswitch-thread.

While I disagree with the reason for doing this, the method might just
work, especially in that it's reusable (of course, it should be noted
in the documentation that a different code should be used for user
functions, even those that run along the same lines, and that codes <10
for example, are henceforth reserved for TCL's internal use, so as to
avoid this whole issue all over again in the near future). Though I
don't much like a string compare in a feature that has the potential to
see an awful lot of use, maybe some internal magic can hide that --
perhaps we should consume number 5 for "internal extensions", apply a
bit of magic to avoid those nasty string comparisons, and accept that a
few scripts will get messed up, but that they'll know better now so it
shouldn't happen again for a very long time. The same thing happened
with a few scripts that had their own [dict] command, and will
inevitably happen again to someone, somewhere, with every single new
command added to the TCL core. Doesn't help this time, but should
help future occurrences.

I've been asking myself a few questions during this sub-thread, things
that I've hit which have ruined the otherwise perfectly good use for the
[switch] command; Do we want to stop the current code block when we hit
a "reswitch", or should we continue to the end? (the continue on for now
option is fairly easily fudged in script, as could be the do-it-now by
following it with a switch-reactive break and some internal magic) Do
we want to continue searching, or just execute the next block
regardless (I feel supporting the C-style semantics is a must, I've
missed that on many an occasion, but making that the only way misses
some of the inherent magic of TCL). If we continue searching, should
we restart the search from the beginning (this can cause loops, and can
be fudged with a bit of scripting, a "do {} while" type loop would help
here -- but it's still occasionally handy). I've personally needed to
synthesise each of those situations from time to time, so I know they
exist.


Two options come to my mind for very good solutions; how about extending
[break] and [continue] with a "-switch ?string?" option. [break
-switch] would stop this code block instead of the inner-most loop.
[continue -switch] would likewise stop this code block, the difference
being that if ?string? wasn't given it would simply continue on with
the next code block. In both cases if a ?string? was supplied, the
next block that matched would be the one to go next. Personally I think
that "default" should ONLY match if NO other block does (same as it
does right now). So [continue] and [break] would never reach a
"default" block. Their semantics would be basically identical if
a ?string? argument IS given, so if you're upset about "default" not
executing, maybe [continue] could run the "default" block if no further
matches exist, vs [break] which would not.

Along those same lines, I've often wanted to be able to "reloop without
retest" (both in [for] and [while]), and have had to do some mildly ugly
hacks to get that functionality. We could consume return code 5 for
that purpose, and use that code to carry the [reswitch] functionality
(yes, I'm un-repenting in my statement that anyone who used return
code five deserves what they get ;) ). A kind of "reloop" command. It
sort of fits in after continue... We've got unconditional-non-reloop
(break), conditional-reloop (continue), and now unconditional-reloop
(reloop). And, combining it with the [continue] and [break] extensions,
you could make it a "reswitch from the beginning ([break] semantics)"
in addition to the two "continue on from where we are" choices.


Fredderic

Uwe Klein

unread,
Jan 22, 2006, 11:34:47 AM1/22/06
to
Hi Fredderic,

on return codes:
what about having introspection and reservation for return codes?


on reswitch and sibblings:
doing the reswitch thing should abort/leave that block of code
at that place.

I'd guess having more than a "dont break like" option is not really
that necessary.

For me the advantage lies in not having the same longish code in 2 switch
arms ( and thus reducing possible errors and furthering my lazyness. )

uwe


Donal K. Fellows

unread,
Jan 22, 2006, 8:31:42 PM1/22/06
to
Uwe Klein wrote:
> had a look at my test implementation posted further up?

No, or at least not in detail. ;-)

> the changes to tclCmdsMZ.c are minimal to achieve this.

But they'd be a real pain to implement as an efficient compilation.
Syntactic stuff is *much* easier to deal with when making bytecode.

Donal.

Donal K. Fellows

unread,
Jan 22, 2006, 8:44:41 PM1/22/06
to
Uwe Klein wrote:
> on return codes:
> what about having introspection and reservation for return codes?

Ugly; they're not local to interpreters. They might even be not local to
threads. That makes managing the allocator tricky.

Donal.

Andreas Leitgeb

unread,
Jan 23, 2006, 6:49:22 AM1/23/06
to
Uwe Klein <uwe_klein_...@t-online.de> wrote:
> I'd guess having more than a "dont break like" option is not really
> that necessary.
>
> For me the advantage lies in not having the same longish code in 2 switch
> arms ( and thus reducing possible errors and furthering my lazyness. )

These two paragraphs semantically contradict each other!
Those who have the same code in 5 arms shall be stuck with it?

Having just a (reverse-)C-style "(don't)break" is a half-assed
solution. In C this solution suffices only because in C
there is also "goto" that lets one jump around, anyway
(inside the switch-body and even backwards).

In Tcl, we should at least be able to have *several* (not
just the immediately previous) branches continue to one
single branch in a structured way - without a general goto.
Otherwise, dup(trip/quad/...)lication of code will not
noticably reduce - at most just in the simple cases.

I see no other sane way than use the exception-mechanism for it.

Andreas Leitgeb

unread,
Jan 23, 2006, 6:54:51 AM1/23/06
to
Uwe Klein <uwe_klein_...@t-online.de> wrote:
> had a look at my test implementation
> posted further up?

Yes, but from the description it seemed to just mimic
the yucky C-switch semantics of controllable fall-through.

(When I came across sthg like "dontbreak" I stopped reading)

Uwe Klein

unread,
Jan 23, 2006, 7:27:42 AM1/23/06
to
Andreas Leitgeb wrote:
> Uwe Klein <uwe_klein_...@t-online.de> wrote:
>
>>I'd guess having more than a "dont break like" option is not really
>>that necessary.
>>
>>For me the advantage lies in not having the same longish code in 2 switch
>>arms ( and thus reducing possible errors and furthering my lazyness. )
>
>
> These two paragraphs semantically contradict each other!
touche. BUT..

> Those who have the same code in 5 arms shall be stuck with it?

>
> Having just a (reverse-)C-style "(don't)break" is a half-assed
> solution. In C this solution suffices only because in C
> there is also "goto" that lets one jump around, anyway
> (inside the switch-body and even backwards).
>
> In Tcl, we should at least be able to have *several* (not
> just the immediately previous) branches continue to one
> single branch in a structured way - without a general goto.
> Otherwise, dup(trip/quad/...)lication of code will not
> noticably reduce - at most just in the simple cases.
>
> I see no other sane way than use the exception-mechanism for it.
>

a basic requirement for this would IMHO be readability.

i.e. the diverse flowchanging options to be introduced must lead
to better readability.

What variations do you/we have in mind?

1. Cbreak: continue with next codeblock

2. reswitch: continue with next switch-test

3. continue: restart at top

4. ......


uwe

Uwe Klein

unread,
Jan 23, 2006, 7:37:10 AM1/23/06
to
Andreas Leitgeb wrote:
> Uwe Klein <uwe_klein_...@t-online.de> wrote:
>
>>had a look at my test implementation
>>posted further up?
>
>
> Yes, but from the description it seemed to just mimic
> the yucky C-switch semantics of controllable fall-through.
i did not want to get my fingers further in the yucky stuff ;-)

>
> (When I came across sthg like "dontbreak" I stopped reading)

i have reservations about introducing an abundace of options in switch.

aditionally i see danger with doing things _slightly_ different
than in another (popular) language.

uwe

Donal K. Fellows

unread,
Jan 23, 2006, 9:00:49 AM1/23/06
to
Uwe Klein wrote:
> a basic requirement for this would IMHO be readability.
>
> i.e. the diverse flowchanging options to be introduced must lead
> to better readability.
>
> What variations do you/we have in mind?
>
> 1. Cbreak: continue with next codeblock
>
> 2. reswitch: continue with next switch-test
>
> 3. continue: restart at top

One possibility would be to have the "payload" for the code (i.e. the
interpreter result) be a (literal) switch label to jump to. That would
enable all sorts of interesting behaviour, though without the awkward
"jump to anywhere in the function" semantics of classic C goto.

Donal.

Uwe Klein

unread,
Jan 23, 2006, 9:44:34 AM1/23/06
to
something like continue_at <label> ?

how do you propose to place the labels?

uwe

Andreas Leitgeb

unread,
Jan 23, 2006, 10:56:43 AM1/23/06
to
Uwe Klein <uwe_klein_...@t-online.de> wrote:

> Andreas Leitgeb wrote:
>> Yes, but from the description it seemed to just mimic
>> the yucky C-switch semantics of controllable fall-through.
> I did not want to get my fingers further in the yucky stuff ;-)

You just got them in at the wrong, yucky stuff. :-)

>> (When I came across sthg like "dontbreak" I stopped reading)

The word was actually "TCL_CARYON" (apart from the typo (carry has 2 'r'))

> I have reservations about introducing an abundace of options in switch.

Why should we need any new options at all?

Either a certain exception is thrown inside a body -> new behaviour
or not -> classic behaviour

> aditionally i see danger with doing things _slightly_ different
> than in another (popular) language.

* C's controllable fallthrough: (without C's "goto")
- very limited use: (continuation possible only to
immediately following branch)
- doesn't really mimic C: Syntax (even at first glance) is
still quite different.

* "reswitch" exception with an optional new <value>:
+ many branches can continue to the same "common"-branch
+ simple & transparent
- interferes with latest optimization attempts towards
a hash-based branch-lookup for 'switch -exact's.

* "continue_at" exception with a <label>:
(that is: like reswitch, but further do -exact matching)
+ many branches can continue to the same "common"-branch
+ even simpler (because one doesn't have to think of a value
that would only match the intended branch)
+ since labels are(would be) literal constants, hash-based
lookup can be done.
-(?) eventually requires magic to tell patterns from labels.

Btw. whether to open the door to "loops with switch" is likely
even more controversial: I originally envisioned a loop-free
version, but the one with labels rather suggests allowing loops.
(especially with respect to hashmap-lookup, where the order
of branches is theoretically "lost")

I think, "continue_at" would actually make me happy, too.
(although I'd hope for a better name)

Andreas Leitgeb

unread,
Jan 23, 2006, 11:29:19 AM1/23/06
to
Fredderic <put_my_n...@optusnet.com.au> wrote:
> Do we want to continue searching, or just execute the next block
> regardless (I feel supporting the C-style semantics is a must, I've
> missed that on many an occasion, but making that the only way misses
> some of the inherent magic of TCL).

Supporting the "continue with immediately next" surely isn't a bad thing.
Not going beyond it, *is* a bad thing.

> If we continue searching, should
> we restart the search from the beginning (this can cause loops, and can

> be fudged with a bit of scripting, [...] -- but it's still occasionally
> handy).

I personally don't care about a loop-ability of switch.
If it gets in, I'll probably use it. On the other hand, its
a "dangerous" tool, that can easily be misused to create
unmaintainable code (programming BASIC in tcl).

> Two options come to my mind for very good solutions; how about extending
> [break] and [continue] with a "-switch ?string?" option.

This would be *the* solution, if reserving new exception codes
was considered a taboo. But reserving a new exception code
for this task looks&feels better, imho.

> So [continue] and [break] would never reach a "default" block.

There are surely pros and cons for reaching the "default" block.
I don't have any strong feelings for or against.
Btw. there can be two "default" blocks, the sequentially first
of whose will just match a literal "default" value :-)


> Along those same lines, I've often wanted to be able to "reloop without
> retest" (both in [for] and [while]), and have had to do some mildly ugly
> hacks to get that functionality. We could consume return code 5 for
> that purpose, and use that code to carry the [reswitch] functionality
> (yes, I'm un-repenting in my statement that anyone who used return
> code five deserves what they get ;) ). A kind of "reloop" command.

hmm, "reloop" doesn't "look" like it would do anything with switch.
perhaps "redo"? This would sound like "reswitch" in switch and
"continue without incr/test" in loops)

Darren New

unread,
Jan 23, 2006, 11:55:14 AM1/23/06
to
Uwe Klein wrote:
> For me the advantage lies in not having the same longish code in 2 switch
> arms ( and thus reducing possible errors and furthering my lazyness. )

And your objection to procs to hold "longish code" is....? :-)

--
Darren New / San Diego, CA, USA (PST)
Luke, the Force is a powerful ally,
second only to The QuickSave.

Uwe Klein

unread,
Jan 23, 2006, 12:01:10 PM1/23/06
to
Andreas Leitgeb wrote:
> Uwe Klein <uwe_klein_...@t-online.de> wrote:
>
>>Andreas Leitgeb wrote:
yucky stuff deleted ..

> The word was actually "TCL_CARYON" (apart from the typo (carry has 2 'r'))
you sure i didn't have these in mind ?;-)
>> http://www.psic.com/product_html/crayon_1.htm

>>I have reservations about introducing an abundace of options in switch.

> Why should we need any new options at all?

if the alternative is jumping on labels that is ok with me.


>
> Either a certain exception is thrown inside a body -> new behaviour
> or not -> classic behaviour

ups i would have liked to just use [continue] but that would break
code that uses [continue] in [switch] to continue in the enclosing loop.

would allowing options to [continue] break anything ?

> * "continue_at" exception with a <label>:
> (that is: like reswitch, but further do -exact matching)
> + many branches can continue to the same "common"-branch
> + even simpler (because one doesn't have to think of a value
> that would only match the intended branch)
> + since labels are(would be) literal constants, hash-based
> lookup can be done.
> -(?) eventually requires magic to tell patterns from labels.
>

what about using the literal patterns as labels?
they are already there and the meaning is obvious.
- you can not jump into some abitrary place.

switch $value \
ABC {
do_body_ABC
continue after AB*
} AB* {
do_body_AB*
continue at/before XYZ
} DEF {
do_body_DEF
if {$loopflag} {
continue at top
} else {
continue after end
} XYZ {
do_body_XYZ
} default {
do_default
}

uwe

Uwe Klein

unread,
Jan 23, 2006, 12:17:02 PM1/23/06
to
Darren New wrote:
> Uwe Klein wrote:
>
>> For me the advantage lies in not having the same longish code in 2 switch
>> arms ( and thus reducing possible errors and furthering my lazyness. )
>
>
> And your objection to procs to hold "longish code" is....? :-)
>
nothing really, on occasion i found that i had an abundace of vars
to carry with me. I hate procs with 10 args.

what i usually do is split processing into 2 consecutive [switch]es

in the first switch prepare all input into general cases
in the second [switch] process the general cases

uwe

Darren New

unread,
Jan 23, 2006, 12:23:18 PM1/23/06
to
Uwe Klein wrote:
>> And your objection to procs to hold "longish code" is....? :-)
>>
> nothing really, on occasion i found that i had an abundace of vars
> to carry with me. I hate procs with 10 args.

And your objection to uplevel is... ? ;-)

> what i usually do is split processing into 2 consecutive [switch]es
>
> in the first switch prepare all input into general cases
> in the second [switch] process the general cases

Probably a better design. I've just always found that when a language
as sophisticated as Tcl seems to lack a fundamental control structure,
it's because I've structured the code in an unclear way. :-)

Uwe Klein

unread,
Jan 23, 2006, 12:32:41 PM1/23/06
to
Darren New wrote:
> Uwe Klein wrote:
>
>>> And your objection to procs to hold "longish code" is....? :-)
>>>
>> nothing really, on occasion i found that i had an abundace of vars
>> to carry with me. I hate procs with 10 args.
>
>
> And your objection to uplevel is... ? ;-)
stopitstopitstopit pit stop!

>
>> what i usually do is split processing into 2 consecutive [switch]es
>>
>> in the first switch prepare all input into general cases
>> in the second [switch] process the general cases
>
>
> Probably a better design. I've just always found that when a language
> as sophisticated as Tcl seems to lack a fundamental control structure,
> it's because I've structured the code in an unclear way. :-)
>
OK lets dump funny switch enhancements and return to our uplevels.

uwe

Fredderic

unread,
Jan 24, 2006, 12:40:25 AM1/24/06
to
On 19 Jan 2006 12:29:20 GMT,
Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at> wrote:

> > we can not use [break] as it would break loop behaviour
> > we can not use [continue] as see above.
> 100% agree that break/continue are out of question

I totally disagree that using [break] and [continue] in [switch]s will
break anything, so long as you do it via an option; can anyone
come up with a solid definitive reason exactly WHY [break] and
[continue] can't be applied to [switch], apart from "because that's the
way is was decided ages ago when TCL was young and still trying to
define itself".

Since neither [break] or [continue] take ANY arguments at all (as far
as my documentation says), there's no chance of any kind of clash
anywhere. After all, what was the rationale of making [return] take
options in addition to its return value, the first place? Since [break]
and [continue] are little more than convenience functions these days,
this opens the possibility to at a latter date introduce the "return
-levels" concept to loop levels within a procedure (which I've used,
and have seen used, very successfully in some other languages). I
certainly know I've wanted to be able to [break 2], or something along
those lines, in a few TCL scripts (and end up using a variable kludge to
"carry" the break). That's a discussion for another time, for sure,
but the broader concept behind [break] and [continue] is "stopping the
currently executing code to some degree". TCL has already implemented
three such degree's (that I know of offhand); inner-most loop, an
intervening catch, or the procedure boundary (which is an error case).
So refusing to expand the [break] and [continue] functions because
they're small and neat is just wrong.


(Personal note: Yes, I do accept, and already accepted the possibility
of, my [catch] idea being rejected. :) I've been using TCL for a few
years now, since about 1997, though until recently I was stuck with
using an oldish version that was supplied -- now that I'm able to use a
reasonably up-to-date version, I'm taking the opportunity to discuss
some of the things that have been bugging me for most of those years,
when they come up, and I'm taking the opportunity here to express some
things that have been bugging me on a conceptual level, during this
overall discussion.)


> > creating a new command (reswitch|nobreak|more|moreswitch ..)
> > is intrusive and might lead to unpleasant complaints on
> > comp.lang.tcl.
> 0% agree on this, though.

I don't think it's intrusive as such, it's just a quick patch
one-hit-wonder type thing, which I have always felt is evil in any
"core" environment. Look at OS kernels (preferably not Windows ;) ),
even some application software, they're all about re-usability and
connectivity. A one-hit-wonder is only acceptable if it IS the means to
obtain such generalised usage. TCL's tendancy towards "package"
type commands (dict, file, etc.) are a very good example of not
creating one-hit-wonder functions, and a very nice style that IMHO
fits in well with TCL. Also IMHO, a switch-only command is just cruft
in every other context -- admittedly sometimes this is necessary, but
this time it isn't.


The rest of this reply was pulled from the "Nonstandard completion
codes" thread, because I think it fits back here better.

> > If we continue searching, should we restart the search from the
> > beginning (this can cause loops, and can be fudged with a bit of
> > scripting, [...] -- but it's still occasionally handy).
> I personally don't care about a loop-ability of switch.
> If it gets in, I'll probably use it. On the other hand, its
> a "dangerous" tool, that can easily be misused to create
> unmaintainable code (programming BASIC in tcl).

I agree... Which is why I thought the use of a [reloop] type function
was appropriate, because it streses the fact that contrary to the other
two, this one CAN cause loops. [switch] to my mind, isn't a looping
construct. However it is none the less a block construct, and so the
possibility to loop is worth considering. One place where I've needed
to wrap a [switch] in a [while], is to implement state machines, for
example. A small, simple tight state machine could very easily be
built using a loop-capable [switch], such as you might use for
processing a character string.

I would love the ability to create a quick tight switch-loop that
processes a few characters of a string at a time, [reswitch]ing with
the currently un-processed portion of the string. I'd also hate to
lose the top-down flow, in SOME cases. Not all, many of them don't
really care. But I've had a few where the top-down flow was very
important. The documentation I have reads: " The switch command matches
its string argument against each of the pattern arguments in
order. " I'd be concerned that hash-based optimisation might remove
this constraint.


> > Two options come to my mind for very good solutions; how about
> > extending [break] and [continue] with a "-switch ?string?" option.
> This would be *the* solution, if reserving new exception codes
> was considered a taboo. But reserving a new exception code
> for this task looks&feels better, imho.

The break and control exceptions are general concepts. They apply to
most looping constructs throughout any language, even totally new
ones. The reswitch "exception" kind of breaks that mold, in my mind,
being very restrictive in purpose (with the string thing, the
exception itself is generalised, but the usefulness of that is a
little wishy -- it doesn't automatically do much for the rest of the
language). At least a reloop exception has a new concept attached,
that can be applied back to add functionality right through, being a "go
back to the start of this code block", as opposed to "skip the rest of
this code block, and optionally (depending on the exact exception) try
for another iteration". The only part that would need further
discussion, is whether reloop would run the increment part of a [for].


> > So [continue] and [break] would never reach a "default" block.
> There are surely pros and cons for reaching the "default" block.

I tried very hard to ignore getting in that. ;) Though my gut feeling
is that "default" should be a "if nothing else matched" type thing.
Other cases can be implemented with little work, but the "if nothing
else matched" is a harder one to implement on your own.


> I don't have any strong feelings for or against.
> Btw. there can be two "default" blocks, the sequentially first
> of whose will just match a literal "default" value :-)

I'd hope that only the last "default" block would be the default one.
Personally, considering the stringyness of TCL, I think they should
have broken with tradition and added an "else" clause to the [switch],
similar to the [if]. ie. taken right out of the body so it couldn't be
confused. (In C, for example, the "default" case is a very distinct
clause in its own right) Though I understand why they didn't do that;
it'd look rather ugly for starters. :)


> > Along those same lines, I've often wanted to be able to "reloop
> > without retest" (both in [for] and [while]), and have had to do
> > some mildly ugly hacks to get that functionality. We could consume
> > return code 5 for that purpose, and use that code to carry the
> > [reswitch] functionality (yes, I'm un-repenting in my statement
> > that anyone who used return code five deserves what they get ;) ).
> > A kind of "reloop" command.
> hmm, "reloop" doesn't "look" like it would do anything with switch.
> perhaps "redo"? This would sound like "reswitch" in switch and
> "continue without incr/test" in loops)

[redo] works for me... My main pet hate in this discussion, is the
introduction of a switch-only command and/or exception. It feels to me
like a patch or hack tacked on the end, where concepts already exist to
perform the same job.

But then that's me... I don't like too many one-hit-wonders (like a
[reswitch] or [continue_at]) in a programming language (mind you,
[continue_at] might be nice to have also... But the idea of "now try
to match this" is to my mind far more "TCLish" than a "goto", which is
essentially what [continue_at] is all about). I also hate exceptions to
rules. I'd much rather make the most of what's already there. If
you're going to add the ability to break execution of a switch code
block and either stop or continue elsewhere, then to my thinking you
should call it break or continue. [continue_at] is the only one that
codes close, but as I said, it sounds far too "goto"ish for me.
(The only good use I've seen for "goto", is adding a cleanup block
that can be goto'd as soon as we realise things have gone sour.)

A -switch option to [break] and [continue] (and [redo] or [reloop])
allows the concept of those functions to persist in the context of a
[switch]; we can "break" a switch _unless_ there's a matching code
block further down, or we can "continue" a switch onto the next code
block or the next matching code block -- it also allows the user the
freedom to pick whether they want to include the default case or not
(although there is a slight corner case, in that a bare [continue
-switch] wouldn't run the default case, where a [continue -switch
string] would, however it's by no means the only one, and well worth
the extra sentence or two in the documentation). This method, however
also keeps the top-down (non-loop) nature of a [switch], unless you
explicitly want it (via [redo]).


I'm hoping this issue won't be solved on the basis of "oh, it's just
too hard to fit that stuff into my new idea for optimisation".
Optimisation is good, but I think it should never be a driving factor
in a high-level non-compiled language, that's what low-level and
compiled languages are for. Develop the language, THEN optimise. Not
the other way around. If the optimisation doesn't work out, maybe
you'll come up with a better method next version.

Besides which, even if the hash switch optimisation only works on the
initial step, and degenerates from there back to the usual switch style
sequential search, it would probably be fine. MOST cases will still
enjoy the optimisation at its best. I'm not sure how the byte-code
compiler in TCL works, but should it not be possible to decide late
which method to use to represent it? If there's no [reswitch]ish
behaviour, then use the hash method. If there is, fall back to the
usual. It may also be possible to add a -fast option to [switch],
telling it that you don't care about the test order, or alternatively
add a -strict option that states that you do (depending on the current
consensus of what the existing official documentation says).


Fredderic

Fredderic

unread,
Jan 24, 2006, 1:10:07 AM1/24/06
to
On Mon, 23 Jan 2006 15:44:34 +0100,
Uwe Klein <uwe_klein_...@t-online.de> wrote:

> >> What variations do you/we have in mind?
> >> 1. Cbreak: continue with next codeblock
> >> 2. reswitch: continue with next switch-test
> >> 3. continue: restart at top

4. Stripping an arbitrarily applied limitation from what we already
have.


> > One possibility would be to have the "payload" for the code (i.e.
> > the interpreter result) be a (literal) switch label to jump to.
> > That would enable all sorts of interesting behaviour, though
> > without the awkward "jump to anywhere in the function" semantics of
> > classic C goto.

> something like continue_at <label> ?

"goto", but only in a switch? Half the fun of [switch] is that it
allows glob and regexp matches. It would be good to be able to match
on AB*, and then the more general A*. This is possible, but what if
one instance of the AB* case would be better served by simply dropping
the A and matching on the B*. This is simple example. If we're
talking about parsing a string, you could very quickly end up with
switches-within-switches involving sub-sets of the main switch patterns,
if all you have is a "goto" (aka [continue_at]).

I'm not saying [continue_at] is a bad idea. And I can't see any clean
alternative other than creating a switch-only function to do it (this
is one of the places where these one-hit-wonder commands ARE
applicable). But it's a stop-gap measure at best, in the context of
the original proposal as I read it, even if it does have its own
unique purpose.


> how do you propose to place the labels?

What's wrong with right after the pattern? We already have a
special-case body, namely "-" (which could theoretically be a valid
procedure name!).

% proc - {} {puts "forty-two"}
% -
forty-two
% switch 42 {
12 {puts twelve}
42 {-}
69 {puts sixty-nine}
}
sixty-nine

And then there's sub-expressions in the case of a RE-matched
[switch]. The switch pattern should be the code blocks "name", except
where a name is explicitly given. This would be particularly important
where [reswitch] comes into play, if multiple blocks are allowed to
have the same pattern (would come in handy where a bunch of matches
have some common pre- and/or post- code).


Fredderic

Andreas Leitgeb

unread,
Jan 24, 2006, 3:03:01 AM1/24/06
to
Uwe Klein <uwe_klein_...@t-online.de> wrote:
> OK lets dump funny switch enhancements and return to our uplevels.

I do hope that this was applied sarcasm...

proc dothing {} {uplevel 1 {
if {$foo eq "bar"} {set snafu "42"}
}}

No, I surely don't want any procedures lying around
and visible from everywhere that just perform a
snippet of another procedure, randomly accessing
or modifying callers local variables.

It might be feasible if we had procedure-local
procedures, but tcl doesn't have such a thing.
(even lambdas are not part of tcl, (yet?))

Uwe Klein

unread,
Jan 24, 2006, 3:43:19 AM1/24/06
to
Good Morning Fredderic,

i had posted this further up(to A.Leitgreb):

<start copy>


Andreas Leitgeb wrote:
> Uwe Klein <uwe_klein_...@t-online.de> wrote:
>

<end copy>

uwe

Donal K. Fellows

unread,
Jan 24, 2006, 5:03:35 AM1/24/06
to
Uwe Klein wrote:
> what about using the literal patterns as labels?
> they are already there and the meaning is obvious.

That was indeed what I was proposing. And it admits *very* efficient
implementation, though I'm not sure I like that it uses an exception
code in the first place. Those things leak.

Donal.

Donal K. Fellows

unread,
Jan 24, 2006, 5:05:00 AM1/24/06
to
Andreas Leitgeb wrote:
> (even lambdas are not part of tcl, (yet?))

The vote on that is probably this week.

Donal.

Matt Newman

unread,
Jan 24, 2006, 6:19:37 AM1/24/06
to
As a long time user of Tcl (1991-) I just want to say that one of the
overriding factors for me in Tcl's appeal has been SIMPLICITY.
Both in terms of writing (*and* reading) scripts, and extending where
needed in C.

The lack of complex syntactical constructs and a simple clarity of
inputs and outputs to commands (result, vars, return-code) enables the
language to be extended in an application-specific manner with relative
ease.

If we end up putting into Tcl a whole raft of complex syntactical
contructs, for me it ceases to be Tcl, becomming more and more like
Perl etc.
If I feel Perl is appropriate for a given project I can use Perl, if I
feel Java is right in a given context I can use Java, but please don't
throw away the simplicity that is Tcl - it really is one of its major
draws.

To be clear - I am very much in favor of Tcl evolving - but only in a
manner that keeps and builds upon its existing strengths.

Donal K. Fellows

unread,
Jan 24, 2006, 6:27:08 AM1/24/06
to
Matt Newman wrote:
> To be clear - I am very much in favor of Tcl evolving - but only in a
> manner that keeps and builds upon its existing strengths.

Nicely said. Thanks.

Donal.

Fredderic

unread,
Jan 24, 2006, 9:19:15 AM1/24/06
to
On Tue, 24 Jan 2006 11:05:00 +0100,
"Donal K. Fellows" <donal.k...@manchester.ac.uk> wrote:

> > (even lambdas are not part of tcl, (yet?))
> The vote on that is probably this week.

Great, another procedure of mine about to be wiped out by a new core
function.

I wrote a lambda procedure (probably miss-named, but it was the
closest name I could think of at the time). Essentially it shoves a
list of variables you feed it into an array, then creates a _lambda
proc that upvar's those variables into the proc as locals, before
executing your script fragment. The scratch proc is then executed
within an [uplevel 1] so that it itself executes in the callers
context.

% set junk 7
7
% lambda {{abc 3} {def junk #0}} {expr [incr abc] + [incr def -1]}
0 10 {abc 4 def 6}}
% set junk
6
% set abc
can't read "abc": no such variable

The second term is the script fragments return value. The third term
is a dict containing the new value of the local variables the script was
executed with. upvar references (created by the third argument in a
variable definition) are handled by fetching the current value of the
referred to variable, storing it in the array, then copying it back
again afterwards. The first term is a catch return code, and in the
case of TCL_ERROR, the errorInfo and errorCode variables get appended
to the return list also.

There's probably a better way of doing it, it's little more than a
quick hack because I wanted to get on with what I was doing, but it
works, I think (I haven't tested it extensively). There's also an
interesting side effect; all referenced variables are read once (before
the script fragment is executed), and written at most once (after it
returns). It'll also create and destroy any referenced variables that
were unset or created by the script.


proc lambda {bindList script} {
set upList {upvar #0}
set upCopy {}
foreach bindItem $bindList {
foreach {varName varValue varLevel} $bindItem {break}
if { $varName == "**" && $varValue != {} && $varLevel != {} } {
set local_list [uplevel $varLevel [list info locals]]
foreach varName [lsearch -inline -all $local_list $varValue] {
upvar 1 $varLevel $varName var
if { [info exists var] } {
set ::_lambda($varName) $var
set ::_lambdb($varName) $var
}
lappend upCopy $varLevel $varName $varName
}
continue
}
if { ! [info exists local($varName)] } {
lappend upList _lambda($varName) $varName
}
if { $varLevel ne "" } {
if { [string is digit $varLevel] } {incr varLevel}
upvar $varLevel $varValue var
if { [info exists var] } {
set ::_lambda($varName) $var
set ::_lambdb($varName) $var
}
lappend upCopy $varLevel $varValue $varName
} else {
set ::_lambda($varName) $varValue
}
}
proc ::_lambda {} [join [list $upList $script] ";"]
set code [catch [list uplevel 1 ::_lambda] resp]
set retInfo [list $code $resp [eval dict:create [array get ::_lambda]]]
if { $code == 1 } {
lappend retInfo $::errorCode $::errorInfo
}
foreach {varLevel varValue varName} $upCopy {
upvar $varLevel $varValue var
if { ! [info exists ::_lambda($varName)] } {
unset var
} elseif { ! [info exists ::_lambdb($varName)] || \
$::_lambda($varName) ne $::_lambdb($varName) } {
set var $::_lambda($varName)
}
}
catch {unset ::_lambdb ::_lambda}
return $retInfo
}


If anyone spots any errors, or has any improvements (or a better name
that won't clash if the lambda proposal gets into core), do let me
know. :)


Fredderic

Fredderic

unread,
Jan 24, 2006, 9:30:44 AM1/24/06
to
On 24 Jan 2006 03:19:37 -0800,
"Matt Newman" <matt....@gmail.com> wrote:

> To be clear - I am very much in favor of Tcl evolving - but only in a
> manner that keeps and builds upon its existing strengths.

This thread hasn't changed anything. Even with any of these
suggestions, [switch] will still work exactly as it used to. Give it a
string, and it'll run the first code block with a corresponding pattern.

The difference, is only in what it CAN do. All the original TCL
concepts still apply. The pattern is a word, and code block is a word,
and the option switches which might now appear in between, look like
option switches. If sub-expression variables are added for RE matches,
they'll (presumably) be in the same familiar order as per [regexp]. So
everything's the same as it used to be, it's just popping up in a new
place.


Fredderic

Neil Madden

unread,
Jan 24, 2006, 10:01:38 AM1/24/06
to
Uwe Klein wrote:

> Darren New wrote:
>> And your objection to procs to hold "longish code" is....? :-)
>>
> nothing really, on occasion i found that i had an abundace of vars
> to carry with me. I hate procs with 10 args.

You could pass a single compound data structure (e.g. a dict, array, or
some sort of object). Encapsulation etc.

-- Neil

Neil Madden

unread,
Jan 24, 2006, 10:05:54 AM1/24/06
to
Fredderic wrote:
> On Tue, 24 Jan 2006 11:05:00 +0100,
> "Donal K. Fellows" <donal.k...@manchester.ac.uk> wrote:
>
>
>>>(even lambdas are not part of tcl, (yet?))
>>
>>The vote on that is probably this week.
>
>
> Great, another procedure of mine about to be wiped out by a new core
> function.

Not unless your procedure happens to be called ::tcl::apply (as proposed
by TIP 194, there is also TIP 187).

-- Neil

Andreas Leitgeb

unread,
Jan 24, 2006, 10:13:25 AM1/24/06
to
Donal K. Fellows <donal.k...@manchester.ac.uk> wrote:

What, exactly, is leaking with exceptions?

Neil Madden

unread,
Jan 24, 2006, 10:53:04 AM1/24/06
to
Adrian Davis wrote:
> I do have to agree here. The "ne" and "eq" operators have made "if"
> comparisons considerably less verbose - To my mind the only (widely
> used) things missing now are "glob" and "regexp" string comparisons.
> Some thing like:-
>
> if {$myvar like *glob*}
>
> ...and...
>
> if {$myvar match {^[Rr]egexp$}}
>
> I have no idea how complex these would be to implement, but I can't
> imagine any Tcl/Tk programmer who wouldn't like to see something along
> these lines!!

They look quite cute, sure. But what about switches and sub-match vars
etc? Will we end up with:

if {$myvar match -nocase -line -expanded -start $idx -- $pattern -> sub1
sub2 sub3} { ... }

?

OK, that's over the top, but are these infix operators going to support
just the bare minimum basic functionality or are they going to become
complete duplicates of the commands?

Should every Tcl command have an infix equivalent in [expr]? Many now
do. Would it be nicer to adopt an OO-like approach to this? For
instance, $a eq $b can be accomplished simply via:

proc string: {str method args} {
uplevel 1 [linsert $args 0 ::string $method $str]
}
set s1 [list string: "my string"]
if {[$s1 equal $s2]} { ... }
# Careful below -- pattern is on left of operator!
if {[$s1 match $s2]} { ... }

Likewise, for regexp:

proc regexp: {pattern method args} {
array set map { match regexp replace regsub }
uplevel 1 [linsert $args 0 $map($method) $pattern]
}
set re [list regexp: {([^:]+):(?://)?([^:/]+)(:\d+)?(/.*)}]
if {[$re match $str -> proto host port path]} {
...
}

These examples assume auto-expansion of leading word when resolving
commands [1]. This is a nice extensible mechanism that works simply with
Tcl's existing command infrastructure. I'm not overly against adding new
operators to [expr] but it seems like duplication of functionality just
to get a prettier infix syntax.

For reference, you can get around the lack of auto-expand now by
avoiding variables:

proc define {name = args} {
uplevel 1 [linsert $args 0 interp alias {} $name {}]
}
define myre = regexp: $somepattern
if {[myre match $str -> var1 ...]} { ... }

[1] http://www.cs.man.ac.uk/~fellowsd/tcl/future.html

-- Neil

Andreas Leitgeb

unread,
Jan 24, 2006, 12:21:46 PM1/24/06
to
Neil Madden <n...@cs.nott.ac.uk> wrote:
> They look quite cute, sure. But what about switches and sub-match vars
> etc?

As soon as you need options conciseness is gone,
anyway, so you can just as well go the old way:
if {[somecmd -opt1 -opt2 $val1 $val2]} ...

Donal K. Fellows

unread,
Jan 24, 2006, 7:12:42 PM1/24/06
to
Fredderic wrote:
> Great, another procedure of mine [called lambda] about to be wiped out

> by a new core function.

Not this time. The process of generation of a lambda expression is
pretty trivial, so much so that it's actually just a matter of using the
[list] command with the right arguments. :-) Given that, the TIP does
not specify a standard constructor command, sticking instead to the
details of mechanisms for evaluating it (and which is namespaced nicely
so it shouldn't hit anyone's code).

Donal.

Don Porter

unread,
Jan 24, 2006, 9:01:24 PM1/24/06
to
Donal K. Fellows wrote:
> ... Given that, the TIP does

> not specify a standard constructor command, sticking instead to the
> details of mechanisms for evaluating it (and which is namespaced nicely
> so it shouldn't hit anyone's code).

We've backed away from that and TIP 194 will propose an [::apply]
command when the vote starts (should be tomorrow).

Half-baked plans to propose [::tcl::apply] instead foundered when it
became apparent that blazing that trail had more work and more
precedent-setting creativity required than anyone wanted to take on as
part of this proposal.

In other command name collision news, though, note that TIP 248 (already
approved) includes a Great Renaming for Tk: [::button] -> [::tk::button]
for example, with existence of [::button] preserved via [namespace import].

Perhaps if that goes well, and can serve as an example, we can come
back and at least do the same for the "new in 8.5" commands like
[::dict], [::lassign], [::apply], etc.

--
| Don Porter Mathematical and Computational Sciences Division |
| donald...@nist.gov Information Technology Laboratory |
| http://math.nist.gov/~DPorter/ NIST |
|______________________________________________________________________|

Donal K. Fellows

unread,
Jan 25, 2006, 4:55:20 AM1/25/06
to
Andreas Leitgeb wrote:
> What, exactly, is leaking with exceptions?

Tcl does not try very hard to stop exception codes "leaking" from one
context to another; after all, that's usually what you want and is
indeed necessary in some circumstances. But it does mean that when we
introduce a new code, we have to consider what happens when things are
used in unexpected situations (e.g. what happens if someone makes the
"magic jump" command an inter-interpreter alias for the purposes of some
kind of debugging?)

On the other hand, I'm not sure we need *any* of this elaborate-ness at
all. Matt Newman's comments on simplicity sound very persuasive to me.

Donal.

Donal K. Fellows

unread,
Jan 25, 2006, 4:59:25 AM1/25/06
to
Don Porter wrote:
> In other command name collision news, though, note that TIP 248 (already
> approved) includes a Great Renaming for Tk: [::button] -> [::tk::button]
> for example, with existence of [::button] preserved via [namespace import].
>
> Perhaps if that goes well, and can serve as an example, we can come
> back and at least do the same for the "new in 8.5" commands like
> [::dict], [::lassign], [::apply], etc.

I'd be tempted to say that all Tcl core commands should exist in the
::tcl namespace and be imported from there. But only if it doesn't
hammer our performance. With Tk that's not an issue, since Tk isn't
byte-compiled and isn't ever going to be; command dispatch is nowhere on
the map compared with the costs of creating and drawing a complex GUI.

Donal.

Andreas Leitgeb

unread,
Jan 25, 2006, 6:15:22 AM1/25/06
to
Don Porter <d...@email.nist.gov> wrote:
> In other command name collision news, though, note that TIP 248 (already
> approved) includes a Great Renaming for Tk: [::button] -> [::tk::button]
> for example, with existence of [::button] preserved via [namespace import].

> Perhaps if that goes well, and can serve as an example, we can come
> back and at least do the same for the "new in 8.5" commands like
> [::dict], [::lassign], [::apply], etc.

In what way would a namespace-imported ::tcl::apply be even
distinguishable from a direct ::apply ? (well, leaving aside
the existence of ::tcl::apply of course)

Andreas Leitgeb

unread,
Jan 25, 2006, 7:16:21 AM1/25/06
to
Donal K. Fellows <donal.k...@manchester.ac.uk> wrote:
> Andreas Leitgeb wrote:
>> What, exactly, is leaking with exceptions?
> Tcl does not try very hard to stop exception codes "leaking" from one
> context to another; after all, that's usually what you want and is
> indeed necessary in some circumstances. But it does mean that when we
> introduce a new code, we have to consider what happens when things are
> used in unexpected situations (e.g. what happens if someone makes the
> "magic jump" command an inter-interpreter alias for the purposes of some
> kind of debugging?)

I'd guess that not more happens, as when you call "break", "continue"
or "return -level $n -code $m ..." through the same means.

> On the other hand, I'm not sure we need *any* of this elaborate-ness at
> all. Matt Newman's comments on simplicity sound very persuasive to me.

You mean where says that he doesn't mean to stop all evolution of tcl ?-)

Btw., a new exception can't be all that new, can it?

Andreas Leitgeb

unread,
Jan 25, 2006, 8:55:48 AM1/25/06
to
Fredderic <put_my_n...@optusnet.com.au> wrote:
> On 19 Jan 2006 12:29:20 GMT,
> Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at> wrote:
>> > we can not use [break] as it would break loop behaviour
>> > we can not use [continue] as see above.
>> 100% agree that break/continue are out of question
>
> I totally disagree that using [break] and [continue] in [switch]s will
> break anything, so long as you do it via an option

Again, I agree with you on the point, that break/continue
*with* arguments/options are at least feasible to re-use.
(The "out of question" was minted on break/continue as
argument-less commands, and I still stick to that)

DKF seems to be very unhappy about new exceptions (at seems
there is some swamp, that we'd better not investigate here)

> Since [break] and [continue] are little more than convenience
> functions these days, this opens the possibility to at a latter
> date introduce the "return -levels" concept to loop levels within
> a procedure (which I've used, and have seen used, very successfully
> in some other languages). I

Yes, I've also dreamt about such a feature in tcl (namely
breaking out of several loop-structures at once), and that's
exactly the reason, why I'm not too happy with break/continue
used with arguments for switch, because this really might
raise some confusion, as to which arguments will leave
which (and how many) levels of loops and/or switches and/or
other constructs before they're really handled.

As long as they are limited to loops, it's somewhat easier
to recognize every loop that encloses the break. If some
argument makes it work on (e.g. for a start) switches, I'd have
no idea, which other constructs would be counted and which not:

while {...} {
switch {...} { ... {
foreach ... {
if {...} {
break -someoptions -level 2
}
}
}
}

> (Personal note: Yes, I do accept, and already accepted the possibility
> of, my [catch] idea being rejected. :) I've been using TCL for a few
> years now, since about 1997, though until recently I was stuck with
> using an oldish version that was supplied -- now that I'm able to use a
> reasonably up-to-date version, I'm taking the opportunity to discuss
> some of the things that have been bugging me for most of those years,
> when they come up, and I'm taking the opportunity here to express some
> things that have been bugging me on a conceptual level, during this
> overall discussion.)

too understandable :-)
I've been Tcl'ing since about 1995 (iirc, that was with tcl7.4b4)
And since the earliest days I'd been asking for a feature, which
is now finally in 8.5: the {expand}-feature :-) (although it's
very different from my original proposals, it's only (but still)
slightly different from my own latest proposal in that direction)
And I've also proposed stuff, that I'm actually actively trying
to forget (preprocessing for comments,...)

> A one-hit-wonder is only acceptable if it IS the means to
> obtain such generalised usage. TCL's tendancy towards "package"
> type commands (dict, file, etc.) are a very good example of not
> creating one-hit-wonder functions

actually, my latest script has a preamble:
interp alias {} sindex {} string index
interp alias {} slen {} string length
...
interp alias {} bscan {} binary scan

To help keep my lines < 80 chars

While I understand, that the core should not clutter
the global namespace too much, I can freely do it in
my own code :-)

> Also IMHO, a switch-only command is just cruft
> in every other context -- admittedly sometimes
> this is necessary, but this time it isn't.

Hmm, you're probably right that "reswitch" really isn't it.
As you say it's much to switch-specific.
But break/continue also have their problems.
Something like "redo" could be a name general
enough, but would be a new exception, still.

>> I personally don't care about a loop-ability of switch.

> I agree... Which is why I thought the use of a [reloop] type function
> was appropriate, because it streses the fact that contrary to the other
> two, this one CAN cause loops. [switch] to my mind, isn't a looping
> construct. However it is none the less a block construct, and so the
> possibility to loop is worth considering.

"if" is also a block-construct, isn't it ?-)

> One place where I've needed
> to wrap a [switch] in a [while], is to implement state machines, for
> example.

Yes, that would be Use#1 for me, too (currently I wrap
switch in a loop for this type of use, and I think that
the keepers of tcl spirit would rather not change that).

> The documentation I have reads: " The switch command matches
> its string argument against each of the pattern arguments in
> order. " I'd be concerned that hash-based optimisation might remove
> this constraint.

Even if it does so, it would do so only for -exact matching.
and in that case, it doesn't make a visible difference other
than speed.

> The only part that would need further
> discussion, is whether reloop would run
> the increment part of a [for].

Imo, it should most certainly *not* run it.
The incr-part must always be followed by the loop-check, so if
you omit the latter, also omit the former.

The incr-part generally advances some index or iterator, and
the loop-condition is supposed to check, if we're out of
iterable things. While it is surely conceivable to have
a situation where the incr-part needs to be run more than
once before checking the condition, I think this would be
a bad thing for almost (but not quite entirely) all loops.

>> Btw. there can be two "default" blocks, the sequentially first
>> of whose will just match a literal "default" value :-)
> I'd hope that only the last "default" block would be the default one.

Yes, of course. t'was merely a joke :-)

> Personally, considering the stringyness of TCL, I think they should
> have broken with tradition and added an "else" clause to the [switch],
> similar to the [if].

alt.history.what-if ?
I guess you're right, but then perhaps not:
the patterns and bodies can be separate arguments,
so you might end up with:
switch 42 12 {} 13 {} default {puts buh}
where the other way would be:
switch 42 12 {} 13 {} else {puts buh}
Not much of a gain :-)

> [redo] works for me... My main pet hate in this discussion, is the
> introduction of a switch-only command and/or exception.

Understandable. I've already said good-bye to "reswitch"
as the name of the not-good-bye's new exception/command :-)

> I'm hoping this issue won't be solved on the basis of "oh, it's just
> too hard to fit that stuff into my new idea for optimisation".
> Optimisation is good, but I think it should never be a driving factor
> in a high-level non-compiled language, that's what low-level and
> compiled languages are for. Develop the language, THEN optimise. Not
> the other way around. If the optimisation doesn't work out, maybe
> you'll come up with a better method next version.

But there are often things that are correctly avoided on the basis of
principial lack of optimizability.

> [ reswitch-behaviour versus hashtable-optimization ]


> It may also be possible to add a -fast option to [switch],
> telling it that you don't care about the test order, or alternatively
> add a -strict option that states that you do (depending on the current
> consensus of what the existing official documentation says).

Now, such a "-fast" option would definitely be
"design controlled by optimizability". I think
this option should be tried very hard to avoid.
(controlling this should not be a "user-servicable part".

It is loading more messages.
0 new messages