Discussion:
pure procedure
(too old to reply)
Daniel H
2011-04-22 09:31:06 UTC
Permalink
Hi,

I have several procedures which I would like to declare as pure, but
there is one small thing inhibiting that: they print to standard out.
The reason they do that is that I want to know at which stage the
program is, or to see e.g. whether the root-finder has difficulties
converging to a root. For example:

print*,'sub_broyden: computing finite difference Jacobian'

Other similar messages are error messages, though I guess in that case I
could return an integer or string and print the message later.

Any suggestions on how to both have the procedure pure and get info on
progress / errors?

Thanks

Daniel
n***@cam.ac.uk
2011-04-22 09:06:41 UTC
Permalink
Post by Daniel H
I have several procedures which I would like to declare as pure, but
there is one small thing inhibiting that: they print to standard out.
The reason they do that is that I want to know at which stage the
program is, or to see e.g. whether the root-finder has difficulties
print*,'sub_broyden: computing finite difference Jacobian'
Other similar messages are error messages, though I guess in that case I
could return an integer or string and print the message later.
Any suggestions on how to both have the procedure pure and get info on
progress / errors?
You need to fool the compiler. You can write an external procedure
that just prints an error message and is not pure, and declare it
in a module as PURE. That might work.

If not, you can do the same trick by calling a jiffy little C
function to do the same, though I recommend using standard error
and not standard output. Again, that might work.

Beyond that, there are some system-dependent tricks that bypass
anything that Fortran knows about, but I don't recommend most
people to use them. WTO under MVS, syslog under Unix, and so on.

But there is no guarantee that ANYTHING will work if the compiler
is sufficiently sensitive. That's extremely unlikely, but it's
not a good idea to rely on this trick being safe.


Regards,
Nick Maclaren.
Arjen Markus
2011-04-22 11:16:39 UTC
Permalink
Post by Daniel H
I have several procedures which I would like to declare as pure, but
there is one small thing inhibiting that: they print to standard out.
The reason they do that is that I want to know at which stage the
program is, or to see e.g. whether the root-finder has difficulties
print*,'sub_broyden: computing finite difference Jacobian'
Other similar messages are error messages, though I guess in that case I
could return an integer or string and print the message later.
Any suggestions on how to both have the procedure pure and get info on
progress / errors?
You need to fool the compiler.  You can write an external procedure
that just prints an error message and is not pure, and declare it
in a module as PURE.  That might work.
If not, you can do the same trick by calling a jiffy little C
function to do the same, though I recommend using standard error
and not standard output.  Again, that might work.
Beyond that, there are some system-dependent tricks that bypass
anything that Fortran knows about, but I don't recommend most
people to use them.  WTO under MVS, syslog under Unix, and so on.
But there is no guarantee that ANYTHING will work if the compiler
is sufficiently sensitive.  That's extremely unlikely, but it's
not a good idea to rely on this trick being safe.
Regards,
Nick Maclaren.
I think F2008 relaxes things a bit, but what Nick is suggesting
is to declare that function/subroutine as pure via an interface
block in a module. The routine is not defined in a module though.

Something like:

module fool_the_compiler
interface
pure subroutine print_message( message )
character(len=*), intent(in) :: message
end subroutine print_message
end interface
end module

In a separate file:

subroutine print_message( message )
character(len=*), intent(in) :: message
write(*,*) message
end subroutine print_message

Regards,

Arjen
Daniel H
2011-04-22 11:28:35 UTC
Permalink
Post by Arjen Markus
I think F2008 relaxes things a bit, but what Nick is suggesting
is to declare that function/subroutine as pure via an interface
block in a module. The routine is not defined in a module though.
module fool_the_compiler
interface
pure subroutine print_message( message )
character(len=*), intent(in) :: message
end subroutine print_message
end interface
end module
subroutine print_message( message )
character(len=*), intent(in) :: message
write(*,*) message
end subroutine print_message
Yes, that's pretty much what I did, and as I just said in the other
answer, it worked.

Can you tell me more about how F2008 might relax this? I'd like to check
whether those features have already been implemented in gfortran or the
latest Intel compiler - or recognize them when they are introduced.
Daniel H
2011-04-22 11:23:54 UTC
Permalink
Post by n***@cam.ac.uk
You need to fool the compiler. You can write an external procedure
that just prints an error message and is not pure, and declare it
in a module as PURE. That might work.
That did work. Intel's latest compiler doesn't complain, even with
-check all -warn all.

Now I am wondering: are there any drawbacks / pitfalls to this? There
must be a reason why printing to standard out is not allowed for pure
procedures. My best guess is that it can't be distinguished from from
other operations on external files.

Also, I am wondering whether it's worth the trouble. How much do I gain
if in this way I manage to declare my procedures as pure? Asked the
other way around: what is the additional benefit of adding the pure
keyword in a function that already conforms to the requirements?
Richard Maine
2011-04-22 15:24:17 UTC
Permalink
Daniel H <***@gmx.de> wrote:
[about lying to the compiler to fake it intothinkinga procedure is pure]
Post by Daniel H
Now I am wondering: are there any drawbacks / pitfalls to this?
Mostly the obvious two.

1. It is nonstandard. As mentioned by others, that means that it might
not work at all on some compilers. Those might even potentially include
future "smarter" versions of the ones you currently use.

1. It adds complication - enough complication that you''ll probably need
to add comments explaining what is going on and why. Otherwise, someone
is likely to do something like "fix" it at some point in the future.
Post by Daniel H
Also, I am wondering whether it's worth the trouble. How much do I gain
if in this way I manage to declare my procedures as pure? Asked the
other way around: what is the additional benefit of adding the pure
keyword in a function that already conforms to the requirements?
Usually no gain at all. People might speculate about potential
performance gains, but I wouldn't place any faith in such speculation
unles backed by measured data. Performance is really not what purity is
about.

