28

Over the years, reading others code, I encountered and collected some examples of MATLAB syntax which can be at first unusual and counterintuitive. Please, feel free to comment or complement this list. I verified it with r2006a.


MATLAB always returns first output argument of a function (if it has at least one) into its caller workspace, also unexpectedly if function is being called without returning arguments like myFunc1(); myFunc2(); the caller workspace still would contain first output of myFunc2(); as "invisible" ans variable. It could play an important role if ans is a reference object - it would remain alive.


set([], 'Background:Color','red')

MATLAB is very forgiving sometimes. In this case, setting properties to an array of objects works also with nonsense properties, at least when the array is empty. Such arrays usually come from harray = findobj(0,'Tag','NotExistingTag')


myArray([1,round(end/2)])

This use of end keyword may seem unclean but is sometimes very handy instead of using length(myArray).


any([]) ~= all([])

Surprisigly any([]) returns false and all([]) returns true. And I always thought that all is stronger then any.

EDIT:

with not empty argument all() returns true for a subset of values for which any() returns true (e.g. truth table). This means that any() false implies all() false. This simple rule is being violated by MATLAB with [] as argument.

Loren also blogged about it.


Select(Range(ExcelComObj))

Procedural style COM object method dispatch. Do not wonder that exist('Select') returns zero!


[myString, myCell]

MATLAB makes in this case an implicit cast of string variable myString to cell type {myString}. It works, also if I would not expect it to do so.


[double(1.8), uint8(123)] => 2 123

Another cast example. Everybody would probably expect uint8 value being cast to double but Mathworks have another opinion. Without a warning this behavior is very dangerous.


a = 5;
b = a();

It looks silly but you can call a variable with round brackets. Actually it makes sense because this way you can execute a function given its handle.


Syntax Foo(:) works not only on data but also with functions if called as Bar.Foo(:), in this scenario the function input argument is passed as char colon ':'.

For example let Bar.Foo = @(x) disp(x) Now calling Bar.Foo(:) prints char ':' in the MATLAB Command Window.

This strange feature works with all MATLAB 7 versions without warnings.


a = {'aa', 'bb'
'cc', 'dd'};

Surprsisingly this code neither returns a vector nor rises an error but defins matrix, using just code layout. It is probably a relict from ancient times.

EDIT: very handy feature, see the comment by gnovice.


set(hobj, {'BackgroundColor','ForegroundColor'},{'red','blue'})

This code does what you probably expect it to do. That function set accepts a struct as its second argument is a known fact and makes sense, and this sintax is just a cell2struct away.


Equvalence rules are sometimes unexpected at first. For example 'A'==65 returns true (although for C-experts it is self-evident). Similarly isequal([],{}) retuns, as expected, false and isequal([],'') returns true.

The string-numeric equivalence means that all string functions can be used also for numeric arrays, for example to find indices of a sub-array in a large array:

ind = strfind( [1 2 3 4 1 2 3 4 1 2 3 4 ], [2 3] )

MATLAB function isnumeric() returns false for booleans. This feels just ... false :-)


About which further unexpected/unusual MATLAB features are you aware?

casperOne
  • 73,706
  • 19
  • 184
  • 253
