j3-fortran / fortran_proposals

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

Conditional Expressions #12

Closed certik closed 4 years ago

certik commented 5 years ago

Initial recent paper: https://j3-fortran.org/doc/year/18/18-274.txt (there is a long history of trying to get something like this standardized).

Motivation

Citing from the paper: People have wanted to write things like

  IF (I<N .AND. A(I)==0) ...

for decades. So far, we have fobbed them off and they have to write

  IF (I<N) THEN
    IF (A(I)) ...
  END IF

which is not just verbose but less convenient when wishing to test a series of conditions.

Similarly, writing

  IF (PRESENT(D)) THEN
    CALL SUB(A,B,C,D)
  ELSE IF (X<1) THEN
    CALL SUB(A,B,C,EPSILON(X))
  ELSE
    CALL SUB(A,B,C,SPACING(X))
  END IF

is verbose but usable when only one argument is conditional, but rapidly degenerates when there are several arguments requiring similar handling.

certik commented 5 years ago

The proposed syntax in 18-274 for the last example would be:

CALL SUB(A,B,C,IF (PRESENT(D)) THEN (D) ELSE IF (X<1) THEN (EPSILON(X)) ELSE (SPACING(X)) END IF)

Here is how Python does it: https://docs.python.org/3/reference/expressions.html#conditional-expressions

victorsndvg commented 4 years ago

Dear @certik ,

I agree that short-circuit conditional evaluation could be an interesting feature.

On the other hand, Fortran provides the merge instrinsic that, I think, it covers the example (quoted) below (usually called ternary operator):

CALL SUB(A,B,C,IF (PRESENT(D)) THEN (D) ELSE IF (X<1) THEN (EPSILON(X)) ELSE (SPACING(X)) END IF)
zbeekman commented 4 years ago

Short circuit conditionals might alleviate a lot of segmentation faults; I know this would have saved my hide a few times.

certik commented 4 years ago

@victorsndvg, @zbeekman thanks for the feedback. Note that this particular proposal began long before my time at the committee and I don't feel very strongly either way on this particular one. I am watching what the committee works on and discusses and I am trying to create issues here for each proposal, to track it and to enable discussions with the wider community outside the committee.

zbeekman commented 4 years ago

Yes weighing in here with community feedback! Thanks for doing this @certik! I'd love to see J3 put more proceedings/documents/etc. on GitHub or GitLab.

zjibben commented 4 years ago

The difference with merge is 1) merge may evaluate all options regardless of the logical expression and 2) merge returns values, not variables. So merge(a, b, present(a)) is compiler-dependent; it might fail if a is not present, because as value could be accessed. By making the variable, not the value, the result of the expression, you can use this as an intent(out) argument. E.g., call get_x(if (l) then (a) else (b) endif) works to assign to either a or b.

Though short-circuiting logical expressions appeared in the initial paper, it isn't really being pursued here. Which is unfortunate; I'm much more interested in short-circuiting logical expressions than conditional expressions.

certik commented 4 years ago

Latest syntax paper: https://j3-fortran.org/doc/year/19/19-247r1.txt

The main feedback from the committee seems to be that the conditional expression proposal above does not make things much simpler or clearer, and the new syntax does not seem appealing. The alternative is to short-circuit logical expressions, so this:

  IF (I<N .AND. A(I)==0) ...

could be written, e.g., as:

  IF (I<N .ANDTHEN. A(I)==0) ...

That way the old .and. works as before, and .andthen. short-circuits the conditional. I opened up #19 for this new proposal.

(There is also an option to make .andthen. just .and., the argument pro is that it does not introduce any new syntax, but one argument against it is that it would change the current freedom for compilers to re-arrange logical expressions -- either way this can be discussed at #19.)