Loren on the Art of MATLAB

November 17th, 2006

Some Ways to Create Function Handles

I recently was asked the best way to create function handles, given the names of functions. This came up because I recommended that we should generally remove instances of feval in our code since it is often not required and adds an extra level of function calls. I will show you several ways to work with a "list" of functions and tell you which ones I prefer and why.

Contents

Avoiding Function Handles Altogether (Not Recommended)

As I said above, I recommend not using feval because it introduces extra function call overhead, and is usually unnecessary. In addition, code is generally more robust with function handles instead of strings for representing functions.

funcList = {'sin','cos','tan'};
for i=1:numel(funcList)
    f = feval(funcList{i},1.0);
end

First Alternative (Not Recommended)

Here's a method that constructs function handles from strings using eval, a function that has a deservedly bad reputation for most applications (see these two articles: Evading Eval and More on Eval).

funcList = {'sin','cos','tan'};
for i=1:numel(funcList)
    func = eval(['@' funcList{i}]);
    f = func(1.0)
end
f =
    0.8415
f =
    0.5403
f =
    1.5574

Acceptable Methods

If you have to start off with strings at all, such as having them passed in as arguments, you can convert them immediately to function handles and then proceed, by using str2func.

funcList = {'sin','cos','tan'};
for i= 1:numel(funcList)
   fh = str2func(funcList{i});
   f = fh(1.0);
end

If you have a fixed function list, simply create the function handles to start and use them. One way is to use feval and cellfun.

funcList = {@sin, @cos, @tan};
vals = repmat({1.0},size(funcList));
f = cellfun(@feval, funcList, vals);

Best Method, When Possible

My favorite method, when I can choose to create function handles from the start, is to just iterate over the list. I find that more readable than the cellfun code and I get to avoid the extra feval call. The expense comes at the for-loop. Preallocation when you plan to actually use the results (unlike these examples) often mitigates the downsides of the loop.

funcList = {@sin, @cos, @tan};
for i = 1:numel(funcList)
   f = funcList{i}(1.0);
end

Your Preferences?

I've told you my preferences. What are yours for creating function handles? Let me know.


Get the MATLAB code

Published with MATLAB® 7.3

