Optional and Keyword Arguments in Functions and Subroutines

In Fortran programming, functions and subroutines often require input parameters to perform calculations. While most arguments are mandatory, Fortran allows arguments to be optional and passed using keywords. This feature increases the flexibility of functions and subroutines, allowing developers to write more robust and reusable code.

This post explores optional and keyword arguments in detail, including syntax, examples, practical applications, advanced usage, and best practices.

1. Introduction to Optional Arguments

  • Optional arguments are parameters that may or may not be provided by the caller.
  • If an optional argument is not provided, the function or subroutine can handle the missing value gracefully.
  • Use the optional attribute to declare an argument as optional.
  • The present() intrinsic function checks whether the optional argument was passed.

Optional arguments are particularly useful when a function has default behavior but can be modified with additional inputs.


2. Syntax of Optional Arguments

function function_name(arg1, arg2)
type :: return_type
type, intent(in) :: arg1
type, intent(in), optional :: arg2
...
end function function_name
  • arg2 is optional; it may or may not be provided
  • Use present(arg2) to check if it exists before using it

3. Example: Optional Argument in a Function

program main
print *, add_numbers(2, 3)
print *, add_numbers(2)
end program main function add_numbers(a, b)
integer :: add_numbers
integer, intent(in) :: a
integer, intent(in), optional :: b
if (present(b)) then
    add_numbers = a + b
else
    add_numbers = a
end if
end function add_numbers

Output:

5
2

Explanation:

  • First call: Both a and b provided → sum is 5
  • Second call: Only a provided → returns a

4. Using Optional Arguments in Subroutines

Optional arguments are also supported in subroutines.

Example: Optional Argument in a Subroutine

program main
call greet_user("Alice")
call greet_user("Bob", "Good evening")
end program main subroutine greet_user(name, message)
character(len=*), intent(in) :: name
character(len=*), intent(in), optional :: message
if (present(message)) then
    print *, message, ",", name
else
    print *, "Hello,", name
end if
end subroutine greet_user

Output:

Hello, Alice
Good evening , Bob

Explanation: If message is not provided, a default greeting is used.


5. Introduction to Keyword Arguments

  • Keyword arguments allow arguments to be passed in any order by explicitly specifying the argument name.
  • Improve code readability by clearly showing which values are assigned to which parameters.
  • Combine with optional arguments for highly flexible function calls.

6. Syntax of Keyword Arguments

call subroutine_name(arg_name = value, other_arg = value)
  • Use the = operator to assign values
  • Order does not matter when using keyword arguments

7. Example: Keyword Arguments in Functions

program main
print *, rectangle_area(length=5.0, width=3.0)
print *, rectangle_area(width=4.0, length=2.0)
end program main function rectangle_area(length, width)
real :: rectangle_area
real, intent(in) :: length
real, intent(in) :: width
rectangle_area = length * width
end function rectangle_area

Output:

15.0
8.0

Explanation: Arguments can be specified in any order using keywords.


8. Combining Optional and Keyword Arguments

Optional arguments and keyword arguments can be combined to create functions and subroutines with flexible interfaces.

Example: Optional Keyword Arguments

program main
print *, calculate_total(100.0, tax=0.1)
print *, calculate_total(200.0)
end program main function calculate_total(price, tax)
real :: calculate_total
real, intent(in) :: price
real, intent(in), optional :: tax
if (present(tax)) then
    calculate_total = price + price * tax
else
    calculate_total = price
end if
end function calculate_total

Output:

110.0
200.0

Explanation:

  • First call: tax provided → total includes tax
  • Second call: tax not provided → total equals price

9. Using Optional and Keyword Arguments in Real-World Scenarios

9.1 Temperature Conversion Function

program main
print *, convert_temperature(100.0, scale="F")
print *, convert_temperature(0.0)
end program main function convert_temperature(celsius, scale)
real :: convert_temperature
real, intent(in) :: celsius
character(len=*), intent(in), optional :: scale
if (present(scale)) then
    if (scale == "F") then
        convert_temperature = celsius * 9.0/5.0 + 32
    else
        convert_temperature = celsius
    end if
else
    convert_temperature = celsius
end if
end function convert_temperature

Output:

212.0
0.0

Explanation: Optional keyword scale allows flexibility to specify Fahrenheit or default Celsius.


9.2 Financial Calculation: Optional Interest Rate

program main
print *, final_amount(1000.0, years=5)
print *, final_amount(1000.0, years=5, rate=0.05)
end program main function final_amount(principal, years, rate)
real :: final_amount
real, intent(in) :: principal
integer, intent(in) :: years
real, intent(in), optional :: rate
real :: r
if (present(rate)) then
    r = rate
else
    r = 0.03
end if
final_amount = principal * (1 + r)**years
end function final_amount

Output:

1159.274
1276.282

Explanation: Optional keyword rate allows using a default rate of 3% if not provided.


10. Best Practices

  1. Use optional arguments when a default value or behavior is appropriate
  2. Use keyword arguments for clarity, especially with many parameters
  3. Check optional arguments with present() before using them
  4. Avoid excessive optional arguments to maintain readability
  5. Document functions and subroutines indicating which arguments are optional
  6. Combine optional and keyword arguments for flexible APIs

11. Advanced Usage

  • Optional and keyword arguments can be combined with modules for reusable code
  • Useful in scientific simulations with configurable parameters
  • Can improve testing by allowing default values for most parameters while overriding selected ones
  • Helpful for libraries and API design in Fortran

12. Examples in Scientific Computing

  1. Physics Simulations: Optional gravitational constant or time step
  2. Numerical Methods: Optional tolerance or iteration limits
  3. Data Analysis: Optional parameters for normalization or filtering
  4. Graphics/Visualization: Optional color, size, or style arguments

Example: Optional Tolerance in Root Finding

program main
print *, "Root with default tolerance:", find_root(0.0, 1.0)
print *, "Root with custom tolerance:", find_root(0.0, 1.0, tol=1.0e-6)
end program main function find_root(a, b, tol)
real :: find_root
real, intent(in) :: a, b
real, intent(in), optional :: tol
real :: tolerance
if (present(tol)) then
    tolerance = tol
else
    tolerance = 1.0e-4
end if
! Dummy root-finding calculation
find_root = (a + b)/2
end function find_root

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *