This post is intended for people with the practice of programming the PLO (sorry for the tautology), by the will of fate forced to write on MatLab. The language is pleasant, but the rake is quite a large number, and not everyone has to step on them all.
I was inspired to write a
recent post about optimizing MatLab code, or rather comments that required more depth in the subject.
So…
')
Story
In MatLab OOP for a long time did not exist.
In 2005, the first scary-looking attempts appeared: a class — a folder, a method — a separate file, properties — a single access method with the parameter “property name”.
The "beautiful" beginning, fortunately, was quickly abandoned.
A few years later, the PLO was made in a more familiar form - classes, inheritance, everything is like in humans. Except for a few details.
Few details
Overload
It is still impossible to define several methods with the same name. MatLab itself explains this by the lack of typing of variables (the only difference between different methods would be the number of parameters) and the optional transfer of parameters to functions (arrived).
The solution is to write many functions with similar names, possibly together with a dispatcher function, analyzing the situation and calling one of these functions.
Abstract static
Cannot define abstract static methods or properties. And sometimes you really want it.
I haven’t found a way out yet, MatLab is aware, he does not consider a bug.
Passing parameters by value or by reference
All parameters are passed by value (which causes many users to advocate a departure from the use of functions - horror, horror!), But through the lazy method. That is, copying occurs only in case of a change in the variable. If this mechanism is well understood, it is possible to win (or rather not lose, compared to the usual transfer of variables by reference) in the computation speed.
Objects of "normal" classes are also passed by value.
However, if the class inherits from the standard MatLab class handle, its objects will be passed by reference.
Generated documentation
After java / C ++ you get used to the fact that the documentation should be automatically created based on the comments you left in the code. MatLab offers a mutant called Publisher, which shaky-swath cope with the task at the script level. Besides the fact that it does not work with classes, I will note the fact that all the comments are included in the documentation, and not just those that I would like. Which means as a refusal to comment for yourself (“But this function is urgently rewritten!”), As well as from a very convenient navigation system in the code on cells, which is also for some reason tied to the syntax of comments.
Fortunately, the craftsmen screwed the perl-script that converts MatLab classes to C ++ (only declaration and comments, of course), which allows using “standard” DOxygen with all its charms - internal links, images, LaTeX, etc.
The project (I have nothing to do with it, but I advertise) is available on MatLab Central.
Speed ​​in OOP
During the transition from a regular script / function to a class, I once found a performance drop 40 times. A simple copy-paste with a couple of combings to make it look like a class - and that’s it, the code gets 40 times slower.
Having rummaged, found out that MatLab brakes during access to class variables from methods of the same class. Take the following class, the only method of which is several times slower than a similar function:
classdef Toto < handle properties RatingDepart TauxRecouv Weight FluxScenario end methods function obj = CollectionTaux2() end function corrigerFluxScenario(obj, Survie, CoefRedGov, CoefRedCredit) nbScenario = size(obj.FluxScenario, 3); for i = 1 : nbScenario for j = 1 : numel(obj.Weight) obj.FluxScenario(i, j, :) = repmat(obj.Weight(j), 1, nbScenario) .* ... reshape(obj.FluxScenario(i, j, :), 1, nbScenario) .* ... (CoefRedGov' .* obj.TauxRecouv(j) + ... CoefRedCredit(:, obj.RatingDepart(j))' .* ... Survie(i, :, obj.RatingDepart(j)) .* (1 - obj.TauxRecouv(j))); end end end end end
MatLab considers this a “sensible overhead” when switching to OOP. That is, at each iteration, they check whether the variable has changed by some third-party processes, whether we still have access to it (as if someone could actually write such a morphe-code on MatLab), etc. "Useful" operations.
After a long conversation with several sane people, MatLab seemed to agree to think about a more decent implementation.
In anticipation of a miracle exit, define local variables at the input to the method:
function corrigerFluxScenario(obj, Survie, CoefRedGov, CoefRedCredit) localFluxScenario = obj.FluxScenario; localWeight = obj.Weight; localRatingDepart = obj.RatingDepart; localTauxRecouv = obj.TauxRecouv; nbScenario = size(localFluxScenario, 3); for i = 1 : nbScenario for j = 1 : numel(localWeight) localFluxScenario(i, j, :) = repmat(localWeight(j), 1, nbScenario) .* ... reshape(localFluxScenario(i, j, :), 1, nbScenario) .* ... (CoefRedGov' .* localTauxRecouv(j) + ... CoefRedCredit(:, localRatingDepart(j))' .* ... Survie(i, :, localRatingDepart(j)) .* (1 - localTauxRecouv(j))); end end obj.FluxScenario = localFluxScenario; end
The loss of productivity in comparison with the script becomes negligible.