36 Responses to “Some Ways to Create Function Handles”

  1. Urs (us) Schwarz replied on :

    wouldn’t it be nice if STR2FUNC was (finally) able to also use absolute paths to functions outside the current ML search path… still yearning
    us

  2. Oliver A. Chapman, PE replied on :

    Loren,

    Thanks for discussing function handles some more.

    However, I still can’t imagine how function handles are useful. This isn’t new for me. It appears that I’ve never had a problem to solve where function handles would be useful and I can’t imagine a problem where they would be useful.

    And, when I say useful, I mean in order, 1. It allows easier to understand code. 2. It requires less code. 3. The resulting code runs faster.

    On the other hand, I learned something very useful with this week’s column: “repmat” works on cell arrays. I’d never get this from the documentation.

    Which brings up a chronic shortcoming of most MatLab function reference pages: They don’t include a list of allowed variable classes for inputs and outputs.

  3. Markus replied on :

    Like Urs, I also need to call functions from a subdirectory sometimes. The only way I found to do this is to put the whole subdirectory onto the Matlab path. But this is actually a bit nasty.

    Oliver, I can tell you that there are situations where function handles are useful. I have been testing a Kalman filter with different state space model functions. Of course I could use a switch-case-statement at every place I use the model functions. But 1. this would be ugly and 2. when introducing a new model function, I would have to update every single switch-case-statement where the model functions are used.

    Regards
    Markus

  4. Daniel Nordlund replied on :

    Wouldn’t the following way of iterating over the list be preferred?

    funcList = {@sin, @cos, @tan};
    for func = funcList
    func{:}(1.0)
    end

    Btw, any idea why non-scalar function handles won’t be supported in the future?

  5. Loren replied on :

    Daniel-

    You could also use your for-loop instead of mine. Depends which one seems clearer to the person writing the code.

    Non-scalar function handles won’t be supported because otherwise how can I tell what f(1) means? Does it mean get me the first function handle or does it mean evaluate f with the value 1? We don’t want people to have to write conditional code:

    if length(f) > 1
      myfunc = f(1);
      y = myfunc(x);
    else
      y = f(x);
    end
    

    Forcing function handles to be scalar gets rid of the ambiguity.

    –Loren

  6. Steve Marschner replied on :

    Loren,

    Thanks for your article; it has clarified my mental model of Matlab functions quite a bit.

    I haven’t been able to solve the problem that led me here, though. I would like to call a function without knowing the number of input or output arguments at compile time. To be concrete, say I have a function handle func, a cell array inputArgs, and an integer numReturnValues, and I would like to do something that has the same effect as

    [returnValues{1:nReturnValues}] = fn(inputArgs{1}, …, inputArgs{length(inputArgs)})

    This construct solves my problem for the output arguments, but I don’t see how to do something similar for the input arguments. Am I missing something?

    Thanks,
    Steve

  7. Loren replied on :

    Steve-

    I am not sure what you are trying to do. Can you just use a cell array for the inputs and then use the comma-separated list syntax to input them?

          inputs = {1 magic(3) 'fred'};
          [outputs{1:nout}] = fh(inputs{:});
    

    Or is your problem with function definition? And would varargin help there?

          fh = @(varargin) myNewFunc(a,b,varargin{:});
    

    –Loren

  8. Raymond replied on :

    Loren,

    I have a matlab script that creates an M-file in the current directory that contains the function myodefunc, then attempts to run ode15s on the function, e.g. ode15s(@myodefunc,…). If the M-file does not yet exist, the first time I run the script I get an error:

    >> script
    ??? Error using ==> feval
    Undefined command/function ‘myodefunc’.

    So the file exists but the handle doesn’t work. Oddly, I can clear the workspace and re-run the script:

    >> clear
    >> script

    Now, no errors are returned. Do functions whose handles are used in a script have to exist before the script is run, and is there a workaround? I can’t seem to find Matlab documentation on this fine point.

    Great blog…thanks for all the tips!

    –Raymond

  9. Loren replied on :

    Raymond-

    In your script, you can try, after creating the M-file and before creating the function handle, doing something to force MATLAB to relook at the directory, something like “which myNewMFile” or exist(’myNewMFilem’,2) and then have the script proceed. During a M-File, MATLAB tries to not refresh/reaccess directory information so it doesn’t slow things down. However, then you can have the issue you are seeing.

    Thanks for the kind words on the blog!
    –Loren

  10. Ray Jones replied on :

    I would like to use function handles to wrap (aka decorate or advise) an existing function. For example, I’d like to capture all calls to the builtin dialog() function, and make them blue. One way to do this is to save off a new dialog.m in my path (see below), and then adjust the path within that function.

    Another method I tried was storing off a handle to the built in dialog, then adding the new function to the path. Both of these methods work, but not when compiled.

    Is there a way to wrap an existing function more explicitly than with path tricks? What I’d really like to do is:
    orig_dialog = @dialog;
    dialog = @new_dialog;

    But that doesn’t behave as one might hope.

    Ray Jones

    ——————————–
    function H = dialog(varargin)
    % play path tricks to wrap an existing function.

    found = 0;
    for i = 1:2:length(varargin),
    if strcmp(varargin{i}, ‘Color’),
    varargin{i+1} = [0.7 0.7 0.9];
    found = 1;
    end
    end

    if ~ found,
    varargin{end+1} = ‘Color’;
    varargin{end+1} = [0.7 0.7 0.9];
    end

    oldpath = path;
    rmpath nd
    H = dialog(varargin{:});
    path(oldpath)

  11. Loren replied on :

    Ray-

    I can’t think of anything offhand. You might be able to accomplish this with some indirection using private functions and more than 1 file to control the scoping. But I am not sure.

    I’m assuming you want to do this because you don’t control all the code with instances for calling dialog. If that’s so, I think you’re only choice is to replace the one that’s there now with one earlier on the path. Otherwise, if you need both, you should have the code control to be able to manage two names, I would have thought.

    –Loren

  12. Zahra Khan replied on :

    You are my hero!
    I’m a student and have been trying to do this for a bit and here is the answer in front of me.
    One perhaps related question: is there a way in matlab to generate variable names automatically or have users input them?

    for example: could I do something like:
    xvariablename=input(’input the name of the x-variable:’,’s’);
    and then actually use this to set the x-variable in my graph say through a string comparison of some sort?

    e.g. if xvariablename=temperature
    plot(temperature)
    end

    but without using if statements because i’ll have a ton if I do this…

    thanks a bunch,
    Zahra

    PS: I liked your talk about nested funcs etc at MIT in January. I’d never heard of them before so it was really useful.

  13. Zahra Khan replied on :

    Also, would like to be able to do something like generate names of the sort:
    temperature1, temperature2, temperature3 automatically…
    can this be done?

  14. Loren replied on :

    Zahra-

    We recommend against you naming variables using temp1, temp2, etc. Instead, either make a cell array for each instance or a structure with dynamic fieldnames. Here’s a link to the FAQ:

    http://matlabwiki.mathworks.com/MATLAB_FAQ#How_can_I_create_variables_A1.2C_A2.2C….2CA10_in_a_loop.3F

    –Loren

  15. matt replied on :

    Hi, I’ve been using matlab 7.5.0 (R2007b) for some time. I’ve been unit testing using mlUnit. mlUnit’s unit test template has a function which basically finds all the nested functions in a unit test program and creates handles to those nested files using a call something like:

    function unit_test()
    h = load_tests_from_mfile

    function test_this()

    end
    end

    function fun_handle = load_tests_from_mfile(…)

    fun_handle = evalin(’caller’, [’@() @test_this’]);
    fun_handle = fun_handle();

    (note this is not the code, but some pseudo code, see mlUnit for complete example)

    This worked great since ‘caller’ was the unit_test program and the handle was @unit_test\test_this

    However I’ve just switched to matlab 7.6.0 (R2008a). Now, the functionality of evalin has changed (I think). In this version, the handle generated is @test_this and is no longer nested. Obviously, when I go to use that nested handle, Matlab can’t find it.

    Do you have any ideas as to how I might work around this?

    thanks
    -Matt

  16. Loren replied on :

    Matt-

    I am unaware of any change to evalin and don’t use mlUnit. I recommend you make a very small test example and contact technical support.

    –Loren

  17. per isakson replied on :

    Hi Matt

    “evalin(’caller’, [’@() @test_this’]);” is a useful trick that was never intended to work. It’s in conflict with the static workspace of nested functions. That’s my mental model anyhow.

    I fear that most of the unit testing tools available for Matlab rely on this trick. If the trick doesn’t work with R2008a that’s too bad for those of us who rely on unit testing.

    /per

  18. StephenLL replied on :

    My initial impression with the new OOP framework in R2008a is that it should eliminate the need for the “trickery” to build a unit testing framework in MATLAB.

  19. Matt replied on :

    Loren, per, StephenLL,

    Thank you for your quick responses. From all the searching on the web I’ve been able to do, it seems like mUnit and mlUnit are the two most widely used unit test frameworks. I’ve been using mlUnit in nested function mode. This has the issue that I’ve pointed out. mUnit also uses that same “trickery”. I found that mlUnit’s class mode does not use that trickery (obviously). I’ve tested it in ML7.5 and ML7.6 and it seems to work. So I guess for now, my solution is to convert to mlUnit class mode.

    If anyone has any other unit test frameworks they could suggest, I’d appreciate the input.

    Thanks.
    -Matt

  20. Brad Phelan replied on :

    I was the author of mUnit

    http://xtargets.com/cms/Tutorials/Matlab-Programming/MUnit-Matlab-Unit-Testing.html

    and the

    “evalin(’caller’, [’@() @test_this’]);”

    hack and it is a pity that it no longer works anymore. StephenLL is correct in that the new OOPs framework should make that sort of coding obsolete. However many hundreds of people have downloaded mUnit and many are probably still using it.

    Unfortunately I don’t have the time to debug the changes to mUnit at the moment. However it is open source GPL code and if anybody can figure out a way to fix it and send me the patches I’ll repost the new installer here.

    http://xtargets.com/downloads/

    Perhapps somebody at Mathworks could suggest the fix to keep mUnit working. As Matt says mUnit is used by many people. Encouraging test driven development can only be a good thing :)

    Regards

    Brad

  21. Loren replied on :

    Matt and Brad-

    The restriction to not create handles to nested functions via eval or evalin is intentional and it was a bug that slipped through that allowed that construct to work in the first place. eval and evalin were intended to allow access to the workspace only, i.e., variables.

    –Loren

  22. Brad Phelan replied on :

    Hi Loren,

    It’s unfortunate that a feature Mathworks were aware its customers were using was classified as a bug and eliminated. I and others had conversations with Mike Karr at least as far back as 2005 noting that this was an important feature and asking that it be regression tested to avoid accidental breakage in a new release. Obviously Mike could not promise anything but it’s unfortunate that Mathworks was unable to preserve this feature.

    The full details of the evalin trick I shared with Mike was posted sometime in 2005 here.

    http://www.xtargets.com/snippets/posts/show/42

    However I have an idea for a partial fix. Will eval still work. As in

    fh = eval(’@foo’)

    if foo is defined in the same workspace. I could modify the mUnit code slightly if that worked? Can anybody confirm this as I don’t have 2008a yet to play with.

    Regards

    Brad

  23. per isakson replied on :

    Hi Brad

    It took me long to answere your question because of problems with activating R2008a at our school.

    EVAL seems to work. See my little test below. However, we might want to ask The Mathworks whether it will still work with R2008b.

    >> version
    ans =
    7.6.0.324 (R2008a)
    >> test4munit
    foo is called successfully
    >>

    function test4munit
    fh = eval( ‘@foo’ );
    fh();
    function foo()
    disp( ‘foo is called successfully’ )
    end
    end

    Regards
    Per

  24. Loren replied on :

    I repeat my earlier comment:


    The restriction to not create handles to nested functions via eval or evalin is intentional and it was a bug that slipped through that allowed that construct to work in the first place. eval and evalin were intended to allow access to the workspace only, i.e., variables.

    –Loren

    If your use of eval is doing more than accessing a variable in the workspace, don’t count on that to continue working. I am not sure when the bug will be fixed, but it is a bug based on the intent of the design.

    –Loren

  25. Warody Lombardi replied on :

    Hi Loren,

    Is there any way of generating a function handle from a sym function?
    I have several symbolic calculations (integrals, etc) to generate some functions, and I need to minimize these functions by “fminbnd”.
    In my MatLab version (2007b) I can’t use matlabFunction.

    Regards,

    Warody

  26. Loren replied on :

    Warody-

    I am not aware of anything before R2008b as you say, matlabFunction.

    –Loren

  27. Grunde Waag replied on :

    Is there a way of making a function handle to a class function?

    methods
       function hei(obj)
         % make function handle to obj.hopp()???
       end
    
       function hopp(obj,p)
         disp(p)
       end
    end
    
  28. Grunde Waag replied on :

    I don’t know the function name on before hand. I just have a string.

  29. Loren replied on :

    Grunde-

    Take a look at str2func. Also in your hei method, just create the function handle you want: fh = @hopp. When you call it with an object of the correct class, the method will get called.

    –Loren

  30. Grunde Waag replied on :

    Thanks a lot.
    Didn’t realize that I can call the function with fn(obj) instead of obj.fn().

    I find function handles very useful. I use them when I want the code to be flexible. For instance if I want to parse some text with headers. When the parser finds a header ‘HEI’ with some corresponding data, it calls the function parseHEI with the data as argument. This makes the code flexible. Whenever I need a new header I just implement the parsheNEWHEADER function and the everything else is ready to go.

  31. Ljubomir Josifovski replied on :

    Are there maybe function handles that are “local” to an .m file?

    Example, if I have

    in file qwe1.m:

      function qwe1()
        q.fh = @qwe;
        save('qwe1', 'q');
        qq = load('qwe1');
        qq.q.fh();
      end
      function qwe()
        disp('qwe from qwe1 called')
      end
    

    and in file qwe2.m:

      function qwe2()
        qq = load('qwe1');
        qq.q.fh();
      end
      function qwe()
        disp('qwe from qwe2 called')
      end
    

    Then in Matlab Version 7.5.0.342 (R2007b) I get

      >> qwe1
      qwe from qwe1 called
      >> qwe2
      qwe from qwe1 called
    

    i.e. the function handle de-serialised in qwe2 “remembers” it points to (private) function qwe in qwe1, not qwe2.

    I was wondering if it is possible to make the handle local to the source file? Like if a was saving ‘qwe’ as a string and used feval latter to call the (private) function qwe when running qwe2 I would have called the function qwe from qwe2. :-)

    Not sure if I am explaining what I know well, here is an example,

    in file qwe3.m:

      function qwe3
        q.fs = 'qwe';
        save('qwe3', 'q');
        qq = load('qwe3');
        feval(qq.q.fs);
      end
      function qwe()
        disp('qwe from qwe3 called')
      end
    

    in file qwe4.m:

      function qwe4()
        qq = load('qwe3');
        feval(qq.q.fs);
      end
      function qwe()
        disp('qwe from qwe4 called')
      end
    

    Now when I run in Matlab

      >> qwe3
      qwe from qwe3 called
      >> qwe4
      qwe from qwe4 called
    

    i.e. the 2nd call goes to the qwe function in file qwe4.m (while if this were a file handle would have gone to qwe in qwe3.m).

    Thanks for you help,
    Ljubomir Josifovski

  32. Loren replied on :

    Ljubomir-

    You can’t make the function handle local to the file. If you pass a function handle pointing to one file’s subfunction, then that subfunction will be called regardless of where the function handle is passed and whether or not that new context has a function of the same name in its scope. To get that behavior you have to use the strings as you note.

    –Loren

  33. Ljubomir Josifovski replied on :

    Thanks Loren. Since I wrote my post I discovered in the help the “functions” function, which spells out the info the handle contains.

    Regards,
    Ljubomir

  34. Veronika replied on :

    Hi!

    MATLAB R2009a corresponds an error ‘Nonscalar arrays of function handles are not allowed; use cell arrays instead’, but it was working before? Is there some common solution how should i change the script to get it working?

    Thanks for answers in advance!

  35. Loren replied on :

    Veronika-

    I recommend following the advice of the error message. Place them in a cell array. E.g.,

    fh = { @sin, @cos};
    x = 0:.01:1;
    ysin = fh{1}(x);
    

    –Loren

  36. Carmen replied on :

    I’m strugling with the error message:
    ‘Nonscalar arrays of function handles are not allowed; use cell arrays instead’
    as well… please help me out with this application.
    This is a modified version of my code part of my code:

    for j=1:10;
        for i=1:10;
            aprox(i,j)=schumaker(vv(:,i,j),nod,agrid);
            aprox2(i,j)=@(x) ppval(aprox(i,j),x);
            a(i,j)=agrid(1);
            b(i,j)= agrid(10);
           [policya(i,j),vvaprox(i,j)]=golden(aprox2(i,j),a(i,j),b(i,j));
    end;
    end;
    

    where both schumaker and golden are two functions defined in separate m-files. When I used the command:
    aprox2(i,j)=@(x) ppval(aprox(i,j),x);
    I get an error message instead of a warning as I did with the older version of matlab… I can’t figure out how to fix this.

    Thanks in advance!

