У нас есть достаточно большой проект на Matlab. Своего матлаб-кода порядка 15 KLOC. Писать на Matlab столько кода - занятие не для слабонервных. Ниже приведен список некоторых особенностей матлаба.
- Размер java heap memory нельзя выставить больше четверти физического размера ОЗУ. Что для некоторых используемых нами java либ уже не хватает.
- В Матлаб есть функция spconvert - импорт разреженных матриц в координатном формате из файла. А вот аналогичной функция для экспорта - нет
- Экспорт матриц для double чисел корректно работает только в ascii формате, см. http://www.mathworks.com/matlabcentral/answers/100620-how-can-i-avoid-truncation-and-loss-of-precision-when-saving-my-data-in-matlab. В другом формате при экспорте числа будут "обрезаться" до single
- Эффективность объектно-ориентированного кода крайне невелика. Скорость доступа к полям объекта, к enum'ам настолько мала, что использовать ООП для сколько-нибудь реальных задач невозможно
- Функция linsolve не работает для разреженных матриц. Например:
>> linsolve(sprand(3,3,0.1), sprand(3,1,1))
Error using linsolve
Linsolve is currently not supported for sparse inputs
Вместо этого предлагается использовать "\"
- Стандартные функции можно случайно переопределить. Например:
>> diag(randi(3,3))
ans =
3
2
3
>> diag = 1;
>> diag(randi(3,3))
??? Index exceeds matrix dimensions.
- Сокращенная запись массивов без запятых может привести к таким опечаткам:
>> [1 -1, 2]
ans =
1 -1 2
>> [1 - 1, 2] % случайно поставили пробел перед второй единицей
ans =
0 2
- В workspace формат вывода по умолчанию "укороченный" и поменять его нельзя
- Не вполне очевидная работа с размерностью данных
>> size(1)
ans =
1 1
>> size([1 2])
ans =
1 2
>> size([])
ans =
0 0
Такая операция выполнима
>> [] * 1
ans =
[]
А такая уже нет:
>> [] * [1 2]
??? Error using ==> mtimes
Inner matrix dimensions must agree
- Малоинформативные сообщения об ошибках. Например, описываем в файле класс :
classdef struc
properties
x
end
end
Работаем в командной строке:
>> a = struc();
>> a(1) = struc()
>> a([]).x * 1
??? Error using ==> mtimes
Not enough input arguments.
И
>> class(a([]).x)
??? Error using ==> class
Not enough input arguments.
Обратите внимание на описание ошибки "для операции умножения не хватает аргументов". Хотя здесь должно было быть сообщение об отсутствующем объекте по заданному индексу.
Продолжим пример и создадим массив объектов, для чего используется специальный синтаксис. Так, например, делать нельзя:
>> a = [];
>> a(1) = struc()
??? The following error occurred converting from struc to double:
Error using ==> double
Conversion to double from struc is not possible.
А вот так уже можно:
>> a=struc();
>> a(2) = struc();
>> a(11) = struc();
>> a
a =
1x11 struc
Автоматически вызываются конструкторы для объектов по индексам от 3 до 10. Соответственно, в массиве объектов контроля выхода за пределы массива уже не происходит.
- Матлаб жесток к тем, кто допускает опечатки в коде:
function [x,z] = f(x,z)
y.field = 1; % случайно вместо переменной "z" изменили поле в "y".
end
И, несмотря на то, что переменная "y" нигде не объявлена, несмотря на то, что мы явно используем поле "field" необъявленной переменной - матлаб при статической проверке кода предупреждения на этой строке не выдаст. Вызов такой функции отработает "молча".
Другой пример, который при проверке не вызовет предупреждений:
function [ a ] = fun1( a,i,b )
a(i) = b;
a(i2) = b+1; % вместо "i" случайно написали 'i2"
a(i) = a1(i);
end
Вызывая такую функцию, получим ожидаемую ошибку:
>> fun1(1:10,2,3)
Undefined function or variable 'i2'.
Error in fun1 (line 3)
- В матлабе фактическим именем функции является не ее имя в сигнатуре, а имя файла, в коротом она описана. Например, файл: function1.m
function [ output_args ] = fun1( input_args )
42
end
Пишем в командной строке:
>> fun1()
??? Undefined function or variable 'fun1'.
А так можно:
>> function1()
ans =
42
- Работа с хэш-массивами не вполне очевидна:
kv = containers.Map('KeyType','int32', 'ValueType', 'any');
% ...заполянем "kv" значениями...
for k = keys(kv) % последовательно выводим на экран ключи нашего хэша
kv(k{1})
end
Если вместо k{1} написать k, то будет ошибка, т.к. ключи перечисляются внутри cell-массива