Forum OpenACS Q&A: Re: Problems defining procs

Collapse
Posted by ultra newb on
Whoops - change the above to:

proc my_proc {} "my code goes here"

or:

proc my_proc {} [list my code goes here]

Collapse
Posted by Gustaf Neumann on
The normal way to define procs is via

proc myproc {} {
  # my code comes here
}
or
ad_proc myproc {} {
  Some documentation
} {
  # my code comes here
}

If you define the body of the proc with double-quotes or [list], the body is evaluated at definition time (at the time the file is sourced). Therefore, if you have e.g. set x $a in the body, $a will be evaluated at definition time and will throw an error. Check you error.log file.

Collapse
Posted by ultra newb on
Yes, I know the "normal" way. I don't want the normal way in this instance because I need the definition of the proc to change based on certain circumstances.

What I need is a proc that returns a list of values. The list of values changes day to day. I want the list of values to come from a backend database. I want the proc to be defined dynamically at startup to return that list of values. I don't want to have to connect to the backend database each time I need the list of values - I just want to connect one time at system startup, get the list of values, and have that list of values "hard-coded" in the proc.

This is easy to do. In fact, I've tested it outside of OpenACS and it works just fine (TCL is made to do stuff like this). It just doesn't work in OpenACS for some reason.

Is there some reason why this sort of definition is not possible in OpenACS or AOLServer?

Collapse
Posted by Claudio Pasolini on
Here is a small example of how to dynamically define a proc:

# get/set the values
set day_values "aaa bbb ccc"
set myproc "
proc myproc {} {
puts \"The day's values are: $day_values\"
}
"
eval $myproc

The values get hardcoded into the proc.

Collapse
Posted by Jeff Rogers on
The util_memoize procs are for exactly this purpose - run something once and return it quickly after that.

https://openacs.org/api-doc/procs-file-view?version_id=2967965&path=packages/acs-tcl/tcl/memoize-procs.tcl

You can wrap it in a proc very easily too, for example:

proc get_values {} {
return [util_memoize get_values_internal 86400]
}

proc get_values_internal {} {
# do slow/heavy database access
return $values
}