Forum OpenACS Development: passing arguments, ad_proc definitions

Is there a way to pass multiple named arguments in ad_proc definitions without explicitly defining them.

For example, if qf_test is defined as:

ad_proc -public qf_test {
} {
this tests ad_proc use of named arguments, and whether or not they need to be defined
} {
if { ![exists arg1] } {
set arg1 "no arg1 parameter passed"
}
return $arg1
}

I want to be able to invoke it with any valid named parameter, such as:

qf_test -arg1 value1 -arg2 value2 -argN valueN

where ad_proc passes the arguments as a list of named argument/value pairs.

Does a feature like this already exist in OpenACS, or do I need to pass the pairs as a list?

Collapse
Posted by Torben Brosten on
An interesting solution, Dave.

How does one pass the argv values through an ad_proc definition?

As

ad_proc -public qf_test {
argv
} {
...

?

Collapse
Posted by Dave Bauer on
I might be confused.

I understand you want to pass an arbitrary set of named arguments to a procedure. This list of names is not specified by the ad_proc that defines the procedure. You can get get_opts will will create an array containing all the named arguments.

Collapse
Posted by Torben Brosten on
If I understand correctly, get_opts is passing a list of named parameters out of a procedure's namespace, to the namespace that called the procedure.

I'm looking to pass an unspecified set of named parameters that is provided with a call, to the namespace within the procedure. For example:

qf_test -foo value1 -bar value2 -fooo valueN -barr valueM

Based on get_opts and your answer, I'm going to assume my question isn't an option to be defined via ad_proc, and that I should use upvar instead. This makes sense, since extra care needs to be taken so that any named parameter that is passed does not interfere with the code in some sort of unplanned value injection method etc.

Thank you,

Torben

Collapse
Posted by Dave Bauer on
Look at how template::element::create works.

It takes any arbitrary named arguments and passes them on to the element definition since element::create is used for every widget etc, and widgets have various different arguments.

So if you call

element::create -one 1 -two 2

then when get_opts is called withing element::create there is an array within the scope of element::create called opts that contains {one 1 two 2}

I am pretty sure it does exactly what you want.

Collapse
Posted by Torben Brosten on
I appreciate your input, Dave.

I'm using something like it for private procs of a package under development.

The functionality needs to be a part of ad_proc, because the public designated procs are planned to be repeatedly called via manually coded (typed) tcl files, and so should be as intuitive and convenient as possible.

Since ad_proc understandably doesn't appear to have the feature, it seems the most dynamic way (that doesn't add extra constraints) is to pass the named parameters as a list for these public designated cases:

qf_test \[list -arg1 value -arg2 value -arg3 value \]

or

qf_test $arg_list

Thank you, again,

Torben

Collapse
Posted by Dave Bauer on
What feature of ad_proc is missing here?

I forgot to mention in ad_proc youd specify like so

ad_proc a_proc { args }

since the arg list is necessary to pass to get_opts.

args works the same with ad_proc as with the standard tcl "proc" command.

Good luck!

Collapse
Posted by Torben Brosten on
Apparently, this is something conceptual within my mind that I revisit now and then (and hopefully didn't post about before). It's the idea that a proc can have any number of ordered parameters. TCL doesn't have this at the procedure definition, but then what language does? (rectorial question)

Using standard proc format, the max number of parameters can be designated with empty string as a default.

Actually, this discussion has been fruitful.

Example:

ad_proc -public qf_test {
{named_param_1 ""}
{named_param_1_value ""}
{named_param_2 ""}
{named_param_2_value ""}
...
pattern continued to max number of parameters
} {

Thank you for the exercise, Dave.

cheers,

Torben

Collapse
Posted by Dave Bauer on
Hmmm. This makes me curious.

Are the parameters known at the time of procedure definition or are they unknown?

If you use the format like this:

ad_proc -public template::element { command form_id element_id args } {
Manage elements of form objects.
} {

This is called like so:

template::element create $form_id $element_id -label "Label" -widget "Widget" -html "html" etc...

You can have an arbitrary list of named parameters which will be in the "args" variable.

If you pass this list to get_opts it will parse them into an array. This seems like what you were asking for, but maybe I am confused.

Collapse
Posted by Torben Brosten on
Yeah, that's the idea, Dave, but this will be used for fringe cases (values with negative numbers, values as lists etc.), and from what I understand, the args breaks with at least the negative numbers.. If I assume named parameter pairs have exactly 2 ordered positions, then 40 named parameter pairs (without complexity of dashes) can be defined:

ad_proc -public qf_test {
{arg1 ""}
{arg2 ""}
...
{arg15 ""}
{arg80 ""}
} { ...

This works regardless of value types (except delineating the special case of empty string versus no value), although it is a bit bulky/clunky. If only there is a shorthand for that..

Collapse
Posted by Torben Brosten on
I should mention that I anticipate only using up to about 20 named parameter pairs in procs..
Collapse
Posted by Torben Brosten on
Actually, one can differentiate between an empty value and a nonexistent value using this technique. An empty value is when a named parameter is passed and it's paired value is empty. A named parameter that is not passed *is* nonexisting.
Collapse
Posted by Dave Bauer on
Correct. When you name the paramter do NOT specify a default value and then you can use info exists to check if it was specified or not.