Coyote's Guide to IDL Programming

Keeping IDL Code Backward Compatible

QUESTION: I love the latest features of IDL, the new keywords, the new ways of doing things, etc. But I work with a group that is ... well, frugal might be a polite way to describe them. In any case, I have to write code that works on versions of IDL that are 4-5 years out of date. Is there a way to take advantage of new features and still write code that is backward compatible?

ANSWER: The short answer, of course, is "No, there is no way to write code that is backward compatible and still takes advantage of new features. Sorry."

The long answer is a bit more complicated and it pains me to even write about it. There are some things that you obviously won't be able to take advantage of in the latest version. For example, you really can't use new commands, since there is no way they can be backward compatible. But some things you can work around.

For example, suppose you wanted to take advantage of the new Dimensions keyword for the Size command, introduced in IDL 5.4, but you want to remain compatible with IDL 5.3. What you can't do is write something like this:

   IF !Version.Release GT 5.3 THEN BEGIN
      s = Size(image, /Dimensions)
      xsize = s[0]
      ysize = s[1]
   ENDIF ELSE BEGIN
      s = Size(image)
      xsize = s[1]
      ysize = s[2]
   ENDELSE

The reason this doesn't work, is that when it is compiled in IDL 5.3, the compiler recognizes that the Size command has been called with what is, apparently, an illegal keyword. The code fails to compile.

To make the code compatible with IDL 5.3, you have to "hide" the offending keyword. The way this is typically done is with one of the virtual functions: Call_Function, Call_Procedure, or Execute. These commands are not "executed" until run-time, so they escape the compiler's notice. So, for example, you could re-work the code above like this.

   IF !Version.Release GT 5.3 THEN BEGIN
      s = Call_Function('Size', image, /Dimensions)
      xsize = s[0]
      ysize = s[1]
   ENDIF ELSE BEGIN
      s = Size(image)
      xsize = s[1]
      ysize = s[2]
   ENDELSE

Although this is a trivial example, you probably get the general idea.

Another way you might be able to fool the compiler would be to use the _Extra keyword inheritance mechanism. This assumes that the old routine had keywords defined for it (or that it is not older than the _Extra mechanism!). You might modify your code like this.

   IF !Version.Release GT 5.3 THEN BEGIN
      extrakeywords = {Dimension:1}
      s = Size(image, _Extra=extrakeywords)
      xsize = s[0]
      ysize = s[1]
   ENDIF ELSE BEGIN
      s = Size(image)
      xsize = s[1]
      ysize = s[2]
   ENDELSE

While not perfect, these techniques allow at least a limited amount of backward compatibility.

A recent (Feb 26-28, 2003) discussion in the IDL newsgroup, entitled "No backward compatibility in IDL 5.6" has shed more light on this subject.

Apparently all versions of IDL check built-in routines at compile time to see if positional parameters and keywords are defined. So, if an additional parameter has been added to a routine, you have to "hide" that routine from earlier versions of IDL with the virtual functions mentioned above. If built-in functions add a keyword to a routine that previously had no keywords defined for it, you must "hide" that routine from earlier versions of IDL.

However, if built-in functions add a keyword to a routine that previously had keywords defined for it, you only have to "hide" that routine from versions of IDL up to and including IDL 5.4. Beginning in IDL 5.5, keywords are evaluated at run-time, not at compile time, so routines with additional keywords defined will compile in IDL 5.5 (although they might not run there).

User-written routines can always be included and referenced in IDL code and compiled in any version of IDL, although it may not always run in earlier versions.

Google
 
Web Coyote's Guide to IDL Programming