The gain is in being allowed to use the procedure in contexts that
require purity. Those contexta are pretty limitted. They are also
exactly the kinds of places where failing to follow the rules is most
likely to get you in trouble.
--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
n***@cam.ac.uk
2011-04-22 16:39:36 UTC
Permalink
Post by Richard Maine
[about lying to the compiler to fake it intothinkinga procedure is pure]
Post by Daniel H
Now I am wondering: are there any drawbacks / pitfalls to this?
Mostly the obvious two.
1. It is nonstandard. As mentioned by others, that means that it might
not work at all on some compilers. Those might even potentially include
future "smarter" versions of the ones you currently use.
1. It adds complication - enough complication that you''ll probably need
to add comments explaining what is going on and why. Otherwise, someone
is likely to do something like "fix" it at some point in the future.
Yes, to both of those.
Post by Richard Maine
Post by Daniel H
Also, I am wondering whether it's worth the trouble. How much do I gain
if in this way I manage to declare my procedures as pure? Asked the
other way around: what is the additional benefit of adding the pure
keyword in a function that already conforms to the requirements?
Usually no gain at all. People might speculate about potential
performance gains, but I wouldn't place any faith in such speculation
unles backed by measured data. Performance is really not what purity is
about.
Not at all. Any half-competent optimising compiler will recognise
that PURE procedures can be made subject to common expression
elimination and code rearrangement, just as the intrinsics can.
I agree that it will have no significant difference on the actual
execution time of the procedure!
Post by Richard Maine
The gain is in being allowed to use the procedure in contexts that
require purity. Those contexta are pretty limitted. They are also
exactly the kinds of places where failing to follow the rules is most
likely to get you in trouble.
Well, yes, but that's not the REAL gain, which is how much they
can speed up debugging in large programs. If you see a PURE
procedure, (a) you can be certain that it isn't going to have a
strange (legal or illegal) side-effect on some other data and
(b) you can put extra calls in your diagnostic statements without
affecting the results.


Regards,
Nick Maclaren.
Dick Hendrickson
2011-04-22 18:46:58 UTC
Permalink
Post by n***@cam.ac.uk
Post by Richard Maine
[about lying to the compiler to fake it intothinkinga procedure is pure]
Post by Daniel H
Now I am wondering: are there any drawbacks / pitfalls to this?
Mostly the obvious two.
1. It is nonstandard. As mentioned by others, that means that it might
not work at all on some compilers. Those might even potentially include
future "smarter" versions of the ones you currently use.
1. It adds complication - enough complication that you''ll probably need
to add comments explaining what is going on and why. Otherwise, someone
is likely to do something like "fix" it at some point in the future.
Yes, to both of those.
Post by Richard Maine
Post by Daniel H
Also, I am wondering whether it's worth the trouble. How much do I gain
if in this way I manage to declare my procedures as pure? Asked the
other way around: what is the additional benefit of adding the pure
keyword in a function that already conforms to the requirements?
Usually no gain at all. People might speculate about potential
performance gains, but I wouldn't place any faith in such speculation
unles backed by measured data. Performance is really not what purity is
about.
Not at all. Any half-competent optimising compiler will recognise
that PURE procedures can be made subject to common expression
elimination and code rearrangement, just as the intrinsics can.
I agree that it will have no significant difference on the actual
execution time of the procedure!
There's one difference between PURE and intrinsic. PURE procedures can
use entities in common or from a module as "input", not just their
arguments. This limits how much multi-line optimization can be done.
x = pure_F(7)
y = F(23)
z = pure_F(7)
isn't optimiziable unless the compiler can see into F and pure_F. In
some ways it's too bad that F95 didn't limit PURE routines to also not
accessing anything as well as not modifying anything.

Dick Hendrickson
Post by n***@cam.ac.uk
Post by Richard Maine
The gain is in being allowed to use the procedure in contexts that
require purity. Those contexta are pretty limitted. They are also
exactly the kinds of places where failing to follow the rules is most
likely to get you in trouble.
Well, yes, but that's not the REAL gain, which is how much they
can speed up debugging in large programs. If you see a PURE
procedure, (a) you can be certain that it isn't going to have a
strange (legal or illegal) side-effect on some other data and
(b) you can put extra calls in your diagnostic statements without
affecting the results.
Regards,
Nick Maclaren.
Richard Maine
2011-04-22 18:56:01 UTC
Permalink
Post by n***@cam.ac.uk
Well, yes, but that's not the REAL gain, which is how much they
can speed up debugging in large programs. If you see a PURE
procedure, (a) you can be certain that it isn't going to have a
strange (legal or illegal) side-effect on some other data and
(b) you can put extra calls in your diagnostic statements without
affecting the results.
Of course, lying to the compiler and tricking it into believing your
lies, as the OP was suggesting, completely defeats that object.
--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
n***@cam.ac.uk
2011-04-22 18:41:40 UTC
Permalink
Post by Dick Hendrickson
Post by n***@cam.ac.uk
Not at all. Any half-competent optimising compiler will recognise
that PURE procedures can be made subject to common expression
elimination and code rearrangement, just as the intrinsics can.
I agree that it will have no significant difference on the actual
execution time of the procedure!
There's one difference between PURE and intrinsic. PURE procedures can
use entities in common or from a module as "input", not just their
arguments. This limits how much multi-line optimization can be done.
x = pure_F(7)
y = F(23)
z = pure_F(7)
isn't optimiziable unless the compiler can see into F and pure_F. In
some ways it's too bad that F95 didn't limit PURE routines to also not
accessing anything as well as not modifying anything.
No, that's not completely true. If it can tell that F doesn't
modify global, accessible state, it need not look into pure_F.
Also, it need not look into either in cases like:

x = pure_F(7)
y = pure_G(23)
z = pure_F(7)
Post by Dick Hendrickson
Post by n***@cam.ac.uk
Well, yes, but that's not the REAL gain, which is how much they
can speed up debugging in large programs. If you see a PURE
procedure, (a) you can be certain that it isn't going to have a
strange (legal or illegal) side-effect on some other data and
(b) you can put extra calls in your diagnostic statements without
affecting the results.
Of course, lying to the compiler and tricking it into believing your
lies, as the OP was suggesting, completely defeats that object.
Well, it does in general, but not necessarily in the case where
the only impurity is writing to a pure output stream, which was
the example in hand.

In a language that had a more precise concept of such a thing,
I believe that a PURE procedure should be allowed to write.
For historical reasons, neither Fortran nor C are like that.


Regards,
Nick Maclaren.
Richard Maine
2011-04-22 19:41:31 UTC
Permalink
Post by n***@cam.ac.uk
Post by Richard Maine
Post by n***@cam.ac.uk
Well, yes, but that's not the REAL gain, which is how much they
can speed up debugging in large programs. If you see a PURE
procedure, (a) you can be certain that it isn't going to have a
strange (legal or illegal) side-effect on some other data and
(b) you can put extra calls in your diagnostic statements without
affecting the results.
Of course, lying to the compiler and tricking it into believing your
lies, as the OP was suggesting, completely defeats that object.
Well, it does in general, but not necessarily in the case where
the only impurity is writing to a pure output stream, which was
the example in hand.
But there is no way to have the compiler check that. I thought you were
saying that guarantee provided by the compiler was the gain. There is no
way to tell the compiler that it should check all the purity conditions
except that (well no standard way; I suppose vendors could have an
option, and I don't recall whether perhaps f2008 eased up on that
particular condition).

The suggestion at hand was to compile the routine without having the
PURE keyword. That throws out all the compiler checking benefits of
PURE. In fact, it probably makes compiler checking worse because it
probably involves making the procedure external instead of a module
procedure. All you have left is the declaration in the separate
interface body that the procedure is PURE. That might tell the reader
that he isn't supposed to have to check the procedure, but since it is
already intentionally lying about one aspect, whose to say that it isn't
unintentionally lying about other parts as well. I'll claim that lying
to the compiler also constitutes lying to the person trying to debug the
code, which is likely to make his job harder - not easier. That's
related to my earlier comment that you'd sure need to document what was
going on and why.
--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
n***@cam.ac.uk
2011-04-22 21:06:19 UTC
Permalink
Post by Richard Maine
Post by n***@cam.ac.uk
Post by Richard Maine
Post by n***@cam.ac.uk
Well, yes, but that's not the REAL gain, which is how much they
can speed up debugging in large programs. If you see a PURE
procedure, (a) you can be certain that it isn't going to have a
strange (legal or illegal) side-effect on some other data and
(b) you can put extra calls in your diagnostic statements without
affecting the results.
Of course, lying to the compiler and tricking it into believing your
lies, as the OP was suggesting, completely defeats that object.
Well, it does in general, but not necessarily in the case where
the only impurity is writing to a pure output stream, which was
the example in hand.
But there is no way to have the compiler check that. I thought you were
saying that guarantee provided by the compiler was the gain. There is no
way to tell the compiler that it should check all the purity conditions
except that (well no standard way; I suppose vendors could have an
option, and I don't recall whether perhaps f2008 eased up on that
particular condition).
Yes and no. Remember that I am also Of A Certain Age, and am
used to self-disclipline as an alternative to compiler checking.
If someone writes a procedure that is pure except for some pure
stream output, then it can be checked by just disabling that
and running it through the compiler once. Then it can be
declared in a module as PURE, and it will get all of the
advantages of a true pure procedure. Been there - done that :-)

That is precisely because, as we agree, a language COULD include
that wrinkle as acceptable in pure code. I have just checked,
and Fortran 2008 doesn't do that - indeed, I don't think that it
could, because of historical baggage.


Regards,
Nick Maclaren.
Daniel Carrera
2011-04-22 22:14:35 UTC
Permalink
Post by n***@cam.ac.uk
That is precisely because, as we agree, a language COULD include
that wrinkle as acceptable in pure code. I have just checked,
and Fortran 2008 doesn't do that - indeed, I don't think that it
could, because of historical baggage.
I think that there is more to it than "historical baggage". Printing
text *is* a side-effect, and defies the notion of purity. For example,
if functions foo() and bar() are pure, that means that:

a = foo() + bar()

should be entirely identical to:

a = bar() + foo()

But if foo() and bar() print text to a file, or to the terminal, then in
a very real sense, the two lines above have different behaviour. With
some effort, I'm sure someone in this list can think of an example where
the difference might be important. For example, the printed output might
be command instructions for some other process.

Daniel.
n***@cam.ac.uk
2011-04-23 06:35:48 UTC
Permalink
Post by Daniel Carrera
Post by n***@cam.ac.uk
That is precisely because, as we agree, a language COULD include
that wrinkle as acceptable in pure code. I have just checked,
and Fortran 2008 doesn't do that - indeed, I don't think that it
could, because of historical baggage.
I think that there is more to it than "historical baggage". Printing
text *is* a side-effect, and defies the notion of purity. For example,
a = foo() + bar()
a = bar() + foo()
But if foo() and bar() print text to a file, or to the terminal, then in
a very real sense, the two lines above have different behaviour. With
some effort, I'm sure someone in this list can think of an example where
the difference might be important. For example, the printed output might
be command instructions for some other process.
You are using a particular semantic model, which is not the only
one. I was slightly over-simplifying but, for the reasons you
give, I would distinguish 'diagnostic' from 'functional' pure
output streams if I designed a language.

