Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Function questions?

197 views
Skip to first unread message

john.chl...@gmail.com

unread,
Aug 26, 2012, 3:57:35 PM8/26/12
to
A) Is there an analog to C's return statement?

e.g., "return 3.14159;"

B) Which is preferred/most current:

1) adding "result(...)" onto the end of the function declaration or
2) assigning the function name to the returning value (a la Pascal)?


---John

Richard Maine

unread,
Aug 26, 2012, 4:18:02 PM8/26/12
to
<john.chl...@gmail.com> wrote:

> A) Is there an analog to C's return statement?
>
> e.g., "return 3.14159;"

f = 3.14159

where f is the result variable name. That's always how you return a
function value. Note that the result variable is a "normal" variable and
can be defined in any way that any other variable can.

> B) Which is preferred/most current:
>
> 1) adding "result(...)" onto the end of the function declaration or
> 2) assigning the function name to the returning value (a la Pascal)?

That's largly a matter of personal taste in most cases. There is one
case where you have to use a result() clause - when the function is
recursive and directly references itself. Some might argue that one
should always use it for the same of consistency. I can see that
argument, but I don't feel particularly strongly about it.

Note that you have a result variable in *ALL* cases. If you don't have a
separate result() clause, the result variable just has the same name as
the function by default. But it is still a result variable.

My personal coding style doesn't end up using many functions at all. A
few, but not many. Almost everything ends up as subroutines. That's
because I'm pretty strict about avoiding function side effects. All but
the simplest of procedures tend to have side effects of some kind or
other, so I end up making them subroutines. For a start, handling errors
almost invariably involves side effects one way or another.

Let me note that the main reason for functions is to be used in
expressions. If you have a function that is always referenced only in
the simple form

x = f(arguments)

then you aren't really taking advantage of it being a function. In that
case, you might as well have it be something like

call compute_f(x,arguments)

which will avoid lots of possible complications.

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain

john.chl...@gmail.com

unread,
Aug 26, 2012, 4:54:39 PM8/26/12
to
But the return also results in exiting from the function - which is what I want, i.e., I want to exit from the function at that point. I don't want to use a "goto".

Also, I just noticed I can use:

integer function m_read(...)

which seems cleaner (to me) than using a "result" - it explicitly tell me the the return type by the function.

---John

Steven G. Kargl

unread,
Aug 26, 2012, 5:05:56 PM8/26/12
to
On Sun, 26 Aug 2012 13:54:39 -0700, john.chludzinski wrote:

> On Sunday, August 26, 2012 4:18:02 PM UTC-4, Richard Maine wrote:
>> <john.chl...@gmail.com> wrote:
>> > A) Is there an analog to C's return statement?
>> >
>> > e.g., "return 3.14159;"
>>
>> f = 3.14159
>>
>> where f is the result variable name. That's always how you return a
>> function value. Note that the result variable is a "normal" variable and
>> can be defined in any way that any other variable can.

>> My personal coding style doesn't end up using many functions at all. A
>>

>> then you aren't really taking advantage of it being a function. In that

>
> But the return also results in exiting from the function - which is what I want,
>> i.e., I want to exit from the function at that point. I don't want to use a "goto".
>
> Also, I just noticed I can use:
>
> integer function m_read(...)
>
> which seems cleaner (to me) than using a "result" - it
>> explicitly tell me the the return type by the function.
>

Can you please fix your newsreader software to not inject a bunch of blank lines
into a response?

This may come as a surprise, but have you considered using the RETURN
statement?


function f(x)
real f, x
if (x == 0.) then
f = 1.
return
end if

if (x == 1./3.) then
f = 1. / 3.
return
end if

f = 0.
end function f


john.chl...@gmail.com

unread,
Aug 26, 2012, 5:25:25 PM8/26/12
to
Excellent! - just what I was looking for! Is this 2003? ---John

Steven G. Kargl

unread,
Aug 26, 2012, 5:33:25 PM8/26/12
to
>>
>> > Also, I just noticed I can use:
>>
>> >
>>
>> > integer function m_read(...)
>>
>> >
>>
>> > which seems cleaner (to me) than using a "result" - it
>>
>> >> explicitly tell me the the return type by the function.
>>
>> >
>>
>>
>>
>> Can you please fix your newsreader software to not inject a bunch of blank lines
>>
>> into a response?
>>

Apparently, the answer to this question is NO.



--
steve

Gordon Sande

unread,
Aug 26, 2012, 6:08:18 PM8/26/12
to
On 2012-08-26 18:25:25 -0300, john.chl...@gmail.com said:

>
> Excellent! - just what I was looking for! Is this 2003? ---John

Nope! 1966. It has always been there even in the Fortran that preceeded
the first standard.

You have done a marvelous job of imitating someone who has never bothered
looking at even to most elementary introductory to Fortran. You would
waste less of your time if you tried the classical method of RTFM. Some
of the older text books are now free pdf files.

RTFM means Read The F***ing Manual if you are new to computing.


Richard Maine

unread,
Aug 26, 2012, 7:05:38 PM8/26/12
to
<john.chl...@gmail.com> wrote:

> But the return also results in exiting from the function - which is what I
> want, i.e., I want to exit from the function at that point. I don't
> want to use a "goto".

Oh, your initial question wasn't clear to me. I thought you were talking
about how to set the value instead of how to return from the function.
In Fortran, that's two distinct things. I covered setting the value. I
guess I assumed that you already knew how to return. That would be...
the RETURN statement. You can alternatively return by just getting to
the END statement of a procedure, but I prefer to make the return
explicit, even if it is at the end of the procedure, leaving the END
statement to do nothing other than mark the end of the source code for
the procedure.

> Also, I just noticed I can use:
>
> integer function m_read(...)
>
> which seems cleaner (to me) than using a "result" - it explicitly tell me
> the the return type by the function.

Some people like that. I don't. It works fine in the simplest cases, but
has several problems that will come up as your code gets more
complicated. I recommend sticking to a single style that will work all
the time.

1. As briefly alluded to before, you have to have a separate result in
at least the case of a directly recursive function.

2. There are several attributes that cannot be put on the function
statement, but that you might eventually want for your functions. In
fact, the type is a bit of an oddity here in that it is essentially the
only attribute that can be put on the function statement. For example,
you might someday want functions that return allocatable results. You
can't specify that on the function statement. Some people occasionally
write functions that return pointer results (although I strongly
recommend against that for reasons that aren't worth discussing at your
apparent current level).

If you ever have a function returning a derived type, that turns out to
be ok, but only because of a special-case exception to normal ordering
rules; I don't like the complication of such special-case exceptions.

Although there is a special-case exception for derived types, there is
not a corresponding exception for specification expressions. So if you
ever want a function with a type parameter that is given by a
non-constant specification expression, you'll probably find that you
can't put the type on the function statement.

I'm a fan of consistency here. I like to declare the function result
variable using the same syntax as for any other variable. In that case,
no special-case rules or syntax needed and no gotchas to watch out for.

Yes, I do visually separate the declarations of procedure arguments (and
function result) from the rest of my code. I put those declarations at
the top of the procedure, distinctly separated from declarations of
purely local things. So yes, they are close to the function or
subroutine statement, but not actually part of it. Although the language
doesn't enforce this separation of purely local declarations from those
that related to the external interface, I consider it good practice.

Buit then, as I mentioned earlier, I don't write a lot of functions at
all. If you come from a C background as at least one question suggests,
this might take some getting used to. In C, *ALL* procedures are
functions, even though some of them don't happen to return anything
useful. In Fortran, most procedures should be subroutines, and functions
are a rare special case.

Ron Shepard

unread,
Aug 26, 2012, 8:02:49 PM8/26/12
to
In article <1kpfr0o.ykzota1bisho8N%nos...@see.signature>,
nos...@see.signature (Richard Maine) wrote:

> Let me note that the main reason for functions is to be used in
> expressions. If you have a function that is always referenced only in
> the simple form
>
> x = f(arguments)
>
> then you aren't really taking advantage of it being a function. In that
> case, you might as well have it be something like
>
> call compute_f(x,arguments)
>
> which will avoid lots of possible complications.

One of these complications that has not been mentioned involves i/o
of the function result

write(*,*) 'f()=', f(arguments)

Here I've written it as sort of a temporary debug statement. The
problem is when f() itself does i/o, such as might occur when you
are writing and debugging the code in the first place. This kind of
recursive i/o is not allowed, but the compiler is not required to
diagnose it, so it sometimes happens by mistake, and then all kinds
of crazy stuff starts to happen. Variables start changing value
when they aren't supposed to, or your program dumps core with no
warnings, and stuff like that. Or your code seems to work, but when
you put a write statement somewhere to print out some intermediate
results, it then fails in some totally unrelated place.

In f77 through f95, it was not allowed to do any kind of recursive
i/o at all. One of the more recent standards revisions, 2003 or
2008, relaxed that restriction in some cases, but I still try to
avoid it out of habit, so I'm not exactly sure what is now allowed
that wasn't before.

If you always use subroutines instead of functions, then this never
happens.

$.02 -Ron Shepard

Robin Vowels

unread,
Aug 26, 2012, 9:18:50 PM8/26/12
to
On Aug 27, 10:02 am, Ron Shepard <ron-shep...@NOSPAM.comcast.net>
wrote:
> In article <1kpfr0o.ykzota1bisho8N%nos...@see.signature>,
>  nos...@see.signature (Richard Maine) wrote:
>
> > Let me note that the main reason for functions is to be used in
> > expressions. If you have a function that is always referenced only in
> > the simple form
>
> >   x = f(arguments)
>
> > then you aren't really taking advantage of it being a function. In that
> > case, you might as well have it be something like
>
> >   call compute_f(x,arguments)

Some usages may require this form as well as embedded in an
expression. There's nothing inherently wrong with the form
a = f(arguments).

In the CALL form, it isn't obvious what (if anything) the subroutine
is doing, and -- in particular -- which dummy argument is the one
being used by the subroutine to return a value.

Thus, the form x = f(arguments) is preferred.

> > which will avoid lots of possible complications.
>
> One of these complications that has not been mentioned involves i/o
> of the function result
>
>    write(*,*) 'f()=', f(arguments)
>
> Here I've written it as sort of a temporary debug statement.  The
> problem is when f() itself does i/o, such as might occur when you
> are writing and debugging the code in the first place.  This kind of
> recursive i/o is not allowed,

but it is allowed in PL/I.

> but the compiler is not required to
> diagnose it, so it sometimes happens by mistake, and then all kinds
> of crazy stuff starts to happen.  Variables start changing value
> when they aren't supposed to, or your program dumps core with no
> warnings, and stuff like that.  Or your code seems to work, but when
> you put a write statement somewhere to print out some intermediate
> results, it then fails in some totally unrelated place.
>
> In f77 through f95, it was not allowed to do any kind of recursive
> i/o at all.  One of the more recent standards revisions, 2003 or
> 2008, relaxed that restriction in some cases, but I still try to
> avoid it out of habit, so I'm not exactly sure what is now allowed
> that wasn't before.

