A modern way to solve the "callback problem" from a subroutine?

21 views
Skip to first unread message

Henrik Holst

unread,
Mar 17, 2008, 11:39:32 PM3/17/08
to
Hello comp.lang.Fortran!

I am writing to seek ideas how to solve the "callback problem" problem
in
a modern fashion using whats available in the Fortran 95/2003
compilers, today.

I found many interesting threads on the subjects by search for
"reverse communication".
There was a discussion on the subject in the monster thread
"How old is the average Fortran programmer?"
but the discussion was drained in noise from old FORTRAN2 relics
talking about
their first codes written on punch cards before the best solution
could be found. :-)

Background:

I am implementing a library for various kind of numerical methods for
solving
ODEs. The basic framework requires the possibility to evaluate f(t,y)
(y is any
0 to 7 dimensional array) at a given point in T x Y space. This poses
a problem
for me because usually the f function does not only depend on t and y
but on
other user definable parameters.


For completeness, I will give an example of what problem we are
talking about
here. I present, a draft of a ODE solving framework: (0-dim. case)

SUBROUTINE RK10(X, Y, F, H)
INTERFACE
FUNCTION F(X, Y)
USE ODE_LIB_KINDS
REAL(WP), INTENT(IN) :: X, Y
REAL(WP) :: F
END FUNCTION
END INTERFACE
REAL(WP), INTENT(INOUT) :: X, Y, H ! X INDEP. VARIABLE
! Y FCT. OF X
! H STEP-SIZE.
REAL(WP) :: K(1) ! K WORKBUF. FOR STAGES

K(1) = H*F(X, Y)
Y = Y + K(1)
X = X + H
END SUBROUTINE RK10


Possible solutions to the problem:

The solutions to the problem above has been suggested before. (With a
short comment from me, to each of them.)

1) INTERNAL FUNCTIONS, are not allowed to be passed as arguments.
A BIG design imo. This was my first try (and failure) to solve the
problem.

2) COMMON BLOCKS, suck because global variables suck.
My whole being says that global variables are evil. If they where not
true evil
before the days of multi-core computing, they must have increased
their
evilness by orders of magnitude today. (base 2)

3) REVERSE COMMUNICATION protocol [1], is complicated and does not
really solve
the problem but hides it in parameter passing spaghetti.

4) TRANSFER intrinsic to pass "data" as bi-parameter.
This is intrusive on the function being called and also potentially
risky to
use. And very ugly of course.

5) OO FEATURES, of Fortran 2003 are "unavailable". My try was to use
CLASS(*)
seems missing from most compilers (g95, gfortran, Ifort10 and S12).


I am open to any suggestions I would just know how the Fortran
community
addresses this in the year of 2008. What solution do you use and why
do you think so (and how come)?
Remark: I am free from legacy code to no such
considerations are worth taking into account.

(I am sorry for the lack of citations to the links in clf to the
relevant threads.
I hope you can search them up for yourself.)
[1] http://citeseer.ist.psu.edu/dongarra95reverse.html

Regards,
--
Henrik Holst, Sweden
http://www.nada.kth.se/~holst/contact.shtml

Greg Lindahl

unread,
Mar 18, 2008, 12:25:06 AM3/18/08
to
In article <0762ae68-b666-4ccc...@b64g2000hsa.googlegroups.com>,
Henrik Holst <henrik...@gmail.com> wrote:

>I found many interesting threads on the subjects by search for
>"reverse communication".

You might do better looking for terms such as "lexical closures".

Anyway, one option you left off was using a module to stash the hidden
data. This is similar to using a common block, but a bit prettier.

>1) INTERNAL FUNCTIONS, are not allowed to be passed as arguments.
>A BIG design imo. This was my first try (and failure) to solve the
>problem.

We use these in perl all of the time, and it's well-understood how to
make them work efficiently. Ah well, no good wishing for what isn't.

-- greg

Arjen Markus

unread,
Mar 18, 2008, 4:20:16 AM3/18/08
to

In an article I have written for the Fortran Forum, I address
precisely this question and how to solve it using F2003
(whether I have found the optimal solution is another matter
of course :)).

If you do not mind the users to have access to the source code
of your library, you can actually use internal functions:

program solve_ode

call solve( func, xbegin, xend, ... )

contains

real function func( x )

! The right-hand side of the equation

end function func

include "library_source.f90"

end program

This way your library does have access to the internal
function and the internal function of course has access
to whatever data it needs from the program.

Of course, the drawback is that the source code must be
available (at least some parts of it) and it may lead
to code duplication.

Reverse communication may be complicated to implement,
but as long as the user code remains simple - just a
do loop and a select construction - it may be a
very useful solution anyway.

Regards,

Arjen

Henrik Holst

unread,
Mar 18, 2008, 8:10:52 AM3/18/08
to
(Excuse my first post; I forgot that tw=80 was too much for usenet)

Thank you Greg Lindahl and Arjen Markus for your responces!

On Mar 18, 9:20 am, Arjen Markus <arjen.mar...@wldelft.nl> wrote:
> In an article I have written for the Fortran Forum, I address
> precisely this question and how to solve it using F2003
> (whether I have found the optimal solution is another matter
> of course :)).

Is it published, and if so, under what name? I did only find "design
patterns for Fortran 90/95" (but seemed interesting by itself). I will
get it when I am at campus. :-)

>
> If you do not mind the users to have access to the source code
> of your library, you can actually use internal functions:
>
> program solve_ode
>
>     call solve( func, xbegin, xend, ... )
>
> contains
>
> real function func( x )
>
>     ! The right-hand side of the equation
>
> end function func
>
> include "library_source.f90"
>
> end program

A not that bad idea, but it cannot be used for the full library. I
have planned to implement 8x2 diffent types for each solvers (for any
kind of dimension on Y).

Another variant

MODULE MYSOLVER
IMPLICIT NONE
CONTAINS
SUBROUTINE F(T,Y)
REAL, INTENT(INOUT) :: T, Y(3,2)
...
END SUBROUTINE
INCLUDE 'ode/rk11.f90'
END MODULE MYSOLVER

