“未定义"重写但未重新定义已定义函数的错误 [英] "Undefined" error for rewriting but not redefining an already defined function

查看:85
本文介绍了“未定义"重写但未重新定义已定义函数的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这有效(画出空"图):

This works (plots an "empty" figure):

function testme
plot(1)

这有效(返回1):

function testme
plot = @(x)x;
plot(1)

这不是(错误:未定义的函数或变量'图'."):

This does not (Error: "Undefined function or variable 'plot'."):

function testme
if 0
    plot = @(x)x;
end
plot(1)

这是怎么回事?为什么重写但未重新定义已定义的函数会导致该函数未定义?

What's going on here? Why does rewriting but not redefining an already defined function render the function undefined?

注1:这不是特定于内置函数的;以下代码返回相同的错误:

Note 1: this is not specific for builtin functions; the following code returns the same error:

function testme
if 0
    myfun = @(x)x;
end
myfun(1)

function x=myfun(x)
x=x*2;

注2:错误发生在函数环境中,而不是脚本中;以下代码不会返回错误(并绘制与第一个示例相同的空图):

Note 2: the error occurs in a function environment, not in a script; the following code does not return an error (and plots the same empty figure as in the first example):

if 0
    plot = @(x)x;
end
plot(1)

更新:对于感兴趣的读者,这里是一些背景信息关于我原来的问题.上面的例子只是最低限度的工作示例来说明主要问题(如果声明).在实践中,我试图使一个函数可用于没有某些库/工具箱功能的同事通过将这些功能覆盖为简化的自定义功能而可用如果它们不存在,请快速解决.特别是有关浸润(和浸蚀).该功能看起来像以下:

Update: For the interested reader, here is some background information on my original problem. The above examples are just minimum working samples to illustrate the main issue (which indeed feature dead end if statements). In practice, I was trying to make a function useable for colleagues who did not have certain library/toolbox functions available, by overwriting those functions for simplified custom ones if they did not exist, as a quick fix. In particular, it concerned imdilate (and imerode). The function looked something like the following:

function [myoutputs] = myfunction(myinputs)

% if the images toolbox is not available, use the following simplified
% replacement function
if ~exist('imdilate','file')
    imdilate = @(IM,SE)vecdilate(IM,SE);
end

%% The original function goes here, which uses a lot of imdilate(IM,SE).

%% local functions
function M = vecdilate(IM,SE)
% simplified version of imdilate (can only process 1-D vertical arrays)

nSE = size(SE);
nIM = size(IM);
SE = logical(SE); % make logical if it isn't yet

% copy and shift xth column x down. new border entries are 0:
M = repmat([IM;zeros(nSE)],nSE);
M = M(1:end-nSE(1));
M = reshape(M,[size(M,1)/nSE(1) nSE(1)]);

% shrink back to column by taking max of every row:
M = max(M(:,SE),[],2);
M = M(ceil(nSE(1)/2)-1+(1:nIM(1))); % clip to obtain correct size

您可能会看到替换功能涵盖了一些的功能,但不是全部,可能不像高效的.目的只是使用功能A(如果有),并且如果不是,则使用B函数.但是令我惊讶的是,前一种情况返回了一个错误,最终导致了这个问题.为了您的利益,我通过重命名该函数来解决了实际问题.原始代码,并使用if/else语句:

You might see that the replacement function covers some functionality of imdilate, but not all, and it might not be as efficient. The purpose simply was to use function A if it was available, and function B if it was not. To my surprise however, the former case returned an error, which eventually resulted in this question. For your interest, I solved the practical problem by renaming the function in the original code, and by using an if/else statement:

function [myoutputs] = myfunction(myinputs)

% if the images toolbox is not available, use the following simplified
% replacement function
if ~exist('imdilate','file')
    mydilate = @(IM,SE)vecdilate(IM,SE);
else
    mydilate = @(IM,SE)imdilate(IM,SE);
end

%% The original function goes here, which uses a lot of mydilate(IM,SE).

%% local functions
function M = vecdilate(IM,SE)
etc. etc. etc.

推荐答案

及时编译(JIT)并不意味着没有编译,并且每一行都被单独解释,因此您仍然可以弄乱代码;)

Just-in-time-compilation (JIT) does not mean that there is no compilation and that every line is interpreted separately, so you can still mess with the code;)

如果您使用未定义的函数(甚至不希望代码运行),也会出现错误,例如

The error would also appear if you use a not-defined function, where you woun't even expect the code to run, like

function [] = test()
if false
    a = @(x)x;
end
a(1)
end

脚本是存储的命令行条目,即编译器别无选择,只能分开处理每一行(您可能希望将其视为键盘宏).相反,函数是封装的代码段.编译器(通常)不会期望任何未知的东西+它认为此封装的代码段可能会被重用.因此,它可以确保事先做好一次适当的工作来编译所有代码(如果编译将一直进行,则称为提前编译).

Scripts are stored command line entries, i.e. the compiler has no choice but to handle every line separately (you may want to think of it as a keyboard macro). Functions in contrast are encapsulated pieces of code. The compiler (in general) does not expect anything unknown + it thinks that this encapsulated piece of code might be reused. Therefore, it makes sure to do a proper job compile all code once beforehand (if the compile would do this all the time, it is called ahead-of-time compilation).

当您清除以下两个变量之间的变量时,这一点尤其明显:

This becomes in particular obvious when your clear the variables in between:

function [] = test()
if false
    plot = @(x)x;
else
    clear all % clear vs clear all
end
plot(1)
end

(请注意, clear 会清除所有变量,但 clear all 也会清除执行代码(请参见

(Note that clear clears all variables but clear all would also clear excising code (see MATLAB Execution Engine))

看看这个有趣的

Have a look at this interesting blog post from Loren

MATLAB通过即时或及时地编译MATLAB代码,提供了两全其美的方法.无论是在类,函数,脚本中还是在命令行中,都可以编译MATLAB代码.用户没有明确的编译步骤可以启动,并且MATLAB代码可以一次仅一行地在块中执行.MATLAB JIT编译器会生成本地机器级别的代码,该代码针对正在执行的MATLAB代码和特定的硬件平台进行了优化.

MATLAB provides the best of both worlds by compiling MATLAB code on-the-fly, or just-in-time. MATLAB code is compiled whether it be in classes, functions, scripts, or simply at the command line. There is no explicit compile step for the user to initiate and MATLAB code can be executed in blocks as small as one line at a time. The MATLAB JIT compiler generates native machine level code that is optimized for the MATLAB code being executed and for the specific hardware platform.

无论如何,您不应在代码中写死胡同或覆盖(本机)函数.最好使用函数句柄来解决此问题,但请确保在所有情况下都对其进行定义

Anyway, you should not write dead ends in your code or overwrite (native) functions. It is good to use function handles to overcome this problem, but make sure that you define it for all cases

function [] = test()
if false % dead end definition
    fnc = @(x)x;
else
    fnc = @plot;
end
fnc(1)
end

这篇关于“未定义"重写但未重新定义已定义函数的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