How can I display function hints for methods in a class?

25 views (last 30 days)
For example,
I wrote a class named elmnet (code below):
classdef elmnet
properties
% Some properties
end
methods
function this = elmnet(Neurons, varagin)
% Constructor code
end
function this = estimate(this, Input, Output)
% Some code
end
end
end
when I try to create an elmnet object, Matlab hints me the correct arguments it uses.
Since the object is created and stored in a variable, in this case 'net', it does not shows correctly the arguments for its methods:
How can i make the methods within a class present me correct hints for calling them?
  3 Comments
Guillaume Marrakchi
Guillaume Marrakchi on 9 Sep 2016
Same here! When creating a new oop framework, shared and used by many people in a team, it is very useful for users to see the methods hints. It would avoid calling help MyClass.myMethod every time they use a method they don't know yet.
Ihab Abboud
Ihab Abboud on 22 Mar 2023
any news on this. it would be great is this is fixed

Sign in to comment.

Answers (6)

Tony
Tony on 23 May 2016
Edited: Tony on 23 May 2016
Have the same issue, function hints for a user-defined class method are not useful.
A slightly different issue, could be the same, though; is for user-defined functions -- the function hint only shows one signature.
Is it possible to change which signature is shown, or show all signatures in user-defined function hint ?
The example code below only produces one function hint, for addme(a,b) signature, which is not sufficient, can this be changed ?
function c = addme (a,b)
% ADDME Add two values together.
%
% C = ADDME(a) adds a to itself.
%
% C = ADDME(a,b) adds a and b together.
%
% See also SUM, PLUS.
c = a + a; %TODO: finish code

Simon Parten
Simon Parten on 3 Aug 2016
Bump this ... it would be an extremely useful feature.

Jan Kappen
Jan Kappen on 31 Aug 2016
This is an really necessary feature!
  3 Comments
Micke Malmström
Micke Malmström on 26 Apr 2018
I dont get how to make it work after reading what is in the link... if there is a way of doing it, could you please give an example on how
Thanks/M
Paul Meinert
Paul Meinert on 12 Jul 2018
Indeed, the functionSignatures.json file only seems to work inside of Matlab "live scripts", not inside the regular command window.
Any help on getting function hints to work inside of the command window, and for class methods would be greatly appreciated. This seems like a major omission or maybe we're all missing something ?

Sign in to comment.


Tom Shlomo
Tom Shlomo on 6 Jan 2020
Any news on this? perhaps something changed with the recent introduction of the arguments block?

