Is there an alternative to eval for delayed evaluation?
6 次查看(过去 30 天)
显示 更早的评论
I'm trying to make an input argument parsing function for use with functions that have many optional input arguments. I accept these as a struct or label/value pairs (via varargin), and I pass it along with a variable containing validation anonymous functions for each argument (e.g. @isnumeric) and another with default values:
function ParseVarargin(varargin, Validation, Defaults)
This function goes through the user-supplied arguments, validates each and if an argument is not supplied, it uses the default value. This is done with assignin('caller',). Now the issue is that some defaults may be expressions that depend on other input arguments (that were processed before of course). The only way I found to do this correctly is to use evalin('caller', ), but that means I must provide my default expressions to ParseVarargin as strings. I really don't like that though as this hides my code in a string. I would have liked instead to make an anonymous function that only gets evaluated when it is called, thus using the user-supplied values. I'm pretty sure there's no alternative, but thought I'd ask the community.
1 个评论
Stephen23
2017-9-20
编辑:Stephen23
2017-9-24
Your whole concept relies on magically making variables appear and disappear in different workspaces: note that this will inherently be complex, buggier, hard to debug, and much slower than simply passing variables as input/output arguments.
Then on top of that you wish to do some magic with function handles and evaluating them in other workspaces with some "delay"... ouch. It might be worth considering some of the effects that this will have on your code (the points made about eval apply to assignin too, with the added disadvantage that you are messing around in more than one workspace):
You really should read this thread too:
回答(1 个)
John D'Errico
2017-9-20
编辑:John D'Errico
2017-9-20
This is absolutely insane! Why would you use assignin here? Just return the arguments as a struct.
Set up your code to take a struct full of parameters. The values of those parameters initially are set to the default. So each field of this struct contains the default value initially.
Then pass in the struct, plus all property/value pairs to a parsing tool. If it sees a property, it checks the corresponding field of the struct, overwriting the default value held there. If there was no field with that name, just create one.
Then return the same struct to the caller function.
Now all of your parameters are contained in one simple struct. Easy to pass around. Easy to use. Easy to access any parameter you may happen to need.
Absolutely no reason to use assignin. Of course, if you prefer buggy, inefficient code, where any bugs will be pure hell to track down, then continue to use assignin.
3 个评论
Stephen23
2017-9-20
编辑:Stephen23
2017-9-21
" Using assignin in this way is not buggy nor inefficient."
It is inefficient using assignin and magically making variables appear in another workspace. There are plenty of discussion on this topic if your search this forum. For example you will completely ruin any JIT optimization, should you call your functions in a loop. Do some experiments if you do not believe us and the MATLAB documentation.
" It's the same as passing back a struct like you suggest and then manually converting each field to its own variable:"
Actually it is not the same thing at all. When you assign variables properly then the compiler can check the syntax properly, and also provide huge speed increases by identifying features that can be run quickly, e.g. in a loop. When you magically make variables appear and disappear then you loose all of those advantages and a lot of efficiency.
" I'm hoping for an alternative to eval (or evalin in my case)"
Using assignin is just the same, and has all of the same disadvantages. There is no way to magically generate variables from a struct (or something similar) without magically generating variables. And this is always slow, buggy, hard to debug, inefficient, obfuscated code. It is clearly also a waste of time, because if you had picked a simpler method, as John D'Errico suggested, then your code would already be working by now.
"...using Matlab features such as highlighting variables"
Actually you end up with the opposite: where your variables come from is untraceable because they just magically pop into existence. Static code checking cannot check these variables, nor does variable highlighting and a whole lot of other tools work. These are the side effects that do not occur to some beginners, but the main ones can be learned about by reading all of the links here:
Regarding John D'Errico's idea: see my FEX submission num2words for an example of exactly that idea: num2words accepts either a structure or name-value pairs, passes them as a structure to the local function n2wOptions which does all of the checking and setting default values, and then returns a structure.
Why did I not just use the inbuilt inputParser class? Because just like you I also needed to make some (default) variable values dependent on other variables, and because this ended up being a lot faster.
No assignin, no magical throwing things into other workspaces, easy to debug, and quite quick.
Jan
2017-9-21
I agree with John and Steven. The automatic creation by assignin is a shot in your knee. Your automatic parsing of inputs can slow down the code remarkably (factor 2 or 20) and makes it much harder to debug and maintain. Developing super-smart methods for intelligent parsing is not efficient or useful. I like to keep it simply stupid, because this allows for concentrating of the function to be calculated.
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Argument Definitions 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!