6

A function can be defined as @(x) x^.2 (for e.g)

But in case, we have a function that takes different representation on different intervals for e.g : if abs(x)<3 fun = x^.2 else 0

How can we use the same way (i mean use @(x) ) to define such a function.

Dan
  • 43,452
  • 14
  • 75
  • 140
Jessica
  • 71
  • 1
  • 1
  • 2
  • 1
    possible duplicate of [How to execute multiple statements in a MATLAB anonymous function?](http://stackoverflow.com/questions/558478/how-to-execute-multiple-statements-in-a-matlab-anonymous-function) – Shai Jul 02 '13 at 08:42
  • 2
    @Shai: disagree. That question is about multiple function evaluations in a single anon, while this is about conditional evaluation in an anon (there *is* a dupe, I've seen it, but I'm not finding it now...) – Rody Oldenhuis Jul 02 '13 at 08:55

4 Answers4

17

There's a few ways to do this.

Multiply by false:

g = @(x) (abs(x)<3) .* x.^2

or define a proper function (the BEST way really):

function y = g(x)

    y = zeros(size(x), class(x));

    inds = abs(x)<3;
    y(inds) = x(inds).^2;

end 

or do the messy-ugly-inefficient-but-fun thing and use an inline-if:

iif = @(varargin) varargin{2 * find([varargin{1:2:end}], 1, 'first')}();
g = @(x) iff( ...
    abs(x)<3,  x.^2, ...
        true,  0);
Rody Oldenhuis
  • 36,880
  • 7
  • 47
  • 94
  • 2
    More explanation: A proper function is even required when you want to avoid computation of the other part that doesn't get selected; eg: `iif(x==0;0;1/x)´ here `1/x` still gets evaluated, even if `x==0`. It's a function and matlab still wants to pass it all the arguments, hence the evaluation. The only way to avoid this (and that's why it's the best, proper way) is by using a separate function, which allows multiline and a normal `if`. – Gunther Struyf Jul 02 '13 at 10:05
  • @GuntherStruyf: true. Added "inefficnet" to the description of the `iif()` method :) – Rody Oldenhuis Jul 02 '13 at 10:34
  • @GuntherStruyf: ahum. That's "inefficient". Typing is hard. – Rody Oldenhuis Jul 02 '13 at 12:06
  • meant it mostly as a comment about avoiding errors. It looks like an if/then/else but it actually isn't when it comes down to how it gets executed. But yeah, it's also inefficient ;) – Gunther Struyf Jul 02 '13 at 15:28
0

As @Gunther mentioned in the comments above, a generic function to handle simple conditions to mimic the tertiary operator ?: can be created to circumnavigate the limitation that Matlab doesn't allow conditionals inside anon functions (if you don't count that messy-ugly-inefficient-but-fun inline version :).

The solution was presented via this link (and perhaps a few other places but SO came back on top of my google search so thought it'd be good to add here). http://www.mathworks.co.jp/matlabcentral/newsreader/view_thread/158054

define a function say iff or ifelse and add it to the Matlab path.

function result = ifelse(condition,trueResult,falseResult)
    error(nargchk(3,3,nargin));  % check correct number of input args
    if condition
        result = trueResult;
    else
        result = falseResult;
    end

then use like this

predict = arrayfun(@(x) ifelse(x>=0.5,1,0), inputData);

In the OP's case, something like this could be used

arrayfun(@(x) ifelse(abs(x)<3,x^.2,0), data)
Paul P M
  • 131
  • 1
  • 8
0

This is what I came up with. I have cases.m function with the following definition:

function [ val ] = cases( table )
  [rows,~] = size(table);
  for i = drange(1:rows)
    condition = table{i,1};
    if (ischar(condition) && strcmpi(condition,'else')) || feval(condition)
      val = feval(table{rows,2});
      return
    end
  end
  val={};
end

The function cases takes a cell array with two columns. Each element is a function with zero arguments. For each row it takes the first element and if it is the string 'else' or a function that returns a true value, the second element is called and its value returned. If no row qualifies, an empty cell is returned. The elements are nullary functions instead of values, so that unneeded cases are not evaluated.

Then I can write case expressions like this:

w=arrayfun(@(j) cases({ ...
   @() (j==0 || j==n) @() (-1)^j/2; ...
   'else' @() (-1)^j }), 0:n);

This produces an array for values from 0 to n with the first and the last value halved.

Juho Östman
  • 1,506
  • 1
  • 11
  • 19
0

To expand on the link hiding in @RodyOldenhuis's answer, have a look at Functional Programming Constructs. That package provides a pretty comprehensive set of functional constructs. The author also did a series of guest posts on the Art of MATLAB blog showing a lot of the details behind this library. If you don't want pull the whole package in to your project, the blog posts also include anonymous one-liners of some of the functions in the package.

Arthur Ward
  • 549
  • 3
  • 20