j3-fortran / fortran_proposals

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

CHARACTER arguments on MERGE() should b #138

Open urbanjost opened 4 years ago

urbanjost commented 4 years ago

The requirement that the CHARACTER arguments to MERGE() must be of the same length prevents it from being used in a straight-forward manner.

In normal assignments the RHS would be padded or truncated to the size of the LHS, or the LHS would be allocated to the size of the RHS.

This is also true if testing strings for equality.

The following code will fail on the third call to SHOW() in a standard-compliant programming environment.

program main
   call show('1234567')
   call show('12345678') ! unequal lengths
   call show()           ! unequal lengths
   call show('123456')   ! unequal lengths
contains

   subroutine show(a)
      character(len=*),optional :: a
      character(len=:),allocatable :: a_local
      a_local=merge(a,'DEFAULT',present(a))
      write(*,'(a)')'value=['//a//']'
   end subroutine show

   end program main

The compilers I tried detect this even at run-time and throw a descriptive message. They should correct for the difference in length there, and the documentation can describe that if the lengths are not the same that the function may run less efficiently instead of not allowing for the difference.

I do not have a strong opinion on whether the returned value should be the length of the longer argument or the same as the original that was selected.

milancurcic commented 4 years ago

I had no idea merge can work on scalar character strings. Cool!

However, is a_local=merge(a,'DEFAULT',present(a)) valid when a is missing? I thought a here can be referenced only if passed as argument to present() or as an actual argument to another procedure with a corresponding optional dummy argument. I get [] on call show() with gfortran-9.2.0, but I expected a run-time error.

sblionel commented 4 years ago

@milancurcic 's question about the use of present(a) is on point. It;s ok to use present() in a merge (see interp F08/0095) but it's not ok to reference a not-present optional dummy as one of the sources.

I have a memory of discussing this general issue at a J3 meeting but can't find a paper on it, nor a mention in my notes. The question is whether the mask is evaluated first and only the true sources referenced, or if a conforming implementation can evaluate both sources and then select the "true" elements. You can't depend on this.

urbanjost commented 4 years ago

On January 11, 2020 at 9:46 AM Steve Lionel notifications@github.com wrote:

@milancurcic https://github.com/milancurcic 's question about the use of present(a) is on point. It;s ok to use present() in a merge (see interp F08/0095 https://j3-fortran.org/doc/year/13/13-278r1.txt ) but it's not ok to reference a not-present optional dummy as one of the sources.

I have a memory of discussing this general issue at a J3 meeting but can't find a paper on it, nor a mention in my notes. The question is whether the mask is evaluated first and only the true sources referenced, or if a conforming implementation can evaluate both sources and then select the "true" elements. You can't depend on this.

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub https://github.com/j3-fortran/fortran_proposals/issues/138?email_source=notifications&email_token=AHDWN3IYH4ZIH3IUCRV7RPTQ5HLSTA5CNFSM4KFPZPE2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEIWDNNY#issuecomment-573322935 , or unsubscribe https://github.com/notifications/unsubscribe-auth/AHDWN3NY3GK2UTJ2Y5FQKDDQ5HLSTANCNFSM4KFPZPEQ .

As the example raises more questions by using the optional argument in the merge() I can change the example to a less-contentious case; but I had that discussion on the Fortran newsgroup and came away with the impression that as long as I did not use "a" in an expression but just passed it that it would be no different than passing an undefined

urbanjost commented 4 years ago

Well, I once thought it was illegal but after discussing it on the Fortran newsgroup I was convinced it was OK as long as the optional parameter was passed directly and not used in an expression. Since this was what I thought was a very good use case for the feature I used that, but I do not want to have this perhaps badly selected example detract from the initial request. MERGE is a good substitute for other types for the C ": ?" syntax with the additional power that array syntax provides too boot; but is hindered by CHARACTER values having to be the same length, which is rarely the case in other parts of Fortran, I will concede my favorite use case is not the best example, but contend the feature is still useful. If merge would short-cut it's parameters and only evaluate the true condition that would be useful in MERGE as well as IF statements, but that is a whole other (bigger) enhancement I would like.

