j3-fortran / fortran_proposals

Proposals for the Fortran Standard Committee
178 stars 15 forks source link

Auto-allocating processor messages #160

Open zjibben opened 4 years ago

zjibben commented 4 years ago

This feature is to address certain cases which require programmers to provide already-allocated strings of sufficient length, but the standard provides no mechanism to determine that length.

klausler commented 4 years ago

Uncharacteristically for Fortran, this proposal would change the behavior of some current conforming programs. I suggested at the J3 meeting that the change be restricted to only automatically allocate deferred-length CHARACTER allocatable variables that are in a deallocated state, since that case is currently an error, but to no avail.

The case that worries me the most is that of internal writes to allocatable CHARACTER. When the internal unit is a deferred-length allocatable CHARACTER scalar data object that is already allocated, this feature would change the current behavior of the internal write from blank-padding into reallocation. (I'm not saying that reallocation is a bad idea or not useful; I'm saying that silently changing the semantics of working programs is a bad idea.)

EDIT: sample program whose behavior will change:

character(len=:), allocatable :: x
allocate(character(len=10) :: x)
write(x,"('hi')")
print *, len(x) ! was 10, now 2
FortranFan commented 4 years ago

@klausler wrote:

Uncharacteristically for Fortran, this proposal would change the behavior of some current conforming programs. I suggested at the J3 meeting that the change be restricted to only automatically allocate deferred-length CHARACTER allocatable variables that are in a deallocated state, since that case is currently an error, but to no avail.

The case that worries me the most is that of internal writes to allocatable CHARACTER. When the internal unit is a deferred-length allocatable CHARACTER scalar data object that is already allocated, this feature would change the current behavior of the internal write from blank-padding into reallocation. (I'm not saying that reallocation is a bad idea or not useful; I'm saying that silently changing the semantics of working programs is a bad idea.) ..

Can you please cross-check again with the relevant committee folks about this?

My understanding is different from yours, that the internal write to an already allocated allocatable character scalar will retain its length when the number of transferred characters during said write is less than the allocated length of the scalar variable. So I expect the output of your sample program to remain as 10.

Please note the following, especially the bullet starting with 'otherwise', from paper https://j3-fortran.org/doc/year/20/20-122r1.txt:

This bullet item is replaced with the following text that now contains two sub-bullets:

"A record of the internal file becomes defined by writing the record.

  • If the internal file is an allocatable, deferred-length character scalar variable, it becomes defined as if by intrinsic assignment of the record.
  • Otherwise, if the number of characters written in a record is less than the length of the record, the remaining portion of the record is filled with blanks; the number of characters to be written shall not exceed the length of the record."

{ writing an internal file to a scalar allocates as needed }

{Note to the Editor: the last sentence in the original bullet has been changed to a clause separated by a semicolon. The intent is that this sentence is attached to the "otherwise". The editor is free to rework this as he feels appropriate.}

klausler commented 4 years ago

It's the first bullet point that's relevant.

FortranFan commented 4 years ago

It's the first bullet point that's relevant.

I think the authors in paper 20-122r1 meant to state in the first bullet, "If the internal file is an unallocated allocatable, deferred-length character scalar variable, it becomes defined as if by intrinsic assignment of the record."

This aspect was discussed in the previous paper they referenced, https://j3-fortran.org/doc/year/18/18-279r1.txt:

3c. Internal WRITE ..

JOR recommends that if the io-unit in an internal WRITE is an unallocated deferred-length character allocatable scalar variable, the WRITE behaves as if the record were assigned as if by intrinsic assignment. The requirement that the variable be unallocated is to provide consistency with the array case described in the next paragraph. If the variable is allocated it behaves as it does in F2008, using the current length.

klausler commented 4 years ago

It's the first bullet point that's relevant.

I think the authors in paper 20-122r1 meant to state in the first bullet, "If the internal file is an unallocated allocatable, deferred-length character scalar variable, it becomes defined as if by intrinsic assignment of the record."

That would be better, but I asked specifically in the plenary meeting on Friday whether the proposal that was passed from JOR would invalidate current Fortran programs in the case of allocated deferred-length allocatable CHARACTER scalar variables, and was told explicitly that (1) yes, it would, and (2) that was intentional.

zjibben commented 4 years ago

@klausler this is what I recall from plenary as well. Personally I'm ok with this behavior, as it's what happens with intrinsic assignment already, but I'd be curious to hear from the community if they consider it undesirable.

everythingfunctional commented 4 years ago

The "as if by intrinsic assignment" means that yes, the variable would be reallocated. And as @klausler says, the committee said that it was intended for that to be the case. Their contention was that in the majority of cases, it probably wouldn't outwardly change behavior because the use cases probably are already reallocating it immediately afterward as workaround to the fact that it isn't done automatically already.

If you know of any cases where the intended behavior is to allocate a character and use internal IO to write into it without it being reallocated, now is the time to speak up, because this will cause a change in behavior.

Personally, I agree with the committee, that the new behavior is probably always what was desired anyway.

klausler commented 4 years ago

I'm really uncomfortable with changing this behavior for internal writes because it breaks a long-standing correspondence between internal writes and fixed-length I/O. Internal writes to CHARACTER arrays treat each element of the array just like a fixed-sized record (RECL=) in an external file. Now, with this change, internal writes to CHARACTER scalars may no longer work in the same way as an internal write to a single-element CHARACTER array would, if the scalar is deferred-length and already allocated.

sblionel commented 4 years ago

My view on this is that it is very unusual for current programs to use deferred-length allocatable character variables for this. Most will use fixed-length character and those will not change. We had many, many requests for this feature in the 202X survey.

Please also note that for the internal WRITE case, the new behavior applies to scalars only, since Fortran doesn't have "ragged arrays".

klausler commented 4 years ago

The feature should be limited for internal WRITEs to the (current) error case of an unallocated deferred-length allocatable character scalar.