0

On this page that explains the use of inputParser class,

we see that every inputParser method call in the examples is of the form

methodname(object, arguments)

instead of

object.methodname(arguments)

For example

addRequired(p,'filename',@ischar)

instead of

p.addRequired('filename',@ischar)

where p is an instance if inputParser.

I would say that this makes it unclear where addRequired is coming from without having to search for it either though which or for the instantiation line in the code before it is being called. Having addRequired available in any context kind of breaks encapsulation, and seems to be the very opposite of what you would want from introducing OOP in the first place.

I suspect there is a good reason to sacrifice readability and write documentation in this particular way.

So my question is, is there any practical difference between "functional" and "OOP" syntax in MATLAB?

Dev-iL
  • 23,742
  • 7
  • 57
  • 99
Hennadii Madan
  • 1,573
  • 1
  • 14
  • 30
  • 4
    Point taken about readbility, but in fact methodname(obj, args...) is in fact the canonical syntax, with obj.methodname(args...) being syntactic sugar. This partly stems from the days of the pre-2008 classdef-based syntax for classes, which did not provide this syntactic sugar at all. – Tasos Papastylianou Jun 06 '19 at 12:36
  • 1
    Furthermore, I believe that searching for addRequired etc in the documentation (i.e. via 'help') provides any overloadings of that function for the various classes as well, so detecting appropriate usage context should not be a problem in that sense. – Tasos Papastylianou Jun 06 '19 at 12:41
  • Thanks for the explanation on historical reasons @TasosPapastylianou. I'll just add a comment in hopes that someone with decision power in MATLAB notices, that readability without reliance on the MATLAB executable matters a lot during code review, that nowadays often happens in the browser (bitbucket, github). – Hennadii Madan Jun 06 '19 at 12:46
  • I've dug this question/answer https://stackoverflow.com/questions/1693429/is-matlab-oop-slow-or-am-i-doing-something-wrong?rq=1 And it seems that there were also performance issues in the past, but not now. – Hennadii Madan Jun 06 '19 at 12:57
  • If it's any consolation, I agree that this doesn't make sense. What's more annoying is that sometimes the "OOP syntax" gives an error, but the "functional syntax" works. Historical reasons aside, the one and only reason I can think about nowadays for using the "functional" syntax, is that this is how non-static class methods are defined (i.e. `function out = funcName(obj, args)`). – Dev-iL Jun 06 '19 at 12:58
  • @Dev-iL Out of curiosity: do you have an example somewhere? – Hennadii Madan Jun 06 '19 at 12:59
  • @TasosPapastylianou It's not just syntactic sugar - check out my answer. – Dev-iL Jun 06 '19 at 13:50
  • 2
    @HennadiiMadan "Why did the developers of X choose to do Y using Z" questions are not really answerable by anybody but said developers, so aren'y very good for SO. Moreover, this specific question might be perceived as you voicing your discontent about some design choice, rather than a actual question. I suggest you change the emphasis in the question to "_What is the difference between functional and OOP syntax in MATLAB?_", in which case an objective answer could be suggested. – Dev-iL Jun 06 '19 at 14:15
  • Hennaddii you may feel vindicated to see that the command-line documentation in `help inputparser` does things as you would want. – Tasos Papastylianou Jun 06 '19 at 20:19
  • @Dev-iL I've edited the question in an attempt to remove the appearance of being opinion-based. – Hennadii Madan Jun 10 '19 at 06:57

1 Answers1

3

I'm afraid these syntaxes are not even fully equivalent, as can be learned from the following example:

>> f = fit( (1:3).', (2:2:6).' ,'poly1')
f = 
     Linear model Poly1:
     f(x) = p1*x + p2
     Coefficients (with 95% confidence bounds):
       p1 =           2  (2, 2)
       p2 =  -6.784e-16  (-4.709e-14, 4.574e-14)
>> methods(f)
Methods for class cfit:

argnames       cfit           coeffvalues    dependnames    feval          formula        integrate      numargs        plot           probnames      setoptions     
category       coeffnames     confint        differentiate  fitoptions     indepnames     islinear       numcoeffs      predint        probvalues     type           

>> f.coeffvalues
Error using cfit/subsref (line 18)
The name 'coeffvalues' is not a coefficient or a problem parameter.  You can only use dot notation to access the coefficients and problem parameters of a cfit or sfit, e.g.,
'f.p1'.

For the current fit, you can access these properties: p1, p2

You can get coefficient names and values either by name, e.g., p1 = f.p1, or by using the coeffnames or coeffvalues functions, e.g., names = coeffnames(f).

To use methods, use functional notation instead, e.g., plot(f). 

>> coeffvalues(f)
ans =
    2.0000   -0.0000

Most importantly:

To use methods, use functional notation instead, e.g., plot(f).

Now suppose we are sadists and want to write a function that behaves like that ourselves, investigating further we find that cfit.coeffvalues is simply a getter for a private property. Now if you look closely at the error above, you'd notice that it didn't even occur in cfit.coeffvalues, but instead in cfit.subsref!

In conclusion,

from this we can learn, empirically, that the functional notation goes directly to the method in question, whereas the OOP notation first goes through the possibly overridden subsref method of the class. I guess if you want to make sure you're skipping any custom subsref, use functional notation.

Dev-iL
  • 23,742
  • 7
  • 57
  • 99
  • 4
    "It's not just syntactic sugar" I would disagree. If you don't define a `subsref`, then by default `obj.method(param)` invokes `method(obj,param)`. That is the definition of syntactic sugar. The fact that you can override the default `subsref` and remove the syntactic sugar does not mean it is not syntactic sugar. – Cris Luengo Jun 06 '19 at 15:05
  • 2
    @CrisLuengo I came to say that and saw you beat me to it :p Also, if one inspects the cfit class, you'll see that the coeffvalues method is not defined within classdef, but only using the old-style which does not support the dot-access syntax in the first place. – Tasos Papastylianou Jun 06 '19 at 20:06
  • Brilliant example, and a kind of reason that I was suspicious of. Thank you. – Hennadii Madan Jun 10 '19 at 06:59
  • @HennadiiMadan You're most welcome; glad it helped! (_I_ also learned something in the process :) ) – Dev-iL Jun 10 '19 at 07:26