To: J3 J3/24-104 From: Brad Richardson Subject: User Defined Procedures In Constant Expressions Date: 2024-January-22 1. Introduction =============== At present there are constraints preventing the use of any user defined procedures in constant expressions. There are several use cases where such a possibility would be highly desirable. 2. Use Cases ============ 2.1 Reuse of Code in Complicated Definition of Named Constants -------------------------------------------------------------- Consider the following definition of a constant to be used to set the kind parameter for real values in a program. integer, parameter :: wp = merge( & selected_real_kind(30), & selected_real_kind(15), & selected_real_kind(30) > 0) It would improve code clarity and reuse if one could instead write simple function real_kind_with_fallback(p, fallback) result(k) integer, intent(in) :: p, fallback integer :: k k = selected_real_kind(p) if (k <= 0) k = fallback end function integer, parameter :: wp = real_kind_with_fallback( & 30, selected_real_kind(15)) 2.2 Define Constants of Derived Types With Private Components ------------------------------------------------------------- Consider the following derived type definition for representing acceleration in some physics calculation. type :: acceleration private real :: meters_per_square_second end type If in some other module (for example containing our physical constants) we'd like to declare Earth's gravity, we can't. For example type(acceleration), parameter :: EARTHS_GRAVITY = & acceleration(meters_per_square_second = 9.81) Bonus points if it becomes possible to support something like the following to completely encapsulate the internal representation. type(acceleration), parameter :: EARTHS_GRAVITY = & 9.81.unit.meters_per_square_second 2.3 Define Constants of Derived Types With Allocatable Components ----------------------------------------------------------------- A common pattern lately is the use of a derived type to handle arrays of strings with different lengths. This generally necessitates a component that is allocatable. For example a typical definition would look like the following. type :: string character(len=:), allocatable :: chars end type It then becomes desirable to define constants of such a type, for example as allowed options for some user interface. type(string), parameter :: valid_responses(*) = & [ string("restart") & , string("repeat") & , string("quit") & ]