相当于不需要输出参数的`evalin`(内部)
equivalent of `evalin` that doesn't require an output argument (internally)
背景——我正在阅读有关访问阴影函数的内容,并开始使用 builtin
。我写了一个小函数:
function klear(x)
% go to parent environment...
evalin('base', builtin('clear','x')) ;
end
这会引发错误:
Error using clear
Too many output arguments.
我认为发生这种情况是因为 evalin
需要输入的任何内容的输出,但是 clear
是没有 return 值的函数之一。
所以有两个问题:我是否正确解释了这一点,如果是这样,是否有一个替代函数允许我在父环境中执行一个函数(不需要输出)?
注意:我完全了解反对尝试访问影子函数的论点(或者更确切地说,避免以重载基函数的方式命名函数等)。这主要是一个帮助我了解在 MATLAB 中可以做什么和不能做什么的问题。
注2
我最初的目标是编写一个需要输入参数的重载函数,以避免 clear
的恶意软件行为,它默认删除所有内容。在 Q&D 伪代码中,
function clear(x)
if ~exist('x','var') return
execute_in_base_env(builtin(clear(x)))
end
您的代码中发生了什么:
evalin('base', builtin('clear','x'));
是在当前上下文中对builtin
求值,因为作为evalin
的参数,所以期望产生输出。完全一样:
ans = builtin('clear','x');
evalin('base',ans);
您看到的错误消息出现在这两行代码的第一行中,而不是第二行中。这不是因为 evalin
,它确实支持不产生输出参数的调用语句。
evalin
需要一个字符串来计算。您需要构建此字符串:
str = 'builtin(''clear'',''x'')';
evalin('base',ans);
(在 MATLAB 中,引号字符通过加倍转义。)
你的函数看起来像这样:
function clear(var)
try
evalin('base',['builtin(''clear'',''',var,''')'])
catch
% ignore error
end
end
(以这种方式将一个字符串插入另一个字符串相当尴尬,这是我不喜欢 eval
和朋友的众多原因之一)。
在这种情况下使用 evalin('caller',...)
可能更好,这样当您从函数中调用新的 clear
时,它会删除函数工作区中的某些内容,而不是基本工作区中的内容。我认为 'base'
应该只在 GUI 中使用,该 GUI 预期控制用户工作区中的变量,而不是从可以在任何地方调用并且预期(在这种情况下按其名称)执行本地操作的函数.
这可能真正有用是有原因的,但一般来说,您应该尽量避免使用 clear
,就像避免使用 eval
和朋友一样。 clear
减慢程序执行速度。将一个空数组分配给变量以从内存中删除其内容(如 所建议的那样)(在用户和 MATLAB JIT 上)要容易得多。如果你使用 function
更多:写函数,而不是脚本!
您的 clear
覆盖有几个问题:
- 它总是
clear
在基础工作区中,无论从哪里调用它。
- 它不支持多输入,这是 clear 的常见用例。
相反,我会让它检查它是否是从基础工作区调用的,以及特殊情况,以便您检查它是否正在清除所有内容。如果某个函数调用 plain clear
来清除它的所有变量,那是不好的做法,但它仍然是该函数逻辑的工作方式,你不想破坏它。否则它可能会出错,或者更糟,return 不正确的结果。
所以,像这样:
function clear(varargin)
stk = dbstack;
if numel(stk) == 1 && (nargin == 0 || ismember('all', varargin))
fprintf('clear: balking at clearing all vars in base workspace. Nothing cleared.\n');
return;
end
% Check for quoting problems
for i = 1:numel(varargin)
if any(varargin{i} == '''')
error('You have a quote in one of your args. That''s not valid.');
end
end
% Construct a clear() call that works with evalin()
arg_strs = strcat('''', varargin, '''');
arg_strs = [{'''clear'''} arg_strs];
expr = ['builtin(' strjoin(arg_strs, ', '), ')'];
% Do it
evalin('caller', expr);
end
我希望不言而喻,这是一个我在实践中不推荐的残暴黑客。 :)
背景——我正在阅读有关访问阴影函数的内容,并开始使用 builtin
。我写了一个小函数:
function klear(x)
% go to parent environment...
evalin('base', builtin('clear','x')) ;
end
这会引发错误:
Error using clear
Too many output arguments.
我认为发生这种情况是因为 evalin
需要输入的任何内容的输出,但是 clear
是没有 return 值的函数之一。
所以有两个问题:我是否正确解释了这一点,如果是这样,是否有一个替代函数允许我在父环境中执行一个函数(不需要输出)?
注意:我完全了解反对尝试访问影子函数的论点(或者更确切地说,避免以重载基函数的方式命名函数等)。这主要是一个帮助我了解在 MATLAB 中可以做什么和不能做什么的问题。
注2
我最初的目标是编写一个需要输入参数的重载函数,以避免 clear
的恶意软件行为,它默认删除所有内容。在 Q&D 伪代码中,
function clear(x)
if ~exist('x','var') return
execute_in_base_env(builtin(clear(x)))
end
您的代码中发生了什么:
evalin('base', builtin('clear','x'));
是在当前上下文中对builtin
求值,因为作为evalin
的参数,所以期望产生输出。完全一样:
ans = builtin('clear','x');
evalin('base',ans);
您看到的错误消息出现在这两行代码的第一行中,而不是第二行中。这不是因为 evalin
,它确实支持不产生输出参数的调用语句。
evalin
需要一个字符串来计算。您需要构建此字符串:
str = 'builtin(''clear'',''x'')';
evalin('base',ans);
(在 MATLAB 中,引号字符通过加倍转义。)
你的函数看起来像这样:
function clear(var)
try
evalin('base',['builtin(''clear'',''',var,''')'])
catch
% ignore error
end
end
(以这种方式将一个字符串插入另一个字符串相当尴尬,这是我不喜欢 eval
和朋友的众多原因之一)。
在这种情况下使用 evalin('caller',...)
可能更好,这样当您从函数中调用新的 clear
时,它会删除函数工作区中的某些内容,而不是基本工作区中的内容。我认为 'base'
应该只在 GUI 中使用,该 GUI 预期控制用户工作区中的变量,而不是从可以在任何地方调用并且预期(在这种情况下按其名称)执行本地操作的函数.
这可能真正有用是有原因的,但一般来说,您应该尽量避免使用 clear
,就像避免使用 eval
和朋友一样。 clear
减慢程序执行速度。将一个空数组分配给变量以从内存中删除其内容(如 function
更多:写函数,而不是脚本!
您的 clear
覆盖有几个问题:
- 它总是
clear
在基础工作区中,无论从哪里调用它。 - 它不支持多输入,这是 clear 的常见用例。
相反,我会让它检查它是否是从基础工作区调用的,以及特殊情况,以便您检查它是否正在清除所有内容。如果某个函数调用 plain clear
来清除它的所有变量,那是不好的做法,但它仍然是该函数逻辑的工作方式,你不想破坏它。否则它可能会出错,或者更糟,return 不正确的结果。
所以,像这样:
function clear(varargin)
stk = dbstack;
if numel(stk) == 1 && (nargin == 0 || ismember('all', varargin))
fprintf('clear: balking at clearing all vars in base workspace. Nothing cleared.\n');
return;
end
% Check for quoting problems
for i = 1:numel(varargin)
if any(varargin{i} == '''')
error('You have a quote in one of your args. That''s not valid.');
end
end
% Construct a clear() call that works with evalin()
arg_strs = strcat('''', varargin, '''');
arg_strs = [{'''clear'''} arg_strs];
expr = ['builtin(' strjoin(arg_strs, ', '), ')'];
% Do it
evalin('caller', expr);
end
我希望不言而喻,这是一个我在实践中不推荐的残暴黑客。 :)