From: anders@lise7.lise.unit.no (Anders Christensen)
Subject: Re: Stem vars as arguments?
Organization: /home/flipper/anders/.organization
Date: 13 Aug 92 22:16:02

Warning: I deleted comp.os.os2.misc from "Newgroups:"

In article <1992Aug13.091449.11425@lri.fr> jpr@sun4.lri.fr (Jean-Pierre Riviere) writes:
> In article <ednstras.713591629@kraken>, ednstras@kraken.itc.gu.edu.au
> (Michael Strasser) writes:
> |> [...]  I would like to be able to use a stem variable as an
> |> argument to an internal procedure, but my attempts have failed so
> |> far.
> 
> I too have encountered similar problems of which I wanted to post today...

When using a stem variable as parameter, only the 'default' value will
be used. You can never use a collection of variables as parameters.
Instead, use:

    subfunc: procedure expose stem.
                                 ^^^ note the dot.

 1)  "stem" refers to the simple variable "stem", 

 2)  "stem." refers to the collection of all compond variables that 
     starts with the head "stem.".

 3)  "stem.1" refers to one particular variable in the collection of 
     variables that starts with the head "stem."

> GetChoice: PROCEDURE EXPOSE Opts.0 Opts.1 Opts.2 Opts.3 Opts.4

Or maybe better (assuming that you want to expose variables like
Opts.5, Opts.6 ... Opts.whatever):

  GetChoice: PROCEDURE EXPOSE Opts.

But note the following trap:

  GetChoice: PROCEDURE guy.name.

The two clauses in the last example will expose the compound variable
named "guy.name.", that is the variable having the head "guy." and the
tail "name.". It will _NOT_ expose any other variable, and in
particular not variables like "guy.name.mail" or "guy.name.passwd". In
other words, _only_ the first dot in a compound variable name is
'magic'.

Also note another potensial dangerous trap in the scoping of Rexx
variables. Suppose you have a main program, and two subroutines: A and
B. The main program calls A, and A calls B. B is to access a variable
set by the main program. If B is to get that variable, A must either
not use PROCEDURE, or it must use PROCEDURE and expose that variable:

    var = foobar ;
    call A
    exit

    A: procedure expose var   /* Must expose 'var' if 'procedure ... */
       call B                            /* ... is to be used at all */
       return

    B: procedure expose var
       say 'var is now' var
       return

If A does not expose 'var', it will not matter whether B expose it or
not, since A has blocked the definition. I believe that the EXPOSE on
stems to expose collections of variables have been a feature in Rexx
for some time, and that most interpreters have these feature.

> So how would it best to deal with the construction of "objects" ?
> For instance, guy is the class name of the object, and name is a variable
> that I use to identify the guy in guy.name Knowing thew guy I can then
> allow him a password for instance : guy.name.passwd
> But If I have to declare guy.name.passwd and not change name nor passwd
> in any procedure I will soon come to BIG PUZZLES too!

You don't declare any variables in rexx. I think your use of compound
variables here have more in common with (nested) structs in C, than
with actual objects (as in OO-programming). 

> Anothe problem is that I have difficulty with avoidind painful select loop
> with construct like :
> /* assgin name of functions to stem var */
> choice.quit = myQUIT
> choice.read = myREAD
> choice.write = myWRITE
> say "choice ?"
> parse pull this
> call choice.this /* doesn't work - I tried variations but to no avail
> (value, interpret) */

First, remember that the tail part of compound variables is case
sensitive (actually the head part is that too, but you'll almost never
crash into that). Suppose you had the following code:

    lower =   'foobar'
    upper =   'FOOBAR'
    space = '  foobar  '

Now, the variables foo.lower, foo.upper and foo.space would be three
completely different and disctinct variables, and the variable
foo.foobar would be identical to the variable foo.upper (supposing
that foobar is an unset variable). In your example, the variable
called 'CHOICE.WRITE' gets the value 'MYREAD', while you (assuming
that you type in 'write' in lower case) are trying to call the routine
'CHOICE.write'.

Then, the dot-magic in compound names only works for variables, never
for labels, since labels are simple symbols. I.e. the dot is not a
legal character in a label. To solve your problem, you can rewrite the
CALL-clause:

    interpret 'call' choice.this

(btw, using this solution, you don't have to bother about case at all,
since the parameter expression to INTERPRET is parsed and the name of
the label is transformed into upper case. 

Somebody mentioned the indirect exposing of variables, as in:

    vars = "foo bar"
    call subfunc
    exit

    subfunc procedure expose one two (vars) three
       /* exposes 'one', 'two', 'three', 'foo' and 'bar'
       return

This is a new Rexx language level 4.00 feature, but in older
interpreters the same effect _might_ be obtained through the use of a
very dirty programming trick (people who don't want their mind
littered with dirty programming tricks should stop reading now!)
Define 'subfunc' as:

    subfunc interpret 'procedure expose one two' vars 'three'

(Yes, I knew you would read on...) This is not allowed in Rexx
language level 4.00, since 'procedure' must be the first statement
after the label, if it is to be used in a subroutine. That ease the
inplementation of compilers, but I can't see any reason why an
interpreters should not allow the programming trick above. The
interpret clause is a magnificent tool :-)

-anders

PS: I only got half the articles in this thread, so I hope I didn't
    repeat anything already said ..