Mikhail Poda
  • 5,742
  • 3
  • 39
  • 52
  • 1
    I believe Community Wiki is warranted in this case, since this is basically a "list-compiling" poll question. – gnovice Nov 10 '09 at 18:56
  • 1
    @gnovice: changed to community wiki – Mikhail Poda Nov 10 '09 at 19:07
  • 9
    "Surprisigly any([]) returns false and all([]) returns true." I don't understand what's so surprising about this; I find it completely obvious. – Timwi Nov 12 '09 at 16:51
  • @Timwi: with not empty argument all() returns true for a subset of values for which any() returns true. This means that any() false implies all() false. That's why I was surprised to see this simple rule violated when used with empty argument. – Mikhail Poda Nov 12 '09 at 18:31
  • 3
    @Mikhail: this is not a problem with Matlab but rather with everyday language. Consider an empty room. "Are all the sheep in this room green?" - the **logical** answer is **yes**, because "no" implies that there exists _at least one non-green sheep_ in the room. Everyday language however doesn't allow such use of "all" (and is overall very ambiguous and imprecise) - and asking "Are all the sheep green?" in English implies the existence of at least one green sheep, making the question itself meaningless in an empty room. – Roman Starkov Jan 26 '10 at 17:01
  • 1
    can't you split your "question" into several answers? there are several points I'd like to up-"oh yeah that's true"-vote... – Tobias Kienzler Feb 04 '11 at 10:21
  • 1
    @Mikhail: my belated $0.02. `all([])` is true and `any([])` is false for the same reason that `prod([])` is 1 and `sum([])` is 0: them are the wages of *associativity*. If an operation `f` is associative, then for any `A`, `B`, `C` such that `A = [B C]`, the invariant `f(A) = f([f(B) f(C)])` *must* hold. (E.g. if `sum` is going to be associative, then the sum of a list *must* be equal to the sum of "the first item of the list" with "the sum of the rest of the list".) This includes the case where `B = A` and `C = []`, so this invariant condition *forces* the definition... – kjo Mar 03 '14 at 04:10
  • @Mikhail: ... of `f([])` to be such that `f(A) = f([f(A) f([])])`. Now, the *only* boolean value `x` such that `all([y x]) == all(y)` for *every* boolean `y` is `x = true`. And the *only* boolean value `x` such that `any([y x]) == any(y)` for *every* boolean `y` is `x = false`. This is why `all([])` *has* to be true, and `any([])` has to be false. MATLAB is being mathematically punctilious here, a good thing, IMO. – kjo Mar 03 '14 at 04:11

3 Answers3

12

Image coordinates vs plot coordinates Used to get me every time.

%# create an image with one white pixel
img = zeros(100);
img(25,65) = 1;

%# show the image
figure
imshow(img);

%# now circle the pixel. To be sure of the coordinate, let's run find
[x,y] = find(img);
hold on
%# plot a red circle...
plot(x,y,'or')
%# ... and it's not in the right place

%# plot a green circle with x,y switched, and it works
plot(y,x,'og')

Edit 1

Array dimensions

Variables have at least two dimensions. Scalars are size [1,1], vectors are size [1,n] or [n,1]. Thus, ndims returns 2 for any of them (in fact, ndims([]) is 2 as well, since size([]) is [0,0]). This makes it a bit cumbersome to test for the dimensionality of your input. To check for 1D arrays, you have to use isvector, 0D arrays need isscalar.

Edit 2

Array assignments

Normally, Matlab is strict with array assignments. For example

m = magic(3);
m(1:2,1:3) = zeros(3,2);

throws a

??? Subscripted assignment dimension mismatch.

However, these work:

m(1:2,1:2) = 1; %# scalar to vector
m(2,:) = ones(3,1); %# vector n-by-1 to vector 1-by-n (for newer Matlab versions)
m(:) = 1:9; %# vector to 'linearized array'

Edit 3

Logical indexing with wrongly sized arrays Good luck debugging this!

Logical indexing seems to make a call to find, since your logical array doesn't need the same amount of elements as there are indices!

>> m = magic(4); %# a 4-by-4 array
>> id = logical([1 1 0 1 0])
id =
     1     1     0     1     0
>> m(id,:)  %# id has five elements, m only four rows
ans =
    16     2     3    13
     5    11    10     8
     4    14    15     1
%# this wouldn't work if the last element of id was 1, btw

>> id = logical([1 1 0])
id =
     1     1     0
>> m(id,:) %# id has three elements, m has four rows
ans =
    16     2     3    13
     5    11    10     8
