From: Zaphod on
Disclaimer: I don't use Matlab much, and have expectations formed from years of programming in other languages. Taking this into consideration, I think that Matlab does not correctly implement anonymous functions.

To illustrate this point, consider the following code examples:

python:
f = lambda x: x + 1
f(1)

javascript:
f = function(x) { return x + 1; }
f(1)

matlab:
f = @(x) x + 1
f(1)

all of the above examples essentially do the same thing. the variable f is assigned to an anonymous function which increments its argument, then f is applied to the argument 1, and returns 2. however, consider these examples:

python:
(lambda x: x + 1)(1) ---> evaluates to 2

javascript:
(function(x) {return x + 1;})(1) ---> evaluates to 2

matlab:
(@(x) x + 1)(1) ----> syntax error, unbalanced or unexpected paren

I think that (@(x) x + 1) should be evaluated first (the outer parens denoting order of operations) and return a value of type int->int, then that function should be applied to the argument 1. This behavior seems particularly inconsistent because the following matlab code works:

f = @(x) @(y) x + y
f(4) ----> evaluates to @(y) x + y

The above example shows that at least in some sense, matlab is capable of evaluating an expression to a value with a function type.

My contention is essentially that Matlab should handle this case in the same way as every other language (I gave examples in python and javascript, but I think that an analogous example can be made in AS3, C++ with Boost, SML and Haskell as well).
From: Doug Schwarz on
In article <hqr1g9$t5p$1(a)fred.mathworks.com>,
"Zaphod " <a3904429(a)owlpic.com> wrote:

> Disclaimer: I don't use Matlab much, and have expectations formed from years
> of programming in other languages. Taking this into consideration, I think
> that Matlab does not correctly implement anonymous functions.
>
> To illustrate this point, consider the following code examples:
>
> python:
> f = lambda x: x + 1
> f(1)
>
> javascript:
> f = function(x) { return x + 1; }
> f(1)
>
> matlab:
> f = @(x) x + 1
> f(1)
>
> all of the above examples essentially do the same thing. the variable f is
> assigned to an anonymous function which increments its argument, then f is
> applied to the argument 1, and returns 2. however, consider these examples:
>
> python:
> (lambda x: x + 1)(1) ---> evaluates to 2
>
> javascript:
> (function(x) {return x + 1;})(1) ---> evaluates to 2
>
> matlab:
> (@(x) x + 1)(1) ----> syntax error, unbalanced or unexpected paren
>
> I think that (@(x) x + 1) should be evaluated first (the outer parens
> denoting order of operations) and return a value of type int->int, then that
> function should be applied to the argument 1. This behavior seems
> particularly inconsistent because the following matlab code works:
>
> f = @(x) @(y) x + y
> f(4) ----> evaluates to @(y) x + y
>
> The above example shows that at least in some sense, matlab is capable of
> evaluating an expression to a value with a function type.
>
> My contention is essentially that Matlab should handle this case in the same
> way as every other language (I gave examples in python and javascript, but I
> think that an analogous example can be made in AS3, C++ with Boost, SML and
> Haskell as well).


MATLAB's parser is limited, partly for historical reasons. It has never
been possible to do something like

f(4)(1)

because of the ambiguity. Does it mean that f(4) is a function handle
and then we want to pass 1 into that function or does it mean that f is
a function, we pass 4 into that function, it returns a vector and then
we index into the first element of that? Well, the parser doesn't know
either. It could be defined, but it hasn't up till now.

I know this isn't quite what you had in mind, but you can sort of do
what you want with feval:

feval(@(x)x+1,1)

returns 2.

--
Doug Schwarz
dmschwarz&ieee,org
Make obvious changes to get real email address.
From: Walter Roberson on
Zaphod wrote:
> Disclaimer: I don't use Matlab much, and have expectations formed from
> years of programming in other languages. Taking this into consideration,
> I think that Matlab does not correctly implement anonymous functions.


> matlab:
> (@(x) x + 1)(1) ----> syntax error, unbalanced or unexpected paren

It is not a matter that Matlab does not correctly implement anonymous
functions: it is a problem of backwards compatibility of code that
Mathworks does not wish to break.

In the languages you cite, python and javascript, in order to call a
function, you must mention the function name and then provide a
{possibly empty} argument list in order for the function to be called.
In Matlab, due to long historical practice, at execution time, functions
are called if they are mentioned by name (outside of a string) _unless_
they are proceeded by @, even if there is no argument list or () .

For example, in matlab,

Done = true;