In PL/I, it has always been possible to include I/O, even in
a recursive function. It makes it so much easier to debug.

john.chl...@gmail.com

unread,
Aug 26, 2012, 9:05:27 PM8/26/12
to
Gordon, I'm well familiar with RTFM but whether you wish to believe it or not - I didn't see that when googling "Fortran95 exit from function".

BTW, if you have nothing constructive to offer, refrain.

Robin Vowels

unread,
Aug 26, 2012, 9:09:59 PM8/26/12
to
On Aug 27, 5:57 am, john.chludzin...@gmail.com wrote:
> A) Is there an analog to C's return statement?
>
>   e.g., "return 3.14159;"

In PL/I you have return (3.14159);
In Fortran, you have x = 3.14159; return

> B) Which is preferred/most current:
>
>   1) adding "result(...)" onto the end of the function declaration or

I prefer this form. The introduction to the function is thus
absolutely clear, because it starts off with the word FUNCTION,
rather than a type specification.

Robin Vowels

unread,
Aug 26, 2012, 9:24:46 PM8/26/12
to
On Aug 27, 6:18 am, nos...@see.signature (Richard Maine) wrote:
On the contrary, he is.

Some usages may require this form as well as embedded in an
expression. There's nothing inherently wrong with the form
a = f(arguments).

It tells you immediately that a value is being returned, and how.

> In that
> case, you might as well have it be something like
>
>   call compute_f(x,arguments)
>
> which will avoid lots of possible complications.

which adds complications.

dpb

unread,
Aug 26, 2012, 10:47:49 PM8/26/12
to
On 8/26/2012 8:05 PM, john.chl...@gmail.com wrote:
...

> Gordon, I'm well familiar with RTFM but whether you wish to believe
> it or not - I didn't see that when googling "Fortran95 exit from function".
>
> BTW, if you have nothing constructive to offer, refrain.

I'd agree it was pretty constructive, actually.

Download a language reference manual from somewhere...I see that
gfortran doesn't have a complete one in its own documentation so get one
from some other source, but get it. There are quite a number of vendor
manuals available.

A text wouldn't be a bad idea, either.

--

Dick Hendrickson

unread,
Aug 26, 2012, 11:14:02 PM8/26/12
to
On 8/26/12 8:18 PM, Robin Vowels wrote:
> On Aug 27, 10:02 am, Ron Shepard<ron-shep...@NOSPAM.comcast.net>
> wrote:
>> In article<1kpfr0o.ykzota1bisho8N%nos...@see.signature>,
>> nos...@see.signature (Richard Maine) wrote:
>>
>>> Let me note that the main reason for functions is to be used in
>>> expressions. If you have a function that is always referenced only in
>>> the simple form
>>
>>> x = f(arguments)
>>
>>> then you aren't really taking advantage of it being a function. In that
>>> case, you might as well have it be something like
>>
>>> call compute_f(x,arguments)
>
> Some usages may require this form as well as embedded in an
> expression. There's nothing inherently wrong with the form
> a = f(arguments).
>
> In the CALL form, it isn't obvious what (if anything) the subroutine
> is doing, and -- in particular -- which dummy argument is the one
> being used by the subroutine to return a value.
>
> Thus, the form x = f(arguments) is preferred.

"is preferred" probably needs a "by whom" qualifier ;) .

The problem with functions (as Richard mentions somewhere upthread) is
side effects. If you routinely use x = f(arguments) then someday you'll
write something like

x(i,j) = f( [maybe]x, [or maybe]i, [or maybe]j, other arguments)

and be really surprised at what a standard conforming optimizer does for
you if f does anything to its arguments. Functions (especially for C
programmers) often have side effects and the Fortran rules make it
dangerous to use side effects.

Call compute_f (result = x, other arguments)

makes things clear for people who use "compute_f" without understanding
what the arguments are for. ;)

Dick Hendrickson

James Van Buskirk

unread,
Aug 26, 2012, 11:55:20 PM8/26/12
to
"Richard Maine" <nos...@see.signature> wrote in message
news:1kpfyap.11md8cb186e22uN%nos...@see.signature...

> 1. As briefly alluded to before, you have to have a separate result in
> at least the case of a directly recursive function.

Consider the following example:

C:\gfortran\clf\proctest>type proctest.f90
module winstuff
use ISO_C_BINDING
implicit none
private
integer, parameter, public :: HANDLE = C_INTPTR_T
public WinMain
abstract interface
recursive function WinMain(hInstance,hPrevInstance, &
lpCmdLine,nCmdShow) bind(C)
import
implicit none
!GCC$ ATTRIBUTES STDCALL :: WinMain
integer(C_INT) WinMain
integer(HANDLE), value :: hInstance
integer(HANDLE), value :: hPrevInstance
character(kind=C_CHAR) lpCmdLine(*)
integer(C_INT), value :: nCmdShow
end function WinMain
end interface
end module winstuff

module mystuff
use ISO_C_BINDING
use winstuff, TestMe=>WinMain
implicit none
contains
recursive function WinMain(hInstance,hPrevInstance, &
lpCmdLine,nCmdShow) bind(C,name='WinMain')
implicit none
!GCC$ ATTRIBUTES STDCALL :: WinMain
integer(C_INT), target :: WinMain
integer(HANDLE), value :: hInstance
integer(HANDLE), value :: hPrevInstance
character(kind=C_CHAR) lpCmdLine(*)
integer(C_INT), value :: nCmdShow
procedure(TestMe), pointer :: test
procedure(WinMain), pointer :: test2
integer(C_INT), pointer :: test3

if(.FALSE.) then
test => WinMain
test3 => WinMain
end if
end function WinMain
end module mystuff

C:\gfortran\clf\proctest>gfortran -c proctest.f90

C:\gfortran\clf\proctest>

No errors! But shouldn't this generate lots of error messages?
In WinMain, the name WinMain should only be the name of the
result variable, so test3 => WinMain should be OK, but pointing
a function pointer at it (test => WinMain) or cloning a
procedure interface from it (procedure(WinMain), pointer :: test2)
should not be OK, right? Or does the standard allow this?

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


glen herrmannsfeldt

unread,
Aug 27, 2012, 12:38:18 AM8/27/12
to
James Van Buskirk <not_...@comcast.net> wrote:
> "Richard Maine" <nos...@see.signature> wrote in message
> news:1kpfyap.11md8cb186e22uN%nos...@see.signature...

>> 1. As briefly alluded to before, you have to have a separate result in
>> at least the case of a directly recursive function.

> Consider the following example:

(snip)

> module mystuff
> use ISO_C_BINDING
> use winstuff, TestMe=>WinMain
> implicit none
> contains
> recursive function WinMain(hInstance,hPrevInstance, &
> lpCmdLine,nCmdShow) bind(C,name='WinMain')

(snip)

> procedure(TestMe), pointer :: test
> procedure(WinMain), pointer :: test2
> integer(C_INT), pointer :: test3

> if(.FALSE.) then
> test => WinMain
> test3 => WinMain
> end if
(snip)


> No errors! But shouldn't this generate lots of error messages?
> In WinMain, the name WinMain should only be the name of the
> result variable, so test3 => WinMain should be OK, but pointing
> a function pointer at it (test => WinMain) or cloning a
> procedure interface from it (procedure(WinMain), pointer :: test2)
> should not be OK, right? Or does the standard allow this?

What does it do with if(.TRUE.) instead?

Is the compiler, and especially the optimizer, good enough
to figure out that the test=>WinMain is never executed, and so
doesn't need to worry about it?

That does seem unusual, though.

-- glen

glen herrmannsfeldt

unread,
Aug 27, 2012, 12:44:00 AM8/27/12
to
In comp.lang.fortran Dick Hendrickson <dick.hen...@att.net> wrote:

(snip)
>> In the CALL form, it isn't obvious what (if anything) the subroutine
>> is doing, and -- in particular -- which dummy argument is the one
>> being used by the subroutine to return a value.

>> Thus, the form x = f(arguments) is preferred.

> "is preferred" probably needs a "by whom" qualifier ;) .

> The problem with functions (as Richard mentions somewhere upthread) is
> side effects. If you routinely use x = f(arguments) then someday you'll
> write something like

> x(i,j) = f( [maybe]x, [or maybe]i, [or maybe]j, other arguments)

> and be really surprised at what a standard conforming optimizer does for
> you if f does anything to its arguments. Functions (especially for C
> programmers)

C has strict rules on when you can, and can't, expect things to
have the appropriate value in the case of side effects. The are
sometimes surprising to C programmers, too, though.

You don't even need functions, just an ordinary expression like:

j=(i++)+(++i);

> often have side effects and the Fortran rules make it
> dangerous to use side effects.

> Call compute_f (result = x, other arguments)

> makes things clear for people who use "compute_f" without understanding
> what the arguments are for. ;)

-- glen

Gib Bogle

unread,
Aug 27, 2012, 2:42:18 AM8/27/12
to
On 27/08/2012 4:44 p.m., glen herrmannsfeldt wrote:

> C has strict rules on when you can, and can't, expect things to
> have the appropriate value in the case of side effects. The are
> sometimes surprising to C programmers, too, though.
>
> You don't even need functions, just an ordinary expression like:
>
> j=(i++)+(++i);

"Ordinary" is in the eye of the beholder ;-)

Wolfgang Kilian

unread,
Aug 27, 2012, 5:15:08 AM8/27/12
to
It looks like there are a couple of (individually) well-founded
recommendations for style, which unfortunately partly contradict each
other - so the debate is bound to continue. My personal view:

- Subroutines are most safe to use, because they side-effects are
tolerable. (See Richard's posts.)

call compute_f (x, args)

- Functions are good because you see that there is a return value by
just looking at the call. For a subroutine you have to scan the code or
the docs for the interface, to know which argument is INTENT(OUT/INOUT)

y = f (x, args)

- But this is valid only if all functions are pure, i.e., all arguments
are INTENT(IN). If this is satisfied, I do prefer the function style.

- However, I almost never end up actually writing PURE, although it
would help the optimizer. With many levels of nested calls (subroutines
or functions), debugging by writing out intermediate results becomes
impossible.

- Caveat: Unless the compiler is smart, do this only if the result is
small in memory. Since the function call is an expression, an
unnecessary temporary copy is likely to happen.

- Allocate-on-assignment may occur. Depending on complexity this may be
an asset or a burden, since it is a sort-of side effect.

- The return value may be a pointer. I do write idioms like

y => get_some_ptr (x, a, b)

and find it much more convincing than

call get_some_ptr (x, a, b, y) ! which one is the pointer?

BUT this requires discipline in writing functions like this, to avoid
the pitfalls. And never confuse '=' with '=>' ...


... and to come back to the OP's question, I also try to avoid RETURN
statements, because they invite the coder to have more than one in a
procedure. The place where I do use them is things like searching in
nested loops (sometimes better than EXIT), in algorithms which in other
languages would be coded using idioms like TRY..CATCH.

Finally, I always declare functions using RESULT and no prefix

function my_long_function_name (args) result (f)
DECLARATION_LINE_FOR :: f

because my names tend to be verbose, so in the implementation a
shorthand is handy. Furthermore, switching from/to a subroutine version
is slightly more straightforward. (If only a function result
declaration could take a redundant INTENT(OUT) attribute!)

As I said, all of this is personal preference, and I'm also open to
suggestions in that area.


-- Wolfgang

--
E-mail: firstnameini...@domain.de
Domain: yahoo

Robin Vowels

unread,
Aug 27, 2012, 5:43:44 AM8/27/12
to
Functions that change their arguments are not well-designed ones.
All Fortran arguments should have INTENT (IN).
The corresponding attribute in PL/I is NONASSIGNABLE.

>  Functions (especially for C
> programmers) often have side effects

That's because functions are the only kind of procedure available
in C, and yes, you'd expect those "functions" to modify their
arguments, and yes, you'd expect side effects.

> and the Fortran rules make it
> dangerous to use side effects.
>
>     Call compute_f (result = x, other arguments)
>
> makes things clear for people who use "compute_f" without understanding
> what the arguments are for.  ;)