Nicholas Ayres
Nicholas Ayres on 17 Mar 2020
Edited: Nicholas Ayres on 17 Mar 2020
It seems I misenterpreted the question. I will leave my previous answer below, but if you DO write the signatures json, you could potentially put "choices={'inputName'}" in the position and then hitting tab will input the input name for the user to check. (and then delete to put in the actual input).
-------------------------------------------------------------------------------------------------------
I've cracked it! It's a little awkward, but I've cracked it.
This method only works with function notation like:
func(obj,inputs)
and NOT dot notation:
obj.func(inputs)
If you only have one function with this name (whether in another class or just a function), all you need to do is write the functionSignature.json as if the function were NOT a member of the class and enforce that the FIRST input to your function is your class. Like so:
{
"func":
{
"inputs":
[
{"name":"obj", "kind":"required", "type":"myClass"},
...
]
}
}
If you wish to use the same function name for multiple classes (or just a function name), you must use the "mutuallyExclusiveGroup" functionality.
{
"func":{
"inputs":[
{"mutuallyExclusiveGroup":
[
[
{"name":"obj","kind":"required","type":"myClass"},
...
],
[
{"name":"obj","kind":"required","type":"testClass2"},
...
]
]
}
]
}
}
Now, whenever you type your function name like so:
func(
and tab complete the first entry, all variables in your workspace matching any of the potential classes will be listed. Once this first entry is selected, the following suggestions will only be for the specific mutally exclusive group to which the class of your object belongs.
If you HAVE to use dot notation, i.e.:
obj.func(inputs)
then you will have to just move the obj part out the front after you've written the statement in function notation.
The bit that I consider awkward about this is that the signature is tied to just the function name and not the class, meaning that if you wish to:
  • Change a function name within a class, you have to move the relevant mutually exclusive block to a new function block, rather than just changing the function name.
  • It is more difficult to locate a mutually exclusive block when deleting/editing.
I have tried testing a load of other methods that SHOULD make sense (e.g. setting the function to be something like "myClass.func"), but these do not work.
If you have any questions, please ask as sometimes I need a little more prompting to get my point accross!!

Thomas
Thomas on 18 Oct 2023
Here is a working example:
Filter is a class in the namespace im and has one method apply().
The package name's folder has to start with a plus sign: +im
The class definition and the code for its methods are seperated into single files in the folder @Filter
Additionally there is a single function rg() in the file rg.m in the package im.
The main.m is in the working directory wd from where the main.m should be run.
At the beginning of main.m, only the path to the package folder where +im is in, has to be added to matlab path.
If you manage your files like this, and use the package name (im - namespace for image manipulations) in your functionSignatures.json, then code suggestion will work with dot notation.
└───class-test
├───libs
functionSignatures.json
└───+im
rg.m
└───@Filter
apply.m
Filter.m
└───wd
main.m
Filter.m
classdef Filter
properties
col (:,1) double
row (1,:) double
end
methods
function filter = Filter(varargin)
if nargin == 2
if all([isnumeric(varargin{1}) isnumeric(varargin{2})])
filter.col = varargin{1};
filter.row = varargin{2};
else
error("Filter(u,v): col and row have to be numeric.");
end
elseif nargin == 3
if isnumeric(varargin{1}) && ...
isa(varargin{2}, "function_handle") && ...
isa(varargin{3}, "function_handle")
n = varargin{1};
fy = varargin{2};
fx = varargin{3};
filter.col = arrayfun(fy, (-n:n)');
filter.row = arrayfun(fx, (-n:n));
else
error("Filter(n,funy,funx): n has to be numeric. " + ...
"funy and funx have to be function handles.");
end
else
error("Filter needs 2 or 3 arguments");
end
end
end
end
apply.m
function img = apply(filter, img)
img = conv2(filter.col(end : -1 : 1), filter.row(end : -1 : 1), img, "same");
end
Note!
apply() is a method of Filter.
e.g.
im.Filter([1 2 1],[1 0 -1]).apply(img);
rg.m
function img = rg(img)
%RG Regularize an image from [min, max] -> [0, 1]
m_min = min(img, [], 'all');
m_max = max(img, [], 'all');
if m_max == m_min
img = .5 * ones(size(img));
return;
elseif sign(m_max) - sign(m_min) < 2
img = (img - m_min) / (m_max - m_min);
else
amp = max([-m_min, m_max]);
img = .5 * (img - m_min) / amp;
end
end
functionSignatures.json
{
"_schemaVersion": "1.0.0",
"im.rg": {
"inputs":
[
{"name":"img", "kind":"required", "type":["double"], "purpose":"double (:,:): An image."}
]
},
"im.Filter": {
"inputs":[
{"mutuallyExclusiveGroup":
[
[
{"name":"col", "kind":"required", "type":["numeric"], "purpose":"array of doubles:\nThe kernel in x-direction."},
{"name":"row", "kind":"required", "type":["numeric"], "purpose":"array of doubles:\nThe kernel in y-direction."}
],
[
{"name":"hs", "kind":"required", "type":["numeric","scalar"], "purpose":"double:\nThe half size of the kernel"},
{"name":"funy", "kind":"required", "type":["function_handle"], "purpose":"function handle: function for kernel in y-direction"},
{"name":"funx", "kind":"required", "type":["function_handle"], "purpose":"function handle: function for kernel in x-direction"}
]
]
}
]
},
"im.Filter.apply": {
"inputs":
[
{"name":"filter", "kind":"required", "type":["im.Filter"], "purpose":"Filter: An instance of class Filter."},
{"name":"img", "kind":"required", "type":["double"], "purpose":"double (:,:): An image."}
]
}
}
main.m
addpath("..\libs\");
dx = im.Filter([1 2 1], [1 0 -1])
dy = im.Filter([1 0 -1], [1 2 1])
sharr_x = im.Filter([47 162 47], [1 0 -1])
sharr_y = im.Filter([1 0 -1], [47 162 47])
sharr_x2 = sharr_x.col * sharr_x.row
sharr_y2 = sharr_y.col * sharr_y.row
n = 16;
m = 2 * n + 1;
img = zeros(m);
i = ones(m, 1) * (-n : n);
s.x = i;
s.y = i';
img = arrayfun(@(s) 1. .* (s.x.^2+s.y.^2<.8*n^2),s,"UniformOutput",false);
img = img{:,:};
figure(1);
subplot(3,3,1); imshow(im.rg(img));
subplot(3,3,5); imshow(im.rg(dx.apply(img)));
subplot(3,3,6); imshow(im.rg(dy.apply(img)));
subplot(3,3,8); imshow(im.rg(sharr_x.apply(img)));
subplot(3,3,9); imshow(im.rg(sharr_y.apply(img)));
here's the result:

Community Treasure Hunt

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

Start Hunting!