Fortran - Errors and error handling - Part 1 - Exploration
Fortran doesn’t have exceptions. You can’t jump out of a function when something unexpected happens, then reflect on what happened outside the function, with the help of a try/catch block. As an alternative, intrinsic (built-in) procedures and constructs like write
, read
and open
allow you to pass an integer
variable as one of its arguments, to which it will assign a specific value indicating whether an error occurred. For example, when you try to open a file that doesn’t exist, you will get a non-zero value in the variable passed as the argument for iostat
:
By Matthias Noback
read moreFortran - Functional Programming Concepts - Reduce
We’ve implemented filter and map operations. The results of both these operations are new arrays. Yet another common operation on arrays is the so-called reduction operation; we “reduce” multiple values to a single value. The most obvious example is calculating the sum of an array of integers: the input is an array (or list) and the output is a single integer
:
pure function sum_all(numbers) result(res)
integer, dimension(:), intent(in) :: numbers
integer :: res
integer :: i
res = 0
do i = 1, size(numbers)
res = res + numbers(i)
end do
end function sum_all
Just like with filter
and map
we can imagine a generalization of this process, which involves looping over the array elements and building up a single return value along the way. We start with the existing sum_all
function. The first step is to let the user decide what the return value should be, which is the logic that happens inside the do
loop. We extract a function for this:
By Matthias Noback
read moreFortran - Functional Programming - List type
In the previous post we looked at this dream scenario:
list([1, 3, 5, 7]) % filter(divisible_by(3)) % map(square)
As mentioned, we can’t chain function calls like this. But we can put intermediate results in local variables and achieve something similar:
integers = list([1, 3, 5, 7])
divisible_by_3 = integers%filter(divisible_by(3))
squared = divisible_by_3%map(square)
If the intermediate values are all the same type, we can reuse the variable:
integers = list([1, 3, 5, 7])
integers = integers%filter(divisible_by(3))
integers = divisible_by_3%map(square)
To enable this syntax, it’s clear that we need to introduce a derived type for a list of integers that has type-bound procedures filter
and map
. These functions should each return a new list, so we can call any of these functions again on the new list. Let’s start with an integer_list_t
which contains an array of integers. We also provide a generic list
interface
with a specific procedure create_integer_list
for creating the integer_list_t
:
By Matthias Noback
read moreFortran - Functional Programming Concepts - Map
We considered the problem of filtering elements in an array, keeping only the ones we want. A decision about that is made by a function we pass as an argument.
A similar problem, but with its own challenges, is when we have an array of values and want to create a new array, with an equal number of elements, but each element has been transformed in some way. For instance, say we have an array of integers and want to square each integer. A procedural approach looks as follows:
By Matthias Noback
read more