How can I write-protect the Matlab language?

2020-08-23 02:20发布

问题:

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,

  1. 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 result s is 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 method
    
  2. Analyze the string s obtained 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!