9

First, here the way i'm calling the function :

eval([functionName '(''stringArg'')']); % functionName = 'someStringForTheFunctionName'

Now, I have two functionName functions in my path, one that take the stringArg and another one that takes something else. I'm getting some errors because right now the first one it finds is the function that doesn't take the stringArg. Considering the way i'm calling the functionName function, how is it possible to call the correct function?

Edit:

I tried the function which :

which -all someStringForTheFunctionName

The result :

C:\........\x\someStringForTheFunctionName
C:\........\y\someStringForTheFunctionName % Shadowed

The shadowed function is the one i want to call.

Amro
  • 123,847
  • 25
  • 243
  • 454
m_power
  • 3,156
  • 5
  • 33
  • 54
  • 1
    related question: [Executing a file or calling a function whose file is placed in another folder with MATLAB?](http://stackoverflow.com/questions/6153323/) – Eitan T Jul 18 '13 at 15:34
  • Darn you Eitan, you always find answers like minutes before me haha good call though! – Shaun314 Jul 18 '13 at 15:45

4 Answers4

7

Function names must be unique in MATLAB. If they are not, so there are duplicate names, then MATLAB uses the first one it finds on your search path.

Having said that, there are a few options open to you.

Option 1. Use @ directories, putting each version in a separate directory. Essentially you are using the ability of MATLAB to apply a function to specific classes. So, you might set up a pair of directories:

@char
@double

Put your copies of myfun.m in the respective directories. Now when MATLAB sees a double input to myfun, it will direct the call to the double version. When MATLAB gets char input, it goes to the char version.

BE CAREFUL. Do not put these @ directories explicitly on your search path. DO put them INSIDE a directory that is on your search path.

A problem with this scheme is if you call the function with a SINGLE precision input, MATLAB will probably have a fit, so you would need separate versions for single, uint8, int8, int32, etc. You cannot just have one version for all numeric types.

Option 2. Have only one version of the function, that tests the first argument to see if it is numeric or char, then branches to perform either task as appropriate. Both pieces of code will most simply be in one file then. The simple scheme will have subfunctions or nested functions to do the work.

Option 3. Name the functions differently. Hey, its not the end of the world.

Option 4: As Shaun points out, one can simply change the current directory. MATLAB always looks first in your current directory, so it will find the function in that directory as needed. One problem is this is time consuming. Any time you touch a directory, things slow down, because there is now disk input needed.

The worst part of changing directories is in how you use MATLAB. It is (IMHO) a poor programming style to force the user to always be in a specific directory based on what code inputs they wish to run. Better is a data driven scheme. If you will be reading in or writing out data, then be in THAT directory. Use the MATLAB search path to categorize all of your functions, as functions tend not to change much. This is a far cleaner way to work than requiring the user to migrate to specific directories based on how they will be calling a given function.

Personally, I'd tend to suggest option 2 as the best. It is clean. It has only ONE main function that you need to work with. If you want to keep the functions district, put them as separate nested or sub functions inside the main function body. Inside of course, they will have distinct names, based on how they are driven.

  • 1
    Alternatively, just change the directory before you call it and then change it back once its been called. No creating additional files, changing names or putting functions together, a total of two lines of basic code more is all you need. – Shaun314 Jul 18 '13 at 15:56
2

OK, so a messy answer, but it should do it. My test function was 'echo'

funcstr='echo'; % string representation of function

Fs=which('-all',funcstr);
for v=1:length(Fs)
    if (strcmp(Fs{v}(end-1:end),'.m')) % Don''t move built-ins, they will be shadowed anyway
        movefile(Fs{v},[Fs{v} '_BK']);
    end
end
for v=1:length(Fs)
    if (strcmp(Fs{v}(end-1:end),'.m')) 
        movefile([Fs{v} '_BK'],Fs{v});
    end
    try
        eval([funcstr '(''stringArg'')']);
        break;
    catch
        if (strcmp(Fs{v}(end-1:end),'.m'))
            movefile(Fs{v},[Fs{v} '_BK']);
        end
    end
end
for w=1:v
    if (strcmp(Fs{v}(end-1:end),'.m'))
       movefile([Fs{v} '_BK'],Fs{v});
    end
end
Hugh Nolan
  • 2,508
  • 13
  • 15
  • So I have two choices, #1 change directory and go back to initial directory or #2 move the file to current directory (change its name) and move it back (change its name back)! – m_power Jul 18 '13 at 17:15
2

You can also create a function handle for the shadowed function. The problem is that the first function is higher on the matlab path, but you can circumvent that by (temporarily) changing the current directory.

Although it is not nice imo to change that current directory (actually I'd rather never change it while executing code), it will solve the problem quite easily; especially if you use it in the configuration part of your function with a persistent function handle:

function outputpars = myMainExecFunction(inputpars)
    % configuration
    persistent shadowfun;
    if isempty(shadowfun)
        funpath1 = 'C:\........\x\fun';
        funpath2 = 'C:\........\y\fun'; % Shadowed

        curcd = cd;
        cd(funpath2);
        shadowfun = @fun;
        cd(curcd); % and go back to the original cd
    end

    outputpars{1} = shadowfun(inputpars); % will use the shadowed function
    oupputpars{2} = fun(inputparts); % will use the function highest on the matlab path
end

This problem was also discussed here as a possible solution to this problem.

I believe it actually is the only way to overload a builtin function outside the source directory of the overloading function (eg. you want to run your own sum.m in a directory other than where your sum.m is located.)

Community
  • 1
  • 1
Gunther Struyf
  • 11,158
  • 2
  • 34
  • 58
0

EDIT: Old answer no longer good

The run command won't work because its a function, not a script.

Instead, your best approach would be honestly just figure out which of the functions need to be run, get the current dir, change it to the one your function is in, run it, and then change back to your start dir.

This approach, while not perfect, seems MUCH easier to code, to read, and less prone to breaking. And it requires no changing of names or creating extra files or function handles.

Shaun314
  • 3,191
  • 4
  • 22
  • 27
  • It looks like it's for `Scripts` only, not functions. – m_power Jul 18 '13 at 15:47
  • Ok yeah I see that it has to work with variables in MATLAB's workspace, hmm, I guess you could create a wrapper script, but that would pretty much defeat the whole purpose of this question.. – Shaun314 Jul 18 '13 at 15:50
  • Yes. Run applies only to scripts. And scripts cannot accept variable inputs. –  Jul 18 '13 at 15:52
  • Yeah, it seems that we have hit that moment when MATLAB can't do this elegantly. Woodchips, your first approach would work, but honestly, it seems like just changing the current dir to the file you want to run and then changing it back would be even easier than doing all that stuff – Shaun314 Jul 18 '13 at 15:55