But I guess I always could force the user to pass a vector (no matter
what).

> This way your library does have access to the internal
> function and the internal function of course has access
> to whatever data it needs from the program.

Now you're selling it. :-)

> Of course, the drawback is that the source code must be
> available (at least some parts of it) and it may lead
> to code duplication.
>
> Reverse communication may be complicated to implement,
> but as long as the user code remains simple - just a
> do loop and a select construction - it may be a
> very useful solution anyway.
>
> Regards,
>
> Arjen

Thank you for some ideas. I will evaluate your idea and see how it
fits with Fortran but more important: how it fits me.

Arjen Markus

unread,
Mar 18, 2008, 8:24:57 AM3/18/08
to
> Henrik Holst, Swedenhttp://www.nada.kth.se/~holst/contact.shtml- Tekst uit oorspronkelijk bericht niet weergeven -
>
> - Tekst uit oorspronkelijk bericht weergeven -

The article ought to be in the coming issue (a sequel to
one you found :))

Regards,

Arjen

Dick Hendrickson

unread,
Mar 18, 2008, 9:51:42 AM3/18/08
to

Can you also force the users to do the right thing in their
F function? If so, add another variable and make the interface
look like
> SUBROUTINE RK10(X, Y, F, H, helper)
use the_users_module
> INTERFACE
> FUNCTION F(X, Y, helper)
> USE ODE_LIB_KINDS
use the_users_module


> REAL(WP), INTENT(IN) :: X, Y
> REAL(WP) :: F

real(helper_type) :: helper


> END FUNCTION
> END INTERFACE
> REAL(WP), INTENT(INOUT) :: X, Y, H ! X INDEP. VARIABLE
> ! Y FCT. OF X
> ! H STEP-SIZE.
> REAL(WP) :: K(1) ! K WORKBUF. FOR STAGES

real(helper_type) :: helper ! whatever the user needs
>
> K(1) = H*F(X, Y, helper)


> Y = Y + K(1)
> X = X + H
> END SUBROUTINE RK10

The derived type variable can contain whatever stuff is needed, it's
essentially opaque in RK10. A major huge big drawback is that it
forces the user to use specific names for the module and for the
derived type. This can be a pain in the butt for people with simple
enough F's that no helper is needed. Maybe you could make helper
optional to somewhat ease the burden.

Dick Hendrickson

PS: As one of those noisy old relics who started with punched
paper tape(!) can I say that your solver doesn't look
very robust ;).

James Van Buskirk

unread,
Mar 18, 2008, 10:37:43 AM3/18/08
to
"Henrik Holst" <henrik...@gmail.com> wrote in message
news:0762ae68-b666-4ccc...@b64g2000hsa.googlegroups.com...

> I am writing to seek ideas how to solve the "callback problem" problem
> in
> a modern fashion using whats available in the Fortran 95/2003
> compilers, today.

> I am implementing a library for various kind of numerical methods for


> solving
> ODEs. The basic framework requires the possibility to evaluate f(t,y)
> (y is any
> 0 to 7 dimensional array) at a given point in T x Y space. This poses
> a problem
> for me because usually the f function does not only depend on t and y
> but on
> other user definable parameters.

> 1) INTERNAL FUNCTIONS, are not allowed to be passed as arguments.


> A BIG design imo. This was my first try (and failure) to solve the
> problem.

Are these going to be allowed in f08? Certainly ifort allows them.

http://groups.google.com/group/comp.lang.fortran/msg/da033bdc9fcbcc2a

> 2) COMMON BLOCKS, suck because global variables suck.
> My whole being says that global variables are evil. If they where not
> true evil
> before the days of multi-core computing, they must have increased
> their
> evilness by orders of magnitude today. (base 2)

You have to use COMMON blocks if you want to be able to mark data
as THREADPRIVATE

http://groups.google.com/group/comp.lang.fortran/msg/f38d88273cfe282a

> I am open to any suggestions I would just know how the Fortran
> community
> addresses this in the year of 2008. What solution do you use and why
> do you think so (and how come)?
> Remark: I am free from legacy code to no such
> considerations are worth taking into account.

Also you can have each thread compile its own function and dynamically
link it:

http://groups.google.com/group/comp.lang.fortran/msg/b5065aaaad9eb748

Or you could poke the function or a trampoline into memory, or you
could use the OS to create threads by hand so that you know the
extra function data is local to the thread rather than global.

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


Dick Hendrickson

unread,
Mar 18, 2008, 11:08:15 AM3/18/08
to
James Van Buskirk wrote:
> "Henrik Holst" <henrik...@gmail.com> wrote in message
> news:0762ae68-b666-4ccc...@b64g2000hsa.googlegroups.com...
>
>> I am writing to seek ideas how to solve the "callback problem" problem
>> in
>> a modern fashion using whats available in the Fortran 95/2003
>> compilers, today.
>
>> I am implementing a library for various kind of numerical methods for
>> solving
>> ODEs. The basic framework requires the possibility to evaluate f(t,y)
>> (y is any
>> 0 to 7 dimensional array) at a given point in T x Y space. This poses
>> a problem
>> for me because usually the f function does not only depend on t and y
>> but on
>> other user definable parameters.
>
>> 1) INTERNAL FUNCTIONS, are not allowed to be passed as arguments.
>> A BIG design imo. This was my first try (and failure) to solve the
>> problem.
>
> Are these going to be allowed in f08? Certainly ifort allows them.

I'm pretty sure they can be. I couldn't find the words that say so,
it's probably one of those swell cases where it's not forbidden so
it's allowed. Makes it hard to find with a search ;(.

Note 12.19 talks about referencing an internal procedure from outside
its host if it was passed as an actual parameter or via a pointer target.

And 7.2.2.4 allows internal procedures to be procedure pointer
targets. There's little practical reason to allow something to
be a target if it can't be referenced out of scope.

Just a guess, Richard probably remembers for sure.

Dick Hendrickson

Dick Hendrickson

