I'm trying to write a function that puts the class, length, and value of each of the things in a cell array into a struct, but I keep getting an error with the switch statements
function [ out, common ] = IDcell( cA )
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
cl={};
val={};
len={};
for x=1:length(cA)
switch cA(x)
case isnum
cl(x)='double';
case ischar
cl(x)='char';
case islogical
cl(x)='logical';
case iscell
cl(x)= 'cell';
end
val=[val cA{x}];
len=[len size(value(x))];
end
out=struct('value', val, 'class', cl, 'length', len);
end
[out]=IDcell(cA)
SWITCH expression must be a scalar or string constant.
Error in IDcell (line 8)
switch cA(x)
isnum is not a Matlab function. isnumeric may be what you were thinking of, but it isn't what you typed. Which means your code is seeing case isnum and it has no idea what the heck isnum is, so it is telling you whatever it is, if you want to use it there you need to make it something that evaluates to a number (what it means by scalar) or to a piece of text (what it means by string constant).
Further, ischar is a matlab function, but you are not using it the right way. You must use it as ischar(cA(x)) for example, will then evaluate to true if cA(x) is a string or snippet of text, will evaluate to false if cA(x) is anything else.
While it would be lovely if switch worked this way, it doesn't. You can't put a thing in the switch part, and then just list functions that need to be evaluated on that thing in the switch part.
The kind of thing you can do is this:
switch class(x)
case 'double'
fprintf('Double\n');
case 'logical'
fprintf('Logical\n');
end
Here I have used the class function the way it needs to be used, with an argument in it. And I then switch my cases based on the output of that function, class outputs a string.
Related
function check(str,arg;type=DataType,max=nothing,min=nothing,description="")
#argcheck typeof(arg)==type
#argcheck arg>min
#argcheck arg<max
#argcheck typeof(description)==String
return arg
end
function constr(name,arg,field)
return :(function $name($arg,$field)
new(check($name,$arg,$field))
end)
end
macro creatStruct(name,arg)
code = Base.remove_linenums!(quote
struct $name
end
end)
print(arg)
append!(code.args[1].args[3].args,[constr(name,arg.args[1].args[1],arg.args[1].args[2])])
code
end
macro myStruct(name,arg)
#creatStruct name arg
end
#myStruct test12 (
(arg1,(max=10))
)
In my code above I'm trying to build a macro that Creates a struct, and within the struct, you can define an argument with boundaries (max, min) and description, etc.
I'm getting this error:
syntax: "#141#max = 10" is not a valid function argument name
and every time I'm trying to solve it, I get another error like:
LoadError: syntax: "struct" expression not at top level
So, I think my Code/Approach is not that cohesive. Anybody can suggest tips and/or another Approche.
You're attempting to make an argument name max with a default value of 10. The error is about max=10 not being a valid name (Symbol), while max is. The bigger issue is you're trying to put this in the struct expression instead of a constructor method:
struct Foo
bar::Float64
max::Int64
end
# constructor
Foo(bar, max=10) = Foo(bar, max)
So you have to figure out how to make an expression for a method with default values, too.
Your second error means that structs must be defined in the top-level. "Top-level" is like global scope but stricter in some contexts; I don't know the exact difference, but it definitely excludes local scopes (macro, function, etc). It looks like the issue is the expression returned by creatStruct being evaluated as code in myStruct, but the LoadError I'm getting has a different message. In any case, the error goes away if I make sure things stay as expressions:
macro myStruct(name,arg)
:(#creatStruct $name $arg)
end
I have a Matlab function which returns an array with probability alpha and nothing (i.e. an empty array) with probability 1-alpha:
function [binary_array_e1 , binary_array_e2 ] = croiser(binary_array_p1,binary_array_p2,alpha )
binary_array_e1=[];
binary_array_e2=[];
compt=1;
if (rand <= alpha)
% some stuff that will put sth in binary_array_e1 and binary_array_e2
end
My question is: how should I manage the fact that the function could return empty arrays at the call of the function? Is something like:
[binary_array_e1 , binary_array_e2]=croiser(binary_array_p1,binary_array_p2,alpha);
be sufficient?
If you want to return an empty variable from a function call, you are totally allowed to do it and you are on the right path. Initialize your variables as empty at the beginning of the function...
function [binary_array_e1 , binary_array_e2 ] = croiser(binary_array_p1,binary_array_p2,alpha )
binary_array_e1=[];
binary_array_e2=[];
% ...
end
and then just check the outcome whenever you need to do it, for example:
[binary_array_e1,binary_array_e2] = croiser(binary_array_p1,binary_array_p2,alpha);
if (isempty(binary_array_e1))
% do something 1...
elseif (isempty(binary_array_e2))
% do something 2...
else
% do something 3...
end
Of course, in order to check the outcome, both variables must be returned and evaluated. But if you are returning two empty arrays in one case and two non-empty arrays in the other case, you could also check only one array:
if (isempty(binary_array_e1))
% do something...
else
% do something else...
end
Anyway... there are so many ways to obtain the same result. For example, you could also return a 'logical' variable that tells you immediately if your arrays have been filled with something or not, or you could return a 'struct' filled with your data in order to make everything more compact (I can elaborate on these solutions if you want). It's up to you but I see nothing wrong in your approach!
Yes, that should be fine. You can later check if the output is an empty array using the function isempty
Is it possible to define and use a function like this?
generate_mode_matrix_and_mode_frequency_and_Hw(generate_Hw: true);
function generate_mode_matrix_and_mode_frequency_and_Hw(generate_Hw)
if generate_Hw ## NOTICE: this argument is optional
.....
end
end
What I want is to specify the name of the argument when passing it. In ruby it's called hash.
The point of doing this is that, when using it, the coder know what the true mean without comment. This is
Compare this 2:
generate_mode_matrix_and_mode_frequency_and_Hw(generate_Hw: true)
generate_mode_matrix_and_mode_frequency_and_Hw(true)
Clearly, the first one is more clear.
Notice: generate_Hw is an optional argument. So without specifying it, the function would also work.
You can use something similar to Property\Value pairs:
function Foo(varargin)
for n=1:2:nargin
switch varargin{n}
case 'var1'
var1 = varargin{n+1};
case 'var2'
var2 = varargin{n+1};
end
end
In this example if you use Foo('var1',value) then var1 would get the desired value. If you don't specify the pair 'var1',value in the input, then var1 will not exist in Foo.
In most OO languages, where variables may point to objects, they may also have a null value, which is highly convenient.
In Matlab, I have a function which parses a command, and then returns a cell array, or false (which is equal to zero — which is another common pattern) if it fails:
function re = parse(s)
...
if (invalid)
re = false;
return;
end
end
The problem is that when I check the result, it gives an error:
re = parse(s);
if (false == re)
Undefined function 'eq' for input arguments of type 'cell'.
I've written a function to check it without an error: strcmp('logical', class(re)) && false == re, but that seems to be really slow for use in hot areas of the code, and also inconvenient if I have to add this function to every M file I'm writing.
Using NaN is even worse, because besides throwing that error, it also isn't equal to itself.
What's a better alternative for use with this pattern?
You can use the isequal function to compare any two items without causing that error. For example:
if isequal (re, false)
%code here
end
A good alternative is to use the empty array: [] and isempty(re) to check. This doesn't throw the error.
Reference: http://www.mathworks.com.au/matlabcentral/newsreader/view_thread/148764
If you can change the function parse one solution would be to return two output arguments [re status] = parse(s), where status would be logical variable. Set it to true in case of success, and to false otherwise.
I would use the empty cell array {} if it is not a valid result otherwise. Using empty matrices is MATLAB standard (see Evgeni Sergeev's answer), but using an empty cell array instead of an empty numeric array ensures that you'll always end up with the same type of result.
If, on the other hand, the empty cell array {} is a valid result of your function, then I'd use an exception to signalize a problem:
if invalid
error('Parse:InvalidArgumentError', 'The input is invalid.');
end
Make sure to use an appropriate error ID (first argument to error) so that you can catch exactly that exception when you call the function:
try:
result = parse(something);
catch ME
if strcmp(ME.identifier, 'Parse:InvalidArgumentError')
fprintf('Ooops\n');
else
% Some other error
ME.rethrow();
end
end
I think the problem is that matlab functions don't return pointers but copies of values.
IMHO the best best approach would be to define your own "pointer" class. Inside you can define an "isNull()" command or even override comparison to produce the behavior you desire.
I would like to know if it's possible to use a colon ":" as argument of a function.
Something like that:
function y=func(x)
if x is a colon
do this
else
do that
end
Also is it possible to pass the key work end as argument of a function, and also 1:end, 3:end-5, etc...
I doubt it's possible, but I would like to be sure.
Also, I get a weird error when I pass "1:end" as argument of a function, it produces no error, but inside the function, no argument is assigned (not even the other arguments). Do someone know what happens?
You can override both for your own classes:
classdef MyClass
properties(Access=public)
data
end
methods
function out = end(A,k,n)
disp(A);
disp(k);
disp(n);
out = [];
end
function B = subsref(A,S)
disp(S);
B = [];
end
end
end
As for functions, I never heard of such a functionality.
No, it's not possible to pass a colon as an argument (it doesn't make any sense).