Clear Filters
Clear Filters

Dynamic properties auto completion in argument validation

34 views (last 30 days)
I love argument validation, and especially the option to use the ? operator to automatically list all class properties.
However, I'm experimenting with dynamic properties which (obviously) can't be auto completed, compare this class:
classdef testclass < dynamicprops
properties
prop1 string = "prop1"
end
methods
function obj = testclass()
obj.addprop("dynamicProp1");
end
function autoComplete(obj, props)
arguments
obj
props.?testclass
end
disp("this auto completes only 'prop1'")
end
end
end
Calling the class via
t = testclass
t.autoComplete(<tab>)
shows "prop1" as expected.
Is there any way to add dynamic properties or any other non-class-constant options? Can the props. in the argument validation section be filled with strings at runtime, like props.createStruct(), where createStruct() is some arbitrary function?
I think the key issue is that this happens at runtime, not at "compile"/definition time, is that right?
Are there workarounds like
function autoComplete(obj, props)
arguments(Repeating)
props {mustBeMember(props, [???])}
end
end
? The argument in mustBeMember seems have to be also known at definition time.
Any ideas?
Thanks, Jan

Answers (1)

Steven Lord
Steven Lord on 6 Mar 2024
The testclass class doesn't have a property named dynamicProp1, and the documentation for the syntax you're using states "A useful function syntax in MATLAB uses the public properties of a class for the names of name-value arguments." (See the Name-Value Arguments from Class Properties section.)
The specific instance of the testclass class that you're passing into autoComplete has a property named dynamicProp1. But the metaclass syntax (the ?nameOfClass syntax) doesn't operate on instances (actually the metaclass function can accept an instance, but it returns the meta.class object for the class not a meta.instance object for that specific instance. There is no "meta.instance" equivalent.)
You haven't shown how you want your autoComplete method to use the data from props, but you could define your own local validation method or function (see the Define Validation Functions section) to allow autoComplete to accept any property name of the instance as the props input (though it won't play with automatic completion if you do.) A very quick version of that could be:
classdef testclass < dynamicprops
properties
prop1 string = "prop1"
end
methods
function obj = testclass()
obj.addprop("dynamicProp1");
end
function autoComplete(obj, props)
arguments
obj
end
arguments(Repeating)
props {mustBePropertyOfClassOrNumber(obj, props)}
end
% Add additional checking (even number of entries in props,
% coming in name-value pairs) here
%
% That could be as simple as setting the properties:
for whichArg = 1:2:numel(props)
fprintf("Setting property %s.\n", props{whichArg})
obj.(props{whichArg}) = props{whichArg+1};
end
disp("this auto completes only 'prop1'")
end
end
methods(Access=private)
function mustBePropertyOfClassOrNumber(obj, props)
if isnumeric(props) % value
return
else % name
assert(isprop(obj, props), ...
"Property " + props + " is not a property of the object.")
end
end
end
end
  1 Comment
Jan Kappen
Jan Kappen on 6 Mar 2024
Thank you very much, I think your answer basically confirms my thoughts.
What I would like to accomplish is the auto-completion for interactive usage. The feature is pure gold.
Right now, I do have an class local validation function, very similar to what you proposed, but even if it's just a wrapper for mustBeMember(prop,<dynamic props>), the auto completion does not work. When mustBeMember(prop,<static string literals>) is used in the argument validation block, auto completion works.
My real method looks like this (it's obviously part of a property caching class):
function updateCachedProperty(obj, propertyNames, values)
arguments
obj
end
arguments (Repeating)
propertyNames (1,1) string {mustBeCachedProperty(obj, propertyNames)}
values
end
for k = 1:length(propertyNames)
obj.(propertyNames{k}) = values{k};
end
obj.CacheValidMap(propertyNames) = true;
end
It works fine and is as comfortable as it can get imo, but auto completion of properties that are already cached would be awesome.
Am I right that there's currently no way to add any non constant expressions to the mustBeMember(prop,... validation function?
Thanks.

Sign in to comment.

Categories

Find more on Argument Definitions in Help Center and File Exchange

Products


Release

R2023b

Community Treasure Hunt

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

Start Hunting!