unread,
Mar 18, 2008, 11:10:08 AM3/18/08
to
James Van Buskirk wrote:
> "Henrik Holst" <henrik...@gmail.com> wrote in message
> news:0762ae68-b666-4ccc...@b64g2000hsa.googlegroups.com...
>
>> I am writing to seek ideas how to solve the "callback problem" problem
>> in
>> a modern fashion using whats available in the Fortran 95/2003
>> compilers, today.
>
>> I am implementing a library for various kind of numerical methods for
>> solving
>> ODEs. The basic framework requires the possibility to evaluate f(t,y)
>> (y is any
>> 0 to 7 dimensional array) at a given point in T x Y space. This poses
>> a problem
>> for me because usually the f function does not only depend on t and y
>> but on
>> other user definable parameters.
>
>> 1) INTERNAL FUNCTIONS, are not allowed to be passed as arguments.
>> A BIG design imo. This was my first try (and failure) to solve the
>> problem.
>
> Are these going to be allowed in f08? Certainly ifort allows them.
>
Darn, I found it right after the last post.

16.5.5 says
"If an internal procedure is invoked via a dummy procedure..."

Dick Hendrickson

Craig Dedo

unread,
Mar 18, 2008, 12:42:45 PM3/18/08
to
"Henrik Holst" <henrik...@gmail.com> wrote in message
news:0762ae68-b666-4ccc...@b64g2000hsa.googlegroups.com...
> Hello comp.lang.Fortran!
>
> I am writing to seek ideas how to solve the "callback problem" problem
> in
> a modern fashion using whats available in the Fortran 95/2003
> compilers, today.
>
<snip>

>
> Background:
>
> I am implementing a library for various kind of numerical methods for
> solving
> ODEs. The basic framework requires the possibility to evaluate f(t,y)
> (y is any
> 0 to 7 dimensional array) at a given point in T x Y space. This poses
> a problem
> for me because usually the f function does not only depend on t and y
> but on
> other user definable parameters.
>
<snip example>

>
> Possible solutions to the problem:
>
> The solutions to the problem above has been suggested before. (With a
> short comment from me, to each of them.)
>
<snip #1>

>
> 2) COMMON BLOCKS, suck because global variables suck.
> My whole being says that global variables are evil. If they where not
> true evil
> before the days of multi-core computing, they must have increased
> their
> evilness by orders of magnitude today. (base 2)
>
<snip #3 - #5>

>
> Regards,
> --
> Henrik Holst, Sweden
> http://www.nada.kth.se/~holst/contact.shtml

Other posters have suggested a number of ways to solve your problem. I
would like to address a common misconception.

I would like you to take another look at the issue of the use of global
data, using an open mind. Global data is not evil. Using global data is
neutral; it is neither inherently good nor inherently evil.

There are several legitimate reasons to use global data. The most obvious
is when the data is conceptually a property of the whole program. If this is
the case, you should use global data and not try to hide the use of global data
through various subterfuges.

One of the most balanced treatments on the use of global data I have read is
section 13.3 (pp. 335-343) of Steve McConnell's Code Complete: A Practical
Handbook of Software Construction, 2nd ed. (ISBN 0-7356-1967-0). This section
covers the dangers of global data, reasons to use global data, and ways to
safely use global data.

In Fortran, one of the best ways to use global data is to put it into a
module that is used in the main program and in all of the procedures where you
need to use the global data. It also helps to use access procedures to obtain
values and change the values.

--
Craig Dedo
17130 W. Burleigh Place
P. O. Box 423
Brookfield, WI 53008-0423
Voice: (262) 783-5869
Fax: (262) 783-5928
Mobile: (414) 412-5869
E-mail: <cd...@wi.rr.com> or <cr...@ctdedo.com>

Henrik Holst

unread,
Mar 18, 2008, 10:37:42 PM3/18/08
to
On Mar 18, 5:42 pm, "Craig Dedo" <cd...@wi.rr.com> wrote:
> "Henrik Holst" <henrikhols...@gmail.com> wrote in message

Thats where I am now.

My solution (today) is based on global data in a module.

-

On a unrelated topic - what a good "burn" I got today from my old
friend: assumption.

Let me describe my test case, which did not work:

I started with a "integration routine" in a module:

MODULE ODEFUNC_LIB
REAL :: VE, G, L
CONTAINS
FUNCTION ODEFUNC(T,U) RESULT(Y)
IMPLICIT NONE
REAL, INTENT(IN) :: T, U(2)
REAL Y(2)
REAL, PARAMETER :: PI = 3.141592653589793
REAL :: THETA, OMEGA

THETA = U(1)
OMEGA = U(2)
Y(1) = OMEGA
Y(2) = (1.0/L)*(G + (1.0/VE)*SIN(2.0*PI*T/VE))*SIN(THETA)
END FUNCTION ODEFUNC
END MODULE ODEFUNC_LIB

And my RK11 routine which I was using to solve this ODE:

SUBROUTINE RK11(X, Y, F, H)


INTERFACE
FUNCTION F(X, Y)
USE ODE_LIB_KINDS

REAL(WP), INTENT(IN) :: X, Y(:)
REAL(WP) :: F(SIZE(Y))
END FUNCTION
END INTERFACE
REAL(WP), INTENT(INOUT) :: X, Y(:), H
REAL(WP) :: K(SIZE(Y),1)

K(:,1) = H*F(X, Y)
Y = Y + K(:,1)


X = X + H

END SUBROUTINE RK11

Now here is the burn: ODEFUNC is not compatible with RK11. The X and
Y parameters will be destroyed in the callback!

Instead I had to do this:

MODULE ODEFUNC_LIB_FIXED
REAL :: VE, G, L
CONTAINS
FUNCTION ODEFUNC(T,U) RESULT(Y)
IMPLICIT NONE
REAL, INTENT(IN) :: T, U(:)
REAL Y(SIZE(U))
REAL, PARAMETER :: PI = 3.141592653589793
REAL :: THETA, OMEGA

THETA = U(1)
OMEGA = U(2)
Y(1) = OMEGA
Y(2) = (1.0/L)*(G + (1.0/VE)*SIN(2.0*PI*T/VE))*SIN(THETA)
END FUNCTION ODEFUNC
END MODULE ODEFUNC_LIB_FIXED

