




Fortran Programming Language









limitations on function reference
AFAIK if f(x) is an arrayvalued function one can't access an element by saying (for example) PRINT *,f(x)(1) but must be more longwinded, by declaring an array g of the same shape as f, with elements of the same type, and then saying g = f(x) PRINT *,g(1) If f is of type character one could also imagine 3 pairs of parentheses: PRINT *,f(x)(1:2)(3:4) to print characters 3 and 4 of elements 1 and 2 of the array f(x) Does some possible ambiguity I haven't thought of prevent allowing that sort of thing?  John Harper, School of Mathematics, Statistics and Computer Science, Victoria University, PO Box 600, Wellington 6140, New Zealand email john.har@vuw.ac.nz phone (+64)(4)463 5341 fax (+64)(4)463 5045
John Harper wrote: > AFAIK if f(x) is an arrayvalued function one can't access an element > by saying (for example) > PRINT *,f(x)(1) > but must be more longwinded, by declaring an array g of the same shape > as f, with elements of the same type, and then saying > g = f(x) > PRINT *,g(1) > If f is of type character one could also imagine 3 pairs of parentheses: > PRINT *,f(x)(1:2)(3:4) > to print characters 3 and 4 of elements 1 and 2 of the array f(x)
One ambiguity is just the one you mention: that between arrays and substrings. If you allow such, you might also allow substrings of substrings, in which case there is definitely an ambiguity. > Does some possible ambiguity I haven't thought of prevent allowing > that sort of thing?
Note that in C, subscripting is an operator, and can be applied to any pointer variable or pointer expression. In that case, an array name can be considered a pointer constant. The return value of a pointer valued function can be subscripted. In C, the () of a function call are also an operator, and can be applied to function pointer valued functions, for example. Using a function for substrings removes some of the ambiguity and allows substrings of substrings in languages like PL/I.  glen
John Harper wrote: > AFAIK if f(x) is an arrayvalued function one can't access an element > by saying (for example) > PRINT *,f(x)(1) > but must be more longwinded, by declaring an array g of the same shape > as f, with elements of the same type, and then saying > g = f(x) > PRINT *,g(1) > If f is of type character one could also imagine 3 pairs of parentheses: > PRINT *,f(x)(1:2)(3:4) > to print characters 3 and 4 of elements 1 and 2 of the array f(x)
An equally upsetting nonfeature is: TYPE :: atype INTEGER :: a END TYPE TYPE(a) FUNCTION f(a) print *, f(42)%a ^ which is not allowed (asked gfortran, ifort and f95). Accessing only a single member of a returned type would come in handy at some times.
On Apr 24, 4:25 am, har@mcs.vuw.ac.nz (John Harper) wrote: > AFAIK if f(x) is an arrayvalued function one can't access an element > by saying (for example) > PRINT *,f(x)(1) > but must be more longwinded, by declaring an array g of the same shape > as f, with elements of the same type, and then saying > g = f(x) > PRINT *,g(1) > If f is of type character one could also imagine 3 pairs of parentheses: > PRINT *,f(x)(1:2)(3:4) > to print characters 3 and 4 of elements 1 and 2 of the array f(x) > Does some possible ambiguity I haven't thought of prevent allowing > that sort of thing?
If you need the idiom regularly, you can define (and possibly overload) a function TAKE(array,index) that simply returns array(index) and use PRINT *,TAKE(f(x),1) Such manipulation function like this TAKE (or SWAP and others) perhaps could be added to the Fortran standard. Admittedly there is little benefit; OTOH, the cost of adding intrinsics is really low.
On Apr 24, 12:21 pm, Daniel Franke <nos@nowhere.com> wrote:
> John Harper wrote: > > AFAIK if f(x) is an arrayvalued function one can't access an element > > by saying (for example) > > PRINT *,f(x)(1) > > but must be more longwinded, by declaring an array g of the same shape > > as f, with elements of the same type, and then saying > > g = f(x) > > PRINT *,g(1) > > If f is of type character one could also imagine 3 pairs of parentheses: > > PRINT *,f(x)(1:2)(3:4) > > to print characters 3 and 4 of elements 1 and 2 of the array f(x) > An equally upsetting nonfeature is: > TYPE :: atype > INTEGER :: a > END TYPE > TYPE(a) FUNCTION f(a) > print *, f(42)%a > ^ > which is not allowed (asked gfortran, ifort and f95). Accessing only a > single member of a returned type would come in handy at some times.
Sometimes, yes, but is it worth the effort of modifying the language? You can easily write an extracting function if you need the idiom often, or use a temporary.
John Harper wrote: > AFAIK if f(x) is an arrayvalued function one can't access an element > by saying (for example) > PRINT *,f(x)(1) > but must be more longwinded, by declaring an array g of the same shape > as f, with elements of the same type, and then saying > g = f(x) > PRINT *,g(1) > If f is of type character one could also imagine 3 pairs of parentheses: > PRINT *,f(x)(1:2)(3:4) > to print characters 3 and 4 of elements 1 and 2 of the array f(x) > Does some possible ambiguity I haven't thought of prevent allowing > that sort of thing?
I don't think it is ambiguous, but it surely can become hard to understand for a person. A couple of thoughts. 1) You're cheating by using "x" as an argument ;). Try 42 instead and then there are a ton of things that someone might try to write (ch* is character, *f is function, *a* is an array): chf(42) af(42) cha(42) a(42) chf(42)(1) af(42)(1) cha(42)(1) a(42)(1) chf(42)(1:3) af(42)(1:3) cha(42)(1:3) a(42)(1:3) chf(42)(1)(2:3) af(42)(1)(2:3) cha(42)(1)(1:3) a(42)(1)(2:3) chf(42)(1:3)(2:4) I think everything is unambiguous, but it's a dog's breakfast and likely to be error prone, especially if the function doesn't have arguments. 2) It's hard to limit this to functions. A function is just an expression with one term. The regularity police will "demand" that this be applied to general expressions. (x(I)(J:K)+y(L)(2))(M:N) just doesn't look worthwhile. 3) This came up for a little discussion during the initial array processing design in the late 80's and was discarded (I don't remember why). It hasn't been reproposed by anybody willing to do the (hard?) initial design work. I'd guess that the belief is that the (perceived) problems outweigh the expected benefit. Dick Hendrickson
>  John Harper, School of Mathematics, Statistics and Computer Science, > Victoria University, PO Box 600, Wellington 6140, New Zealand > email john.har@vuw.ac.nz phone (+64)(4)463 5341 fax (+64)(4)463 5045
On Apr 23, 10:25 pm, har@mcs.vuw.ac.nz (John Harper) wrote: > AFAIK if f(x) is an arrayvalued function one can't access an element > by saying (for example) > PRINT *,f(x)(1) > but must be more longwinded, by declaring an array g of the same shape > as f, with elements of the same type, and then saying > g = f(x) > PRINT *,g(1)
To slice an expression one could define a function function slice(ivec,i1,i2) result(jvec) ! return the slice ivec(i1:i2), avoiding outofbounds ! array access integer, intent(in) :: ivec(:) integer, intent(in) :: i1,i2 integer, allocatable :: jvec(:) integer :: j1,j2,nj j1 = max(lbound(ivec,dim=1),i1) j2 = min(ubound(ivec,dim=1),i2) nj = j2  j1 + 1 allocate (jvec(nj)) jvec = ivec(j1:j2) end function slice and write slice(f(x),i1,i2) One can also write a function that gets a component of a derived type, to which an expression could be passed. It would be convenient to make such a function ELEMENTAL. An advantage of writing a function is that one can check that the slice is within the bounds of the array. > If f is of type character one could also imagine 3 pairs of parentheses: > PRINT *,f(x)(1:2)(3:4) > to print characters 3 and 4 of elements 1 and 2 of the array f(x) > Does some possible ambiguity I haven't thought of prevent allowing > that sort of thing?
Octave (and I assume Matlab) allow this, as does R, with slightly different syntax. Here is an example. octave:1> x = [10,20,30] x = 10 20 30 octave:2> y = x(2:3)(2) y = 30 I agree it would be a convenient feature to have in Fortran if it does not break something, but I don't deem it essential.
>  John Harper, School of Mathematics, Statistics and Computer Science, > Victoria University, PO Box 600, Wellington 6140, New Zealand > email john.har@vuw.ac.nz phone (+64)(4)463 5341 fax (+64)(4)463 5045
Beliavsky wrote: > On Apr 23, 10:25 pm, har @mcs.vuw.ac.nz (John Harper) wrote: >> AFAIK if f(x) is an arrayvalued function one can't access an element >> by saying (for example) >> PRINT *,f(x)(1) >> but must be more longwinded, by declaring an array g of the same shape >> as f, with elements of the same type, and then saying >> g = f(x) >> PRINT *,g(1) > To slice an expression one could define a function > function slice(ivec,i1,i2) result(jvec) > ! return the slice ivec(i1:i2), avoiding outofbounds > ! array access > integer, intent(in) :: ivec(:) > integer, intent(in) :: i1,i2 > integer, allocatable :: jvec(:) > integer :: j1,j2,nj > j1 = max(lbound(ivec,dim=1),i1)
This sort of works, but it's not very convenient. The lower bound of an assumed shape array, like IVEC(:), is always 1. So, if f(x) doesn't return a 1based subscripted array, the caller will have to pass in the lower bound, or do arithmetic on i1 and j1 on the call side. Dick Hendrickson > j2 = min(ubound(ivec,dim=1),i2) > nj = j2  j1 + 1
PS: I'd worry a little here about trying to get a zero sized slice. I think everything works, but I'd probably stick in an nj = max(nj,0) just to be sure.
> allocate (jvec(nj)) > jvec = ivec(j1:j2) > end function slice > and write > slice(f(x),i1,i2) > One can also write a function that gets a component of a derived type, > to which an expression could be passed. It would be convenient to make > such a function ELEMENTAL. > An advantage of writing a function is that one can check that the > slice is within the bounds of the array. >> If f is of type character one could also imagine 3 pairs of parentheses: >> PRINT *,f(x)(1:2)(3:4) >> to print characters 3 and 4 of elements 1 and 2 of the array f(x) >> Does some possible ambiguity I haven't thought of prevent allowing >> that sort of thing? > Octave (and I assume Matlab) allow this, as does R, with slightly > different syntax. Here is an example. > octave:1> x = [10,20,30] > x = > 10 20 30 > octave:2> y = x(2:3)(2) > y = 30 > I agree it would be a convenient feature to have in Fortran if it does > not break something, but I don't deem it essential. >>  John Harper, School of Mathematics, Statistics and Computer Science, >> Victoria University, PO Box 600, Wellington 6140, New Zealand >> email john.har@vuw.ac.nz phone (+64)(4)463 5341 fax (+64)(4)463 5045