Anyway, the reason that the order is irrelevant in this context
is that it cannot affect the behaviour of any other part of the
It is therefore NOT a side-effect, though I accept that it is a
potentially visible effect.


Regards,
Nick Maclaren.
Daniel H
2011-04-23 09:54:58 UTC
Permalink
Post by n***@cam.ac.uk
Post by Daniel Carrera
Post by n***@cam.ac.uk
That is precisely because, as we agree, a language COULD include
that wrinkle as acceptable in pure code. I have just checked,
and Fortran 2008 doesn't do that - indeed, I don't think that it
could, because of historical baggage.
(snip)
Post by n***@cam.ac.uk
Post by Daniel Carrera
But if foo() and bar() print text to a file, or to the terminal, then in
a very real sense, the two lines above have different behaviour. With
some effort, I'm sure someone in this list can think of an example where
the difference might be important. For example, the printed output might
be command instructions for some other process.
You are using a particular semantic model, which is not the only
one. I was slightly over-simplifying but, for the reasons you
give, I would distinguish 'diagnostic' from 'functional' pure
output streams if I designed a language.
Anyway, the reason that the order is irrelevant in this context
is that it cannot affect the behaviour of any other part of the
It is therefore NOT a side-effect, though I accept that it is a
potentially visible effect.
Thanks for all the comments. Indeed, I was thinking purely (pun
intended) about 'diagnostic' output; I put the print/write statements
with side effects in separate subroutines. The reason I am still
thinking about it is that my code is several layers deep, and the
innermost is the crucial one where I want these diagnostic messages.
Because of this, none of the other layers can be pure, although
otherwise they would be. What's more, I already have an
if(print_diagnostic)
in front of each such print statement, so that if this is false, the
procedure is in effect pure.

For me, an important reason for purity was that I thought it helps when
building parallel applications - which the present project is likely
going to be. However, skimming through Intel's manual and its discussion
on the various ways of parallelization, I found no mention of the PURE
keyword, although of course it's made clear that side effects might
inhibit efficient parallelization.

So it seems to me that adding PURE wouldn't help in that respect, but
that surprises me a bit. Specifically, I have a nested, performance
critical do-loop where the innermost loop performs many independent
iterations which each call several 'effectively-pure' subroutines (i.e.,
pure apart from those darned diagnostic prints). I would have expected
that telling the compiler explicitly that these are PURE would help in
parallelizing, but I might be thinking too much in terms of the
'auto-parallelization' feature of Intel's compiler.

To force my question into one line (hopefully not making it too
general/unclear): does the PURE keyword help in parallel applications?
n***@cam.ac.uk
2011-04-23 10:24:14 UTC
Permalink
Post by Daniel H
For me, an important reason for purity was that I thought it helps when
building parallel applications - which the present project is likely
going to be. However, skimming through Intel's manual and its discussion
on the various ways of parallelization, I found no mention of the PURE
keyword, although of course it's made clear that side effects might
inhibit efficient parallelization.
So it seems to me that adding PURE wouldn't help in that respect, but
that surprises me a bit. Specifically, I have a nested, performance
critical do-loop where the innermost loop performs many independent
iterations which each call several 'effectively-pure' subroutines (i.e.,
pure apart from those darned diagnostic prints). I would have expected
that telling the compiler explicitly that these are PURE would help in
parallelizing, but I might be thinking too much in terms of the
'auto-parallelization' feature of Intel's compiler.
To force my question into one line (hopefully not making it too
general/unclear): does the PURE keyword help in parallel applications?
If you mean shared-memory ones, such as OpenMP-based ones then,
yes, massively. Whether compilers actually take advantage of it
is another matter.


Regards,
Nick Maclaren.
Richard Maine
2011-04-23 15:42:03 UTC
Permalink
Post by Daniel H
For me, an important reason for purity was that I thought it helps when
building parallel applications ...
I would have expected
that telling the compiler explicitly that these are PURE would help in
parallelizing, but I might be thinking too much in terms of the
'auto-parallelization' feature of Intel's compiler.
To force my question into one line (hopefully not making it too
general/unclear): does the PURE keyword help in parallel applications?
Wrong concept - at least in terms of the standard. PURE isn't about
"helping" parallelization. Rather, it is more about avoiding things that
are ill-defined if parallelized.

Output is one of those kinds of things. You might not care about what
order things get output in, but the standard isn't into deciding what
you care about. When there is something that gives different results for
different valid implementations (and different order is a difference),
that typically is labelled as nonstandard.

Note, by the way, that if multiple writes were really done in parallel,
you could see the results being mixed character-by-character. If you are
assuming that the outputs would be mixed only at the level of an entire
line or write statement, then that implies some kind of serialization.
Not that such things are inherently impossible, but it would have to be
carefully specified; it wouldn't "just happen".
--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
n***@cam.ac.uk
2011-04-24 07:50:48 UTC
Permalink
Post by Richard Maine
Wrong concept - at least in terms of the standard. PURE isn't about
"helping" parallelization. Rather, it is more about avoiding things that
are ill-defined if parallelized.
Well, yes, but it IS a massive help, because of that! And, yes,
it does allow autoparallelisation. So it may not be how the
standard phrases it, but it delivers what the OP wants ....
Post by Richard Maine
Output is one of those kinds of things. You might not care about what
order things get output in, but the standard isn't into deciding what
you care about. When there is something that gives different results for
different valid implementations (and different order is a difference),
that typically is labelled as nonstandard.
Grrk. That's not the case for coarrays in unordered images - see
Note 9.15 in Fortran 2008. Except for that, I agree that current
output works the way you describe, but my point is that there is
no need to constrain a diagnostic output statement like that.