Jonas
  • 74,690
  • 10
  • 137
  • 177
  • [Comment](https://blogs.mathworks.com/loren/2016/10/24/matlab-arithmetic-expands-in-r2016b/#comment-46601) by Steve Eddins related to Edit 3: _I wish I could go back in time to prevent us from making the change that allowed logical indexing with mismatched sizes_ – Luis Mendo Sep 27 '19 at 10:42
8

Instead of listing examples of weird MATLAB syntax, I'll address some of the examples in the question that I think make sense or are expected/documented/desired behavior.

  • How ANY and ALL handle empty arguments:

    The result of any([]) makes sense: there are no non-zero elements in the input vector (since it's empty), so it returns false.

    The result of all([]) can be better understood by thinking about how you might implement your own version of this function:

    function allAreTrue = my_all(inArray)
      allAreTrue = true;
      N = numel(inArray);
      index = 1;
      while allAreTrue && (index <= N)
        allAreTrue = (inArray(index) ~= 0);
        index = index + 1;
      end
    end
    

    This function loops over the elements of inArray until it encounters one that is zero. If inArray is empty, the loop is never entered and the default value of allAreTrue is returned.

  • Concatenating unlike classes:

    When concatenating different types into one array, MATLAB follows a preset precedence of classes and converts values accordingly. The general precedence order (from highest to lowest) is: char, integer (of any sign or number of bits), single, double, and logical. This is why [double(1.8), uint8(123)] gives you a result of type uint8. When combining unlike integer types (uint8, int32, etc.), the left-most matrix element determines the type of the result.

  • Multiple lines without using the line continuation operator (...):

    When constructing a matrix with multiple rows, you can simply hit return after entering one row and enter the next row on the next line, without having to use a semicolon to define a new row or ... to continue the line. The following declarations are therefore equivalent:

    a = {'aa', 'bb'
    'cc', 'dd'};
    
    a = {'aa', 'bb'; ...
    'cc', 'dd'};
    
    a = {'aa', 'bb'; 'cc', 'dd'};
    

    Why would you want MATLAB to behave like this? One reason I've noticed is that it makes it easy to cut and paste data from, for example, an Excel document into a variable in the MATLAB command window. Try the following:

    • Select a region in an Excel file and copy it.
    • Type a = [ into MATLAB without hitting return.
    • Right-click on the MATLAB command window and select "Paste".
    • Type ]; and hit return. Now you have a variable a that contains the data from the rows and columns you selected in the Excel file, and which maintains the "shape" of the data.
gnovice
  • 125,304
  • 15
  • 256
  • 359
  • 1
    I think it helps to point out why "all([])" confuses people - it's because "all" works differently in everyday language than it does in logic/programming. I've posted an example as a comment on the question. – Roman Starkov Jan 26 '10 at 17:06
  • At least, concatenating unlike integers throws an error (r2010a) – Jonas Apr 21 '10 at 18:33
5

Arrays vs. cells

Let's look at some basic syntax to start with. To create an array with elements a, b, c you write [a b c]. To create a cell with arrays A, B, C you write {A B C}. So far so good.

Accessing array elements is done like this: arr(i). For Cells, it's cell{i}. Still good.

Now let's try to delete an element. For arrays: arr(i) = []. Extrapolating from examples above, you might try cell{i} = {} for cells, but this is a syntax error. The correct syntax to delete an element of a cell is, in fact, the very same syntax you use for arrays: cell(i) = [].

So, most of the time you access cells using special syntax, but when deleting items you use the array syntax.

If you dig deeper you'll find that actually a cell is an array where each value is of a certain type. So you can still write cell(i), you'll just get {A} (a one-valued cell!) back. cell{i} is a shorthand to retrieve A directly.

All this is not very pretty IMO.

Roman Starkov
  • 59,298
  • 38
  • 251
  • 324
  • 6
    The cell behavior is actually quite consistent: arr(i) returns the ith element of the array. In the case of a numeric array, the ith element is numeric scalar, in case of a cell array, the ith element is a scalar cell, in case of a struct array the ith element is a scalar structure. The curly brackets are used to 'dig into' the cell, like the fieldnames are used to 'dig into' a structure. Also, like for structures, you can then go on to access elements of the contents of a cell, such as cellArray{i}(1,2) – Jonas Apr 28 '10 at 19:44