Fortran 2003/2008:优雅的默认参数?

kdb*_*kdb 9 fortran optional-parameters optional-arguments default-parameters default-arguments

在fortran中,我们可以定义默认参数.但是,如果不存在可选参数,则也不能设置它.当使用参数作为具有默认值的关键字参数时,这会导致类似的笨拙结构

PROGRAM PDEFAULT 

  CALL SUB
  CALL SUB(3)

CONTAINS 
  SUBROUTINE SUB(VAL)
    INTEGER, OPTIONAL :: VAL
    INTEGER :: AVAL ! short for "actual val"

    IF(PRESENT(VAL)) THEN
       AVAL = VAL
    ELSE 
       AVAL = -1   ! default value 
    END IF

    WRITE(*,'("AVAL is ", I0)') AVAL
  END SUBROUTINE SUB

END PROGRAM PDEFAULT
Run Code Online (Sandbox Code Playgroud)

就个人而言,我经常遇到意外打字的问题VAL而不是AVAL,即接口中的变量名之间的断开,以及代码中使用的初始化值可能引入运行时错误 - 更不用说这种初始化方式相当冗长.

是否有一些更优雅的方式使用具有默认值的可选参数?

示例写一些类似的东西会更自然

IF(NOT(PRESENT(VAL))) VAL = -1 
Run Code Online (Sandbox Code Playgroud)

因为它避免了VALvs AVAL混乱.但它无效,大概是因为Fortran通过引用传递参数,因此如果语句中VAL不存在,则CALL不会与内存关联VALVAL = -1导致段错误.

Vla*_*r F 6

你很好地描述了这种情况.没有别的方法我知道了,这是标准的符合.具有类似命名的局部变量的模式是人们经常使用的模式.另一种选择是放在if (present()) else任何地方,但这很尴尬.

关键是它们是可选参数,而不是默认参数.Fortran没有默认参数.可能会更好,但这不是委员会成员在准备Fortran 90时在80年代所选择的.


Gab*_*abe 6

在研究这个问题时,我发现你实际上可以使用OPTIONALVALUE属性做一些像提议的例子(至少使用gfortran,不知道不同的编译器可能会如何处理它).例如:

PROGRAM PDEFAULT 

  CALL SUB
  CALL SUB(3)

CONTAINS 
  SUBROUTINE SUB(VAL)
    INTEGER, OPTIONAL,VALUE :: VAL

    IF(.NOT. PRESENT(VAL)) VAL = -1 ! default value

    WRITE(*,'("VAL is ", I0)') VAL
  END SUBROUTINE SUB

END PROGRAM PDEFAULT
Run Code Online (Sandbox Code Playgroud)

这是在gfortran的4.9版本中实现的.这里是参数传递约定文档中的相关解释:

对于可选的伪参数,缺少的参数由NULL指针表示,除了具有VALUE属性的INTEGER,LOGICAL,REAL和COMPLEX类型的标量伪参数.对于那些,隐藏的布尔参数(logical(kind = C_bool),value)用于指示参数是否存在.

我还发现这个讨论很有趣,作为历史背景.

也许有更多知识渊博的人可能会评论这是否是一个坏主意(除了依赖于编译器),但至少从表面看它似乎是一个很好的解决方法.

请注意,此行为不是Fortran标准的一部分,并且取决于给定编译器的实现.例如,使用ifort时的示例代码段错误(版本16.0.2).

  • 不合标准的部分是当VAL不存在时分配给它.在我自己的代码中,我使用了原始帖子中的技术,我将评论"省略可选参数的默认值"是下一版本标准(目前称为F202X)的一个特性. (4认同)
  • 我_believe_这不是有效的Fortran(这并不是说它不会在一些编译器/运行时的实践中做到这一点).如果`val`不存在则不允许引用/定义它.这是`if`语句.标准对使用非现有伪参数的限制没有提到`value`属性."可定义的匿名副本"仅适用于具有"value"属性的当前伪参数的情况.[希望有人可以证明我错了.] (3认同)
  • 另外,我用ifort和segfaults测试了代码.我将在答案中澄清它不是标准的一部分,并且依赖于实现. (2认同)