Leave a Reply

Wrap code fragments inside <pre> tags, like this:

<pre class="code">
a = magic(3);
sum(a)
</pre>

If you have a "<" character in your code, either follow it with a space or replace it with "&lt;" (including the semicolon).


Loren Shure works on design of the MATLAB language at The MathWorks. She writes here about once a week on MATLAB programming and related topics.

  • Jun: I totally can not believe it, Loren. You are really helpful. Thank you so much, MATLAB master!
  • Loren: Wow folks- Always lots of interest when there’s a quickie to try out! I will only make 2 general...
  • Loren: Jun- ismember is your friend here: >> [aa,ind] = ismember(Array2,Arra y1) aa = 1 1 1 1 1 1 1 ind = 1 2 1 4 4 3...
  • Dan: I like the first way better than the second way. Combining the arrays into one and running any is nice, although...
  • James Myatt: How about I = (a == 0 | b == 0); a(I) = []; b(I) = [];
  • Tunc: Hello Loren, love your blog because of such inspiring and challenging comments to such ’small’...
  • Pekka Kumpulainen: Here is my tradeoff. I usually want to keep the original variables as they are most probably...
  • Iain: Followup: Of course, to allow NaNs (counting them as non-zero): mask = (a~=0) & (b~=0); The mask says “a...
  • Matt Fig: I would usually go with something like this: y = a&b; x = a(y); y = b(y); But I was surprised to find...
  • kk: c=all([a;b]) a(c) a(b)

These postings are the author's and don't necessarily represent the opinions of The MathWorks.