Passing substructures to procedures

by Richard Russell, August 2006

As described in the main documentation you can pass entire structures to a procedure or function as follows:

        DIM object{name$,pos{x,y,z}}
        object.pos.x = 1.0
        object.pos.y = 2.0
        object.pos.z = 3.0
        PRINT FN_distance(object{})
        END
 
        DEF FN_distance(s{})
        = SQR(s.pos.x^2 + s.pos.y^2 + s.pos.z^2)

However you cannot pass an entire substructure to a procedure or function. The following code doesn't work (it will crash BBC BASIC):

        REM This doesn't work - don't try it at home!
        DIM object{name$,pos{x,y,z}}
        object.pos.x = 1.0
        object.pos.y = 2.0
        object.pos.z = 3.0
        PRINT FN_distance(object.pos{})
        END
 
        DEF FN_distance(p{})
        = SQR(p.x^2 + p.y^2 + p.z^2)

In most cases passing the parent structure instead, as in the first example, isn't a major inconvenience, however it does mean that the substructure must always have the same name (in this case pos{}).

It would be desirable to be able to use a common FN_distance function (for example) even if the substructure doesn't always have the same name; in particular this would make it easier to incorporate the function in a library. There is a way of achieving this, which involves passing to the procedure or function both the parent structure and the substructure. Here's how you would do it for this particular example:

        DIM object{name$,pos{x,y,z}}
        object.pos.x = 1.0
        object.pos.y = 2.0
        object.pos.z = 3.0
        PRINT FN_distance(object{},object.pos{})
        END
 
        DEF FN_distance(s{},p{})
        PTR(p{}) = PTR(s{}) + PTR(p{})
        = SQR(p.x^2 + p.y^2 + p.z^2)

Note the manipulation of memory in FN_distance which makes this work.

Now you can use the same function with a differently-named substructure:

        DIM newobj{type%,loc{x,y,z}}
        newobj.loc.x = 4.0
        newobj.loc.y = 5.0
        newobj.loc.z = 6.0
        PRINT FN_distance(newobj{},newobj.loc{})
        END