Reorder optional arguments?

9 views
Skip to first unread message

Dag Sverre Seljebotn

unread,
Nov 10, 2010, 1:00:41 PM11/10/10
to fwrap...@googlegroups.com
How should fwrap deal with optional arguments? There are several kinds
of optional arguments:

i) Declared optional in Fortran
ii) Inferred to be optional by fwrap (e.g. array bounds, intent(out)
arrays, more below)

In both cases, the argument in question is not necessarily at the end of
the argument list. This problem is amplified because of category ii):
E.g. array bounds can sometimes be inferred, so that arguments that are
required Fortran-side (and are thus not pushed to the end of the
argument list by the Fortran programmer) can be optional Python side.

Example 1:

subroutine returnsarray(arr, m, n)
implicit none
real, dimension(m, n), intent(out) :: arr
integer, intent(in) :: m, n
...
end subroutine returnsarray

Here, arr is optional in f2py, and thus also in my fwrap branch [1]. The
wrapper will allocate an output array if not provided. Problem is,
should "arr" be moved to the end of the output list, or not?

BTW, given "arr", m and n can be inferred instearAs this is not what
f2py does it's outside my radar currently...

Choices Python-side:

a)
Keep order:
def returnsarray(arr, m, n): ...

Still possible to call as returnsarray(None, m, n) to auto-allocate
result array.

b)
Move optional arguments to end:
def returnsarray(m, n, arr=None): ...

This is what f2py does. +1 from me.

c)
def returnsarray(arr=None, m=None, n=None):
if m is None: raise ValueError("argument required: m")
if n is None: raise ValueError("argument required: n")

This allows returnsarray(m=m, n=n) in addition to returnsarray(None, m,
n). This seems to seamlessly also support

returnsarray(arr=arr) # m and n


Example 2:

subroutine takesarray(m, n, arr)
implicit none
real, dimension(m, n), intent(in) :: arr
integer, intent(in) :: m, n
...
end subroutine takesarray

Here it is only relevant to infer m and n, and the sane way to call the
function from Python is

takesarray(arr)

f2py would move the m and n arguments last in this case, so that they
can be optionally provided, corresponding to slicing; takesarray(arr, m, n).

So this makes a case for moving the optional arguments. However, a case
could be made for simply dropping the arguments altogether (which is
perhaps easier to understand than moving them around), as they are
redundant with the slicing syntax; takesarray(arr[:m, :n]).

Input most welcome.

Dag Sverre

[1] My work is here, these ones in particular in the "outarray" branch:

https://github.com/dagss/fwrap

Dag Sverre Seljebotn

unread,
Nov 10, 2010, 1:04:05 PM11/10/10
to fwrap...@googlegroups.com

BTW, I actually wouldn't mind a rename too in this situation: 'Always
prefix with "out" unless the variable name already starts with "out" or
"result"'.

def returnsarray(m, n, out_arr=None):

And what f2py does is in fact to hide intent(out) arguments completely,
it doesn't accept an optional output buffer.

Dag Sverre

Kyle Mandli

unread,
Nov 10, 2010, 3:11:28 PM11/10/10
to fwrap...@googlegroups.com
I prefer removing everything that is strictly an output value to provide the least amount of confusion and the most pythonic wrapper.  Plan b though seems like the best way to go about things, I am not sure if I like the idea of renaming variables much as argument conflicts would then have to be checked (e.g. I named another argument out_arr).  

Kyle


--
You received this message because you are subscribed to the Google Groups "Fwrap Users" group.
To post to this group, send email to fwrap...@googlegroups.com.
To unsubscribe from this group, send email to fwrap-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/fwrap-users?hl=en.


Dag Sverre Seljebotn