If a person doesn't understand what the arguments are,
he shouldn't be using the subroutine/function.

As for making things clear to such people, it [result=x] really
doesn't, particularly if the user doesn't know what it means.

> >>> which will avoid lots of possible complications.
>
> >> One of these complications that has not been mentioned involves i/o
> >> of the function result
>
> >>     write(*,*) 'f()=', f(arguments)
>
> >> Here I've written it as sort of a temporary debug statement.  The
> >> problem is when f() itself does i/o, such as might occur when you
> >> are writing and debugging the code in the first place.  This kind of
> >> recursive i/o is not allowed,
>
> > but it is allowed in PL/I.
>
> >> but the compiler is not required to
> >> diagnose it, so it sometimes happens by mistake, and then all kinds
> >> of crazy stuff starts to happen.  Variables start changing value
> >> when they aren't supposed to, or your program dumps core with no
> >> warnings, and stuff like that.  Or your code seems to work, but when
> >> you put a write statement somewhere to print out some intermediate
> >> results, it then fails in some totally unrelated place.

That is the sort of think you'd expect in Fortran -- particularly
early programs -- because of the lack of subscript checking.

In PL/I, subscript checking is part of the language.

Ron Shepard

unread,
Aug 27, 2012, 8:37:43 AM8/27/12
to
In article <k1fdqr$dvo$1...@dont-email.me>,
Wolfgang Kilian <see...@domain.invalid> wrote:

> - Functions are good because you see that there is a return value by
> just looking at the call. For a subroutine you have to scan the code or
> the docs for the interface, to know which argument is INTENT(OUT/INOUT)

You still need to scan the code to see which arguments are modified
even with functions.

>
> y = f (x, args)
>
> - But this is valid only if all functions are pure, i.e., all arguments
> are INTENT(IN).

That is not what PURE means in fortran. In fortran PURE functions
and subroutines can modify arguments.

> If this is satisfied, I do prefer the function style.

Even when all arguments are INTENT(in), you still have the problem
with recursive i/o with functions. PURE functions in fortran cannot
do i/o, so that does solve that problem, but then that means that
you cannot debug such code with write statements. Also, PURE
functions and subroutines cannot do some other useful things, like
STOP for error conditions.

PURE is one of the attributes that require explicit interfaces, so
all of this presents no problem to the compiler, it can sort out
what can and cannot be modified in all cases. It is human readers
of the code where the confusion arises. When PURE was added to the
language (in f95 I think), I was a little surprised and disappointed
in this particular choice of definitions. I thought that a more
restrictive choice would have been more useful, more along the lines
you suggest above. One thing I wanted was that pure functions could
be used freely in expressions

x(i,j) = pure1(i,j) + pure2(i,j)

knowing only that they were pure, without the need to scan the code
or know other details of the interface. You can do the above in
some situations, of course, but it is up to the programmer to know
the code and to make sure it is legal. I would have liked that to
be a no-brainer.

The STOP statement restriction is often a practical issue for me. I
currently have code that I've been working on for several months
that contains some functions that will eventually be PURE, but right
now they check for error conditions and STOP when appropriate. At
some time in the future, I intend to take out the error tests and
add the PURE attribute, but during development it has been just too
useful to have those tests there. It seems like the programmer
should not have to make that choice, there should be some way to
have both PURE and to allow STOP statements or to somehow otherwise
abort execution when errors are detected. Think about all of the
fortran intrinsic functions (matmul(), acos(), sqrt(), and so on)
that perform error tests but are otherwise treated by the compiler
as pure (e.g. regarding expression optimizations). Programmers
should be able to write code the same way.

$.02 -Ron Shepard

Gordon Sande

unread,
Aug 27, 2012, 8:46:50 AM8/27/12
to
Good, so you are not a freshman with a first job inspite of the
behaviour. But maybe
it would help to realize that not all knowledge is organized with your
word order and
your jargon. It would be easier to look at an introductory book where
functions are
described rather than guessing that some jargon you chose might also be
used by those
describing Fortran. The same general phenomena is why it is often hard
to find new things
using the index of a book but quite possible once you have seen it once
before and
need to confirm both details and substance.

The comment is that you will save yourself time by using google to get
some tutorial
material on Fortran. Even an old text book on F77 available for free as
a pdf would
qualify but beware that it is not current on multiple worthy later
enhancements. There
are Language Reference Manuals associated with the various vendors to
give the current
version. They will either be full pdf files or a web version. If you
are doing any amount
of Fortran, or are just interested in doing a decent comparison to
broaden your knowledge,
then get a copy of a current book.

As is you are drawing commentary on a lack of analysis of your problem
so are just
mimicking the C details, an inability to tame your newsreader and an a
ability to pose
questions that seem to show that you have not bothered to find out
anything about
Fortran. All things that mean the number of folks who are inclined to
respond to
your questions will decline quickly. There are a couple names that seem
to be of
characters who are more intent on expressing their disdain for Fortran
or starting
flame wars who appear now and then. They seem to be mostly ignored and
fortunately
seem to loose interest and stay away.

c.l.f is usually helpful but you at least need to show that you are
trying to help
yourself.






Wolfgang Kilian

unread,
Aug 27, 2012, 9:37:44 AM8/27/12
to
On 08/27/2012 02:37 PM, Ron Shepard wrote:
> In article<k1fdqr$dvo$1...@dont-email.me>,
> Wolfgang Kilian<see...@domain.invalid> wrote:
>
>> - Functions are good because you see that there is a return value by
>> just looking at the call. For a subroutine you have to scan the code or
>> the docs for the interface, to know which argument is INTENT(OUT/INOUT)
>
> You still need to scan the code to see which arguments are modified
> even with functions.
>
>>
>> y = f (x, args)
>>
>> - But this is valid only if all functions are pure, i.e., all arguments
>> are INTENT(IN).
>
> That is not what PURE means in fortran. In fortran PURE functions
> and subroutines can modify arguments.

Oops, thanks - I shouldn't have used the term 'pure' here. It's a style
choice that I try to follow: use functions only if all arguments are
INTENT(IN), otherwise subroutines. The Fortran standard has no means to
enforce this.
Fully agreed. And as soon as PURE statements have been introduced on
several levels, there is inevitably the point where you _need_ to write
out and check some intermediate results, maybe after changing a single
line somewhere. Or so it happens with the code I have been working on.

>
> $.02 -Ron Shepard

Dick Hendrickson

unread,
Aug 27, 2012, 10:41:21 AM8/27/12
to
On 8/27/12 7:37 AM, Ron Shepard wrote:
> In article<k1fdqr$dvo$1...@dont-email.me>,
> Wolfgang Kilian<see...@domain.invalid> wrote:
>
>> - Functions are good because you see that there is a return value by
>> just looking at the call. For a subroutine you have to scan the code or
>> the docs for the interface, to know which argument is INTENT(OUT/INOUT)
>
> You still need to scan the code to see which arguments are modified
> even with functions.
>
>>
>> y = f (x, args)
>>
>> - But this is valid only if all functions are pure, i.e., all arguments
>> are INTENT(IN).
>
> That is not what PURE means in fortran. In fortran PURE functions
> and subroutines can modify arguments.

I don't see what you are driving at here. PURE procedures have a ton of
constraints and they are summarized in a note:

From F2003

"NOTE 12.44
The above constraints are designed to guarantee that a pure procedure is
free from side effects (modifications of data visible outside the
procedure)...."

I think the constraints on PURE procedures apply to more than just their
arguments. They apply to anything visible, like common or module
variables, or even I/O (other than internal).

The arguments don't have to all be INTENT(IN). Some can be procedures,
there are exceptions for pointers, and PURE subroutines can modify their
arguments (but not functions).

Dick Hendrickson

Ian Harvey

unread,
Aug 27, 2012, 10:56:44 AM8/27/12
to
On 2012-08-27 10:37 PM, Ron Shepard wrote:
> In article <k1fdqr$dvo$1...@dont-email.me>,
> Wolfgang Kilian <see...@domain.invalid> wrote:
>
>> - Functions are good because you see that there is a return value by
>> just looking at the call. For a subroutine you have to scan the code or
>> the docs for the interface, to know which argument is INTENT(OUT/INOUT)
>
> You still need to scan the code to see which arguments are modified
> even with functions.
>
>>
>> y = f (x, args)
>>
>> - But this is valid only if all functions are pure, i.e., all arguments
>> are INTENT(IN).
>
> That is not what PURE means in fortran. In fortran PURE functions
> and subroutines can modify arguments.

In F95 or F2003 functions cannot modify their arguments - noting the
rules for functions are different to those for subroutines.

But in F2008 I'm not so sure. If the change (pointer dummy data
arguments can be changed?) is intentional then I'm surprised. Whoever
kept Note 12.50 in F2008 might be surprised too.

(This change doesn't seem right... I must be missing something -
allowing pure functions to arbitrarily modify what could be global
program state in an opaque way defeats the whole point of pure functions
- doesn't it?)

Richard Maine

unread,
Aug 27, 2012, 11:43:46 AM8/27/12
to
Ron Shepard <ron-s...@NOSPAM.comcast.net> wrote:

> That is not what PURE means in fortran. In fortran PURE functions
> and subroutines can modify arguments.

Subroutines, yes. Functions, no.

I have to run, so no time to say anything else, which is probably for
the better anyway.

Though I'll just briefly repeat my personal opinion that functions that
return pointers are a very bad idea. Even experts screw up when trying
to use them - quite regularly. As for novices - well I have said that if
someone doesn't throughly understand the reasons why I recomend against
such functions, then that person has pretty much no chance of using them
without having lots of bugs. I'd say that deliberate use of
pointer-returning functions is sufficient reason for me to decline to
help people with debugging. That's a case of digging their own hole.

Sjouke Burry

unread,
Aug 27, 2012, 3:57:28 PM8/27/12
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote in
news:k1etug$val$1...@speranza.aioe.org:

> In comp.lang.fortran Dick Hendrickson <dick.hen...@att.net>
> wrote:
>
> (snip)
>>> In the CALL form, it isn't obvious what (if anything) the subroutine
>>> is doing, and -- in particular -- which dummy argument is the one
>>> being used by the subroutine to return a value.
>
>>> Thus, the form x = f(arguments) is preferred.
>
>> "is preferred" probably needs a "by whom" qualifier ;) .
>
>> The problem with functions (as Richard mentions somewhere upthread)
>> is side effects. If you routinely use x = f(arguments) then someday
>> you'll write something like
>
>> x(i,j) = f( [maybe]x, [or maybe]i, [or maybe]j, other
>> arguments)
>
>> and be really surprised at what a standard conforming optimizer does
>> for you if f does anything to its arguments. Functions (especially
>> for C programmers)
>
> C has strict rules on when you can, and can't, expect things to
> have the appropriate value in the case of side effects. The are
> sometimes surprising to C programmers, too, though.
>
> You don't even need functions, just an ordinary expression like:
>
> j=(i++)+(++i);

