Hi!

After some thinking, I would like to modify my suggestion: It should be possible to check if _all_ the overloads of a particular (member) function has at least one output argument. And for those functions, enforce an "ans" output.

That is, if a function has two overloads, and at least one of them void, no "would be produced":

void foo(double a, double b);
double foo(double a); // No "ans" produced!

But if _all_ overloads have non-void returns, it an "ans" will be produced:

double foo(double a, double b); // "ans" produced
double foo(double a);  // "ans "produced

I think the normal situation is that all the overloads are either non-void or void and this will be covered by this. It will also not add any noticeable overhead or larger wrapper files. Nor do we have to worry about strange "[]" returns from void functions.

What say you?
Joel

P.S.: I could take a shot at the implementation, if we agree on a design.

2014-08-19 20:51 GMT+02:00 Kris Thielemans <kris.f.thielemans@gmail.com>:
From: Joel Andersson  Sent: 19 August 2014 11:29
>
> There is one thing I find particularly annoying when playing around with CasADi
> from MATLAB; the fact that the "ans" argument in MATLAB is not generated
> when you want it.
>

Yes, this is quite annoying, I agree.

> A function such as arcsinh in CasADi is now wrapped as follows:
> function varargout = function_name(varargin)
>   [varargout{1:nargout}] =
> casadi_coreMATLAB_wrap(1532,'SX_arcsinh',self,varargin{:});
> end
>
> The problem is that if you type "asinh(x)" in MATLAB, nargout will be zero, so
> nothing will be returned from the wrapper. To get an "ans" argument, you need
> to replace "nargout" with 1, or more generally with max(nargout,1):
> function varargout = function_name(varargin)
>   [varargout{1:max(1,nargout)}] =
> casadi_coreMATLAB_wrap(1532,'SX_arcsinh',self,varargin{:});
> end
>
> My proposed resolution is to always return at least one output whenever any
> overload of the function has any outputs arguments. This means that if you
> have two overloaded functions, one without outputs and another with outputs, a
> dummy output (0-by-0 matrix) would be returned from the overload with no
> outputs:
>
> void foo(double a); // no outputs, but dummy output [] returned
> int foo(double a, double b); // outputs
>
> Does this sound reasonable? In a MATLAB script, you'd put a semicolon after
> foo(a) anyway, preventing the creation of [].
>

I don't find it 100% satisfactory (it's not entirely clean, and people might not automatically put the semicolon if the function shouldn't return anything) but it's definitely a better solution than what we have at present. Also, the above example is somewhat contrived (anyone making an API like that is asking for confusion) as normally the overloading happens based on the input arguments, but I guess we have to cover corner cases as well.

I have no clear idea how you'd implement it though. When wrapping the code, you'd need to know which functions return void, and if so, return [], no? If so, I guess we could just as well modify the matlab class as well? (ok, that'd seems to mean we need to transport a lot of complication into the matlab code which we don't have now, so probably not a good idea).

Another idea:
As opposed to returning [], return a special object (e.g. SwigVoid). Once we do that, a few different options:
- set its display properties to the empty string. So effectively you want see it. (hmmm)
- let the matlab wrapper detect that. Something like this (not checked!)

function varargout= swig_return(varargin)
(
  If (nargout==0 && nargin==1 && class(varargin{1}, 'SwigVoid'))
   return;
  else
    varargout = varargin;
    return;
)

function varargout = function_name(varargin)
   [varargout{1:nargout}] = swig_return(...
     casadi_coreMATLAB_wrap(1532,'SX_arcsinh',self,varargin{:}));
  end

if we then make swig_return a method of SwigRef, it could work. Or indeed, make a method swig_call_wrapper that does this all in one go...

not sure if this can work though

Kris




--
--
Joel Andersson, PhD
Ptge. Busquets 11-13, atico 3
E-08940 Cornella de Llobregat, Spain
Home: +34-93-6034011
Mobile: +32-486-672874 (Belgium) / +34-63-4408800 (Spain) / +46-707-360512
(Sweden)