I haven't been able to find much help on this on the web, so I'm turning to
the mailing list.
We've been getting terribly frustrated with scoping and passing variables
around in TCL. I have a form that accepts a lot of inputs and am calculating
stuff based on those inputs. My problem basically is I want to avoid passing
all the variables around to all the procs (especially procs that don't even
use them and just pass them on somewhere else!) or making a global copy of
every variable.
I think I don't understand uplevel, upvar, global and namespaces etc
properly, so it would be great if somebody could direct me to some help.
Here's my problem:
If I use uplevel around a chunk of code, I find it ignores parameters passed
into the procedure.
Here's what I've been doing: assume I have a main procedure which has
variables x, y and z.
I call test2 from this procedure (w is not a variable in the main
procedure).
test2 is defined as:
proc test2 {w} {
uplevel {
set result [expr w + x +y +z]
return $result
}
}
This proc breaks because w does not exist on the level above.
I then tried to use upvar:
proc test2 {w} {
upvar w w
uplevel {
set result [expr w + x +y +z]
return $result
}
}
This works fine if I call test2 once, but if I call it a 2nd time, I get an
error telling me w already exists. Unsetting didn't work either because it
was a link.
My colleague came up with the following fix using namespaces which seems to
work - he redefines the ACS procedure set_form_variables.
(apologies to non-ACS people for including ACS code here ;-) )
Is this the best solution? I don't like having to refer to the namespace
everywhere I need to access x, y and z. Surely there must be a solution
using uplevel etc.?
I think I really need to learn more about all this kind of stuff - any
pointers?
cheers,
Brian
Call this and have it accept product_id with some value.
----Cut here----
> ad_proc ba_set_form_variables {{error_if_not_found_p 1}} {
>
> Exactly the same as set_form_variables, except it sets the variables
> in a namespace called "ba_ns"
>
> }
> if { $error_if_not_found_p == 1} {
> uplevel { if { [ns_getform] == "" } {
> ns_returnerror 500 "Missing form data"
> return
> }
> }
> } else {
> uplevel { if { [ns_getform] == "" } {
> # we're not supposed to barf at the user but we want to
> return
> # from this subroutine anyway because otherwise we'd get an
> error
> return
> }
> }
> }
>
> # at this point we know that the form is legal
> # The variable names are prefixed with a V to avoid confusion with the
> form variables while checking for naughtiness.
> namespace eval ba_ns {
> set Vform [ns_getform]
> set Vform_size [ns_set size $Vform]
> set Vform_counter_i 0
> while {$Vform_counter_i<$Vform_size} {
> set Vname [ns_set key $Vform $Vform_counter_i]
> set Vvalue [ns_set value $Vform $Vform_counter_i]
> check_for_form_variable_naughtiness $Vname $Vvalue
> set $Vname $Vvalue
> incr Vform_counter_i
> }
> }
> }
>
>
> proc test1 {} {
>
> set product_id "you won't see this either"
> return $::ba_ns::product_id
>
> }
>
> set product_id "you won't see this"
>
> ba_set_form_variables
>
> doc_body_append "[test1]"
---end----