下面的示例在Python中可能有助于说明“前哨值”的含义:
SENTINEL = object()
def foo(opt=SENTINEL):
if opt is SENTINEL:
opt = make_me_fresh_default_opt_please()
# etc
在上面的代码片段中,变量SENTINEL
被初始化为一个全新的“ nonce”对象,该对象实际上没有任何内容,并且在定义该文件的文件之外的其他任何地方都没有可能的含义。foo
是一个带有可选参数的函数opt
。常量SENTINEL
是由使用foo
的一两件事,只有一两件事,以测试被称为不带参数的条件。这是通过完成的if opt is SENTINEL
。
要了解为什么要这样便宜的“ nonce”常量,例如SENTINEL
,将上面的代码片段与使用标准Python值(None
)来测试无参数条件的代码进行对比:
def foo2(opt=None):
if opt is None:
opt = make_me_fresh_default_opt_please()
# etc
此函数foo2
无法区分以下1的两个调用:
foo2()
foo2(None)
因此,总而言之,这里的“前哨”是指代码其余部分未知的常数,其唯一目的是用作某种条件下布尔测试的基础。
在MATLAB中是否有类似的简单方法来生成这样的定点常量?
编辑:我想强调一点,我的问题严格来说是关于如何创建一个哨兵,而未提及使用此类哨兵的目的的问题。我提供了一个具体而合理的示例,说明为什么有人想要这样一个定点常量,部分目的是确保该帖子的读者知道我所说的“哨兵”一词的含义。在此示例中,前哨碰巧只是用于测试“没有传递参数”条件,但是可能有无数其他可能需要使用前哨值进行测试的条件。因此,这个问题着重不是关于测试“无参数传递”条件,而是关于生成哨兵常量的问题。
EDIT2:基于Notlikethat's和Bas Swinckels的答案:
function y = foo(varargin)
p = inputParser;
p.addParameter('Opt', @DEFAULT);
p.parse(varargin{:});
opt = p.Results.Opt;
if DEFAULT(opt)
opt = rand();
end
y = opt;
% etc
end
function its_me = DEFAULT(opt)
its_me = isequal(opt, @DEFAULT);
end
%{
>> foo('Opt', 3)
ans =
3
>> foo()
ans =
0.9134
>> foo
ans =
0.6324
%}
好吧,那可能太可爱了。如果代码更接近Notlikethat的原始建议(请注意make_sentinel
下面是一个独立的函数),则该代码将更加简单明了:
% foo.m
function y = foo(varargin)
DEFAULT = make_sentinel();
p = inputParser;
p.addParameter('Opt', DEFAULT);
p.parse(varargin{:});
opt = p.Results.Opt;
if isequal(opt, DEFAULT)
opt = rand();
end
y = opt;
% etc
end
% make_sentinel.m
function sentinel = make_sentinel()
sentinel = ...
@() 'qqqxyz_lalala_the_user_would_be_a_moron_to_use_this_function';
% or, more conventionally,
% sentinel = @() 0;
end
>> foo('Opt', 6)
ans =
6
>> foo()
ans =
0.9575
>> foo
ans =
0.9649
并证明由make_sentinel
所产生的前哨确实是独特的(并且不付诸报酬):
>> foo('Opt', make_sentinel())
ans =
@()'qqqxyz_lalala_the_user_would_be_a_moron_to_use_this_function'
1当然,foo
前面定义的不能区分foo()
和foo(SENTINEL)
,但是,AFAIC,像后者那样的调用属于“错误编程”类别(因为它要求调用代码“摆脱它的作用”以颠覆被调用代码的)。意图),而且我也不必担心这种变态。相反,foo2(None)
前面显示的示例说明了在例行编程过程中容易发生的情况,尤其是当其实际源代码类似于foo(some_variable)
,并且some_variable
意外地保留了标准Python值时None
。
一种解决方案几乎是直接等效的:
function y = foo(opt)
%default argument
if nargin<1
opt = @SENTINEL;
end
%actual check
if isequal(opt, @SENTINEL)
opt = make_me_fresh_default_opt_please()
end
% etc
end
function SENTINEL % private function in the same file
end
诚然,它并不是那么简单,但是与其他任何东西一样,它也要取决于Matlab语法。
您也可能会作弊,并以完全相同的方法为基础:
SENTINEL = java.lang.Object;
% etc...
牺牲有保证的唯一性以更加简化,这tempname
是一种生成不太可能与有效数据发生冲突的字符串的简便方法(尤其是如果有效数据不是字符串...的话)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句