You mean a totally illegal expression in C should mean something
in fortran??????????
Pew.... How do you translate an illegal expression???????????
And how is that just an ordinary expression???????????????
Please dont offer me such "ordinary" code.

Ian Harvey

unread,
Aug 27, 2012, 5:20:43 PM8/27/12
to
I think you need to add the necessary standard checking option to the
gfortran command line to be sure, but with that I think you are right
for the "test =>" case at least. F2003/F2008 12.5.2/12.6.2:

If RESULT is not specified, the result is /function-name/ and
all occurrences of the function name in /execution-part/
statements are references to the result variable.

The declaration of test2 is not in the executable part. There are words
in the [Scope of] Local identifiers bit (16.2/16.3.1) that there are
limited uses of the function name inside the function, one of which is
recursive references to the function, which I guess the declaration of
the procedure pointer could perhaps be?

In the "test =>" case I think syntax rules are being broken, so
diagnostics are required.

Recent ifort also doesn't complain.

Richard Maine

unread,
Aug 27, 2012, 5:37:11 PM8/27/12
to
Ian Harvey <ian_h...@bigpond.com> wrote:

> The declaration of test2 is not in the executable part. There are words
> in the [Scope of] Local identifiers bit (16.2/16.3.1) that there are
> limited uses of the function name inside the function, one of which is
> recursive references to the function, which I guess the declaration of
> the procedure pointer could perhaps be?

I didn't study the example code and don't have any direct comment on it,
but I do have a comment on the above.

No, a declaration is never a "reference" in the technical sense used in
the standard. "Reference" in the standard has a very particular meaning
much more specific than the general English usage. A reference of a
variable is its use in a context that requires its value. Thus, for
example

x = whatever

is not a reference to x. Nor is any declaration of x a reference to it.

For a procedure, a reference is a use in a context that requires
invocation of the procedure. That would not include anything like a
declaration of a procedure pointer. The fact that the procedue might
later get invoked via the procedure pouinter is irrelevant. A procedure
pointer declaration itself is not a reference.

Gary Scott

unread,
Aug 27, 2012, 8:11:42 PM8/27/12
to
On 8/27/2012 8:37 AM, Wolfgang Kilian wrote:
> On 08/27/2012 02:37 PM, Ron Shepard wrote:
>> In article<k1fdqr$dvo$1...@dont-email.me>,
>> Wolfgang Kilian<see...@domain.invalid> wrote:
>>
>>> - Functions are good because you see that there is a return value by
>>> just looking at the call. For a subroutine you have to scan the code or
>>> the docs for the interface, to know which argument is INTENT(OUT/INOUT)
>>
>
> Oops, thanks - I shouldn't have used the term 'pure' here. It's a style
> choice that I try to follow: use functions only if all arguments are
> INTENT(IN), otherwise subroutines. The Fortran standard has no means to
> enforce this.

Very small percentage of programming can get by with this approach.
Vast majority needs to call a C API at some point (OS, graphics, etc.).

Ian Harvey

unread,
Aug 27, 2012, 9:54:30 PM8/27/12
to
On 2012-08-28 12:56 AM, Ian Harvey wrote:
> On 2012-08-27 10:37 PM, Ron Shepard wrote:
>> In article <k1fdqr$dvo$1...@dont-email.me>,
>> Wolfgang Kilian <see...@domain.invalid> wrote:
>>
>>> - Functions are good because you see that there is a return value by
>>> just looking at the call. For a subroutine you have to scan the code or
>>> the docs for the interface, to know which argument is INTENT(OUT/INOUT)
>>
>> You still need to scan the code to see which arguments are modified
>> even with functions.
>>
>>>
>>> y = f (x, args)
>>>
>>> - But this is valid only if all functions are pure, i.e., all arguments
>>> are INTENT(IN).
>>
>> That is not what PURE means in fortran. In fortran PURE functions
>> and subroutines can modify arguments.

Oops. In case it wasn't clear...

> In F95 or F2003 functions cannot modify their arguments - noting the
^ pure