On January 11, 2020 at 9:46 AM Steve Lionel notifications@github.com wrote:

@milancurcic https://github.com/milancurcic 's question about the use of present(a) is on point. It;s ok to use present() in a merge (see interp F08/0095 https://j3-fortran.org/doc/year/13/13-278r1.txt ) but it's not ok to reference a not-present optional dummy as one of the sources.

I have a memory of discussing this general issue at a J3 meeting but can't find a paper on it, nor a mention in my notes. The question is whether the mask is evaluated first and only the true sources referenced, or if a conforming implementation can evaluate both sources and then select the "true" elements. You can't depend on this.

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub https://github.com/j3-fortran/fortran_proposals/issues/138?email_source=notifications&email_token=AHDWN3IYH4ZIH3IUCRV7RPTQ5HLSTA5CNFSM4KFPZPE2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEIWDNNY#issuecomment-573322935 , or unsubscribe https://github.com/notifications/unsubscribe-auth/AHDWN3NY3GK2UTJ2Y5FQKDDQ5HLSTANCNFSM4KFPZPEQ .
urbanjost commented 4 years ago

I was trying to think if making MERGE have the TRUE and FALSE return values optional so the parameter could be passed by the standard would be a solution, but it would make MERGE pretty funky. I had a discussion about this and there was a pretty convincing argument made that passing the value directly was no different than passing an undefined value or unassigned pointer, in that it would not cause a problem unless used in an expression by the called procedure, but you are right that the standard states explicit restrictions on optional arguments, which was missed in my earlier discussion. I started off wanting backed up that it could not be passed and was convinced otherwise. It really would be a nice use of MERGE. If you have a lot of optional parameters the code can get messy. I guess another approach I have seen suggested is to allow a default value to be specified on the declaration of the optional value; but that would maybe be confusing because you would be implying it gets set on each call? That is, would

character(len=*),optional :: string='default value'

be a better way to do what I wanted with MERGE in that particular case? But that is a whole other line of thought, even if worth pursuing.

On January 10, 2020 at 11:04 PM Milan Curcic notifications@github.com wrote:

I had no idea merge can work on scalar character strings. Cool!

However, is a_local=merge(a,'DEFAULT',present(a)) valid when a is missing? I thought a here can be referenced only if passed as argument to present() or as an actual argument to another procedure with a corresponding optional dummy argument. I get [] on call show() with gfortran-9.2.0, but I expected a run-time error.

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub https://github.com/j3-fortran/fortran_proposals/issues/138?email_source=notifications&email_token=AHDWN3KMTF2QJMTYNQVJGNDQ5FANHA5CNFSM4KFPZPE2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEIVYTXY#issuecomment-573278687 , or unsubscribe https://github.com/notifications/unsubscribe-auth/AHDWN3IWQ4ZGLZFD37L5XGTQ5FANHANCNFSM4KFPZPEQ .
FortranFan commented 4 years ago

@urbanjost, so is your interest really the idea behind #22 with default value of optional arguments? And not MERGE?

urbanjost commented 4 years ago

For the use case I originally specified that would be better and I definitely support that change. I mad my own function for scalars that is just like merge except the return values are optional just so it does not break the rules over passing optional arguments with a metamorphic class(*) variable and looking at all the places I use it all but two are for what #22 does. I also tried doing it with pointers to eliminate some of the problems with having to declare a local variable, which #22 would eliminate. So I would say #22 would work great; there are still a few places not concerned with optional arguments where it is a pain to deal with the lengths being equal, but essentially you are right - I would prefer "22" to be implemented instead of this if the choice were between the two. And I have not seen nearly the activity for this as for "22"; so if I am the only one that wants this it can be dropped (as I have a work-around).