And then the parameter passing worked as I hoped. (In the usual
fashion
this makes me very "displeased" with things.)

Since this was so very unexpected (but seems standard: both g95 and
Intel "screwed me") so I am thinking that this too should be done in
another way? Pointers or what else? Remembering to use (:) notation
is just too risky business and failure to do so is hard to detect.

(Recap, for those just joining this thread:
Callback routines and Fortran = bad, mkay? :-))

Gary Scott

unread,
Mar 18, 2008, 10:44:48 PM3/18/08
to

It seems no worse to me than callback routines in any language. It's
just a fundamentally bad way to program. The thing I hate most about
Win32 is the horrid callback design.

>
> --
> Henrik Holst, Sweden
> http://www.nada.kth.se/~holst/contact.shtml
>


--

Gary Scott
mailto:garylscott@sbcglobal dot net

Fortran Library: http://www.fortranlib.com

Support the Original G95 Project: http://www.g95.org
-OR-
Support the GNU GFortran Project: http://gcc.gnu.org/fortran/index.html

If you want to do the impossible, don't hire an expert because he knows
it can't be done.

-- Henry Ford

glen herrmannsfeldt

unread,
Mar 19, 2008, 2:50:52 AM3/19/08
to
Craig Dedo wrote:

> "Henrik Holst" <henrik...@gmail.com> wrote:
(snip)

>> 2) COMMON BLOCKS, suck because global variables suck.
>> My whole being says that global variables are evil.
>> If they where not true evil before the days of multi-core
>> computing, they must have increased their
>> evilness by orders of magnitude today. (base 2)

I don't know what multicore has to do with it. If you
are running multithreaded or recursive then you have to be
careful how you use static data, and COMMON is a form of
static data.

(snip)

> I would like you to take another look at the issue of the use of
> global data, using an open mind. Global data is not evil. Using global
> data is neutral; it is neither inherently good nor inherently evil.

I agree. If data is truly global, which usually also means that the
program is designed for a single purpose and won't be reusable in
general then global data works well.

> There are several legitimate reasons to use global data. The most
> obvious is when the data is conceptually a property of the whole
> program. If this is the case, you should use global data and not try to
> hide the use of global data through various subterfuges.

For the OP problem, though, it isn't such a good solution, but it
is a common one. C has file scope variables which are a little better,
but they are still static and the usual problems with static data
are there. My choice might be a generic pointer that could be passed
through to the called function pointing to whatever data structure
was needed: array, structure, array of pointers, etc.

-- glen

relaxmike

unread,
Mar 19, 2008, 10:52:26 AM3/19/08
to
Hi Henrik,

One solution you do not mention is the function pointer (cray
pointers).
This is the most universal solution for the problem of separating
one algorithm from the particular applications of that algorithm.

I developed that solution in the following thread about object
oriented optimization
where I use function pointers to separate an optimization software in
fortran 77
from the function to optimize :
http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/f4caec248299a2c3/a7955e3261651da1?lnk=gst&q=object+oriented+optimization#a7955e3261651da1

In the following thread, I used the same technic to separate one
integration
algorithm from the particular functions to integrate (your problem is
exactly the same) :
http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/b221deff642bcf9a/7012a67d50d0cdce#7012a67d50d0cdce

The same solution can be applied for a parsing system (e.g. xml, data
file, or even fortran
himself), where the main algorithm is generic (the opening of the
file, loop over the lines,
processing each line, etc..), but particular analysis can be defined
for the particular data
to parse with function pointers. This way, one can separate the
general lexical analysis
from the particular data to parse : fortran lexer, xml lexer, etc...
The same is for the
general grammar analyser and the particular semantic to analyse :
fortran grammar, xml
grammar, etc...

One can think also about the problem of solving a non linear system
f(x)=0 with a Newton
method, where the Newton method can remain generic, while the
particular function
to solve and its derivatives are defined outside and passed to the
solver with
function pointers.

I applied the same principle for a statistical component. We use the
bootstrap method to compute a standard deviation associated with a
statistical result. The bootstrap method is generic and is just the
computation
of a population of data by a randomization process of the original
data.
The use of the bootstrap method for a particular kind of statistical
result
is done with a function pointer, which defines what is the
statistical
result which is to be bootstrapped. That way, one can use the same
soft
to bootstrap the average, the maximum or any other type of statistical
result.

And so on...

But not all compilers support that type of pointers.
For example gfortran does and Intel Fortran also does, but not g95.
It will be a standard feature in fortran 2003 compilers, called
"Pointers to procedures".
I wonder why we had to wait for so long before such a feature
was introduced in fortran. It has been in the core of C since the
begining (at least 20-30 years ago) !

Best regards,

Michaël

GaryScott

unread,
Mar 19, 2008, 11:19:20 AM3/19/08
to
On Mar 19, 9:52 am, relaxmike <michael.bau...@gmail.com> wrote:
> Hi Henrik,
>
> One solution you do not mention is the function pointer (cray
> pointers).
> This is the most universal solution for the problem of separating
> one algorithm from the particular applications of that algorithm.
>
> I developed that solution in the following thread about object
> oriented optimization
> where I use function pointers to separate an optimization software in
> fortran 77
> from the function to optimize :http://groups.google.com/group/comp.lang.fortran/browse_thread/thread...

>
> In the following thread, I used the same technic to separate one
> integration
> algorithm from the particular functions to integrate (your problem is
> exactly the same) :http://groups.google.com/group/comp.lang.fortran/browse_thread/thread...

We had to wait so long, because adding pointers was a bad idea to
begin with. It was primarily the need to interoperate with bad
programming practices in other languages that prompted their addition.

>
> Best regards,
>
> Michaël

Richard Maine

unread,
Mar 19, 2008, 11:50:29 AM3/19/08
to
relaxmike <michael...@gmail.com> wrote:

> Hi Henrik,
>
> One solution you do not mention is the function pointer (cray
> pointers).
> This is the most universal solution for the problem of separating
> one algorithm from the particular applications of that algorithm.

...
> But not all compilers support that type of pointers.

And even compilers that support Cray pointers don't necessarily support
Cray pointers to functions. In fact, the Cray compilers didn't, so this
counts as a "nonstandard" extension to a nonstandard extension. The set
of compilers this will work with is pretty limitted, making this rather
far from "universal." Pretty much none of the compilers that I've ever
used extensively support it.

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

glen herrmannsfeldt

unread,
Mar 19, 2008, 6:15:45 PM3/19/08
to
GaryScott wrote:
(snip)

> We had to wait so long, because adding pointers was a bad idea to
> begin with. It was primarily the need to interoperate with bad
> programming practices in other languages that prompted their addition.

There are a number of cases where pointers really are the
best solution. It seems that they have been overused in C and
some other languages, but that doesn't make them bad.

In PL/I, they are part of the list processing facility.
They work well for linked lists, trees, and other data
structures built up dynamically. They work especially
well as structure pointers, where one can point at a
data structure and then work with the different parts
of that structure (including other pointers).

-- glen

Arjen Markus

unread,
Mar 20, 2008, 3:54:02 AM3/20/08
to

It would seem that any language feature stands a chance
to get a bad reputation:

"GOTOs considered harmful" is the seminal paper for
making GOTOs suspicious. But I have seen variations on that
theme for recursive make and polymorphism. Some people
swear by object-oriented programming for everything
instead of procedural style. And then there is the
old aphorism that "you can write FORTRAN in any language".

I am sure there are more examples.

What they all seem to have in common is that overly
liberal use of the feature _can_ lead and probably
_will_ lead to incomprehensible programs or program
systems that you can not possibly hope to maintain
without pain, but this observation leads to a group
of zealots that proclaim that That Feature Is
Evil And That You Should Always Use Some Other
Feature (preferably in the language of their choice).

(Do not mind me too much, I had a very bad day yesterday ;))

Regards,

Arjen

relaxmike

unread,
Mar 20, 2008, 4:54:41 AM3/20/08
to
Your message is really funny Arjen ;) !

"We had to wait so long, because adding pointers was a bad idea to
begin with. It was primarily the need to interoperate with bad
programming practices in other languages that prompted their
addition."

It is a pity that a good feature was added for a bad reason.

"And even compilers that support Cray pointers don't necessarily
support

Cray pointers to functions. [...] Pretty much none of the compilers


that I've ever
used extensively support it."

I suggest you to change the compiler that you use extensively ! ;)

Michaël

Greg Lindahl

unread,
Mar 20, 2008, 5:02:41 AM3/20/08
to
In article <898fa25b-be0f-4966...@a1g2000hsb.googlegroups.com>,
Arjen Markus <arjen....@wldelft.nl> wrote:

>"GOTOs considered harmful" is the seminal paper for
>making GOTOs suspicious.

... until you learn that "FOO considered harmful" frequently passed
the lips of the guy who wrote that seminal paper. Cry wolf too many
times, and it dilutes the message.

-- greg

Greg Lindahl

unread,
Mar 20, 2008, 5:06:02 AM3/20/08
to
In article <22da01c5-8adc-4264...@m44g2000hsc.googlegroups.com>,
relaxmike <michael...@gmail.com> wrote:

>>"And even compilers that support Cray pointers don't necessarily
>>support Cray pointers to functions. [...] Pretty much none of the
>>compilers that I've ever used extensively support it."
>
>I suggest you to change the compiler that you use extensively ! ;)

Hey, you should be nice! It's hard to track a non-standard that
changes as rapidly as Cray pointers. Compiler vendors based on the
actual Cray front-end have had to add a lot of code to comply with the
'standard', because it's a moving target... with most customers
insisting that a compiler is horribly broken when it doesn't support
some extension supported by a limited number of compilers.

-- greg

relaxmike

unread,
Mar 20, 2008, 7:07:01 AM3/20/08
to
> Hey, you should be nice! It's hard to track a non-standard that
> changes as rapidly as Cray pointers.

You are right : it is not so easy to pass from one compiler
to the other, especially when you have to maintain thousands of
lines of codes, on several projects. It is really an
issue.

GaryScott

unread,
Mar 20, 2008, 10:17:08 AM3/20/08
to
On Mar 19, 5:15 pm, glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:
> GaryScott wrote:
>
> (snip)
>
> > We had to wait so long, because adding pointers was a bad idea to
> > begin with.  It was primarily the need to interoperate with bad
> > programming practices in other languages that prompted their addition.
>
> There are a number of cases where pointers really are the
> best solution.  It seems that they have been overused in C and
> some other languages, but that doesn't make them bad.
>
> <snip>
> -- glen
I'm not really as anti-pointer as that sounded, however, it is
possible to solve these problems in other ways. You can write a
linked list (double, single, skip) functionality without pointers and
in my opinion more clearly. "Best" is highly subjective. Clear,
clean, easy to understand code may be best for some, whereas,
efficient memory utilization might be someone else's criterion. I've
solved virtually every type of problem without ever needing pointers.
The only exceptions have been the need to associate an application
memory buffer or structure with allocated memory returned by the
operating system, or to assign a callback procedure. I would add that
if linked lists are so overwhelmingly beneficial, then we should build
them into the language, perhaps as an intrinsic object.

Richard Maine

unread,
Mar 20, 2008, 12:16:30 PM3/20/08
to
relaxmike <michael...@gmail.com> wrote:
[saying that ARjen wrote]

> "And even compilers that support Cray pointers don't necessarily
> support
> Cray pointers to functions. [...] Pretty much none of the compilers
> that I've ever
> used extensively support it."
>
> I suggest you to change the compiler that you use extensively ! ;)

That was me, not Arjen. I think you failed to notice the plural on
"compilers", since you switched it to singular in your reply. It is not
just one compiler that doesn't support it. *MOST* compilers don't
support the particular use. Finding one that did would have, in many
case, also required changing operating systems and hardware, sometimes
on multi-million dollar machines.

