Search code examples
functiontype-conversionfortranstring-concatenationoperator-precedence

Fortran elemental function - is this behavior normal?


Consider the following function

ELEMENTAL FUNCTION int2str(i) RESULT(s)
    INTEGER, INTENT(IN) :: i
    CHARACTER(LEN = 50) :: appo
    CHARACTER(LEN = :), ALLOCATABLE :: s
    WRITE(appo, '(I0)') i
    ALLOCATE(s, source = TRIM(appo))
END FUNCTION int2str

The function, being elemental, is a scalar function (in my case it takes one scalar integer and gives back one scalar character, even though allocatable in length) that applies elementwise to arrays.

Why the output of

print *, '>>>'//int2str([1, 3, 5, 7])//'<<<'

is (unexpectedly to me)

>>>1<<<>>>3<<<>>>5<<<>>>7<<<

whereas the output of

print *, '>>>', int2str([1, 3, 5, 7]), '<<<'

is (expectedly)

>>>1357<<<

?

What I mean is that the function should apply to every one of the four scalar integers composing the array, thus returning a length-4 array each element of which being a string, but it seems to me that its elementwise-ness applies to the whole concatenation of three strings, as though the // operator has precedence over the function's result.


Solution

  • For character concatenation, the expression

    '>>>'//['1','3','5','7']
    

    depends on the scalar '>>>' and the array ['1','3','5','7']. As with other intrinsic binary operations where the operands are a scalar and a rank-1 array, the expression is a rank-1 array.

    In determining the value of the expression, the scalar operand is treated as an array like

    ['>>>','>>>','>>>','>>>']
    

    and the expression is equivalent to

    ['>>>','>>>','>>>','>>>'] // ['1','3','5','7']
    

    Finally, the expression has value where the elements are operands pairwise:

    ['>>>1','>>>3','>>>5','>>>7']
    

    You can see the parallels with the expression

    9+[1,3,5,7]  ! [9,9,9,9]+[1,3,5,7]  --> [10,12,14,16]
    

    When there are two concentation operations going on, the obvious value is the result.


    Note that I didn't express this in terms of an elemental function's result. This is partly because the fact the array comes from a function isn't significant. Also, your elemental function is not actually allowed: an elemental function result may not be allocatable.

    On the invalid function, Vladimir F has submitted a bug report covering gfortran not detecting violation of the numbered constraint C1290 of Fortran 2008. In that report you can see that if you remove the result(s) and declare int2str as having the allocatable attribute the function is rejected. Some other compilers do already detect violation.