I think that everyone is agreed that attempting to shoehorn such
'unordered' diagnostic methods into the existing model by using
the existing statements would be a mistake.


Regards,
Nick Maclaren.
Daniel Carrera
2011-04-23 10:27:03 UTC
Permalink
Post by n***@cam.ac.uk
Post by Daniel Carrera
Post by n***@cam.ac.uk
That is precisely because, as we agree, a language COULD include
that wrinkle as acceptable in pure code. I have just checked,
and Fortran 2008 doesn't do that - indeed, I don't think that it
could, because of historical baggage.
I think that there is more to it than "historical baggage". Printing
text *is* a side-effect, and defies the notion of purity. For example,
a = foo() + bar()
a = bar() + foo()
But if foo() and bar() print text to a file, or to the terminal, then in
a very real sense, the two lines above have different behaviour. With
some effort, I'm sure someone in this list can think of an example where
the difference might be important. For example, the printed output might
be command instructions for some other process.
You are using a particular semantic model, which is not the only
one. I was slightly over-simplifying but, for the reasons you
give, I would distinguish 'diagnostic' from 'functional' pure
output streams if I designed a language.
I understand that in Daniel H's specific example, he only wants
diagnostic messages. But there is nothing in any language that does, or
could, distinguish between "diagnostic output" and "functional output",
to use your terminology. It is entirely logical, and even necessary,
that a function only be considered pure if it cannot print.

Consider another example: Pure functions cannot alter global variables.
We could easily come up with an example where altering a global variable
is perfectly innocent and is purely for diagnostics. Like a counter to
keep track of how many times a function is called. But you don't say
that this is a bug in Fortran's pure procedures, or that it is due to
"historical baggage". Altering global variables *is* a side-effect, just
like printing text, and there is no way any person or compiler can know,
a priori, whether this is action is "diagnostic" or "functional". They
are side-effects. Period.
Post by n***@cam.ac.uk
Anyway, the reason that the order is irrelevant in this context
is that it cannot affect the behaviour of any other part of the
It is therefore NOT a side-effect, though I accept that it is a
potentially visible effect.
I don't really know what you are trying to say here, but I'd like to
reiterate that a side-effect is *any* effect other than the return value
of the function.

Daniel.
n***@cam.ac.uk
2011-04-23 10:27:08 UTC
Permalink
Post by Daniel Carrera
I understand that in Daniel H's specific example, he only wants
diagnostic messages. But there is nothing in any language that does, or
could, distinguish between "diagnostic output" and "functional output",
to use your terminology. It is entirely logical, and even necessary,
that a function only be considered pure if it cannot print.
That is false on both counts. I can't offhand remember which
languages have that concept, but I have assuredly seen it.
And it is straightforward to define what happens in an
appropriate machine model, though that is rarer.


Regards,
Nick Maclaren.
Daniel Carrera
2011-04-23 11:22:11 UTC
Permalink
Post by n***@cam.ac.uk
Post by Daniel Carrera
I understand that in Daniel H's specific example, he only wants
diagnostic messages. But there is nothing in any language that does, or
could, distinguish between "diagnostic output" and "functional output",
to use your terminology. It is entirely logical, and even necessary,
that a function only be considered pure if it cannot print.
That is false on both counts. I can't offhand remember which
languages have that concept, but I have assuredly seen it.
And it is straightforward to define what happens in an
appropriate machine model, though that is rarer.
I'd be interested to see that. IMO the inability to print diagnostics is
the single annoying aspect of pure procedures, and I'd be interested to
see a language that attains purity without losing the ability to print
diagnostics. I cannot easily imagine how that would work.

Daniel.
n***@cam.ac.uk
2011-04-23 12:09:33 UTC
Permalink
Post by Daniel Carrera
Post by n***@cam.ac.uk
Post by Daniel Carrera
I understand that in Daniel H's specific example, he only wants
diagnostic messages. But there is nothing in any language that does, or
could, distinguish between "diagnostic output" and "functional output",
to use your terminology. It is entirely logical, and even necessary,
that a function only be considered pure if it cannot print.
That is false on both counts. I can't offhand remember which
languages have that concept, but I have assuredly seen it.
And it is straightforward to define what happens in an
appropriate machine model, though that is rarer.
I'd be interested to see that. IMO the inability to print diagnostics is
the single annoying aspect of pure procedures, and I'd be interested to
see a language that attains purity without losing the ability to print
diagnostics. I cannot easily imagine how that would work.
The following is a draft:

A DIAGNOSE statement is like a PRINT statement, but may occur
in PURE procedures, and writes a message to a processor-defined
file. No other I/O statements are defined for that file. In
addition, it has the following semantics:

If the definition does not specify the order of execution,
such as in DO CONCURRENT, then the order of execution of any
DIAGNOSE statements in that code is unspecified.

If it occurs in a procedure that need not be executed, then
DIAGNOSE statements within that call need not produce any output.

More or less, that's it. Fortran forbids the reopening of a
file in the same execution, and the file cannot be closed, so
it cannot be reread.


