octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: functions with 'named' arguments


From: Dupuis
Subject: Re: functions with 'named' arguments
Date: Fri, 4 Apr 2008 03:55:18 -0700 (PDT)



John W. Eaton wrote:
> 
> 
> 
> We don't need nargin to make argument lists work in Octave.  But we do
> need to be able to provide a nargin function, and it must remain
> compatible with the way that nargin currently works in Octave and
> Matlab.  It doesn't matter what R does or doesn't do.
> 
> If you want named arguments to work in Octave, then I think you should
> provide a patch that makes it work.  If you don't want to do that, or
> you can't do it, then at the very least provide a propsal or how the
> feature is supposed to work *in Octave*.  You don't need to get into
> implementation details.  You need to explain what the syntax and the
> semantics of the feature should be.  Your proposal must not break the
> current semantics of nargin, as doing that would break too much
> existing code.  If you provide a complete proposal for how the feature
> is supposed to work, then perhaps someone else who can implement it
> will agree that it is a useful feature and do the work to prepare a
> patch.
> 

For the first part: historically, Matlab introduced mechanisms to provide
generic functions, first at a fixed number of variables arguments, think
about optim which in the past accepted the function to be optimised to have
extra arguments P0 up to P9; latter it was replaced by the varargin
mechanism. In both cases, this mean
- for the programmer: to decide the role and the meaning of each
supplemental arg. Inside the function, (s)he has to take actions based upon
the number of inputs args, their types, and so on. 
- for the user: (s)he must know that the third supplemental arg is for such
variable, that for some special treatment the fourth arg must be at logical
one, and so on.
This mechanism is error prone: f.i., is some args may be either 'LS', either
'TLS', care has to be exercised in order to avoid confusion. Furthermore,
unrecognised arguments must be explicitelly detected. A last point is that
evaluation occurs early: f(3*sin(x)) requires to perform the computation
before calling the function, the mechanism is basically call-by-value

With the suggested approach, the function interface is clearly defined, the
list of accepted supplemental args is public, and the matching between
user-supplied values and function variables is performed by the internal
engine. Unrecognised arguments are automatically trapped, default values are
evident from the function definition. This is a comfort both for the
programmer and the user. The programmer knows the right variable will be
initialised, no need to care for nargin or testing. The user has the choice
to modify default variables with a great flexiblity. Evaluation occurs
latter, and only when required.

>From a performance perspective:
- compilation will require a bit more work
- run-time won't change because the bindings must be known at compile-time  
- in both cases, the parsing and error-detection code will disappear from
the function body

About the nargin function, the number of arguments is detectable at compile
time, so this doesn't introduce compatibily problems. To me, the biggest
change is a switch between two schemes:
- actual: early evaluation, variables evaluated in the context of the caller
- proposed: delayed evaluation, binding occurs in the context of the callee

For the second part: I don't have enough free time to program the suggested
features in a reasonnable delay, and I strongly agree that we should think
first, and program later. So here is my tentative proposal:
This is a suggestion to introduce tagged arguments into Octave. The purpose
is to define a mechanism where a function interface can be totally
determined at compile-time. The interface will be defined by the three
following parts, in the specified order:
1) [optionnal] required arguments
2) [optionnal] variable number of unspecified arguments
3) [optionnal] optionnal arguments, with  a known default value if they're
not initialised within the function call

-Required arguments are in the form tag_1, tag_2, and so on. Failure to not
provide them all must be detected as a compile-time error.
-Unspecified arguments are in the form "..." 
-A tagged argument is of the form: tag_1 =  some expression, tag_2 = another
expression, and so on. The tag will be used to perform the binding between
some user-supplied value or expression and the corresponding local variable
in the function environment. The binding will be order-insensitive :
f(tag_1=some val, tag_2 = other val) 
and
 f(tag_2 = other val, tag_1 = some val)
will result into the same initialisation for the local variables; and
partial match will be allowed, if unambiguous: let some function be defined
as f(mean=1, median=2). Then
f(m=5); f(me=7) are ambigous
f(mea=4); f(med=9) are unambigous,
and f(meanvalue=3); f(sd=4) will result in error. In the same way, f(mean=2,
mean=4) must result in an error, 'Repeated input value'

At the function call, the binding must occur this way:
1) tagged arguments are tentativelly matched with the function definition.
Mismatched or ambiguous ones must be affected to the varargin list, if any,
or flagged as error.
2) untagged arguments are then matched on a first come, first serve basis,
but skipping over the arguments already bound thanks to a matching tag

The initialisation must be performed this way:
1) expressions in the function call must be performed in the caller context,
in order to obtain a value for each argument. F.i., f(3*sin(x)) must become
f(some_value)
2) local variables from the argument list, where a bounding is available
through the actual function call, will receive the bounded value
3) local variables from the argument list without bounding and a constant
initialiser, will receive this initialiser
4) local variables from the argument list without bounding and where the
initialiser is an expression at the level of the function DEFINITION, will
receive the value computed from the expression, where the variables will be
evaluated in the function context first. If, at the time of the evaluation,
some of the variables are still not initialised, this must be trapped as an
error

Basically:
1) is similar to actual behaviour
2) is not available actually, and we have to choose wether we introduce a
new operator or break compatibility, as now f(x=3) will result in x being
set in the caller context
3) this is similar to the new syntax where initialiser are permitted
4) this a behavioural change: the function definition may provide some
expression which will be evaluated, if required, in the function context


Regards

Pascal
-- 
View this message in context: 
http://www.nabble.com/functions-with-%27named%27-arguments-tp16095584p16490998.html
Sent from the Octave - Maintainers mailing list archive at Nabble.com.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]