unread,
Nov 10, 2010, 3:25:42 PM11/10/10
to fwrap...@googlegroups.com
On 11/10/2010 09:11 PM, Kyle Mandli wrote:
> I prefer removing everything that is strictly an output value to
> provide the least amount of confusion and the most pythonic wrapper.
> Plan b though seems like the best way to go about things, I am not
> sure if I like the idea of renaming variables much as argument
> conflicts would then have to be checked (e.g. I named another argument
> out_arr).

Sometimes you want to avoid allocating the out array, i.e. the output
array is already sitting in memory for some reason. There is not always
enough memory around to have a temporary. So I think keeping "arr"
around even if it is intent(out) is mandatory, but I guess I should take
this as a vote for moving it to the end?

In my opinion, if you do

real, dimension(n), intent(out) :: arr, out_arr

you deserve the trouble you get :-) We can always not rename in that
case. Or the favorite Cython solution: Provide a compiler directive to
let people choose :-)

Dag Sverre

Kurt Smith

unread,
Nov 10, 2010, 6:43:36 PM11/10/10
to fwrap...@googlegroups.com
On Wed, Nov 10, 2010 at 12:00 PM, Dag Sverre Seljebotn <da...@student.matnat.uio.no> wrote:
How should fwrap deal with optional arguments? There are several kinds of optional arguments:

i) Declared optional in Fortran
ii) Inferred to be optional by fwrap (e.g. array bounds, intent(out) arrays, more below)

In both cases, the argument in question is not necessarily at the end of the argument list. This problem is amplified because of category ii): E.g. array bounds can sometimes be inferred, so that arguments that are required Fortran-side (and are thus not pushed to the end of the argument list by the Fortran programmer) can be optional Python side.

Example 1:

subroutine returnsarray(arr, m, n)
 implicit none
 real, dimension(m, n), intent(out) :: arr
 integer, intent(in) :: m, n
 ...
end subroutine returnsarray

Here, arr is optional in f2py, and thus also in my fwrap branch [1]. The wrapper will allocate an output array if not provided. Problem is, should "arr" be moved to the end of the output list, or not?

BTW, given "arr", m and n can be inferred instearAs this is not what f2py does it's outside my radar currently...

Choices Python-side:

a)
Keep order:
def returnsarray(arr, m, n): ...

Still possible to call as returnsarray(None, m, n) to auto-allocate result array.

b)
Move optional arguments to end:
def returnsarray(m, n, arr=None): ...

This is what f2py does. +1 from me.

+1.  Least surprise coming from f2py, and it's pretty clear what's going on.
 

c)
def returnsarray(arr=None, m=None, n=None):
   if m is None: raise ValueError("argument required: m")
   if n is None: raise ValueError("argument required: n")

This allows returnsarray(m=m, n=n) in addition to returnsarray(None, m, n). This seems to seamlessly also support

returnsarray(arr=arr) # m and n


Example 2:

subroutine takesarray(m, n, arr)
 implicit none
 real, dimension(m, n), intent(in) :: arr
 integer, intent(in) :: m, n
 ...
end subroutine takesarray

Here it is only relevant to infer m and n, and the sane way to call the function from Python is

takesarray(arr)

f2py would move the m and n arguments last in this case, so that they can be optionally provided, corresponding to slicing; takesarray(arr, m, n).

So this makes a case for moving the optional arguments. However, a case could be made for simply dropping the arguments altogether (which is perhaps easier to understand than moving them around), as they are redundant with the slicing syntax; takesarray(arr[:m, :n]).

Thinking out loud...What about the following case?

>>> arr = np.zeros((100, 100), order='f')
>>> takesarray(arr, 50, 50)

i.e. the end user specifically wants to use a smaller section of the array (doesn't make much sense for a 2D array, but could make sense for a 1D work array, frequently used in older libraries).  Would this be completely analogous to

>>> takesarray(arr[:50, :50])

or would there be any difference in corner cases?  (Haven't thought about it much yet.)

My gut would be to say, make m & n optional, allowing access at the Python level.

 
Reply all
Reply to author
Forward
0 new messages