sets the variable named 'Done' to the logical true value, data class
logical, numeric value 1. Looks simple and obvious enough, but it hides
the fact that true is actually a function being called here with no
arguments. Matlab doesn't special case this in any way, such as by
immediately substituting the logical truth value upon recognizing that
true is being called without any arguments: it just calls the function
named 'true' and lets the function itself figure out that it was called
with no arguments and lets the function decide what that means. It
happens that for Matlab, all of the following are equivalent:

Done = true;
Done = true();
Done = true(1);
Done = true(1,1);

The numbers for the arguments are array sizes: true with no arguments or
the empty argument constructs a 1 x 1 array of logical true values. If
the programmer had instead coded

Done = true(5,1);

then that would set 'Done' to the column vector, 5 rows by 1 column,
each with the logical true value.


Now, because of this historical precedent and the amount of code that
could end up broken if it were changed, Matlab simply disallows further
indexing or invocation *of any kind* after a function call. You cannot,
for example, in Matlab meaningfully write true(5,1)(2:4,1) to construct
the 5 x 1 column vector of true values and then extract the 2nd, 3rd and
4th row of that anonymous column vector. There are lots of times when it
would nice to be able to do something like that, but Matlab prohibits
it. It isn't a "bug" in the handling of anonymous functions or of
anonymous objects: it is simply part of the language definition.

The reasons that have been sometimes stated by Mathworks employees as to
why one cannot do further indexing or invocation is that apparently if
they were to allow that, it would not be possible to differentiate
between foo(2,4) meaning "call foo with no arguments and index the
result at row 2 column 4" versus foo(2,4) meaning "call foo with the
list of arguments 2 and then 4." With anonymous functions thrown in,
there is also a third potential meaning: "call foo with no arguments and
if it returns a function hsndle, call that function with the list of
arguments 2 and then 4."

My _personal_ view (as a user who happens to be delegated by my systems
administrator as being eligible to submit bug reports myself without
going through him, but who has no other closer contact to Mathworks), is
that probably there is no _real_ conflict, if Mathworks were to simply
require the call-with-no-arguments cases to supply the empty argument
list, such as foo()(2,4) . After all, since that syntax is currently
prohibited, there are no valid existing programs that can possibly use
it, so enhancing the syntax by adding it as a possibility would not
break any backwards compatibility.

However, I understand that the Mathworks parser is.. ummm, not exactly
modular, shall we say. Apparently there are some nasty context-
dependencies in the interpretation of some expressions that make the
parser tricky code. I think I could name a few of the more troublesome
spots; the ones I am thinking of are mostly for backwards compatibility,
but at least one of them is a nice syntactical sugar that people would
likely begrudge having eliminated.
From: Bruno Luong on
Doug Schwarz <see(a)sig.for.address.edu> wrote in message
>
> MATLAB's parser is limited, partly for historical reasons. It has never
> been possible to do something like
>
> f(4)(1)
>
> because of the ambiguity. Does it mean that f(4) is a function handle
> and then we want to pass 1 into that function or does it mean that f is
> a function, we pass 4 into that function, it returns a vector and then
> we index into the first element of that? Well, the parser doesn't know
> either. It could be defined, but it hasn't up till now.
>

Sorry but I don't buy. Let's consider f(1)(4)

Let's us try to do the same work as the more advanced parser. First we have to evaluate f(1)

f(1) (4) -> g=f(1); g(4)

Matlab currently are perfectly capable to determine what to do with g=f(1): if f is a non-scalar array :

>> f={@(x) 1, @(x) 2}

f =

@(x)1 @(x)2

% if f is a single function handle
>> f(1)

ans =

@(x)1

>> f=@(x) 1

f =

@(x)1

>> f(1)

ans =

1

Then it can go on as such for successive parenthesis.

To me, there is no reason why Matlab parser won't be able to be extended to do cascade indexing.

Bruno
From: Zaphod on
Thanks for your responses... very detailed and interesting. It seems like a big part of this issue is maintaining backward compatibility, and not stepping on other syntax. This is a nitpick, but the reason I think it is dubious to refer to them as "anonymous" is that in every use case I can think of except for feval / arrayfun, a function must have a name before it is called (i.e. even when you pass an "annon" function as an argument to another function, it is given an name in the scope of the function being called before it can ever be used). I will admit however that I can't think of a practical use for fail case I showed. As such my gripe here isn't that missing this functionality is a big inconvenience, but that it is inconsistent with other languages (many of which are quite consistent in how this is handled) as well as somewhat internally inconsistent (i.e. with the fact that you
can return anonymous functions as values, and the fact that parens normally denote order of evaluation).