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

expandable switch statement?

50 views
Skip to first unread message

ddd

unread,
May 22, 2011, 7:22:54 AM5/22/11
to
Hi Tcl'ers,

I am looking for an "expandable" switch statement or something similar. I
have a given switch statement in my code as e.g.:

switch -glob aaab {
a*b -
b {expr {1}}
a* {expr {2}}
default {expr {3}}
}

Now later in the code I want to "add" another alternative to the switch
statement like:

c {expr {4}}

Is there a procedure I can call like add_to_switch? It seems I am looking
for something like a decision table. The end result should then be:

switch -glob aaab {
a*b -
b {expr {1}}
a* {expr {2}}
c {expr {4}}
default {expr {3}}
}

This is a basic idea, because I have not yet a definitive idea how to
spacify and handle the order of alternatives.

thanks,

s

Schelte Bron

unread,
May 22, 2011, 9:15:57 AM5/22/11
to
ddd wrote:
> I am looking for an "expandable" switch statement or something
> similar.

The switch command (at least in the format you used) takes a list as
its last argument. So you can simply put that into a variable and
use the normal list operations to manipulate it:

set switch {


a*b -
b {expr {1}}
a* {expr {2}}
default {expr {3}}
}

switch -glob aaab $switch

set switch [linsert $switch end-2 c {expr {4}}]

switch -glob c $switch


Schelte.

Alexandre Ferrieux

unread,
May 22, 2011, 9:17:39 AM5/22/11
to

If I understand your need correctly, you might well be better served
by an appropriate loop on a (modifiable) list rather than self-
modifying code (though Tcl can do it as well):

set ll {    a*b     -
    b       {...}
    a*      {...}
    c       {...}
}
set def {...}

proc mainswitch x {
foreach {pat action} $::ll {
if {[string match $pat $x]} {return [uplevel 1 $action]}
}
return [uplevel 1 $::def]
}

proc addcase {pat action} {lappend ::ll $pat $action}

Now if you really want to use [switch], this works as well:

proc mainswitch2 x {
switch -glob -- $x [concat $::ll [list default $::def]]
}

problem being the fact that the [switch] body won't benefit from
compilation speedup.
You can get the best of both worlds by calling [proc] dynamically, but
that may be beyond what you need. Please tell me.

-Alex

ddd

unread,
May 23, 2011, 4:52:05 AM5/23/11
to
On Sun, 22 May 2011 06:17:39 -0700 (PDT), Alexandre Ferrieux
<alexandre...@gmail.com> wrote:

> If I understand your need correctly, you might well be better served
> by an appropriate loop on a (modifiable) list rather than self-
> modifying code (though Tcl can do it as well):
>
> set ll {    a*b     -
>     b       {...}
>     a*      {...}
>     c       {...}
> }
> set def {...}
>
> proc mainswitch x {
> foreach {pat action} $::ll {
> if {[string match $pat $x]} {return [uplevel 1 $action]}
> }
> return [uplevel 1 $::def]
> }
>
> proc addcase {pat action} {lappend ::ll $pat $action}
>
> Now if you really want to use [switch], this works as well:
>
> proc mainswitch2 x {
> switch -glob -- $x [concat $::ll [list default $::def]]
> }
>
> problem being the fact that the [switch] body won't benefit from
> compilation speedup.
> You can get the best of both worlds by calling [proc] dynamically, but
> that may be beyond what you need. Please tell me.
>
> -Alex

Thanks both Schelte and Alex!

Probably I start with Scheltes idea, because it is simplest. I am not
concerned about speed at the moment, because I use the switch just once
during a program run (it is a url router for a cgi application). But I am
still open to suggestions. Basically my application is a cgi, which
dispatches on different urls mentioned in the switch statement. I want to
modify the switch statement before invocation sometimes because I have some
session or authentication information, and then the routes have different
properties.

thanks,

s

Donal K. Fellows

unread,
May 23, 2011, 9:13:39 AM5/23/11
to
On May 22, 12:22 pm, ddd <d...@ddd.dd> wrote:
> I am looking for an "expandable" switch statement or something similar.  I
> have a given switch statement in my code as e.g.:
>
> switch -glob aaab {
>    a*b     -
>    b       {expr {1}}
>    a*      {expr {2}}
>    default {expr {3}}
> }
>
> Now later in the code I want to "add" another alternative to the switch
> statement like:
>
>    c       {expr {4}}

I'd do it like this, using the alternate form of [switch]:

set defs {


   a*b     -
   b       {expr {1}}
    a*      {expr {2}}
}

switch -glob -- $value {*}$defs default {
expr {3}
}

Like that, adding another clause is just this:

lappend defs c {expr {4}}

Yet you won't disrupt the special handling of 'default', which has to
be the last clause. (You could also put the default handling script in
its own variable, or other arbitrarily complex solution. Your call.)

Donal.

ddd

unread,
May 24, 2011, 3:16:26 AM5/24/11
to
On Mon, 23 May 2011 06:13:39 -0700 (PDT), Donal K. Fellows
<donal.k...@manchester.ac.uk> wrote:

> I'd do it like this, using the alternate form of [switch]:
>
> set defs {
>    a*b     -
>    b       {expr {1}}
>     a*      {expr {2}}
> }
>
> switch -glob -- $value {*}$defs default {
> expr {3}
> }
>
> Like that, adding another clause is just this:
>
> lappend defs c {expr {4}}
>
> Yet you won't disrupt the special handling of 'default', which has to
> be the last clause. (You could also put the default handling script in
> its own variable, or other arbitrarily complex solution. Your call.)
>
> Donal.

Thanks Donal, this is a great solution using {*}.

Maybe a related question, but how do you search for {*} on the wiki? (I
already know about wiki.tcl.tk/17158, but I don't know how to search for it).

thanks,

s.

Donal K. Fellows

unread,
May 24, 2011, 4:15:33 AM5/24/11
to jos.de...@gmail.com
On May 24, 8:16 am, ddd <d...@ddd.dd> wrote:
> Maybe a related question, but how do you search for {*} on the wiki?

It seems to not work for that. So I ask Jos Decoster if that can be
made to work, at least for the exact page name part of the search. :-)

Donal.

0 new messages