Regards,
Nick Maclaren.
Daniel Carrera
2011-04-23 13:10:23 UTC
Permalink
Post by n***@cam.ac.uk
Post by Daniel Carrera
I'd be interested to see that. IMO the inability to print diagnostics is
the single annoying aspect of pure procedures, and I'd be interested to
see a language that attains purity without losing the ability to print
diagnostics. I cannot easily imagine how that would work.
A DIAGNOSE statement is like a PRINT statement, but may occur
in PURE procedures, and writes a message to a processor-defined
file. No other I/O statements are defined for that file. In
If the definition does not specify the order of execution,
such as in DO CONCURRENT, then the order of execution of any
DIAGNOSE statements in that code is unspecified.
If it occurs in a procedure that need not be executed, then
DIAGNOSE statements within that call need not produce any output.
More or less, that's it. Fortran forbids the reopening of a
file in the same execution, and the file cannot be closed, so
it cannot be reread.
Sounds great. I would love to see something like that. I'm no expert,
but it looks safe and side-effect free.

Daniel.
Thomas Koenig
2011-04-23 20:28:45 UTC
Permalink
Post by n***@cam.ac.uk
A DIAGNOSE statement is like a PRINT statement, but may occur
in PURE procedures, and writes a message to a processor-defined
file.
What about

... and issues a diagnostic in a processor-defined way.

If that diagnostic is written to standard error, sent by e-mail to
the system administrator, sent to syslog, displayed as an alert box
or printed out as cuneiform tablets (provided the right operational
hardware is installed) would then be left to the compiler writers.
Dan Nagle
2011-04-23 20:41:13 UTC
Permalink
Hello,
Post by Thomas Koenig
... and issues a diagnostic in a processor-defined way.
If that diagnostic is written to standard error, sent by e-mail to
the system administrator, sent to syslog, displayed as an alert box
or printed out as cuneiform tablets (provided the right operational
hardware is installed) would then be left to the compiler writers.
The usual standardese double-talk is "made available" ...

There might be a note following to say what
was actually meant.

FWIW
Clause 1 says compilers (well, processors) must be able
to "detect and report the occurrence within a submitted program unit"
of various syndromes.

That doesn't say anything about how, but it's not run-time.
--
Cheers!

Dan Nagle
n***@cam.ac.uk
2011-04-24 07:24:52 UTC
Permalink
Post by Thomas Koenig
Post by n***@cam.ac.uk
A DIAGNOSE statement is like a PRINT statement, but may occur
in PURE procedures, and writes a message to a processor-defined
file.
What about
... and issues a diagnostic in a processor-defined way.
If that diagnostic is written to standard error, sent by e-mail to
the system administrator, sent to syslog, displayed as an alert box
or printed out as cuneiform tablets (provided the right operational
hardware is installed) would then be left to the compiler writers.
Right. I said it was a draft. Your fix also allows for the
single/multiple file issue, needed for coarrays - and is very
similar to the wording in LIA-1.


Regards,
Nick Maclaren.
glen herrmannsfeldt
2011-04-24 00:00:35 UTC
Permalink
Post by n***@cam.ac.uk
Post by Daniel Carrera
I understand that in Daniel H's specific example, he only wants
diagnostic messages. But there is nothing in any language that does, or
could, distinguish between "diagnostic output" and "functional output",
to use your terminology. It is entirely logical, and even necessary,
that a function only be considered pure if it cannot print.
That is false on both counts. I can't offhand remember which
languages have that concept, but I have assuredly seen it.
And it is straightforward to define what happens in an
appropriate machine model, though that is rarer.
It always seemed to me that STOP with a character constant
was meant as a diagnostic message. That is, I give up and
here is why... But no STOP in PURE, either.

-- glen
glen herrmannsfeldt
2011-04-23 07:41:49 UTC
Permalink
Daniel Carrera <***@gmail.com> wrote:
(snip)
Post by Daniel Carrera
I think that there is more to it than "historical baggage". Printing
text *is* a side-effect, and defies the notion of purity. For example,
a = foo() + bar()
a = bar() + foo()
But if foo() and bar() print text to a file, or to the terminal, then in
a very real sense, the two lines above have different behaviour.
I suppose so. But in debugging, one might be able to live with the
uncertainty in the order of output. Even more, consider STOP.
Once you STOP, it doesn't really matter what else might have happened.

I would rather have output in the wrong order than nothing at all.
Post by Daniel Carrera
With some effort, I'm sure someone in this list can think of an
example where the difference might be important. For example,
the printed output might be command instructions for some other process.
-- glen
Daniel Carrera
2011-04-23 10:37:53 UTC
Permalink
Post by glen herrmannsfeldt
Post by Daniel Carrera
But if foo() and bar() print text to a file, or to the terminal, then in
a very real sense, the two lines above have different behaviour.
I suppose so. But in debugging, one might be able to live with the
uncertainty in the order of output. Even more, consider STOP.
Once you STOP, it doesn't really matter what else might have happened.
I would rather have output in the wrong order than nothing at all.
Sure, there are pros and cons to purity. It is up to you to decide
whether pure procedures are valuable to you or not.

