Calling a nested function from a dynamic regular expression throws an error

조회 수: 6 (최근 30일)
Calling a local function from a dynamic regular expression works without error:
function test()
regexp('123456','\d(?@subfun($&))')
end
function subfun(s) %#ok<DEFNU>
disp(s)
end
and prints the expected sequence in the command window:
>> test
1
2
3
4
5
6
ans =
1 2 3 4 5 6
But calling an identical nested function:
function test()
function subfun(s) %#ok<DEFNU>
disp(s)
end
regexp('123456','\d(?@subfun($&))');
end
throws this error:
Error using regexp
Attempt to add "matched" to a static workspace.
See MATLAB Programming, Restrictions on Assigning to Variables for details.
Error in test (line 5)
regexp('123456','\d(?@subfun($&))');
Some experimentation showed that "matched" refers to the '&$' matched string token. I hypothesize that the "static workspace" referred to is somehow internal to regexp.
The error message's hyperlink goes to a page "Variables in Nested and Anonymous Functions", which states "If you attempt to dynamically add a variable to the workspace of an anonymous function, a nested function, or a function that contains a nested function, then MATLAB® issues an error of the form Attempt to add variable to a static workspace."
Given that there are no allocations within the nested function, why does this error occur? How is it possible to call a nested function (with dynamic input arguments) from a dynamic regular expression? I am using MATLAB R2012b.

채택된 답변

Guillaume
Guillaume 2016년 3월 2일
편집: Guillaume 2018년 5월 2일
Hum, interesting problem! The documentation of dynamic regular expressions is unfortunately lacking on the workspace used. As far as I can tell it's not a workspace private to regexp but the actual workspace of the function it executes in.
For example,
regexp('', '(?@ y = 5)')
will create y in the local workspace. So the problem is that regexp is trying to create the matched variables in the workspace of the function and as the documentation says, you can't create dynamic variables in functions with nested functions.
Don't know why it try to create that variables. I guess it's an implementation detail, where at some point &$ is replaced by a valid variable name before the expression is evaluated. Note that if you actually name a variable matched, then matlab tries to use matched_0 instead. It kind of makes sense, but yes, completely undocumented. I guess it's worthy of a bug report to mathworks.
You get the same problem in anonymous functions for the same reason:
>>fn = @() regexp('1234', '\d(?@ disp($&); disp(matched))')
>>fn
Error using regexp
Attempt to add "matched_0" to a static workspace.
See Variables in Nested and Anonymous Functions.
It's still the same behaviour in 2015b and newer.
For info, still a problem in R2018a. Also: fixed a typo in my example!
  댓글 수: 3
Guillaume
Guillaume 2016년 3월 4일
FWIW, I reported the issue to mathworks and it's been acknowledged. Whether or not it results in any change (at least in the documentation) is anybody guess. I wouldn't hold my breath...
Walter Roberson
Walter Roberson 2016년 3월 4일
I suspect you would see the same problem if you just had the "end" matching the "function" so you are using a static workspace,
function test()
regexp('123456','\d(?@$&)');
end

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Stephen23
Stephen23 2020년 3월 30일
편집: Stephen23 2020년 3월 31일
The best and most general workaround I have found so far is to call regexp from a local function, with function handles to the nested function/s. Here is a complete working example.
function out = dynesty()
% Demonstrate calling a nested function from a dynamic regular expression.
str = '123456789';
out = {};
rgx = '\d(?@fDyn($&,$`,$''))'; % ($&=current,$`=precede,$'=follow)
localFun(@nestFun,str,rgx);
function nestFun(varargin)
out(end+1,1:nargin) = varargin;
end
end
function varargout = localFun(fDyn,varargin) %#ok<INUSL>
[varargout{1:nargout}] = regexp(varargin{:});
end
Which returns exactly the expected output:
>> dynesty()
ans =
'1' '' '23456789'
'2' '1' '3456789'
'3' '12' '456789'
'4' '123' '56789'
'5' '1234' '6789'
'6' '12345' '789'
'7' '123456' '89'
'8' '1234567' '9'
'9' '12345678' ''

카테고리

Help CenterFile Exchange에서 Get Started with MATLAB에 대해 자세히 알아보기

제품

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by