Jump to content

Nested function: Difference between revisions

→‎{{header|Fortran}}: Following the specification...
(→‎{{header|Go}}: Add Fortran.)
(→‎{{header|Fortran}}: Following the specification...)
Line 73:
 
=={{header|Fortran}}==
===Arithmetic statement functions===
Fortran allows the user to define functions (and subroutines also) but from the start these are compiled as separate items and cannot themselves contain the definition of another function (or subroutine) - except for the special form allowing the definition of what is called an arithmetic statement function, such as follows:<lang Fortran> FUNCTION F(X)
REAL X
Line 81 ⟶ 82:
This (deranged) function contains within it the definition of function DIST (which must be achieved in a single arithmetic statement), and which has access to all the variables of its containing function as well as its own parameters. Such functions are defined following any declarations of variables, and precede the executable statements.
 
===Containerisation===
With the advent of F90 comes the CONTAINS statement, whereby within a function (or subroutine) but oddly, at its ''end'' (but before its END) appears the key word CONTAINS, after which further functions (and subroutines) may be defined in the established manner. These have access to all the variables defined in the containing routine, though if the contained routine declares a name of the containing routine then that outside name becomes inaccessible.
 
Such contained routines are not themselves allowed to contain routines, so that the nesting is limited to two levels - except that arithmetic statement functions are available, so that three levels could be employed. Languages such as Algol, pl/i, Pascal, etc. impose no such constraint. <lang Fortran> SUBROUTINE POOBAH(TEXT,L,SEP) !I've got a little list!
CHARACTER*(*) TEXT !The supplied scratchpad.
INTEGER L !Its length.
CHARACTER*(*) SEP !The separator to be used.
INTEGER N !A counter.
L = 0 !No text is in place.
N = 0 !No items added.
CALL ADDITEM("first") !Here we go.
CALL ADDITEM("second")
CALL ADDITEM("third")
CONTAINS !Madly, defined after usage.
SUBROUTINE ADDITEM(X) !A contained routine.
CHARACTER*(*) X !The text of the item.
N = N + 1 !Count another item in.
TEXT(L + 1:L + 1) = CHAR(ICHAR("0") + N) !!Place the single-digit number.
L = L + 1 !Rather than mess with unknown-length numbers.
LX = LEN(SEP) !Now for the separator.
TEXT(L + 1:L + LX) = SEP !Placed.
L = L + LX !Advance the finger.
LX = LEN(X) !Trailing spaces will be included.
TEXT(L + 1:L + LX) = X !Placed.
L = L + LX !Advance the finger.
L = L + 1 !Finally,
TEXT(L:L) = CHAR(10) !Append an ASCII line feed. Starts a new line.
END SUBROUTINE ADDITEM !That was bitty.
END SUBROUTINE POOBAH !But only had to be written once.
 
PROGRAM POKE
CHARACTER*666 TEXT !Surely sufficient.
INTEGER L
CALL POOBAH(TEXT,L,". ")
WRITE (6,"(A)") TEXT(1:L)
END</lang>
 
Fortran doesn't offer a "list" construction as a built-in facility so it seemed easiest to prepare the list in a CHARACTER variable. These do not have a length attribute as in a string, the LEN function reports the size of the character variable not something such as the current length of a string varying from zero to the storage limit. So, the length of the in-use portion is tracked with the aid of an auxiliary variable, and one must decide on a sufficiently large scratchpad area to hold the anticipated result. And, since the items are of varying length, the length of the whole sequence is returned, not the number of items. Subroutine POOBAH could be instead a function, but, it would have to return a fixed-size result (as in say <code>CHARACTER*66 FUNCTION POOBAH(SEP)</code>) and can't return a length as well, unless via messing with a global variable such as in COMMON or via an additional parameter as with the L above.
 
To achieve the required output of one item per line would mean the output of one item at a time, and all the items are packed into TEXT with unknown boundaries. TEXT could instead have been an array (say <code>CHARACTER*28 TEXT(36)</code>) so that each item occupied one element, but that would have required a length for each item as well. This would be another way of providing a "list" data aggregate. A single character sequence seemed less trouble, but to achieve the one-item-per-line layout meant inserting control codes to start a new line. Oddly, the CHAR(10) is the linefeed character in ASCII but on this windows system it is treated as CRLF. If output were to go to an old-style lineprinter, such inline control codes would not be recognised.
 
F95 introduced facilities whereby a string style compound variable with both content and current length could be defined and manipulated, and when assigned to it would be reallocated storage so as to have exactly the size to hold the result. Later fortran standardised such a scheme.
 
=={{header|Go}}==
1,220

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.