Matlab subsref and end - matlab

I have a custom matrix class, that I want to be able to index as:
x = myobj(1,2).d(3,4) % myobj(1,2,3,4)
x = myobj(2, 3).d(3, end) % myobj(1,3,1,end)
I want these to work for assignment too.
I've started with:
class MyClass < double
methods
function obj = MyClass(x)
obj = obj#double(x);
end
function obj = subsref(obj, s)
varargout{:} = subsref#double(obj, subsintercept(obj, s));
end
function obj = subsasgn(obj, s, b)
obj = subsasgn#double(obj, subsintercept(obj, s), b);
end
end
end
And then I can mess with the indexing in subsintercept. However, I've hit a problem. With a minimal implementation:
function s = subsintercept(obj, s)
disp('subsintercept');
for i = 1:length(s)
disp(s(i));
end
end
I get this expected behaviour
>> myobj = MyClass(zeros(1,2,3,4))
>> myobj(1,2).d(3,4)
subsintercept
type: '()'
subs: {[1] [2]}
type: '.'
subs: 'd'
type: '()'
subs: {[3] [4]}
<error due to not having finished subsintercept yet>
But this unexpected
>> myobj(1,2).d(3,end)
subsintercept
type: '()'
subs: {[1] [2]}
type: '.'
subs: 'd'
<error due to not having finished subsintercept yet>
Why does adding the end cause me not to receive the 3?
Is this behaviour documented?

Some testing reveals that this:
result = myobj(1,2).d(3,end)
Is translated to:
end_ = str2func('end');
d_temp = subsref(myobj, substruct('()', {1 2}, '.', 'd'));
ei = end_(d_temp, 2, 2);
result = subsref(myobj, substruct('()', {1 2}, '.', 'd', '()', {3, ei}));
i.e., that subsref gets called twice!*
*And surprisingly, not as subsref(d_temp, substruct('()', {3, ei}))the second time

Related

MATLAB dynamically read/write attributes - getattr, setattr?

class A(): pass
a = A()
setattr(a, 'dog', True)
Is there a MATLAB equivalent? If not, what's the most compact alternative? Currently I do
for i=1:length(keys)
k = keys{i};
v = values{i};
if k == "arg1"
obj.arg1 = v;
elseif k == "arg2"
obj.arg2 = v;
...
Likewise for getattr? If needed, assume all keys are already Properties.
Non-Python readers: setattr(obj, 'a', 1) <=> obj.a = 1 and getattr(obj, 'a') <=> obj.a.
obj.arg1 is the same as obj.('arg1').
So in your code snippet is equivalent to:
for i=1:length(keys)
obj.(keys{i}) = values{i};
end

Proper string conversion with implicit data type in MATLAB

