问题
Matlab allows you to overwrite built in functions without so much as a warning.
For example, I've overwritten the function max() with a variable, but Matlab doesn't alert me to this. An error is only thrown later when the function is called, and doesn't help you see the actual problem:
min = 0;
max = 10;
x = linspace(min,max,20);
y = exp(x);
disp(['the value is: ', num2str(max(y))])
Error message:
Subscript indices must either be real positive integers or logicals.
Is there a way to write-protect all of the Matlab language at startup, or in a settings file to prevent this?
回答1:
I don't know a way to do what you want. But there's a way to check if a specific function has been shadowed, either by a variable or by other function, using which: namely, analyze the output of which(fname, '-all'), where fname is a string containing the function name.
Take the max function as an example: compare (no shadowing)
>> clear all
>> fname = 'max';
>> which(fname, '-all')
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@logical\max) % logical method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@char\max) % char method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@double\max) % double method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@uint8\max) % uint8 method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@uint16\max) % uint16 method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@uint32\max) % uint32 method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@uint64\max) % uint64 method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@int8\max) % int8 method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@int16\max) % int16 method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@int32\max) % int32 method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@int64\max) % int64 method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@single\max) % single method
C:\Program Files\MATLAB\R2010b\toolbox\matlab\timeseries\@timeseries\max.m % timeseries method
C:\Program Files\MATLAB\R2010b\toolbox\distcomp\parallel\@codistributed\max.m % codistributed method
C:\Program Files\MATLAB\R2010b\toolbox\shared\statslib\@ordinal\max.m % ordinal method
with (shadowing)
>> fname = 'max';
>> max = 10;
>> which(fname, '-all')
max is a variable.
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@logical\max) % Shadowed logical method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@char\max) % Shadowed char method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@double\max) % Shadowed double method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@uint8\max) % Shadowed uint8 method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@uint16\max) % Shadowed uint16 method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@uint32\max) % Shadowed uint32 method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@uint64\max) % Shadowed uint64 method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@int8\max) % Shadowed int8 method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@int16\max) % Shadowed int16 method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@int32\max) % Shadowed int32 method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@int64\max) % Shadowed int64 method
built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@single\max) % Shadowed single method
C:\Program Files\MATLAB\R2010b\toolbox\matlab\timeseries\@timeseries\max.m % Shadowed timeseries method
C:\Program Files\MATLAB\R2010b\toolbox\distcomp\parallel\@codistributed\max.m % Shadowed codistributed method
C:\Program Files\MATLAB\R2010b\toolbox\shared\statslib\@ordinal\max.m % Shadowed ordinal method
In the second case, which(fname, '-all') tells you that max is a variable that is shadowing several methods.
So, to test if shadowing is taking place,
Assign the output of
which(fname, '-all')to a variable.In principle this could be done as
s = which(fname, '-all');. Unfortunately, however, this produces a different output; in particular, the% ...part in the lines above (which tells if there is shadowing) is removed:>> fname = 'max'; >> s = which(fname, '-all') s = 'variable' 'built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@logical\max)' 'built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@char\max)' 'built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@double\max)' 'built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@uint8\max)' 'built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@uint16\max)' 'built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@uint32\max)' 'built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@uint64\max)' 'built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@int8\max)' 'built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@int16\max)' 'built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@int32\max)' 'built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@int64\max)' 'built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@single\max)' 'C:\Program Files\MATLAB\R2010b\toolbox\matlab\timeseries\@timeseries\max.m' 'C:\Program Files\MATLAB\R2010b\toolbox\distcomp\parallel\@codistributed\max.m' 'C:\Program Files\MATLAB\R2010b\toolbox\shared\statslib\@ordinal\max.m'So we need to resort to evalc to get the full output:
s = evalc('which(fname, ''-all'')');. The resultsis a long string containing all lines (including the% ...parts) separated by line feed characters:>> fname = 'max'; >> s = evalc('which(fname, ''-all'')') s = max is a variable. built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@logical\max) % Shadowed logical method built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@char\max) % Shadowed char method built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@double\max) % Shadowed double method built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@uint8\max) % Shadowed uint8 method built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@uint16\max) % Shadowed uint16 method built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@uint32\max) % Shadowed uint32 method built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@uint64\max) % Shadowed uint64 method built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@int8\max) % Shadowed int8 method built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@int16\max) % Shadowed int16 method built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@int32\max) % Shadowed int32 method built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@int64\max) % Shadowed int64 method built-in (C:\Program Files\MATLAB\R2010b\toolbox\matlab\datafun\@single\max) % Shadowed single method C:\Program Files\MATLAB\R2010b\toolbox\matlab\timeseries\@timeseries\max.m % Shadowed timeseries method C:\Program Files\MATLAB\R2010b\toolbox\distcomp\parallel\@codistributed\max.m % Shadowed codistributed method C:\Program Files\MATLAB\R2010b\toolbox\shared\statslib\@ordinal\max.m % Shadowed ordinal methodAnalyze the string
sobtained in step 1 to see if it contains'% Shadowed'. This is easily done with strfind: namely,strfind(s, '% Shadowed')will be non-empty if there is shadowing.
In conclusion:
Putting it all together,
isShadowed = ~isempty(strfind(evalc('which(fname, ''-all'')'), '% Shadowed'));
returns true if the function with name contained in variable fname is shadowed, and false otherwise.
Example with a variable:
>> clear all
>> fname = 'max';
>> max = 10;
>> isShadowed = ~isempty(strfind(evalc('which(fname, ''-all'')'), '% Shadowed'))
isShadowed =
1
>> clear max
>> isShadowed = ~isempty(strfind(evalc('which(fname, ''-all'')'), '% Shadowed'))
isShadowed =
0
Example with a named function:
Create a function in file std.m and place it in your path. This will shadow Matlab's std function.
>> fname = 'std';
>> isShadowed = ~isempty(strfind(evalc('which(fname, ''-all'')'), '% Shadowed'))
isShadowed =
1
Now delete the function file (or remove its folder from the path):
>> fname = 'std';
>> isShadowed = ~isempty(strfind(evalc('which(fname, ''-all'')'), '% Shadowed'))
isShadowed =
0
Example with an anonymous function:
>> std = @(x) x+1;
>> fname = 'std';
>> isShadowed = ~isempty(strfind(evalc('which(fname, ''-all'')'), '% Shadowed'))
isShadowed =
1
>> clear std
>> isShadowed = ~isempty(strfind(evalc('which(fname, ''-all'')'), '% Shadowed'))
isShadowed =
0
回答2:
As of 9/2015, I have not found a way to easily write protect native matlab functions/language, as a setting/flag/etc at startup.
If you are concerned about a particular function, there are various ways to see if they are shadowed, including Luis Mendo's answer: which('name_of_function', '-all').
If a method is found in the future, I will gladly accept that answer!
来源:https://stackoverflow.com/questions/32287856/how-can-i-write-protect-the-matlab-language