views:

422

answers:

3

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.


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?

+4  A: 

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.

romkyns
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
+2  A: 

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
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.
romkyns
At least, concatenating unlike integers throws an error (r2010a)
Jonas
+3  A: 

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 to vector (for newer Matlab versions)
m(:) = 1:9; %# vector to 'linearized array'
Jonas