I consider it particularly bad advice to adopt coding practices aimed at
ony such a small set of compilers as those that this works on. I'm not
quite sure how to read the smiley here, so maybe I'm reacting to
something intended to have no serious content. But if I've badly misread
this, I still feel a reply is needed for the sake of other readers who
might also misread it.

The codes I tended to write were not just to amuse myself, but for
actual use... most often by other people, sometimes by quite a lot of
other people. targetting for a particular compiler would mean not only
that I had to stick to that compiler and the machines it ran on, but
also that I'd need to tell all my users that they had to get that same
compiler and machine. If you have ever written code for use by others,
you would understand how well that would likely go over. It was quite
bad enough telling people that they would need to have a Fortran
compiler at all... or any other compiler for that matter. I'd get people
complaining that I didn't give them a prebuilt executable for their
machine (when I had no access to a machine of that particular kind, and
this was software given to them for free.)

Oh, and actually I have changed the set of compilers that I most
extensively use - multiple times over the years, but I assure you that
it was always for more substantiative reasons than suggested here. Most
recently, the set changed rather significantly when I retired. I don't
feel like paying the cost of the ones I was mostly using at work (and I
don't have some of thos emachines at home either), when this has now
become more of a hobby than a job. So I'm using a free one, and the set
is down to pretty much one. It doesn't support the feature in question
either; it does compile my various codes fine.

Perhaps this is all a big overreaction on my part. I'm pretty sure it
is. But the adice strikes me as so incredibly bad, that I have trouble
letting it pass, even in jest, without comment.

james...@att.net

unread,
Mar 20, 2008, 12:52:48 PM3/20/08
to
On Mar 20, 1:54 am, Arjen Markus <arjen.mar...@wldelft.nl> wrote:
...
> [...] Some people

> swear by object-oriented programming for everything
> instead of procedural style. [...]

This is unrelated to the rest of this thread, but in what way is OOP
not procedural? OOP tends to be *more* procedural than non-OO
imperative languages. If nothing else, then due to the common
recommendation that access to components of something should be done
through procedures (methods) rather than directly.

I looked up "procedural programming" in wikipedia and it's not much
help. The distinction seems to be made by the same folks that claim
that an OOP "object" corresponds to a non-OOP "module". This latter
is a sufficiently common mistake as to qualify as a FAQ here.

The wikipedia entry for "procedural programming" contains the
following: "The focus of procedural programming is to break down a
programming task into a collection of data structures and subroutines,
whereas in object oriented programming it is to break down a
programming task into objects." Except that an object is an instance
of a class which in turn is a collection of data structures and
methods (procedures). So the defining distinction isn't a distinction
at all. In particular, OOP still is procedural. The syntax is
different, but the semantics and pragmatics are the same. At least,
until inheritance is brought into the picture. But the above seems to
be an effort to define OOP without mentioning inheritance.

--
J. Giles

"I conclude that there are two ways of constructing a software
design: One way is to make it so simple that there are obviously
no deficiencies and the other way is to make it so complicated
that there are no obvious deficiencies." -- C. A. R. Hoare

glen herrmannsfeldt

unread,
Mar 20, 2008, 1:30:24 PM3/20/08
to
GaryScott wrote:
(snip)

> I'm not really as anti-pointer as that sounded, however, it is
> possible to solve these problems in other ways. You can write a
> linked list (double, single, skip) functionality without pointers and
> in my opinion more clearly. "Best" is highly subjective. Clear,
> clean, easy to understand code may be best for some, whereas,
> efficient memory utilization might be someone else's criterion.

Efficient memory utilization is often important. When Fortran
was young, computers only had one program in storage at a time so
that there was no reason not to give that program all available storage.
Many Fortran "tricks" are based on how to use that memory within
the program.

When you have more than one program running and using memory at
the same time, efficient use of memory is important. When a
program can't anticipate its memory usage, dynamic allocation
is needed. In the case of a linked list of unknown and highly
variable length, pointers allow more efficient memory usage.
If the total length is known, or approximately known, then
an array of appropriate size can be allocated and array
elements referenced as part of a list. (I have done
that even in C.)

> I've
> solved virtually every type of problem without ever needing pointers.
> The only exceptions have been the need to associate an application
> memory buffer or structure with allocated memory returned by the
> operating system, or to assign a callback procedure. I would add that
> if linked lists are so overwhelmingly beneficial, then we should build
> them into the language, perhaps as an intrinsic object.

PL/I has locate mode I/O for that case. One can read data in such
that the system supplies a pointer to the data in the input buffer
or write data directly into the output buffer. That saves copying
large amounts of data unnecessarily, especially for read-modify-write
when only small modifications are being made.

-- glen

Craig Powers

unread,
Mar 20, 2008, 2:56:21 PM3/20/08
to

Perhaps the choice of terminology is unfortunate, but the distinction
that I draw between a pure OO style and a pure "procedural" style is
that in the OO style, *everything* (all data and all procedures) is a
member of an object, whereas in the pure "procedural" style, *nothing*
is a member of an object. Obviously, there's some overlap in that
whatever serves as the "main" program will be written in a somewhat
procedural style even though it is a member of an object. At the same
time, I object to the attempt to force everything into objects (a la
Java) even in instances where I'm coding something that proceeds in a
linear "first do A, then do B, then do C" style with few or no
operations or data that would be logically grouped as "objects".

james...@att.net

unread,
Mar 20, 2008, 3:34:11 PM3/20/08
to
On Mar 20, 12:56 pm, Craig Powers <eni...@hal-pc.org> wrote:
...

> Perhaps the choice of terminology is unfortunate, but the distinction
> that I draw between a pure OO style and a pure "procedural" style is
> that in the OO style, *everything* (all data and all procedures) is a
> member of an object, whereas in the pure "procedural" style, *nothing*
> is a member of an object.  [...]

So, the difference really is "merely" syntax? That's the only
difference there is between derived types plus procedures defined on
those types and derived types with type-bound procedures.
Semantically and pragmatically they are completely interchangeable,
identical, isomorphic, whatever. Their only difference is syntax.

Now, don't get me wrong. I think syntax is often the most important
aspect of language design. The phrase "merely syntax" always sets my
teeth on edge. But I don't think syntactic differences constitute a
sufficient distinction to qualify as an important programming
paradigm.

glen herrmannsfeldt

unread,
Mar 20, 2008, 4:56:59 PM3/20/08
to
Craig Powers wrote:
(snip on OO programming)

> Perhaps the choice of terminology is unfortunate, but the distinction
> that I draw between a pure OO style and a pure "procedural" style is
> that in the OO style, *everything* (all data and all procedures) is a
> member of an object, whereas in the pure "procedural" style, *nothing*
> is a member of an object. Obviously, there's some overlap in that

Note that you can write OO style in a non-OO language, and
vice versa. In most cases a compromise is best. Especially
for scientific software with number crunching inner loops you
want to keep object creation/destruction out of that loop.

On the other hand, the get/set style of OO programming still
works even if there is global access to the data. It is really
what you do that counts (assuming the reader believes it).

> whatever serves as the "main" program will be written in a somewhat
> procedural style even though it is a member of an object. At the same
> time, I object to the attempt to force everything into objects (a la
> Java) even in instances where I'm coding something that proceeds in a
> linear "first do A, then do B, then do C" style with few or no
> operations or data that would be logically grouped as "objects".

My favorite example is used for UDP network data:
create UDP object, add data to object, send object. Three
calls to say what could be done in one, just to make it look OO.
(That is for Java with garbage collect.)

TCP is different, so OO might make more sense. If it
doesn't make programs more readable it seems a waste.

-- glen

Craig Powers

unread,
Mar 20, 2008, 4:51:56 PM3/20/08
to
james...@att.net wrote:
> On Mar 20, 12:56 pm, Craig Powers <eni...@hal-pc.org> wrote:
> ...
>> Perhaps the choice of terminology is unfortunate, but the distinction
>> that I draw between a pure OO style and a pure "procedural" style is
>> that in the OO style, *everything* (all data and all procedures) is a
>> member of an object, whereas in the pure "procedural" style, *nothing*
>> is a member of an object. [...]
>
> So, the difference really is "merely" syntax? That's the only
> difference there is between derived types plus procedures defined on
> those types and derived types with type-bound procedures.
> Semantically and pragmatically they are completely interchangeable,
> identical, isomorphic, whatever. Their only difference is syntax.
>
> Now, don't get me wrong. I think syntax is often the most important
> aspect of language design. The phrase "merely syntax" always sets my
> teeth on edge. But I don't think syntactic differences constitute a
> sufficient distinction to qualify as an important programming
> paradigm.

I think there's more to it than syntax. Fundamentally, I agree that OO
amounts to a system whereby a bunch of stuff that's tedious in a non-OO
language gets done under-the-hood (although taken to extremes, it forces
the under-the-hood stuff even on operations where it's not appropriate),
so it's basically just a distinction in syntax when one looks at solving
the same problem in both an OO and non-OO imperative language.

I agree that it's possible to write the same thing in both syntaxes, but
I think that the strict OO syntax tends to go hand-in-hand with a
different approach to designing the program -- though I couldn't say
whether that's because OO leads to the same people designing
differently, or whether it's because OO draws different people who
already have a predilection for designing that way.

That's just my personal impression, I have no evidence to back it up and
it might very well be wrong.

relaxmike

unread,
Mar 20, 2008, 5:08:56 PM3/20/08
to
Be sure Richard that I did not want to be aggressive.
I am very concerned by the fact that not all compilers support
function pointers. In fact, I have allready used a set of compilers :
PGI, Sun, Sgi, Ibm, Intel, g95, gfortran and Absoft to make the full
list.
I am aware that maintaining several large scientific softwares over
several
years and on several machine under various OS (Linux, Windows, Sun,
HP, 32 bits,
64 bits, parallel etc...) is really a difficult task.

In fact, very few people know that this feature is available, even if
it is only on a limited set of compilers.
One cannot say that the only solution for the "callback problem" is
internal
procedure, common block or reverse communication : Cray function
pointers
exist and are available on a limited set of fortran compilers (2
compilers), for a limited
set of platforms (at least windows and linux 32 bits).

Michaël

robin

unread,
Mar 20, 2008, 6:23:00 PM3/20/08
to
"Henrik Holst" <henrik...@gmail.com> wrote in message
news:0762ae68-b666-4ccc...@b64g2000hsa.googlegroups.com...

> I am implementing a library for various kind of numerical methods for


> solving
> ODEs. The basic framework requires the possibility to evaluate f(t,y)
> (y is any
> 0 to 7 dimensional array) at a given point in T x Y space. This poses
> a problem
> for me because usually the f function does not only depend on t and y
> but on
> other user definable parameters.

Since that is the case, the function to be evaluated should be f(t, y, a, b, ... z),
where a, b, c, ... z are those additional definable parameters.
In other words, the list of variables should be included in the function
reference.


Arjen Markus

unread,
Mar 21, 2008, 6:24:22 AM3/21/08
to
On 20 mrt, 17:52, "jamesgi...@att.net" <jamesgi...@att.net> wrote:
> On Mar 20, 1:54 am, Arjen Markus <arjen.mar...@wldelft.nl> wrote:
> ...
>
> > [...]              Some people
> > swear by object-oriented programming for everything
> > instead of procedural style. [...]
>
> This is unrelated to the rest of this thread, but in what way is OOP
> not procedural?  OOP tends to be *more* procedural than non-OO
> imperative languages.  If nothing else, then due to the common
> recommendation that access to components of something should be done
> through procedures (methods) rather than directly.
>

Perhaps "imperative" is the correct term and not "procedural".
But my remark/rant was not so much geared to the difference
in programming paradigm as to those zealots that say that OOP
is a good thing and anything else is bad.

I agree, though, that OOP as seen in most C++ or Java programs
is very procedural, even though lots of things are going on
under the hood.


Regards,

Arjen

GaryScott

unread,
Mar 21, 2008, 10:59:51 AM3/21/08
to
On Mar 20, 3:51 pm, Craig Powers <eni...@hal-pc.org> wrote:

> jamesgi...@att.net wrote:
> > On Mar 20, 12:56 pm, Craig Powers <eni...@hal-pc.org> wrote:
> > ...
> >> Perhaps the choice of terminology is unfortunate, but the distinction
> >> that I draw between a pure OO style and a pure "procedural" style is
> >> that in the OO style, *everything* (all data and all procedures) is a
> >> member of an object, whereas in the pure "procedural" style, *nothing*
> >> is a member of an object.  [...]
>
> > So, the difference really is "merely" syntax?  That's the only
> > difference there is between derived types plus procedures defined on
> > those types and derived types with type-bound procedures.
> > Semantically and pragmatically they are completely interchangeable,
> > identical, isomorphic, whatever.  Their only difference is syntax.
>
> > Now, don't get me wrong.  I think syntax is often the most important
> > aspect of language design.  The phrase "merely syntax" always sets my
> > teeth on edge.  But I don't think syntactic differences constitute a
> > sufficient distinction to qualify as an important programming
> > paradigm.
>
> I think there's more to it than syntax.  Fundamentally, I agree that OO
> amounts to a system whereby a bunch of stuff that's tedious in a non-OO
> language gets done under-the-hood (although taken to extremes, it forces
> the under-the-hood stuff even on operations where it's not appropriate),
> so it's basically just a distinction in syntax when one looks at solving
> the same problem in both an OO and non-OO imperative language.
>
<snip>

My problem with gaining a thorough understanding of OO is the
terminology is too imprecise and varies in significant ways depending
on programming language and domain. For example, the term CLASS is
confusing to me. If it were called "OBJECT TEMPLATE", I could
remember it better. I also generally don't like using the exact same
key word to define a template and to declare an instance of that
template (possibly using a slightly different syntax). The same
problem occurs with derived types. I would have preferred something
like a "TYPEDEF" or "TYPE TEMPLATE" to declare a template, and "TYPE"
or "TYPE INSTANCE" to declare a data type instance.

james...@att.net

unread,
Mar 21, 2008, 11:17:20 AM3/21/08
to
On Mar 21, 4:24 am, Arjen Markus <arjen.mar...@wldelft.nl> wrote:
...
> Perhaps "imperative" is the correct term and not "procedural".
> But my remark/rant was not so much geared to the difference
> in programming paradigm as to those zealots that say that OOP
> is a good thing and anything else is bad.

Well my remark/rant was more geared to find out what people think OO
*is* anymore. Now that the proponents of the paradigm are trying to
distance themselves from inheritance, what's left? Without
inheritance, there's nothing going on "under the hood" that's not
identical to the internal workings of conventional imperative
languages. The syntax is different.

About a year ago someone posted here a long list of definitions of OOP
terms. I thought the thing most significant about the list was that
OOP itself was only defined implicitly. An "Object Oriented Program"
was one designed according to an "Object Oriented Design", the latter
was a design created by "Object Oriented Analysis" of the problem, the
latter was an analysis consistent with "Object Oriented Principles",
etc. I used to know what OOP was back in the days when the proponents
freely admitted that inheritance was the main innovation. I have no
idea any more.

Arjen Markus

unread,
Mar 21, 2008, 11:22:23 AM3/21/08
to
On 21 mrt, 16:17, "jamesgi...@att.net" <jamesgi...@att.net> wrote:
> On Mar 21, 4:24 am, Arjen Markus <arjen.mar...@wldelft.nl> wrote:
> ...
>
> Well my remark/rant was more geared to find out what people think OO
> *is* anymore.  Now that the proponents of the paradigm are trying to
> distance themselves from inheritance, what's left?  Without
> inheritance, there's nothing going on "under the hood" that's not
> identical to the internal workings of conventional imperative
> languages.  The syntax is different.
>
> About a year ago someone posted here a long list of definitions of OOP
> terms.  I thought the thing most significant about the list was that
> OOP itself was only defined implicitly.  An "Object Oriented Program"
> was one designed according to an "Object Oriented Design", the latter
> was a design created by "Object Oriented Analysis" of the problem, the
> latter was an analysis consistent with "Object Oriented Principles",
> etc.  I used to know what OOP was back in the days when the proponents
> freely admitted that inheritance was the main innovation.  I have no
> idea any more.
>

With polymorphism having gone too (note the pun!), yes, I agree:
OOP has made a U turn.

All that is left is something like: methods and data should be
closely together. And that is nothing really distinguishing.

Regards,

Arjen

Jan Vorbrüggen

unread,
Mar 26, 2008, 7:17:24 AM3/26/08
to
> FUNCTION ODEFUNC(T,U) RESULT(Y)
> IMPLICIT NONE
> REAL, INTENT(IN) :: T, U(2)
> REAL Y(2)
>
> And my RK11 routine which I was using to solve this ODE:
>
> FUNCTION F(X, Y)
> USE ODE_LIB_KINDS
> REAL(WP), INTENT(IN) :: X, Y(:)
> REAL(WP) :: F(SIZE(Y))
> END FUNCTION
>
> Now here is the burn: ODEFUNC is not compatible with RK11. The X and
> Y parameters will be destroyed in the callback!

What else did you expect? You lied to the compiler about the actual
interface: in one case you are passing an explicit-length array and
returning such, in the other case an assumed-length one.

If, in the interface definition, you had used Y(*), all should be well.

Jan

robin

unread,
Mar 26, 2008, 7:45:13 AM3/26/08
to
"glen herrmannsfeldt" <g...@ugcs.caltech.edu> wrote in message
news:v_6dnXghsrV1AH_a...@comcast.com...

> Efficient memory utilization is often important. When Fortran
> was young, computers only had one program in storage at a time so
> that there was no reason not to give that program all available storage.

It took it all anyway, and conservation of memory was very
important.

That was one reason for using EQUIVALENCE.

Both ALGOL and PL/I addressed that problem
with dynamic storage.


Reply all
Reply to author
Forward
0 new messages