Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!mailrus!ames!amelia!lemming.nas.nasa.gov!fouts
From: fouts@lemming.nas.nasa.gov.nas.nasa.gov (Marty Fouts)
Newsgroups: comp.lang.fortran
Subject: Re: Data types _without_ pointers
Message-ID: <1038@amelia.nas.nasa.gov>
Date: 22 Sep 88 23:44:32 GMT
References: <1032@amelia.nas.nasa.gov> <4026@lanl.gov>
Sender: news@amelia.nas.nasa.gov
Reply-To: fouts@lemming.nas.nasa.gov.nas.nasa.gov (Marty Fouts)
Organization: NASA Ames Research Center
Lines: 153

In article <4026@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>From article <1032@amelia.nas.nasa.gov>, by fouts@lemming.nas.nasa.gov.nas.nasa.gov (Marty Fouts):
>> [...]
>> NO. NO. NO. (Gee, I can capshout too ;-)  A pointer is also a
>> mechanism by which I introduce an arbitrary data structure into my
>> language, allowing me to easily express data structures that the 
>> original language designer didn't think to provide.  [...]
>
>I have never seen a data structure that couldn't be described without
>pointers.

Read the note you are responding to.  I'm not claiming a structure
that can't be described without structures.  I'm claiming that many
data structures and their use can be expressed in a very readable way
by using pointers, and that I like that readability.  I use that
readability.

Take as an example, a fifo (a structure I use sometimes in discrete
event modeling.)  I can implement a fifo using an array and two
integers (to keep track of where I am).  Using the convention that the
head number records the first used entry in the queue and that
the tail number records the first unused entry, except when they both
have the same value, in which case the fifo is empty, I can write the
two Fortran routines:

      SUBROUTINE ADDTO(FIFO,ISIZE,IHEAD,ITAIL,VALUE)
      DIMENSION FIFO(ISIZE)
      IF ((ITAIL .EQ. IHEAD) .AND. (IHEAD .NE. 0)) THEN
C
C FIFO FULL ERROR HANDLING
C
        RETURN
      ENDIF
      ITAIL = ITAIL + 1
      IF (ITAIL .GT. ISIZE) ITAIL = 1
      FIFO(ITAIL) = VALUE
      IF (IHEAD .EQ. 0) IHEAD = 1
      RETURN
      END

      FUNCTION REMOVE(FIFO,ISIZE,IHEAD,ITAIL,VALUE)
      DIMENSION FIFO(ISIZE)
      IF (ITAIL .EQ. IHEAD) THEN
C
C FIFO EMPTY ERROR HANDLING
C
         RETURN
     ENDIF
     REMOVE = FIFO(IHEAD)
     IHEAD = IHEAD + 1
     IF (IHEAD .GT. ISIZE) IHEAD = 1
     IF (IHEAD .EQ. ITAIL) THEN
        IHEAD = 0
        ITAIL = 0
     ENDIF
     RETURN
     END

I can also do the same thing using pointers (from C):

typedef struct fifo_entry {
    real value;
    struct fifo_entry *next;
} FIFO_ENTRY, *FIFO_ENTRY_PTR;

typedef struct fifo {
   FIFO_ENTRY_PTR head, tail;
} FIFO;

void addto(fifo,new_value)
    FIFO fifo;
    real new_value;
{
    FIFO_ENTRY_PTR new_entry;

    new_entry = (FIFO_ENTRY_PTR)malloc(sizeof(FIFO_ENTRY));
    if (new_entry == 0) {
      /* MEMORY ERROR EXIT */
      return;
    }

    new_entry->value = new_value;

    if (fifo.tail != 0)  (fifo.tail)->next = new_entry;
    fifo.tail = new_entry;
    if (fifo.head == 0) fifo.head = new_entry;
    return;
}

real remove(fifo)
    FIFO fifo;
{
    real return_value;
    FIFO_ENTRY_PTR old_entry;

    if (fifo.head == 0) {
      /* EMPTY FIFO ERROR EXIT */
      return
    }

    old_entry = fifo.head;
    return_value = old_entry->value;
    fifo.head = fifo.head->next;
    free((char *)old_entry);
}


Neither of these is a good substitute for (Not available in any
language I usually use)

Declare fifo to be a fifo of real;

and using 'fifo = x' to add x to the end of fifo and 'x = fifo' to
remove x from the begining of the fifo.

In the example, the two forms are (to me, because I've had a lot of
experience with both) about equally readable.  The Fortran form is
somewhat more restricted because it implements a fixed length fifo,
but that doesn't matter in the applications I run.

I would prefer the third form, but if I have to chose between the
first two, I would prefer the second, because it more closely maps to
what I'm thinking about when I think of fifos.

The code gets even messier with more difficult structures, like
balanced binary trees.

On the other hand, if you implement recursive structures using Hoare's
notation, you have to think about recursive structures, and I just
haven't been trained to do that.  Try representing a dynamic length
fifo using Hoare's structure and answering the questions:

1) What happens when I add to a fifo?
2) How do I represent this structure?
3) How do I keep track of the head/tail?
4) How do I detect an empty fifo?

BTW, recursive structures are a very clumsy way to think about bags,
which differ from sets by being allowed to contain duplicate entries,
and about ordered sets/bags, which require the set to be maintained in
a sequence which is externally enforced.

In summary:  Yes, you can have data types without pointers, either by
forcing them on top of existing languages, or by using Hoare's
recursive structure technique.  I never said otherwise.  I said that
if I don't have the data types and have to build my own abstractions,
I prefer to use pointers to do it.

+-+-+-+     I don't know who I am, why should you?     +-+-+-+
   |        fouts@lemming.nas.nasa.gov                    |
   |        ...!ames!orville!fouts                        |
   |        Never attribute to malice what can be         |
+-+-+-+     explained by incompetence.                 +-+-+-+