F Prog Lang Like Java
Volume Number: 13
Issue Number: 9
Column Tag: Alternative Environments
The F Programming Language Tastes Like Java
by Walt Brainerd, David Epstein and Richard Hendrickson
F is a new programming language derived from Fortran in
much the way Java is derived from C
This article describes the startling comeback of Fortran by discussing the features
found in the F subset of Fortran 95 comparing them with the features found in Java.
The combined strengths of Java and the F programming language make a wonderful
introduction for beginners and a powerful package for professional programmers
working on large projects. Even people familiar with modern Fortran and Java are
unlikely to have noticed the benefits of combining the two.
Both languages claim multi-platform portability. Java capitalizes on the look and feel
of C++ while aiming at professional programmers; F capitalizes on the efficiency and
pedagogical design of Fortran 95 while aiming at teenage beginners, experienced
scientists, engineers and large teams of programmers. Java offers powerful
object-oriented capabilities familiar to the C++ community; F offers organized
module-oriented capabilities familiar to the Fortran 95 community.
Getting over the initial shock that Fortran is not all that different from Java can be a
stretch for any programmer not in a coma since 1995. The amazing similarities
surprised even the authors, who had brought together over four decades of Fortran
language design committee experience to create F while the Green team was creating
Java.
The simple step taken by both language design teams is a move away from procedures
as a first class citizen and the insistence that procedures be encapsulated inside a more
powerful mechanism -- a class in Java and a module in F.
After comparing the features of F and Java, we suggest some benefits of combining F
and Java for introductory programming instruction as well as for large professional
projects and efficiency driven applications.
A Binary Tree
An example may help to show the similarities between F and Java. Listing 1 shows a
binary tree written in both F and Java. Notice that the mythical phrase, "Java does not
have pointers," is better said as, "Java does not support the dangerous pointer
arithmetic found in C and C++.
The tree is made possible by the below statements that declare a recursive type:
type (node), pointer :: left, right ! found inside F "node
Tree left, right; // found inside Java "Tree
In F, the word "pointer" is actually used in the declaration of the "nested defined type;
in Java, the word "pointer" is not used in the declaration of the "nested class.
Listing 1: BinTree.f and BinTree.j
BinaryTree
A binary tree written in F is easily translated into Java.
! A Binary Tree in F // A Binary Tree in Java
module m_binary_tree class Tree {
public :: main, Insert, PrintTree
private :: NewTree
type, public :: node
integer :: value int value;
type (node), pointer :: left, right Tree left, right;
endtype node
contains
function NewTree(num) result(tree) Tree (
integer, intent(in) :: num int num) {
type (node), pointer :: tree
allocate (tree)
tree%value = num value = num;
nullify(tree%left) left = null;
nullify(tree%right) right = null;
endfunction NewTree }//Constructor
recursive subroutine Insert(tree, num) static Tree Insert(
type (node), pointer :: tree Tree tree,
integer, intent(in) :: num int num) {
if (.not. associated (tree)) then if (tree==null) {
tree = NewTree(num) return new Tree(num);
elseif (num < tree%value) then }elseif(num
call Insert(tree%left) tree.left = Insert
(tree.left, num);
return tree;
call Insert(tree%right) tree.right = Insert
(tree.right, num);
return tree;
endif }//if
endsubroutine Insert }//Insert
recursive subroutine PrintTree(tree) static void PrintTree(
type (node), pointer :: tree Tree tree) {
if (associated (tree)) then if (tree != null) {
call PrintTree (tree%left) PrintTree(tree.left);
print *, tree%value System.out.println
(tree.value);
call PrintTree (t%right) PrintTree(tree.right);
endif }//if
endsubroutine PrintTree }//PrintTree
subroutine main public static void
type (node), pointer :: tree Tree tree;
integer :: i int i;
nullify (tree) tree = null;
print *, "Unsorted list" System.out.println
("Unsorted list");
do i = 1, 30, 3 for (i=1; i<3*10; i=i+3){
print *, modulo(i,10) System.out.println
(i%10);
call insert(tree, modulo(i,10)) tree = Insert
(tree, i%10);
enddo }//for
print *, "Sorted list" System.out.println
("Sorted list");
call print_tree (tree) PrintTree(tree);
endsubroutine main }//main
endmodule m_tree_sort }//Tree
program tree_sort
use m_tree_sort
call main()
endprogram tree_sort
The strategy for pointers in F and Java is actually the same -- no physical address is
made available and what is being pointed to must be specified in the declaration (that
is, no void pointers). In F, pointers only can point to objects that are targets; in Java,
everything is being pointed to, even procedures. A non-mainstream view of Java is not
that there are no pointers, but that everything in Java is being pointed to.
The F Programming Language
We expect the average reader to be more familiar with Java than with the F
programming language. Thus, an introduction to some of the F programming language
is called for.
One major difference between F and Java is that Java technology often refers to much
more than a programming language -- the class hierarchy from which all objects are
derived, the Java Virtual Machine (JVM), bytecode and Just-In-Time compilers, to
name just a few. F, on the other hand, does not have a standard module hierarchy or set
of software tools considered part of the F technology other than the F compilers. Thus,
this overview of F is a description of the F programming language. For those seeking
more specifics, the grammar for F (in BNF) can be found on the Imagine1 web page
(listed at the end of this article). F Statements
Figure 1 categorizes all the F statements. Instead of calling a procedure main as in
Java, there is a single main program required in F and it can be given any name. An F
program can use modules and reference public procedures and other public entities
from the used modules. Modules and their contained procedures can also use other
modules. This creates module hierarchies whose roots are the modules that were used
in the program. Using a module is similar to importing a package in Java. Both
languages encourage a hierarchical organization.
Organizational Constructs
program
use ... module
endprogram public :: proc-list
private :: proc-list
contains
........subroutine........function endmodule use module use module
endsubroutine endfunction
Action Constructs
if / elseif / else / endif
select case / case / case default / endselect
do / cycle / exit / enddo
where / elsewhere / endwhere
Declarations
type integer character intrinsic interface
endtype real logical module procedure
complex endinterface
Actions
= (assignment) allocate call stop
=> (pointer assignment) deallocate return
Input/Output
print open write inquire backspace
read close rewind
endfile
Figure 1. Categorizing all the F statements.
One design goal in F is to require explicit declarations for entities and not rely on any
defaults. This is the opposite extreme from the "old Fortran" with its implicit
declaration of an integer by starting its name with the letter "i" as in
itotal = 0 ! Declares an integer in earlier Fortrans
One result of requiring everything to be explicitly stated is that the student's first
module that contains a procedure will require a public statement. This leads into an
early discussion of public and private if the instructor so chooses.
Those challenged to make a thorough comparison of F and Java will notice that Java
does allow defaults and that the default for a function is protected. If Java were to
employ the strategy used in F, the word protected would have to be specified explicitly.
The F Attributes
Figure 2 lists the attributes for F entities. A little description of public and private
is given here as these attributes differ slightly from the others.
Attribute Description
pointer target Pointers can only point at objects that are
targets.
public private All module entities are either public or
private.
intent All subroutine arguments must be declared as intent in,
out,
or inout. All function arguments must be intent in.
dimension Arrays can be from one to seven dimensions.
allocatable For dynamic allocation.
parameter A constant.
save A static local variable.
Figure 2. Attributes for F entities.
Procedures are listed in public or private statements in the module that defines them.
All other module entities require a public or private attribute in their declaration
statement. One other use of the word "private" is to declare the components of a public
defined type as private to the module. Such a module would supply its users with access
to the defined type and the procedures that operate on entities declared to be of this
type. The insides of the type are hidden from the users of this module. An example of
this can be seen in Listing 2, which hides the internal parts of a car from its users.
Listing 2: CarModule.f
CarModule
This car module exports a type that has private components.
module m_car
use m_engine
private ! do not export entities from module m_engine
public :: GetCarInfo !, ... public procs listed here
private :: IncreaseCost !, ... private procs listed here
type, public :: t_car
private ! components are private to this module
type (t_engine) :: engine ! t_engine from m_engine
integer :: cost_of_engine