I just wanted to express that the idea of purity is that the result
(effect) of a procedure depends only on its input, and cannot be
influenced by where it is in the program, or how many times it was
called, and so on. The consequences of this can some times feel like
programming while wearing a straight jacket (try to write "Hello world"
in Haskell and you'll see what I mean), but it does have its benefits.
It is up to each person to decide if the trade off is worth it to them.

Daniel.
glen herrmannsfeldt
2011-04-23 07:39:14 UTC
Permalink
***@cam.ac.uk wrote:
(snip)
Post by n***@cam.ac.uk
Post by Richard Maine
Post by n***@cam.ac.uk
Well, it does in general, but not necessarily in the case where
the only impurity is writing to a pure output stream, which was
the example in hand.
But there is no way to have the compiler check that. I thought you were
saying that guarantee provided by the compiler was the gain. There is no
way to tell the compiler that it should check all the purity conditions
except that (well no standard way; I suppose vendors could have an
option, and I don't recall whether perhaps f2008 eased up on that
particular condition).
Yes and no. Remember that I am also Of A Certain Age, and am
used to self-disclipline as an alternative to compiler checking.
I suppose I understand the reasons behind the restrictions,
but it seems to me that whoever put the restrictions in never
tried debugging a complicated program. It wouldn't seem so
bad to me if STOP was allowed, especially STOP with a character
consant. If you really give up, then you usually don't care
that some other things might not work exactly right.

If they just made the restrictions as system defined, or
undefined, but compilers weren't restricted from allowing them,
or were even required to allow them, it wouldn't seem so bad.

Note that besides PURE there is ELEMENTAL. Now, one could always
remove the PURE for debugging and restore it later, but that
usually isn't true for ELEMENTAL. Also, with ELEMENTAL there is
no guarantee on the order of evaluation, but one might be able
to live with that. Allow one to print out debugging messages
and realize that they might come out in the wrong order.
Post by n***@cam.ac.uk
If someone writes a procedure that is pure except for some pure
stream output, then it can be checked by just disabling that
and running it through the compiler once. Then it can be
declared in a module as PURE, and it will get all of the
advantages of a true pure procedure. Been there - done that :-)
That is precisely because, as we agree, a language COULD include
that wrinkle as acceptable in pure code. I have just checked,
and Fortran 2008 doesn't do that - indeed, I don't think that it
could, because of historical baggage.
-- glen
Daniel Carrera
2011-04-22 19:38:07 UTC
Permalink
Post by Richard Maine
Post by n***@cam.ac.uk
Well, yes, but that's not the REAL gain, which is how much they
can speed up debugging in large programs. If you see a PURE
procedure, (a) you can be certain that it isn't going to have a
strange (legal or illegal) side-effect on some other data and
(b) you can put extra calls in your diagnostic statements without
affecting the results.
Of course, lying to the compiler and tricking it into believing your
lies, as the OP was suggesting, completely defeats that object.
Indeed. Nobody forces you to use pure procedures. If you use them,
presumably it's because you *want* the assurance of a side-effect free
procedure.

Daniel.
glen herrmannsfeldt
2011-04-23 07:44:05 UTC
Permalink
Daniel Carrera <***@gmail.com> wrote:

(snip)
Post by Daniel Carrera
Indeed. Nobody forces you to use pure procedures. If you use them,
presumably it's because you *want* the assurance of a side-effect free
procedure.
Yes, but ELEMENTAL is different, and has the same restrictions.

Now, no-one forces you to use ELEMENTAL either, but if you do
use it then you are stuck. You can't just remove the attribute.

-- glen
Daniel Kraft
2011-04-23 09:21:42 UTC
Permalink
Post by glen herrmannsfeldt
(snip)
Post by Daniel Carrera
Indeed. Nobody forces you to use pure procedures. If you use them,
presumably it's because you *want* the assurance of a side-effect free
procedure.
Yes, but ELEMENTAL is different, and has the same restrictions.
Now, no-one forces you to use ELEMENTAL either, but if you do
use it then you are stuck. You can't just remove the attribute.
But here at least, in Fortran 2008 you can add IMPURE and continue using
ELEMENTAL ;)

Overall I agree though, that it really would be nice to have debugging
output possible from PURE procedures. I also frequently use output for
debugging, and would surely use PURE more liberally and often (and would
like to do so) if this would not restrict me there.

Cheers,
Daniel
--
http://www.pro-vegan.info/
--
Done: Arc-Bar-Cav-Kni-Ran-Rog-Sam-Tou-Val-Wiz
To go: Hea-Mon-Pri
Daniel Carrera
2011-04-23 10:46:24 UTC
Permalink
Post by Daniel Kraft
Overall I agree though, that it really would be nice to have debugging
output possible from PURE procedures. I also frequently use output for
debugging, and would surely use PURE more liberally and often (and would
like to do so) if this would not restrict me there.
I sympathize, because I use pure and elemental procedures everywhere in
my code. It *does* make debugging more difficult. But as I've said
earlier, there are reasons why printing is prohibited, this is not just
a random idea that the Fortran committee just had. All pure functional
languages prohibit printing except in impure code. Printing *is* a
side-effect, and changing the print order *could* alter the result of
the program (e.g. if the stuff you are printing are commands (e.g. for
Gnuplot or Postscript)). Therefore, it must be considered "impure".

Daniel.
Aris
2011-04-23 11:33:38 UTC
Permalink
Post by Daniel Carrera
Post by Daniel Kraft
Overall I agree though, that it really would be nice to have debugging
output possible from PURE procedures. I also frequently use output for
debugging, and would surely use PURE more liberally and often (and would
like to do so) if this would not restrict me there.
I sympathize, because I use pure and elemental procedures everywhere in
my code. It *does* make debugging more difficult.
Attributes, like "PURE" are easy to pre-process out and in again,
even with sed. Just put a recognizable comment at the end of the line.
Daniel Carrera
2011-04-23 13:12:48 UTC
Permalink
Post by Aris
Post by Daniel Carrera
Post by Daniel Kraft
Overall I agree though, that it really would be nice to have debugging
output possible from PURE procedures. I also frequently use output for
debugging, and would surely use PURE more liberally and often (and would
like to do so) if this would not restrict me there.
I sympathize, because I use pure and elemental procedures everywhere in
my code. It *does* make debugging more difficult.
Attributes, like "PURE" are easy to pre-process out and in again,
even with sed. Just put a recognizable comment at the end of the line.
It's a bit less straight forward if the procedure is ELEMENTAL, or if
you have procedure A that calls B that calls C that calls D and you want
to put the diagnostic in D.
Daniel Kraft
2011-04-24 05:34:12 UTC
Permalink
Post by Daniel Carrera
Post by Aris
Post by Daniel Carrera
Post by Daniel Kraft
Overall I agree though, that it really would be nice to have debugging
output possible from PURE procedures. I also frequently use output for
debugging, and would surely use PURE more liberally and often (and would
like to do so) if this would not restrict me there.
I sympathize, because I use pure and elemental procedures everywhere in
my code. It *does* make debugging more difficult.
Attributes, like "PURE" are easy to pre-process out and in again,
even with sed. Just put a recognizable comment at the end of the line.
It's a bit less straight forward if the procedure is ELEMENTAL, or if
you have procedure A that calls B that calls C that calls D and you want
to put the diagnostic in D.
Well, in the case of ELEMENTAL you just have to preprocess "IMPURE" *in*
(assuming you have a compiler that understands this F2008 feature, which
is a rather easy one, though -- and gfortran does since a good half year).

