[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: translating an array name to a string

Craig Markwardt wrote:
> 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
> ; *******

This is definitely nicer looking, and it reminded me of a caveat.  If
you attempt to fetch a variable which doesn't yet exist, an undefined
variable will be created on that level for you.

I think our methods offer equal protection against certain types of
failure, but I also think call_function provides additional insurance
against RSI deciding specifically to remove our capacity to use
routine_names() (which they might do if we keep talking about it so much
and people catch on!).  It is simple to parse *compiler* statements like
forward_function for disallowed names.  It is impossible (OK, very, very
awkward), to prohibit the use of classified *strings*.  This is probably
paranoid, but that's why I chose call_function.  In any case I will
modify my method to include the n_elements() test (which I was stupid
not to think of).


 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            |