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
optionalattribute 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
arg2is 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
aandbprovided → sum is 5 - Second call: Only
aprovided → returnsa
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:
taxprovided → total includes tax - Second call:
taxnot 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
- Use optional arguments when a default value or behavior is appropriate
- Use keyword arguments for clarity, especially with many parameters
- Check optional arguments with
present()before using them - Avoid excessive optional arguments to maintain readability
- Document functions and subroutines indicating which arguments are optional
- 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
- Physics Simulations: Optional gravitational constant or time step
- Numerical Methods: Optional tolerance or iteration limits
- Data Analysis: Optional parameters for normalization or filtering
- 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
Leave a Reply