How to write a single Octave script with function definitions compatible with Matlab scripts?

前端 未结 2 1180
Happy的楠姐
Happy的楠姐 2020-12-19 18:13

If I write this:

clc
clear

close all
format long
fprintf( 1, \'Starting...\\n\' )

function results = do_thing()
         


        
相关标签:
2条回答
  • 2020-12-19 19:08

    Octave's implementation of local functions in scripts is different from Matlab's. Octave requires that local functions in scripts be defined before their use. But Matlab requires that local functions in scripts all be defined at the end of the file.

    So you can use local functions in scripts on both applications, but you can't write a script that will work on both. So just use functions if you want code that will work on both Matlab and Octave.

    Examples:

    Functions at end

    disp('Hello world')
    foo(42);
    
    function foo(x)
      disp(x);
    end
    

    In Matlab R2019a:

    >> myscript
    Hello world
        42
    

    In Octave 5.1.0:

    octave:1> myscript
    Hello world
    error: 'foo' undefined near line 2 column 1
    error: called from
        myscript at line 2 column 1
    

    Functions before use

    disp('Hello world')
    
    function foo(x)
      disp(x);
    end
    
    foo(42);
    

    In Matlab R2019a:

    >> myscript
    Error: File: myscript.m Line: 7 Column: 1
    Function definitions in a script must appear at the end of the file.
    Move all statements after the "foo" function definition to before the first local function definition. 
    

    In Octave 5.1.0:

    octave:2> myscript
    Hello world
     42
    

    How it works

    Note that technically the functions here in Octave are not "local functions", but "command-line functions". Instead of defining a function that is local to the script, they define global functions that come into existence when the function statement is evaluated.

    0 讨论(0)
  • 2020-12-19 19:09

    The answer is in the comments, but for the sake of clarity:

    % in file `do_thing.m`
    function results = do_thing()
        results = 1;
    end
    
    % in your script file
    clc;   clear;   close all;   format long;
    fprintf( 1, 'Starting...\n' );
    results = do_thing();
    

    Accompanying explanatory rant:

    • The canonical and safest way to define functions is to define them in their own file, and make this file accessible in octave / matlab's path.
    • Octave has supported 'dynamic' function definitions (i.e. in the context of a script or the command-line) since practically forever. However, for the purposes of compatibility, since matlab did not support this, most people did not use it, and quite sensibly relied on the canonical way instead.
    • Matlab has recently finally introduced dynamic function definitions too, but has opted to implement them explicitly in a way that breaks compatibility with octave, as you describe above. (rant: this may be a coincidence and an earnest design decision, but I do note that it also happens to go against prior matlab conventions regarding nested functions, which were allowed to be defined anywhere within their enclosing scope).
    • In a sense, nothing has changed. Matlab was incompatible with advanced octave functionality, and now that it has introduced its own implementation of this functionality, it is still incompatible. This is a blessing in disguise. Why? Because, if you want intercompatible code, you should rely on the canonical form and good programming practices instead of littering your scripts with dynamic functions, which is what you should be doing anyway.
    0 讨论(0)
提交回复
热议问题