> rules for functions are different to those for subroutines.
^ pure ^ pure
>
> But in F2008 I'm not so sure. If the change (pointer dummy data
> arguments can be changed?) is intentional then I'm surprised. Whoever
> kept Note 12.50 in F2008 might be surprised too.
>
> (This change doesn't seem right... I must be missing something -
> allowing pure functions to arbitrarily modify what could be global
> program state in an opaque way defeats the whole point of pure functions
> - doesn't it?)

Elaborating... in F2003 the main "don't modify global variables"
constraint (C1272) says:

In a pure subprogram any designator with a base object that
is in common or accessed by host or use association, is a
dummy argument of a pure function, is a dummy argument with
INTENT (IN) of a pure subroutine, or an object that is
storage associated with any such variable, shall not be
used in the following contexts:

(1) In a variable definition context;
(2-4 - don't point *at* them)
(5) As an actual argument associated with a dummy argument
with INTENT(OUT) or INTENT(INOUT) or with the POINTER
attribute.

(I would have thought that INTENT(OUT) and INTENT(INOUT) in (5) counted
as variable definition contexts.)

In F2008, the same five items, but the lead in is different:

In a pure subprogram any designator with a base object that
is in common or accessed by host or use association, is a
dummy argument with the INTENT (IN) attribute, is a coindexed
object, or an object that is storage associated with any such
variable, shall not be used...

The blanket restriction on function dummy arguments being changed has
been dropped! So now we can...

MODULE xyzzy
IMPLICIT NONE
CONTAINS
PURE FUNCTION gimme_a_letter(ptr) RESULT(r)
! ptr is a data pointer, so C1276 doesn't apply.
INTEGER, INTENT(INOUT), POINTER :: ptr
CHARACTER :: r
!***
r = ACHAR(ptr+IACHAR('A')-1)
! ptr's base object isn't in common, accessed by use or
! host association, isn't a dummy argument with INTENT(IN),
! isn't coindexed, isn't storage associated with anything,
! relevant, so C1283 doesn't apply. We can change it!
ptr = ptr + 1
END FUNCTION gimme_a_letter
END MODULE xyzzy

PROGRAM abczyx
USE xyzzy
IMPLICIT NONE
CHARACTER(26) :: alphabet
INTEGER, POINTER :: ptr
!***
ALLOCATE(ptr, SOURCE=1)
FORALL (INTEGER :: i = 1:LEN(alphabet)) &
alphabet(i:i) = gimme_a_letter(ptr)
PRINT "(A)", alphabet
END PROGRAM abczyx

(Apologies for any syntax errors - hopefully my intent is clear...)

What gets printed?

Ron Shepard

unread,
Aug 28, 2012, 12:05:02 AM8/28/12
to
In article <1kph9a0.10o0f321nh0ho8N%nos...@see.signature>,
nos...@see.signature (Richard Maine) wrote:

> > That is not what PURE means in fortran. In fortran PURE functions
> > and subroutines can modify arguments.
>
> Subroutines, yes. Functions, no.

Thanks to Richard and the others for correcting my mistake. I hope
this did not mislead the original poster before the corrections
appeared.

$.02 -Ron Shepard

Wolfgang Kilian

unread,
Aug 28, 2012, 2:49:28 AM8/28/12
to
I don't get the point, why is this related to Fortran's
function/subroutine or INTENT(IN/OUT) distinction?

I understand that Fortran is used predominantly in scientific computing,
where the main purpose of programs is to calculate numbers, and the
underlying mathematics is expressible in terms of functions (in the
mathematical sense). Most of this can and should be done without side
effects or INTENT(OUT) arguments. Otherwise, use subroutines.

Wolfgang Kilian

unread,
Aug 28, 2012, 3:00:00 AM8/28/12
to
On 08/28/2012 08:49 AM, Wolfgang Kilian wrote:

> Most of this can and should be done without side
> effects or INTENT(OUT) arguments. Otherwise, use subroutines.

... correcting myself: that's obviously too strong as a general rule.
The point is still to use functions (in new code) only if there are
neither side effects nor INTENT(OUT) arguments. Why not?

Wolfgang Kilian

unread,
Aug 28, 2012, 4:05:37 AM8/28/12
to
On 08/27/2012 05:43 PM, Richard Maine wrote:
> [...]

> Though I'll just briefly repeat my personal opinion that functions that
> return pointers are a very bad idea. Even experts screw up when trying
> to use them - quite regularly. As for novices - well I have said that if
> someone doesn't throughly understand the reasons why I recomend against
> such functions, then that person has pretty much no chance of using them
> without having lots of bugs.

(I sort of expected that I would trigger this comment by expressing my
[also personal] opinion..)

I did experience quite a few of difficult-to-find bugs by using pointers
since Fortran 90, in particular nonlocal pointers. Both in (my) code
and in compilers. It just happens that I don't remember a problem
related to pointer-returning functions. In fact, the most common coding
mistake was not too keep proper track of TARGET attributes. Maybe, I
use such functions only in a very restrictive way. Probably I'm neither
novice nor expert.

Fortunately, with each iteration of the Fortran standard, the number of
situations where pointers are really necessary decreases rapidly.

glen herrmannsfeldt

unread,
Aug 28, 2012, 5:02:46 AM8/28/12
to
Wolfgang Kilian <see...@domain.invalid> wrote:

(snip)
> I did experience quite a few of difficult-to-find bugs by using pointers
> since Fortran 90, in particular nonlocal pointers. Both in (my) code
> and in compilers. It just happens that I don't remember a problem
> related to pointer-returning functions. In fact, the most common coding
> mistake was not too keep proper track of TARGET attributes. Maybe, I
> use such functions only in a very restrictive way. Probably I'm neither
> novice nor expert.

There are a few things that are much easier with pointers,
such as linked lists and trees. For those cases, I don't see much
wrong with functions returning pointers.

It is not good for a function to return the only pointers to
something, such that the caller is responsible for deallocating it.
Returning an element of a linked list or a node of a tree,
as a pointer, shouldn't be so bad, though. There should be a
list or tree deallocator, though.

> Fortunately, with each iteration of the Fortran standard, the number of
> situations where pointers are really necessary decreases rapidly.

-- glen

Wolfgang Kilian

unread,
Aug 28, 2012, 5:44:47 AM8/28/12
to
On 08/28/2012 11:02 AM, glen herrmannsfeldt wrote:
> Wolfgang Kilian<see...@domain.invalid> wrote:
>
> (snip)
>> I did experience quite a few of difficult-to-find bugs by using pointers
>> since Fortran 90, in particular nonlocal pointers. Both in (my) code
>> and in compilers. It just happens that I don't remember a problem
>> related to pointer-returning functions. In fact, the most common coding
>> mistake was not too keep proper track of TARGET attributes. Maybe, I
>> use such functions only in a very restrictive way. Probably I'm neither
>> novice nor expert.
>
> There are a few things that are much easier with pointers,
> such as linked lists and trees. For those cases, I don't see much
> wrong with functions returning pointers.

And IIRC, Fortran 2008 introduces recursive derived types with
ALLOCATABLE components, so pointers will no longer be required for
allocating ordinary lists/trees - hopefully.

> It is not good for a function to return the only pointers to
> something, such that the caller is responsible for deallocating it.
> Returning an element of a linked list or a node of a tree,
> as a pointer, shouldn't be so bad, though. There should be a
> list or tree deallocator, though.

Final subroutines - which unfortunately are among the last parts of
F2003 to be implemented in compilers.

>> Fortunately, with each iteration of the Fortran standard, the number of
>> situations where pointers are really necessary decreases rapidly.
>
> -- glen

Gary Scott

unread,
Aug 28, 2012, 8:38:41 AM8/28/12
to
On 8/28/2012 1:49 AM, Wolfgang Kilian wrote:
> On 08/28/2012 02:11 AM, Gary Scott wrote:
>> On 8/27/2012 8:37 AM, Wolfgang Kilian wrote:
>>> On 08/27/2012 02:37 PM, Ron Shepard wrote:
>>>> In article<k1fdqr$dvo$1...@dont-email.me>,
>>>> Wolfgang Kilian<see...@domain.invalid> wrote:
>>>>
>>>>> - Functions are good because you see that there is a return value by
>>>>> just looking at the call. For a subroutine you have to scan the
>>>>> code or
>>>>> the docs for the interface, to know which argument is
>>>>> INTENT(OUT/INOUT)
>>>>
>>>
>>> Oops, thanks - I shouldn't have used the term 'pure' here. It's a style
>>> choice that I try to follow: use functions only if all arguments are
>>> INTENT(IN), otherwise subroutines. The Fortran standard has no means to
>>> enforce this.
>>
>> Very small percentage of programming can get by with this approach. Vast
>> majority needs to call a C API at some point (OS, graphics, etc.).
>>
>
> I don't get the point, why is this related to Fortran's
> function/subroutine or INTENT(IN/OUT) distinction?

:(

>
> I understand that Fortran is used predominantly in scientific computing,
> where the main purpose of programs is to calculate numbers, and the
> underlying mathematics is expressible in terms of functions (in the
> mathematical sense). Most of this can and should be done without side
> effects or INTENT(OUT) arguments. Otherwise, use subroutines.
>
> -- Wolfgang
>

Fortran is a general purpose programming language. It is used for a
wide variety and type of applications. The majority of those need to
call C APIs which don't abide by the restricted use of functions as only
for calculating a return value (they nearly all have side effects with
the return value being an error code).

>

Wolfgang Kilian

unread,
Aug 28, 2012, 9:01:43 AM8/28/12
to
On 08/28/2012 02:38 PM, Gary Scott wrote:
> On 8/28/2012 1:49 AM, Wolfgang Kilian wrote:
>> On 08/28/2012 02:11 AM, Gary Scott wrote:
>> [...]
>> I understand that Fortran is used predominantly in scientific computing,
>> where the main purpose of programs is to calculate numbers, and the
>> underlying mathematics is expressible in terms of functions (in the
>> mathematical sense). Most of this can and should be done without side
>> effects or INTENT(OUT) arguments. Otherwise, use subroutines.
>>
>> -- Wolfgang
>>
>
> Fortran is a general purpose programming language. It is used for a wide
> variety and type of applications. The majority of those need to call C
> APIs which don't abide by the restricted use of functions as only for
> calculating a return value (they nearly all have side effects with the
> return value being an error code).

This is true, but also tends to be system-dependent, so Fortran wrapper
(sub)routines are likely to be present that localize the system
dependencies. For OpenMP, MPI, Lapack, etc. there are native Fortran
interfaces, which have their own conventions anyway.

Richard Maine

unread,
Aug 28, 2012, 11:49:19 AM8/28/12
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

> There are a few things that are much easier with pointers,
> such as linked lists and trees. For those cases, I don't see much
> wrong with functions returning pointers.

I disagree. Strongly. To the extent that my personal opinion is that
pointer function results should have never been added to the language.

> It is not good for a function to return the only pointers to
> something, such that the caller is responsible for deallocating it.
> Returning an element of a linked list or a node of a tree,
> as a pointer, shouldn't be so bad, though. There should be a
> list or tree deallocator, though.

Again, I disagree. Deallocation is not the only problem.

It is also far too easy to make a simple typo by writing = instead of =>
for the invocation of such a function. You end up with a statement that
is legal, but code that doesn't work.

I'll repeat my prior more general observation about functions, which
directly applies to those returning pointers.

If you have a function whose only references are in the simple form

x = f(arguments)

without ever involving evaluation of an expression other than the
trivial one that consists of just the function reference as the only
primary, then you are not taking advantage of the procedure being a
function. It might as well be a subroutine. The same argument applies to
the pointer form

p => pointer_function(arguments)

But with the pointer form, all invocations pretty much have to be of
that form to avoid problems. If you reference the pointer function in
the middle of an expression, you just get the dereferenced target
anyway, so that might as well just have been the result instead of the
pointer.

Yes, there are rare special cases where you can get by with it. But
those are far more rare than the buggy cases, and do not, in my opinion,
justify using the error-prone form. You can always get by without the
function. Posting some example where you think the use safe is not going
to convince me that the practice is wise.

Heck, I have seen relatively experienced people in this forum post
examples of special cases where they considered pointer-valued functions
to be safe, but instead managed to illustrate my point by having a
related bug in the posted example (namely by typing = instead of =>).

glen herrmannsfeldt

unread,
Aug 28, 2012, 2:16:21 PM8/28/12
to
Richard Maine <nos...@see.signature> wrote:

(snip, I wrote)
>> There are a few things that are much easier with pointers,
>> such as linked lists and trees. For those cases, I don't see much
>> wrong with functions returning pointers.

> I disagree. Strongly. To the extent that my personal opinion is that
> pointer function results should have never been added to the language.

(snip)
> Again, I disagree. Deallocation is not the only problem.

> It is also far too easy to make a simple typo by writing = instead of =>
> for the invocation of such a function. You end up with a statement that
> is legal, but code that doesn't work.

That problem never happens in C or Java.

> I'll repeat my prior more general observation about functions, which
> directly applies to those returning pointers.

> If you have a function whose only references are in the simple form

> x = f(arguments)

> without ever involving evaluation of an expression other than the
> trivial one that consists of just the function reference as the only
> primary, then you are not taking advantage of the procedure being a
> function. It might as well be a subroutine. The same argument applies to
> the pointer form

> p => pointer_function(arguments)

> But with the pointer form, all invocations pretty much have to be of
> that form to avoid problems. If you reference the pointer function in
> the middle of an expression, you just get the dereferenced target
> anyway, so that might as well just have been the result instead of the
> pointer.

So you can't pass the pointer value returned from a function
as an argument to another function or subroutine?

Otherwise, I am not against subroutines instead of functions.

I have done much more linked lists and trees in C and Java,
with pointers and Object references, respectively, than Fortran.

-- glen

Richard Maine

unread,
Aug 28, 2012, 2:32:58 PM8/28/12
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

> Richard Maine <nos...@see.signature> wrote:

> > It is also far too easy to make a simple typo by writing = instead of =>
> > for the invocation of such a function. You end up with a statement that
> > is legal, but code that doesn't work.
>
> That problem never happens in C or Java.

As long as we are into random irrelevancies, it probably also doesn't
happen in Portugese. At least I have trouble imagining how it would (not
that I know any Portugese). But my advice on Fortran programming doesn't
apply to Portugese either.

Phillip Helbig---undress to reply

unread,
Aug 28, 2012, 3:41:52 PM8/28/12
to
In article <k1ie4g$l44$1...@dont-email.me>, Gary Scott
<garyl...@sbcglobal.net> writes:

> Fortran is a general purpose programming language.

Yes.

> It is used for a
> wide variety and type of applications.

Yes.

> The majority of those need to
> call C APIs

Really? First, how is majority defined: programs, programmers, lines of
code, hours of CPU time, number of users,...? Second, what is your
source for this claim?

glen herrmannsfeldt

unread,
Aug 28, 2012, 3:50:03 PM8/28/12
to
Richard Maine <nos...@see.signature> wrote:

(snip)
>> Richard Maine <nos...@see.signature> wrote:

>> > It is also far too easy to make a simple typo by writing = instead of =>
>> > for the invocation of such a function. You end up with a statement that
>> > is legal, but code that doesn't work.

(then I wrote)
>> That problem never happens in C or Java.

> As long as we are into random irrelevancies, it probably also doesn't
> happen in Portugese. At least I have trouble imagining how it would (not
> that I know any Portugese). But my advice on Fortran programming doesn't
> apply to Portugese either.

Well, that it true.

But also C has a different way to indicate if you want the pointer
or the pointee. Also, a special operator to dereference a structure
pointer, as that happens often enough.

Java has Object reference variables instead of pointers, and
you can't do some things that you can with C pointers. Still,
without any operators, you get the value of the reference and
not the value of the object.

Now, for my actual question from the previous post, can you
pass the pointer value from a function as an actual argument
to a subroutine or another function? As you note, in many
contexts a pointer variable has the value (l-value or r-value)
of the pointee. But maybe not as an actual argument to a pointer
dummy argument.

-- glen

Richard Maine

unread,
Aug 28, 2012, 4:21:05 PM8/28/12
to
Phillip Helbig---undress to reply <hel...@astro.multiCLOTHESvax.de>
wrote:
That seems like.... um... quite a reaction.

I don't know about Gary's, but my source for simillar data is personal
observation. I don't claim anything so precise as to merit
quantification by counting any of the above measures. I probably would
not have used a quantitative term like "majority". But it is sure a lot,
based, as noted on personal observation.

For codes I have personally written, an awful lot of them interface with
C code one way or another. My measurement for "awful lot" in that case
is based on the importance of the codes, which in turn is measured by
the amount of use the codes got. All measurements, of course, off the
top of my head instead of hard data. Sure, I have written many, many
quickies of only a few hundred lines that get briefly used and tossed;
those don't count for much in my measurement. But the apps people
remember me for - ones I wrote 20+ years ago and are still in use - all
of those involve some degree or other of C interfacing. They get data
from database interfaces in C. They do communication between machines in
C. Some of them did things with C that have subsequently been adopted
into the Fortran standard, but my codes still have the old C interfacing
versions; spawning external programs is one example of that. That one
got used in an awful lot of my apps, if only for things like displaying
help files. Yes, I had a trivial "plan b" version in case I was stuck
doing a port somewhere that I really could not be bothered to spawn an
external program, but as a rule, it was a lot less work to spawn an
external text browsing program than to try to hack a good portable one
together in Fortran (particularly if one is sticking with strictly
standard Fortran, which is a bit limitting in terms of nice
interactivity with keyboards).

In the other direction, several of my "apps" mostly constitute libraries
used by programs that other people write; some of those programs are
Fortran, and some are C.

The personal observation also extends to second-hand data, again nothing
so quantitative as lines of code. More like number of people. Seems like
I couldn't turn around without running into people who had questions
about interfacing Fortran and C. That's been both on this newsgroup
(pretty hard not to notice here, I'd have thought).

There were sure enough people asking, and asking emphatically enough,
that it got heard by the Fortran standards committee. I once made the
statementon the committee floor that C interop was the single most
important feature in f2003 - the only feature that I considered so
important that the standard could not be released without doing. I
suppose that the fact that I heard no contradiction didn't necessarily
mean that everyone there agreed 100% with that, but it was sure clear
that there was strong agreement that C interop in the Fortran standard
was important.

The measurement for that was almost surely based on the number of people
vehemantly demanding it rather than on any carefully quantitative
measure like lines of code. Though I would guess there to be a
correlation with the size of the applications involved. I suspect that
the larger the app, the more likely it is that C interop is going to
come up somewhere in it.

Richard Maine

unread,
Aug 28, 2012, 4:35:21 PM8/28/12
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

> Richard Maine <nos...@see.signature> wrote:
>
> (snip)
> >> Richard Maine <nos...@see.signature> wrote:
>
> >> > It is also far too easy to make a simple typo by writing = instead of =>
> >> > for the invocation of such a function. You end up with a statement that
> >> > is legal, but code that doesn't work.
>
> (then I wrote)
> >> That problem never happens in C or Java.
>
> > As long as we are into random irrelevancies, it probably also doesn't
> > happen in Portugese. At least I have trouble imagining how it would (not
> > that I know any Portugese). But my advice on Fortran programming doesn't
> > apply to Portugese either.
>
> Well, that it true.
>
> But also C has a different way to indicate if you want the pointer
> or the pointee....

And is different in many other ways as well. One of those differences is
that there is no such thing as a subroutine in C. Everything is a
function. So my advice to avoid using functions for the purpose would be
about as applicable as my comment about Portugese. (Functions returning
void are still functions).

> Now, for my actual question from the previous post, can you
> pass the pointer value from a function as an actual argument
> to a subroutine or another function?

I deliberately avoided answering that, as I considered the question of
whether you can to have no bearing on my advice about whether you
should.

To literally answer, of course you can (as in the standard allows it) in
some situations, but they probably aren't what you are thinking of. If
the dummy argument is a non-pointer data argument with intent(in), then
the actual argument can be an expression. A pointer can be a valid
primary in an expression and gives the value of its target.

I sort of doubt that's what you were asking about, but then I have a
history of guessing incorrectly about what you are talking about, so I
figured I'd give a completely literal answer just in case.

For the more "interesting" cases, I think I recall an interp on the
question. I believe the answer to have been "no" for f2003, though I
can't swear to that. I also think I recall at least a proposal to add
that as a feature in f2008, but I don't know what happened to that
proposal. Afraid I'm not interested in doing the research to dig out the
interp or the proposal; they aren't handy at my fingertips. My advice
remains "don't do that". If you want to procede against my advice,
that's fine, but I'm not oferring to help in the research.

James Van Buskirk

unread,
Aug 28, 2012, 4:44:19 PM8/28/12
to
"Wolfgang Kilian" <see...@domain.invalid> wrote in message
news:k1iffm$vdj$1...@dont-email.me...
No Fortran wrappers for Win32 API nor OpenGL. Just use C interop to
tell the compiler how to invoke the procedures (or be invoked by
them) and the interface is direct.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


James Van Buskirk

unread,
Aug 28, 2012, 4:48:08 PM8/28/12
to
"Wolfgang Kilian" <see...@domain.invalid> wrote in message
news:k1i3ue$rld$1...@dont-email.me...

> And IIRC, Fortran 2008 introduces recursive derived types with ALLOCATABLE
> components, so pointers will no longer be required for allocating ordinary
> lists/trees - hopefully.

How in the world is that going to work? You have to insert into,
delete from, and rebalance trees. Can you really do all the
necessary shuffling with allocatables rather than pointers?

ken.fa...@gmail.com

unread,
Aug 28, 2012, 4:54:03 PM8/28/12
to
On Tuesday, August 28, 2012 1:21:07 PM UTC-7, Richard Maine wrote:
> Phillip Helbig---undress to reply <hel...@astro.multiCLOTHESvax.de>
>
> wrote:
>
>
>
> > In article <k1ie4g$l44$1...@dont-email.me>, Gary Scott
>
> > <garyl...@sbcglobal.net> writes:
>
> >
>
> > > Fortran is a general purpose programming language.
>
> >
>
> > Yes.
>
> >
>
> > > It is used for a
>
> > > wide variety and type of applications.
>
> >
>
> > Yes.
>
> >
>
> > > The majority of those need to
>
> > > call C APIs
>
> >
>
> > Really? First, how is majority defined: programs, programmers, lines of
>
> > code, hours of CPU time, number of users,...? Second, what is your
>
> > source for this claim?
>
>
>
> That seems like.... um... quite a reaction.
[...]

I suspect Phillip's reaction stems from his (like mine)
"sheltered upbringing" on VMS. :-) Unlike the various
*nix, whose programming language and utilites are almost
universally coded in C, VMS as an operating system is
language-neutral in it's interfaces to library and
system service routines.

One is easily (for some values of "easily" :-) able to
call routines written in one language from essentially
all other supported languages, which gives the possibility
for people to code in which ever language they like, or is
most appropriate to the task, and link their procedures into
a larger program written in some other language. In practice,
of course, only a subset of languages is used in any
organization, but...

Given the run-time library support in VMS, there's rarely a
need to call another language for system support stuff, whether
spawning a subprocess to do <whatever>, including running
another program, or calling the print symbiont routines to
setup a print job with full controll of the parameters
without having to spawn a "Print" command.

Anyway, VMS is long in tooth and sits in my hobby cube at home
by now as linux and similar occupy my "real" work these days,
but I can understand Phillip's reaction given the previous
context.

-Ken

Phillip Helbig---undress to reply

unread,
Aug 28, 2012, 5:01:41 PM8/28/12
to
In article <1kpjfo7.1f7fdk1qdtmsqN%nos...@see.signature>,
nos...@see.signature (Richard Maine) writes:

> That seems like.... um... quite a reaction.

Just curious. :-|

Since almost all of my Fortran programming has been on VMS, it is quite
easy to avoid C there. (C on VMS is fine, but it doesn't have the
special status it does under unix.) Other codes I am familiar with are
weather- and climate-modelling codes, run on Crays back when I was
working in that area. No C as far as I know. I don't know if I am
typical; I'm pretty sure I am not. However, I think almost all people
have the tendency to think that their own experience is more typical
than it is.

Richard Maine

unread,
Aug 28, 2012, 5:03:12 PM8/28/12
to
James Van Buskirk <not_...@comcast.net> wrote:

> "Wolfgang Kilian" <see...@domain.invalid> wrote in message
> news:k1i3ue$rld$1...@dont-email.me...
>
> > And IIRC, Fortran 2008 introduces recursive derived types with ALLOCATABLE
> > components, so pointers will no longer be required for allocating ordinary
> > lists/trees - hopefully.
>
> How in the world is that going to work? You have to insert into,
> delete from, and rebalance trees. Can you really do all the
> necessary shuffling with allocatables rather than pointers?

I briefly wondered about that myself when Wolfgang posted that. I
decided that you probably could, not that I sat down and verified it in
detail. I'm not sure that I'd actually choose to do it that way myself.
My aversion to pointer function results doesn't extend to rejection of
pointers in all roles. Heck, a lot of list/tree structures end up having
pointers to external data anyway. I think I'd still stick with pointers
for purposes like lists/trees, but on due consideration (several seconds
worth), I think it is probably possible with allocatable components.

The "magic words" are move_alloc. I think that's what makes it possible.

Phillip Helbig---undress to reply

unread,
Aug 28, 2012, 5:08:29 PM8/28/12
to
In article <bd89f399-1e8d-4755...@googlegroups.com>,
ken.fa...@gmail.com writes:

> I suspect Phillip's reaction stems from his (like mine)
> "sheltered upbringing" on VMS. :-)

To some extent, yes.

> Unlike the various
> *nix, whose programming language and utilites are almost
> universally coded in C, VMS as an operating system is
> language-neutral in it's interfaces to library and
> system service routines.

Right. This is one of the many reasons we love VMS. It is just a
rumour, though, that all languages are used somewhere in VMS if only to
ensure that all RTLs have to ship with the OS. VMS itself was written
in a variety of languages, one of the main ones being BLISS (which is
also the case with Rdb), but there is C, Fortran (I think), PL/I,
Pascal, MACRO (VAX assembler), DCL (VMS "shell" language), maybe even
some BASIC and COBOL.

The main point, though, is that support for all languages is good
(except that Fortran support stopped after 95) and the OS itself is
language-neutral, at least in the way it presents itself to the user or
programmer.

> One is easily (for some values of "easily" :-) able to
> call routines written in one language from essentially
> all other supported languages, which gives the possibility
> for people to code in which ever language they like, or is
> most appropriate to the task, and link their procedures into
> a larger program written in some other language.

Right.

> Given the run-time library support in VMS, there's rarely a
> need to call another language for system support stuff, whether
> spawning a subprocess to do <whatever>, including running
> another program, or calling the print symbiont routines to
> setup a print job with full controll of the parameters
> without having to spawn a "Print" command.

Just the system services in VMS are probably more involved than some
other entire operating systems (no joke).

> Anyway, VMS is long in tooth and sits in my hobby cube at home

Of course, new code is still being written for VMS, in a variety of
languages.

Richard Maine

unread,
Aug 28, 2012, 5:13:34 PM8/28/12
to
Phillip Helbig---undress to reply <hel...@astro.multiCLOTHESvax.de>
wrote:

> Since almost all of my Fortran programming has been on VMS, it is quite
> easy to avoid C there.

Yeah. Been there. I rather liked VMS in its day, and that was one of the
many things I liked about it. But it was a long time ago. Not all
changes are good, and the industry seems to have slid back quite a bit
on some things like that. I don't have to like it, but I do have to
adapt to it anyway. You were asking about how "majority" was defined.
I'd say it was a pretty easy bet that by pretty much any plausible
measure, the very large majority of new code today is not written for
VMS systems.

Tobias Burnus

unread,
Aug 28, 2012, 5:15:02 PM8/28/12
to
James Van Buskirk:
> "Wolfgang Kilian" <see...@domain.invalid> wrote in message
> news:k1i3ue$rld$1...@dont-email.me...
>
>> And IIRC, Fortran 2008 introduces recursive derived types with ALLOCATABLE
>> components, so pointers will no longer be required for allocating ordinary
>> lists/trees - hopefully.
>
> How in the world is that going to work?

Well, you simply allocate them
allocate(a%next)
a%next%val = value
or you use
a = t(next=a, val=value)
to extend them.

Hopefully without a full reallocation. I think at some point, compilers
will handle this case. Especially if the latter works, it makes it
rather simple to use it to implement a stack.

> You have to insert into,
> delete from, and rebalance trees.

Well, deleting is possible - but not arbitrary deleting.

If you want to rebalence a tree or delete from an arbitrary position, it
is better to use a pointer and not an allocatable.

> Can you really do all the
> necessary shuffling with allocatables rather than pointers?

No.

Tobias

Phillip Helbig---undress to reply

unread,
Aug 28, 2012, 5:30:02 PM8/28/12
to
In article <1kpjj3k.8skwm51jxpa2oN%nos...@see.signature>,
nos...@see.signature (Richard Maine) writes:

> > Since almost all of my Fortran programming has been on VMS, it is quite
> > easy to avoid C there.
>
> Yeah. Been there. I rather liked VMS in its day, and that was one of the
> many things I liked about it. But it was a long time ago.

It has almost vanished from academia. It is still alive in many other
areas.

> Not all
> changes are good, and the industry seems to have slid back quite a bit
> on some things like that.

Indeed.

> I don't have to like it, but I do have to
> adapt to it anyway. You were asking about how "majority" was defined.
> I'd say it was a pretty easy bet that by pretty much any plausible
> measure, the very large majority of new code today is not written for
> VMS systems.

Certainly true. Probably Unix (including Linux), then Windows, then
Apple stuff (which is Unix under the hood) (if an app counts as code).
However, the very large majority of new code today is not written in
Fortran either, so it's not clear what the implications are of the fact
that other OS's are more popular today.

Wolfgang Kilian

unread,
Aug 29, 2012, 4:32:57 AM8/29/12
to
On 08/28/2012 10:48 PM, James Van Buskirk wrote:
> "Wolfgang Kilian"<see...@domain.invalid> wrote in message
> news:k1i3ue$rld$1...@dont-email.me...
>
>> And IIRC, Fortran 2008 introduces recursive derived types with ALLOCATABLE
>> components, so pointers will no longer be required for allocating ordinary
>> lists/trees - hopefully.
>
> How in the world is that going to work? You have to insert into,
> delete from, and rebalance trees. Can you really do all the
> necessary shuffling with allocatables rather than pointers?

I thought that was the rationale for introducing type-recursive
allocatable components?

In any case, since I have uses for this anyway, I wrote a short module
that can build a list, print, and extract/insert list slices at
arbitrary position. That should cover all cases, right? (If you like,
you may turn the idea into a generic list handler.) I checked the
program as a pointer version, but it is trivial to eliminate all
pointers in favor of allocatables (see below). Lacking a F2008
compiler, I couldn't check the version with allocatables only.

The version with allocatables only has no way to involuntarily introduce
memory leaks or circles in the data structure.

In the example, list scanning is done by recursive procedures and takes
linear time. It is probably better to do this iteratively and/or use
shortcuts; this would require additional pointers on top of the
allocatable backbone. However, they just point to something, there is
never a (DE)ALLOCATE statement for a pointer, which is the main point of
the argument.

If the reasoning is correct, I would conjecture that pointers can be
eliminated naturally from all data structures that are representable as
a directed acyclical graph. For others, it's also possible, but one
needs additional pointers for back- and circular references, which spoil
the simplicity of the approach.

Here is some code:
----------------------------------------------------------------------
! Simple list-handling module
! using pointers

! To trade all pointers for allocatables:
! - remove the move_alloc subroutine, so the intrinsic is used instead
! - change pointer -> allocatable
! - change associated -> allocated

module list_alloc

implicit none

type :: entry_t
integer :: value = 0
type(entry_t), pointer :: next => null ()
! type(entry_t), allocatable :: next ! not allowed in F2003
end type entry_t

type :: list_t
type(entry_t), pointer :: first => null ()
! type(entry_t), allocatable :: first
end type list_t

contains

subroutine move_alloc (from, to)
type(entry_t), pointer, intent(inout) :: from, to
to => from
from => null ()
end subroutine move_alloc

subroutine append_entry (list, value)
type(list_t), intent(inout) :: list
integer, intent(in) :: value
call find_last_append (list%first)
contains
recursive subroutine find_last_append (entry)
type(entry_t), pointer, intent(inout) :: entry
if (associated (entry)) then
call find_last_append (entry%next)
else
allocate (entry)
entry%value = value
end if
end subroutine find_last_append
end subroutine append_entry

subroutine list_extract_slice (list, slice, beg, len)
type(list_t), intent(inout) :: list
type(list_t), intent(out) :: slice
integer, intent(in) :: beg, len

call split_at_beg (list%first, 1)

contains

recursive subroutine split_at_beg (list_entry, i)
type(entry_t), pointer, intent(inout) :: list_entry
integer, intent(in) :: i
if (associated (list_entry)) then
if (i == beg) then
call move_alloc (list_entry, slice%first)
call join_tail (slice%first, list_entry, 0)
else
call split_at_beg (list_entry%next, i + 1)
end if
end if
end subroutine split_at_beg

recursive subroutine join_tail (slice_entry, last_list_entry, i)
type(entry_t), pointer, intent(inout) :: slice_entry, last_list_entry
integer, intent(in) :: i
if (associated (slice_entry)) then
if (i == len) then
call move_alloc (slice_entry, last_list_entry)
else
call join_tail (slice_entry%next, last_list_entry, i + 1)
end if
end if
end subroutine join_tail

end subroutine list_extract_slice

subroutine list_insert_slice (list, slice, beg)
type(list_t), intent(inout) :: list
type(list_t), intent(inout) :: slice
integer, intent(in) :: beg

call split_at_beg (list%first, 1)

contains

recursive subroutine split_at_beg (list_entry, i)
type(entry_t), pointer, intent(inout) :: list_entry
integer, intent(in) :: i
type(entry_t), pointer :: tail_first
if (associated (list_entry)) then
if (i == beg) then
call move_alloc (list_entry, tail_first)
call move_alloc (slice%first, list_entry)
call join_tail (list_entry, tail_first)
else
call split_at_beg (list_entry%next, i + 1)
end if
end if
end subroutine split_at_beg

recursive subroutine join_tail (list_entry, tail_first)
type(entry_t), pointer, intent(inout) :: list_entry, tail_first
if (associated (list_entry)) then
call join_tail (list_entry%next, tail_first)
else
call move_alloc (tail_first, list_entry)
end if
end subroutine join_tail

end subroutine list_insert_slice

subroutine list_print (list)
type(list_t), intent(in) :: list
call print_entry_rec (list%first)
contains
recursive subroutine print_entry_rec (entry)
type(entry_t), pointer, intent(in) :: entry
if (associated (entry)) then
print *, entry%value
call print_entry_rec (entry%next)
end if
end subroutine print_entry_rec
end subroutine list_print

end module list_alloc


program main

use list_alloc
implicit none

type(list_t) :: list, slice
integer :: i

print *, "Fill list: 1 2 3 4 5 6 7 8 9 10"
do i = 1, 10
call append_entry (list, i)
end do
call list_print (list)
print *

print *, "Extract slice from beg=5, len=3"
call list_extract_slice (list, slice, 5, 3)
print *, "New list: 1 2 3 4 8 9 10"
call list_print (list)
print *
print *, "Slice: 5 6 7"
call list_print (slice)
print *

print *, "Insert slice at beg=3"
call list_insert_slice (list, slice, 3)
print *, "New list: 1 2 5 6 7 3 4 8 9 10"
call list_print (list)

end program main

----------------------------------------------------------------------

Steve Lionel

unread,
Aug 29, 2012, 9:48:21 AM8/29/12
to
On 8/28/2012 5:08 PM, Phillip Helbig---undress to reply wrote:
> It is just a
> rumour, though, that all languages are used somewhere in VMS if only to
> ensure that all RTLs have to ship with the OS. VMS itself was written
> in a variety of languages, one of the main ones being BLISS (which is
> also the case with Rdb), but there is C, Fortran (I think), PL/I,
> Pascal, MACRO (VAX assembler), DCL (VMS "shell" language), maybe even
> some BASIC and COBOL.

To the best of my knowledge, this rumor is not true. I'm fairly certain
there is no BASIC, Pascal, Ada, APL, RPG2 or DIBOL in VMS or its runtime
libraries. There might be a small amount of Fortran.

VMS was language-neutral from the very start, and that is one of the
many things I love about it. Whatever VMS' relevance in today's
computing world is, and it is definitely still used, it embodies many
excellent software engineering practices that have largely been ignored
or abandoned in today's UNIX-derived world. For a long time, the OS
that came closest, I thought, to a disciplined and multi-language
approach to APIs was Windows, but that too is rapidly disappearing,
especially with "the interface formerly known as Metro" and its C++-only
APIs. Upward compatibility of APIs and linked applications was a firm
rule on VMS - again, Windows is quite good at this, Linux most
definitely less so.

--
Steve Lionel
Developer Products Division
Intel Corporation
Merrimack, NH

For email address, replace "invalid" with "com"

User communities for Intel Software Development Products
http://software.intel.com/en-us/forums/
Intel Software Development Products Support
http://software.intel.com/sites/support/
My Fortran blog
http://www.intel.com/software/drfortran

Refer to http://software.intel.com/en-us/articles/optimization-notice
for more information regarding performance and optimization choices in
Intel software products.

James Van Buskirk

unread,
Aug 29, 2012, 2:22:46 PM8/29/12
to
"Wolfgang Kilian" <see...@domain.invalid> wrote in message
news:k1kk3o$2g1$1...@dont-email.me...

> On 08/28/2012 10:48 PM, James Van Buskirk wrote:

>> "Wolfgang Kilian"<see...@domain.invalid> wrote in message
>> news:k1i3ue$rld$1...@dont-email.me...

>>> And IIRC, Fortran 2008 introduces recursive derived types with
>>> ALLOCATABLE
>>> components, so pointers will no longer be required for allocating
>>> ordinary
>>> lists/trees - hopefully.

>> How in the world is that going to work? You have to insert into,
>> delete from, and rebalance trees. Can you really do all the
>> necessary shuffling with allocatables rather than pointers?

> I thought that was the rationale for introducing type-recursive
> allocatable components?

> In any case, since I have uses for this anyway, I wrote a short module
> that can build a list, print, and extract/insert list slices at arbitrary
> position. That should cover all cases, right? (If you like, you may turn
> the idea into a generic list handler.) I checked the program as a pointer
> version, but it is trivial to eliminate all pointers in favor of
> allocatables (see below). Lacking a F2008 compiler, I couldn't check the
> version with allocatables only.

Notice that I referred only to trees, not lists. The usual
implementation of red-black trees has back pointers so this wouldn't
be feasible with only allocatables. AVL trees, like

http://home.comcast.net/~kmbtib/Fortran_stuff/avl.zip

(not as good as some of the java applets around, but at least it's
all in Fortran) require some tricky shuffling, especially during
deletion. gfortran seems to have SUBROUTINE MOVE_ALLOC so maybe it's
possible to attempt the transition to allocatable components in the
above link. I am not sure that I am going to have enough time and
energy in the near future to give it a try, however.

Phillip Helbig---undress to reply

unread,
Aug 29, 2012, 4:47:03 PM8/29/12
to
In article <aa6kt...@mid.individual.net>, Steve Lionel
<steve....@intel.invalid> writes:

> On 8/28/2012 5:08 PM, Phillip Helbig---undress to reply wrote:
> > It is just a
> > rumour, though, that all languages are used somewhere in VMS if only to
> > ensure that all RTLs have to ship with the OS. VMS itself was written
> > in a variety of languages, one of the main ones being BLISS (which is
> > also the case with Rdb), but there is C, Fortran (I think), PL/I,
> > Pascal, MACRO (VAX assembler), DCL (VMS "shell" language), maybe even
> > some BASIC and COBOL.
>
> To the best of my knowledge, this rumor is not true. I'm fairly certain
> there is no BASIC, Pascal, Ada, APL, RPG2 or DIBOL in VMS or its runtime
> libraries. There might be a small amount of Fortran.

OK, I mentioned Pascal without any qualification (like I did for BASIC,
COBOL and even Fortran). But there is definitely BLISS, C, PL/I, MACRO
and DCL.

> VMS was language-neutral from the very start, and that is one of the
> many things I love about it. Whatever VMS' relevance in today's
> computing world is, and it is definitely still used, it embodies many
> excellent software engineering practices that have largely been ignored
> or abandoned in today's UNIX-derived world.

I think anyone who knows both---at least if he has worked in both worlds
under similar conditions---must agree with us here.

Ian Harvey

unread,
Sep 3, 2012, 6:50:43 PM9/3/12
to
(bump, from a different nntp server because I'm seeing lots of orphaned
replies which make me suspect article propagation issues...)

If someone familiar with F2008 can have a look at this - I struggle to
believe that the standard would break the concept of PURE functions, but
from my reading of the draft I think it has.

On 2012-08-28 11:54 AM, Ian Harvey wrote:
> On 2012-08-28 12:56 AM, Ian Harvey wrote:
...
>
> Oops. In case it wasn't clear...
>
>> In F95 or F2003 functions cannot modify their arguments - noting the
> ^ pure
>
>> rules for functions are different to those for subroutines.
> ^ pure ^ pure
>>
>> But in F2008 I'm not so sure. If the change (pointer dummy data
>> arguments can be changed?) is intentional then I'm surprised. Whoever
>> kept Note 12.50 in F2008 might be surprised too.
>>
>> (This change doesn't seem right... I must be missing something -
>> allowing pure functions to arbitrarily modify what could be global
>> program state in an opaque way defeats the whole point of pure functions
>> - doesn't it?)
>
> Elaborating... in F2003 the main "don't modify global variables"
> constraint (C1272) says:
>
> In a pure subprogram any designator with a base object that
> is in common or accessed by host or use association, is a
> dummy argument of a pure function, is a dummy argument with
> INTENT (IN) of a pure subroutine, or an object that is
> storage associated with any such variable, shall not be
> used in the following contexts:
>
> (1) In a variable definition context;
> (2-4 - don't point *at* them)
> (5) As an actual argument associated with a dummy argument
> with INTENT(OUT) or INTENT(INOUT) or with the POINTER
> attribute.
>
> (I would have thought that INTENT(OUT) and INTENT(INOUT) in (5) counted
> as variable definition contexts.)
>
> In F2008, the same five items, but the lead in is different:
>
> In a pure subprogram any designator with a base object that
> is in common or accessed by host or use association, is a
> dummy argument with the INTENT (IN) attribute, is a coindexed
> object, or an object that is storage associated with any such
> variable, shall not be used...
>
> The blanket restriction on function dummy arguments being changed has
> been dropped! So now we can...
>
> MODULE xyzzy
> IMPLICIT NONE
> CONTAINS
> PURE FUNCTION gimme_a_letter(ptr) RESULT(r)
> ! ptr is a data pointer, so C1276 doesn't apply.
> INTEGER, INTENT(INOUT), POINTER :: ptr
> CHARACTER :: r
> !***
> r = ACHAR(ptr+IACHAR('A')-1)
> ! ptr's base object isn't in common, accessed by use or
> ! host association, isn't a dummy argument with INTENT(IN),
> ! isn't coindexed, isn't storage associated with anything,
> ! relevant, so C1283 doesn't apply. We can change it!
> ptr = ptr + 1
> END FUNCTION gimme_a_letter
> END MODULE xyzzy
>
> PROGRAM abczyx
> USE xyzzy
> IMPLICIT NONE
> CHARACTER(26) :: alphabet
> INTEGER, POINTER :: ptr
> !***
> ALLOCATE(ptr, SOURCE=1)
> FORALL (INTEGER :: i = 1:LEN(alphabet)) &
> alphabet(i:i) = gimme_a_letter(ptr)
> PRINT "(A)", alphabet
> END PROGRAM abczyx
>
> (Apologies for any syntax errors - hopefully my intent is clear...)
>
> What gets printed?
>

Dick Hendrickson

unread,
Sep 3, 2012, 7:46:56 PM9/3/12
to
On 9/3/12 5:50 PM, Ian Harvey wrote:
> (bump, from a different nntp server because I'm seeing lots of orphaned
> replies which make me suspect article propagation issues...)
>
> If someone familiar with F2008 can have a look at this - I struggle to
> believe that the standard would break the concept of PURE functions, but
> from my reading of the draft I think it has.

I'm not sure, but I think the issue is that F2008 added VALUE as an
attribute. This means that VALUE dummy arguments can be modified,
because they have no external visibility. I think the other constraints
still guarantee that non-VALUE things can't be modified. In fact, the
NOTE still says they can't! It's takes more effort than I have to trace
through all of the constraints. But, I think the list of 5 still makes
it impossible for a PURE function to modify anything outside of the funtion.

That's my guess.

Dick Hendrickson

Ian Harvey

unread,
Sep 3, 2012, 8:09:44 PM9/3/12
to
On 2012-09-04 9:46 AM, Dick Hendrickson wrote:
> On 9/3/12 5:50 PM, Ian Harvey wrote:
>> (bump, from a different nntp server because I'm seeing lots of orphaned
>> replies which make me suspect article propagation issues...)
>>
>> If someone familiar with F2008 can have a look at this - I struggle to
>> believe that the standard would break the concept of PURE functions, but
>> from my reading of the draft I think it has.
>
> I'm not sure, but I think the issue is that F2008 added VALUE as an
> attribute. This means that VALUE dummy arguments can be modified,
> because they have no external visibility. I think the other constraints
> still guarantee that non-VALUE things can't be modified. In fact, the
> NOTE still says they can't! It's takes more effort than I have to trace
> through all of the constraints. But, I think the list of 5 still makes
> it impossible for a PURE function to modify anything outside of the
> funtion.
>
> That's my guess.

Ok... I can see how VALUE has been accomodated with F2008, and that
specific aspect seems fine.

I wonder if those changes have inadvertently created the problem that I
see. The authors may have had the expectation that all dummy arguments
to a pure function were either INTENT(IN) or VALUE, but that's not
necessarily the case, so there are scenarios where that list of five
sub-points to C1283 simply don't apply - you don't trigger the
conditions in the lead-in paragraph of that constraint.

Dick Hendrickson

unread,
Sep 4, 2012, 1:04:41 PM9/4/12
to
I don't know the answer. I tried looking around in the PURE and
argument association sections and didn't see anything obvious.

I think the only dummy argument options are nonpointer data object,
procedure dummy, and pointer dummy. I think the first two are easily
covered by the 2008 rules. It's the pointer dummy that I don't see
anything about. Maybe we need to appeal to Richard?

I'll try to think a little more later in the day.

Dick Hendrickson

Dick Hendrickson

unread,
Sep 5, 2012, 4:16:19 PM9/5/12
to
I made up a little example and sent it to the J3 mailing list. So far,
one person agrees there is a problem, nobody else has said anything.

My example:

PURE FUNCTION YYY (X)
POINTER X
YYY = 1.0
X = 2.0
END FUNCTION YYY

I don't see anything that prohibits the X = 2.0 line, assuming X points
to a local variable in the caller.

Dick Hendrickson

Terence

unread,
Sep 6, 2012, 6:43:32 PM9/6/12
to
Dick Henderson posted the following paragraph and example. I don't disagree
with his opinion on whether the code disobeys any standard, but a compiler
'should' detect that X has the attributes of an address of a variable being
passed, and should not accept the use of the same name within the same unit
scope, unless the two names are treated as distinct references to variables
of different types. I.e. that the passed variable in the example is NOT
appropriately referenced within the scope and a warning should result. I
would go as far as to say that since X is difined as a local pointer within
the unit , it can only be set to the address of a variable in that unit and
not a constant or to any variable which is not a pointer

Dick's paragraph:-

Richard Maine

unread,
Sep 6, 2012, 7:03:50 PM9/6/12
to
I have a bit of trouble in parsing Terence's reply, but I think I
figured it out. Sounds to me as though he is probably confused about
Fortran pointers in general.

If the function were not pure, there would certainly be no problem with
the code shown. Pointers in Fortran are automatically dereferenced in
most contexts, including the one shown. The line

X = 2.0

does not do anything particularly like setting X to the address of a
constant. That's not how Fortran pointers work. It just sets the value
of the pointer target to that constant.

Again, this is all perfectly fine except possibly for the issue of
purity. It is only the PURE that raises any question at all.

Ian Harvey

unread,
Sep 6, 2012, 7:10:12 PM9/6/12
to
On 2012-09-07 8:43 AM, Terence wrote:
> Dick Henderson posted the following paragraph and example. I don't disagree
> with his opinion on whether the code disobeys any standard, but a compiler
> 'should' detect that X has the attributes of an address of a variable being
> passed, and should not accept the use of the same name within the same unit
> scope, unless the two names are treated as distinct references to variables
> of different types. I.e. that the passed variable in the example is NOT
> appropriately referenced within the scope and a warning should result. I
> would go as far as to say that since X is difined as a local pointer within
> the unit , it can only be set to the address of a variable in that unit and
> not a constant or to any variable which is not a pointer

The syntax for setting the thing that a pointer points to is different
from the syntax for setting the value of the thing that a pointer points to.

x => something

says "make x point at something",

x = val

says "whatever x is pointing at, give it the value val".

In Dick's example (...thanks muchly for submitting that...) the
assumption is that prior to the call the actual argument that is
associated with the dummy argument X has already been pointed somewhere
useful ("a local variable in the caller") (there's also an assumption of
an explicit interface in the caller). The statement X = 2.0 then sets
the value of the thing being pointed at to 2.0.

This looks like a hole in F2008 that allows this supposedly PURE
function to fiddle with things that are out of the scope of the
function, other than through the return value of the function. In
earlier standards this hole was not permitted.
0 new messages