Nested function: Difference between revisions

→‎{{header|Fortran}}: Less messing about...
(→‎{{header|Fortran}}: Less messing about...)
Line 89:
=={{header|Fortran}}==
===Arithmetic statement functions===
Fortran allows the user to define functions (and subroutines also) but from thefirst startFortran (1958) on 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
DIST(U,V,W) = X*SQRT(U**2 + V**2 + W**2) !The contained function.
Line 95:
F = T + DIST(T,SIN(X),ATAN(X) + 7) !Invoked...
END</lang>
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. Since they are for arithmetic they cannot be used for character manipulations, and the CHARACTER variable only appeared with F77.
 
===Containerisation===
Line 136:
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 if trailing spaces are not to be written out. 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 whereas CR returned to the start of the line with no advance. If output were to go to an old-style lineprinter, such in-line control codes would not be recognised.
 
===When storage is abundant===
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.
Another way of providing a "list" is via an array as in <code>CHARACTER*28 TEXT(9)</code>) so that each item occupied one element, and the maddening question "how long is a piece of string" arises twice: how much storage to allow for each element when all must be as long as the longest text expected, and, how many elements are to be allowed for.<lang Fortran> SUBROUTINE POOBAH(TEXT,N,SEP) !I've got a little list!
CHARACTER*(*) TEXT(*) !The supplied scratchpad.
INTEGER N !Entry count.
CHARACTER*(*) SEP !The separator to be used.
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 to add.
N = N + 1 !Count another item in.
WRITE (TEXT(N),1) N,SEP,X !Place the N'th text, suitable decorated..
1 FORMAT (I1,2A) !Allowing only a single digit.
END SUBROUTINE ADDITEM !That was simple.
END SUBROUTINE POOBAH !Still worth a subroutine..
 
PROGRAM POKE
CHARACTER*28 TEXT(9) !Surely sufficient.
INTEGER N
CALL POOBAH(TEXT,N,". ")
WRITE (6,"(A)") (TEXT(I)(1:LEN_TRIM(TEXT(I))), I = 1,N)
END</lang>
The output statement could be <code>WRITE (6,"(A)") TEXT(1:N)</code> but this would write out the trailing spaces in each element. A TRIM intrinsic function may be available, but, leading spaces may be desired in the case that there are to be more than nine elements. If so, <code>FORMAT (I2,2A)</code> would be needed up to ninety-nine, or more generally, I0 format. Except that would not write out leading spaces and would spoil the neatness of a columnar layout. With file names, the lack of leading spaces (or zero digits) leads to the ideas explored in [[Natural_sorting|"Natural" sorting]]. One could define constants via the PARAMETER statement to document the linkage between the number of array elements and the correct FORMAT code, though this is messy because for NMAX elements the format code requires <Log10(NMAX) + 1> digits, and in such an attempt I've seen Log10(10) come out not as one but as 0·9999932 or somesuch, truncating to zero.
 
The previous method stored the various texts in one CHARACTER variable with no wasted space, but elements could be accessed only sequentially. If element <code>i</code> were desired, it can only be found after stepping along from the start and if the collection expands beyond a few dozen elements, repeated random access soon becomes slow. If this is important, rather than have the items separated by a special in-line symbol one can instead have an array of fingers to say the end of each item's text. In this case the pooled storage for the texts wastes no space on special symbols but this index array must have some predefined size (and be capable of indexing the size of the pool: 16-bits? 32-bits?), but random access is now easy.
 
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. Similarly, one could define a data aggregate containing a count <code>N</code> as well as the <code>TEXT</code> and a function could return such a compound entity as its result. It may also be possible to arrange that array TEXT becomes "ragged", that is, TEXT(i) is not always 28 characters long, but only as much as is needed to store the actual item.
 
=={{header|Go}}==
1,220

edits