I have arbitrary strings that shall be converted to suited data types (i.e. scalar double, double array or string), depending on their content.
str2num() does its job when interpreting the status return value, but the function itself evaluates the content of the string which:
causes str2num('3-7') to be -4 (double), but I want to stick to '3-7' (char array)
is a severe security issue, since it can potentially execute any code
One workaround is to use str2double(), which does not end up with double arrays, but just scalars or strings. Unfortunately, isstrprop() is not really appropriate for this.
Example inputs (and outputs):
'123.4' -> 123.4 (double scalar) [covered by str2double() and str2num()]
abc' -> 'abc' (char array) [inherently covered by str2double() and str2num()]
'123,456' -> [123, 456] (double array) [covered by str2num() only]
'3-7' -> '3-7' (char array) [don't know how to cover]
use str2double and strsplit:
C = {'123.4','abc','123,456','3-7'};
for ii = 1:numel(C)
CC = strsplit(C{ii},',');
res = [str2double(CC)];
if isnan(res)
res = C{ii};
end
disp(res)
disp(class(res))
disp('****************')
end
shows:
123.4000
double
****************
abc
char
****************
123 456
double
****************
3-7
char
****************
Solution (thanks to #user2999345):
function res = str2impl(str, delimiter)
narginchk(1,2);
if isempty(str)
res = [];
return
end
if nargin < 2
delimiter = ',';
end
splits = strsplit(str, delimiter);
res = str2double(splits);
if any(isnan(res)) & ~strcmpi(str, 'NaN') % NaN not specifically requested
res = str;
end
ends up in
C = {'123.4','abc','123,456','3-7','NaN','',[]};
for ii = 1:numel(C)
r{ii,1} = str2impl(C{ii});
end
disp(r)
[ 123.4000]
'abc'
[1×2 double]
'3-7'
[ NaN]
[]
[]

MATLAB object representation in HDF5

Is it possible to retrieve object properties that were saved in MATLAB with -v7.3 in Python?
For example, take this class:
classdef TestClass < handle
properties
Name = 'Nobody';
Value = 42;
end
methods
function this = TestClass(name, value)
if nargin > 0
this.Name = name;
end
if nargin > 1
this.Value = value;
end
end
function doSomething(this)
fprintf('My name is â%sâ and my value is â%dâ.\n', this.Name, this.Value);
end
end
end
and create and save a few objects:
a=TestClass('Theo', 17)
b=TestClass
c=[a,b]
d={a,b}
save('testClassF.mat', 'a', 'b', 'c', 'd')
Using hdf5 in Python, I can see that a is represented as
array([3707764736, 2, 1, 1, 1, 1], dtype=uint32)
and b is
array([3707764736, 2, 1, 1, 1, 2], dtype=uint32).
A little more digging shows that '#refs#/e' yields a's Name, and '#refs#/f' yields its Value. But where does the mapping occur?

Print all elements of a struct

I am just approaching Matlab, I have a function with a struct:
function [out] = struct1()
Account(1).name = 'John';
Account(1).number = 321;
Account(1).type = 'Current';
%.......2 to 9
Account(10).name = 'Denis';
Account(10).number = 123;
Account(10).type = 'Something';
for ii= 1:10
out=fprintf('%s\n','%d\n','%s\n',Account{ii}.name, Account{ii}.number,Account{ii}.type);
end
end
The above code gives me an error: "Cell contents reference from a non-cell array object."
How do I output all elements of such struct to get this output using "fprintf"?
name: 'John'
number: 321
type: 'Current'
...... 2 to 9
name: 'Denis'
number: 123
type: 'Something'
You are indexing the elements of the struct array with { and } which are only used for cell arrays. Simple ( and ) will work just fine.
Also, since you have the line breaks in the formatspec, you should just combine all three strings together.
Example:
formatspec = 'name: %s\nnumber: %d\ntype: %s\n';
for ii= 1:10
out=fprintf(formatspec,Account(ii).name,Account(ii).number,Account(ii).type);
end

Input argument "b" is undefined

i am new in matlab and search everything. I am writing a the function. i could not able to understand why this error is comning :"Input argument "b" is undefined." . shall i intialise b =0 ? whereas it is the parameter coming from input console. my code:
function f = evenorodd( b )
%UNTITLED2 Summary of this function goes here
%zohaib
% Detailed explanation goes here
%f = b;%2;
f = [0 0];
f = rem(b,2);
if f == 0
disp(b+ 'is even')
else
disp(b+ 'is odd')
end
console:
??? Input argument "b" is undefined.
Error in ==> evenorodd at 6
f = rem(b,2);
From what I see, this is what you are trying to do:
function f = evenorodd( b )
f = rem(b,2);
if f == 0
fprintf('%i is even\n', b)
else
fprintf('%i is odd\n', b)
end
=======================
>> evenorodd(2);
2 is even
No need to initialize f as [0,0].
In MATLAB, you cant concatenate a number and string with + operator. Use fprintf.
The above function evenorodd takes one argument (integer) and returns 0 or 1.