But I've never done that so far in reality; it seems doable, though, if
you really want to.

Yours,
Daniel
--
http://www.pro-vegan.info/
--
Done: Arc-Bar-Cav-Kni-Ran-Rog-Sam-Tou-Val-Wiz
To go: Hea-Mon-Pri
Daniel Carrera
2011-04-24 08:19:57 UTC
Permalink
Post by Daniel Kraft
Post by Daniel Carrera
It's a bit less straight forward if the procedure is ELEMENTAL, or if
you have procedure A that calls B that calls C that calls D and you want
to put the diagnostic in D.
Well, in the case of ELEMENTAL you just have to preprocess "IMPURE" *in*
(assuming you have a compiler that understands this F2008 feature, which
is a rather easy one, though -- and gfortran does since a good half year).
Ok. I wasn't aware of that feature.
jfh
2011-04-26 02:25:24 UTC
Permalink
Post by Daniel Kraft
Post by glen herrmannsfeldt
(snip)
Post by Daniel Carrera
Indeed. Nobody forces you to use pure procedures. If you use them,
presumably it's because you *want* the assurance of a side-effect free
procedure.
Yes, but ELEMENTAL is different, and has the same restrictions.
Now, no-one forces you to use ELEMENTAL either, but if you do
use it then you are stuck.  You can't just remove the attribute.
But here at least, in Fortran 2008 you can add IMPURE and continue using
ELEMENTAL ;)
Overall I agree though, that it really would be nice to have debugging
output possible from PURE procedures.  I also frequently use output for
debugging, and would surely use PURE more liberally and often (and would
like to do so) if this would not restrict me there.
Cheers,
Daniel
--http://www.pro-vegan.info/
--
Done:  Arc-Bar-Cav-Kni-Ran-Rog-Sam-Tou-Val-Wiz
To go: Hea-Mon-Pri
When I wanted SI units and debugging information to be possible from
PURE functions (actually f95 ELEMENTAL functions in my case) I made
the return value and the argument of type var, which was declared as

type var
real(dp) value ! numerical value
real powers(nSI) ! m,kg,sec,amp,mol,kelvin
character:: badch*1 = '.'
end type var type var

where dp was kind(1d0) and badch was set to various values other than
'.' to flag various kinds of error, and then I made an impure
procedure print useful information afterwards if an error had been
flagged. After some tedious writing of arithmetical operations and
functions to work on type(var) the main disadvantage turned out to be
that the run-time of the program was much longer than if I had just
used real(dp) function values.

-- John Harper

Daniel Carrera
2011-04-22 19:28:45 UTC
Permalink
Post by Richard Maine
Post by Daniel H
Also, I am wondering whether it's worth the trouble. How much do I gain
if in this way I manage to declare my procedures as pure? Asked the
other way around: what is the additional benefit of adding the pure
keyword in a function that already conforms to the requirements?
Usually no gain at all. People might speculate about potential
performance gains, but I wouldn't place any faith in such speculation
unles backed by measured data. Performance is really not what purity is
about.
The gain is in being allowed to use the procedure in contexts that
require purity. Those contexta are pretty limitted. They are also
exactly the kinds of places where failing to follow the rules is most
likely to get you in trouble.
Personally I like pure functions a lot and my linking has nothing to do
with performance. Purity gives me confidence that functions will behave
the way I expect. That they will behave like a black box with only input
and output and will not give me any surprises later.

For example, can you be sure that:

a = foo() + bar()

Will give you the same value as:

a = bar() + foo() ?


If you see:

a = foo(3.0)
b = foo(3.0)
c = foo(3.0)

Can you be confident that a == b == c ? Can you be confident that
re-arranging these lines will not alter the result?


In my programs, I generally make all functions pure, and leave any
impure behaviour to subroutines. With this convention, I feel that my
code is more predictable and easier to reason through.

Daniel.
glen herrmannsfeldt
2011-04-22 16:28:15 UTC
Permalink
***@cam.ac.uk wrote:

(snip on output in PURE procedures)
Post by n***@cam.ac.uk
You need to fool the compiler. You can write an external procedure
that just prints an error message and is not pure, and declare it
in a module as PURE. That might work.
(snip)
Post by n***@cam.ac.uk
Beyond that, there are some system-dependent tricks that bypass
anything that Fortran knows about, but I don't recommend most
people to use them. WTO under MVS, syslog under Unix, and so on.
WTO, my old favorite. Some years ago, working in a place where
printed output came out slow, and there was a public printer
printing all operator messages, and the PL/I DISPLAY statement
does a WTO, and one number would tell if my program worked or
not, I just DISPLAY that number. Then I know quickly that my
program did or didn't work right.

-- glen
Loading...