[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: translating an array name to a string
Hi JD--
I agree that the use of ROUTINE_NAMES is has some potential problems
because it is undocumented. I agree with you also that you need to
protect your usage of ROUTINE_NAMES with a CATCH handler, since there
are a lot of ways for things to go wrong.
But I don't agree with your implementation :-).
First, the awkward use of CALL_FUNCTION can be avoided by using the
FORWARD_FUNCTION declaration. This is always safe, even if the
function being declared is a built-in one.
Second, your check to see if a variable is undefined is rather
convoluted. It involves two passes to get it right. I prefer instead
to use the N_ELEMENTS command to immediately determine whether a
variable is undefined. Unlike *assigning* an undefined variable,
which does produce an error, simply taking the N_ELEMENTS of an
undefined variable will not cause an error.
Finally, users need to be aware that the capability to use
ROUTINE_NAMES to create new variables at another calling level has
only come with IDL version 5.3. This is documented at
http://cow.physics.wisc.edu/~craigm/idl/idl.html under Introspection,
by the way.
So here is my revised version of your code :-) It's shorter and the
flow control is primarily linear.
; *******
forward_function routine_names
catch, err
if err NE 0 then begin
catch, /cancel
message, 'Assign operation failed'
endif
; Protect against an already-defined variable
if n_elements(routine_names(var_name,fetch=1)) GT 0 then begin
catch,/cancel
message,'A variable named '+var_name+' already exists.'
endif
; Still here... we need to export ourself to the main level
dummy=routine_names(var_name,myvar,store=1)
catch, /cancel
; *******
Craig
"J.D. Smith" <jdsmith@astro.cornell.edu> writes:
> By the way, for those of you using routine_names for heavy magic... you
> might consider examining the following extra-cautions snippet to export
> a variable to the $MAIN$ level:
>
> var_free=0
> catch, err
> if err ne 0 then begin
> ;; An undefvar indicates routine_info ran and
> ;; the variable is free
> if !ERROR_STATE.NAME ne 'IDL_M_UNDEFVAR' then begin
> catch,/cancel
> message,"Can't complete operation... Try obj=sp_sel()"
> endif
> var_free=1
> endif
>
> ;; If we need to check if the variable name is available, do so.
> if var_free eq 0 then $
> rn=call_function('routine_names',var_name,FETCH=1)
>
> if n_elements(rn) ne 0 then begin
> catch,/cancel
> message,'A variable named '+var_name+' already exists.'
> endif
>
> ;; Still here... we need to export ourself to the main level
> rn=call_function('routine_names',var_name,myvar,store=1)
>
> basically the idea is to wrap routine_names as a string in
> call_function, to allow your routine to compile even if RSI yanks or
> renames it (it wouldn't compile if you tried to call it directly).
> You'll get an error, of course, which will be caught. You have to
> discriminate between errors caused by the successful operation of
> routine_names(), and those caused by incorrect arguments, changed
> keywords (IDL_M_KEYWORD_BAD), or other mutations routine_names() has
> undergone (such as vanishing altogether -- IDL_M_UPRO_UNDEF). You
> obviously have to have a backup plan too, to tell your users what to do
> in case routine_names() has broken. But it's better than your program
> not running at all though.
>
> JD
>
> --
> J.D. Smith | WORK: (607) 255-6263
> Cornell Dept. of Astronomy | (607) 255-5842
> 304 Space Sciences Bldg. | FAX: (607) 255-5875
> Ithaca, NY 14853 |
--
--------------------------------------------------------------------------
Craig B. Markwardt, Ph.D. EMAIL: craigmnet@cow.physics.wisc.edu
Astrophysics, IDL, Finance, Derivatives | Remove "net" for better response
--------------------------------------------------------------------------