How can one write version-specific code in an octave script?

I need an octave to script to work with different versions of Octave (at this time, 5.2 and 6.2).

(Similarly with C, for example, one could use ‘conditional compilation’ via the C-pre-processor.)

The simple approach of an if statement, based on OCTAVE_VERSION doesn’t work: the v6 interpreter cannot parse v5 syntax in the never (with v6) executed branch of the if.

Are you referring to .m file code or .oct file (C++) code?
Could you please give a minimal example for what you tried and why it doesn’t work for you?

For example, this is a line of .m script that is used for octave version 5.2:

 foo = @(x,y) deal (a=(y<x)./bar (y), 1./(a+!a));

However, this syntax is invalid with octave version 6.2.
The question is how to prevent octave version 6.2 from attempting to parse it.

For example, the if-guard in following line works successfully with both v5 and v6:

if [version<'6'](1) printf('hello v5\n') endif

But the same approach with the anon. fn. fails with a parsing error with v6:

if [version<'6'](1) foo = @(x,y) deal (a=(y<x)./bar (y), 1./(a+!a)); endif

Please note that the question is not: why does this approach not work? It is what is the correct approach to handle version-specific code in .m files?

Afaict, the parser tries to parse the entire file (including any if branches) when a file is executed. There aren’t any “pre-processor” directives I’m aware of.
As a work-around (not a very elegant one admittedly), you could try and move the offending portion of the code to a script file that you would call conditionally on the version. IIUC, that script would only be parsed on execution if that branch is reached.
Does that work for you?

Btw, the version test you are using will fail once Octave 10 will be released. Consider using the verLessThan or compare_versions functions instead.

1 Like

You could also try eval(). I don’t think the Octave interpreter will try to compile the eval string before starting execution of the script.

2 Likes

Thanks for the suggestions—I’ll see how they work out.

The syntax of assignment inside an anonymous function isn’t valid in Matlab or in Octave version 6 and higher. It is probably better to simply re-code to a syntax that all versions of Octave and Matlab accept rather than trying to have version-specific code with conditionals.

Replacing the anonymous function with a subfunction is the obvious solution, although you could also just introduce a temporary variable outside of the anonymous function.

Here’s an example of solution #1 using a subfunction:

function retval = mainfcn (input1, input2)

  retval = subfcn (input1, input2);

endfunction

function r = subfcn (x,y)
  a= (y<x) ./ bar (y);
  r = deal (a, 1./(a+!a));
endfunction
1 Like

Yes, that is the solution I have selected for version 6 but unfortunately it doesn’t work with version 5; I get:

handles to nested functions are not yet supported

(But the anon. fn approach works fine in v5.)

Maybe the code you have is more complicated than the excerpt shows, but I don’t see that you need to take a handle to a function in this case. Instead of

foo = @(x,y) subfcn (x, y)
...
r = foo (x,y)

it should be possible to just directly call the subfcn with

r = subfcn (x,y)

The warning message also refers to “nested functions” which are not the same as subfunctions. It may be that the subfunction you wrote is accidentally contained within a larger function thus making it a nested function. You should be able to remove it from the enclosing function which would permit you to take a handle to it even in Octave version 5.

The actual code is used in a ‘function function’ situation so it uses a handle. Also I have some demo code for it which I understand creates an enclosing function for each demo, so I don’t think that the enclosing function can be removed.

Thanks—eval does indeed work round the problem. It’s needed around the code in only one of the branch paths and fortunately, it’s just one line.