Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Calling rex functions in an external .rex file?

301 views
Skip to first unread message

clackmannan

unread,
Sep 2, 2014, 4:52:12 PM9/2/14
to
Hi,
As a rexx newbie can anyone help me understand if it's possible to call a function that's in another .rex file? I'm not making much progress with the ooRexx documentation.
I'm assuming it's possible, since it seems silly to not allow it, but I can't find anything on how the main .rex file knows about the file that contains the external procedure.
So in a simple example, is it possible to do something like this?

-->test.rex
say "hello 1"
call mysay("hello 2")
call yousay("hello 3")
exit
mysay:
string = arg(1)
say string

-->ext.rex
yousay:
string = arg(1)
say string


Jeremy Nicoll - news posts

unread,
Sep 2, 2014, 8:09:52 PM9/2/14
to
clackmannan <clack...@hotmail.com> wrote:

>So in a simple example, is it possible to do something like this?
>
>-->test.rex
>say "hello 1"
>call mysay("hello 2")

This is syntactically wrong. You either call a subroutine, eg

call mysay "hello 2"

or invoke a function, eg:

thing = mysay("hello 2")

that is, brackets in this situation imply a function call. A function needs
to return a result, ie have a statement inside it like

return "hello mum"

But note that your subroutines also need a return statement, eg

return

or nothing after your first call will be executed.


>call yousay("hello 3")

When yousay is defined elsewhere you'd need eg:

call 'yousay' "hello 3"

or

wotsit = 'yousay'("hello 3")

- which will work if yousay.rex is in the same directory as your main rex
exec or elsewhere in the (long) list of places that ooRexx will look. You
can also use eg

this = 'C:\this\that\other\yousay.pqr'("hello 4")

that is, the file containing the called routine doesn't even have to have a
".rex" extension. I've used that technique to call .kex (Kedit editor
macros; KEXX is a subset of REXX) as subroutines from ooRexx. I can't quite
remember the ins & outs but I think that because, eg

'yousay'

is enclosed in quotes the ooREXX interpreter will look for a suitable file
to execute assuming that it has exactly the same name, ie a lowercase one.
If your filename was YouSay.rex then I think you need 'YouSay'(...) in the
code. This is possibly OS-dependent as well.


As well as this there's a separate technique that allows you to put multiple
routines into a single file and have ooREXX load that before starting to
execute your main program. I'd suggest you get the one file == one external
function stuff working first.


--
Jeremy C B Nicoll - my opinions are my own.

Email sent to my from-address will be deleted. Instead, please reply
to newsre...@wingsandbeaks.org.uk replacing "aaa" by "284".

LesK

unread,
Sep 2, 2014, 11:16:16 PM9/2/14
to
On 9/2/2014 8:09 PM, Jeremy Nicoll - news posts wrote:
> clackmannan <clack...@hotmail.com> wrote:
>
>> So in a simple example, is it possible to do something like this?
>>
>> -->test.rex
>> say "hello 1"
>> call mysay("hello 2")
>
> This is syntactically wrong. You either call a subroutine, eg
>
> call mysay "hello 2"
>
> or invoke a function, eg:
>
> thing = mysay("hello 2")
>
> that is, brackets in this situation imply a function call. A function needs
> to return a result, ie have a statement inside it like
<snip>
>
Parentheses, not brackets. Brackets look like this: []

--

Les (Change Arabic to Roman to email me)

Bob Martin

unread,
Sep 3, 2014, 3:24:30 AM9/3/14
to
To a non-programmer in the UK parentheses are "brackets"!

clackmannan

unread,
Sep 3, 2014, 9:44:29 AM9/3/14
to
On Tuesday, September 2, 2014 8:09:52 PM UTC-4, Jeremy Nicoll - news posts wrote:
> clackmannan wrote:
> >So in a simple example, is it possible to do something like this?
> >-->test.rex
> >say "hello 1"
> >call mysay("hello 2")
>
> This is syntactically wrong. You either call a subroutine, eg
> call mysay "hello 2"
> or invoke a function, eg:
> thing = mysay("hello 2")
> that is, brackets in this situation imply a function call. A function needs
> to return a result, ie have a statement inside it like
> return "hello mum"

OK, understood. Thanks for explaining. I guess I was lucky it worked before :)

> - which will work if yousay.rex is in the same directory as your main rex
> exec or elsewhere in the (long) list of places that ooRexx will look. You
> can also use eg
> this = 'C:\this\that\other\yousay.pqr'("hello 4")

OK, if the name of the external file is the same as the routine name then either of these works fine, which is what I was looking for.

call yousay "hello 3"
call 'M:\SourceCode\Script\rexx\yousay' "hello 4"

You implied it's possible to have 1 external file contain multiple routines, so any hints on the magic that needs to happen to make that work?



Jeremy Nicoll - news posts

unread,
Sep 3, 2014, 10:07:03 AM9/3/14
to
LesK <5mr...@tampabay.rr.com> wrote:

>Parentheses, not brackets. Brackets look like this: []

What? In the UK, ( and ) are round brackets, [ and ] are square brackets, {
and } are curly brackets, and < and > are angle brackets.

See this explanation of round and square brackets, as used in writing
English: http://www.oxforddictionaries.com/words/brackets

LesK

unread,
Sep 3, 2014, 11:51:40 AM9/3/14
to
On 9/3/2014 10:07 AM, Jeremy Nicoll - news posts wrote:
> LesK <5mr...@tampabay.rr.com> wrote:
>
>> Parentheses, not brackets. Brackets look like this: []
>
> What? In the UK, ( and ) are round brackets, [ and ] are square brackets, {
> and } are curly brackets, and < and > are angle brackets.
>
> See this explanation of round and square brackets, as used in writing
> English: http://www.oxforddictionaries.com/words/brackets
>
That's nice I suppose, but it doesn't agree with what is commonly used
in the IT industry and especially in the context of ooRexx.

Jeremy Nicoll - news posts

unread,
Sep 3, 2014, 2:35:09 PM9/3/14
to
LesK <5mr...@tampabay.rr.com> wrote:

>On 9/3/2014 10:07 AM, Jeremy Nicoll - news posts wrote:
>> LesK <5mr...@tampabay.rr.com> wrote:
>>
>>> Parentheses, not brackets. Brackets look like this: []
>>
> > What? In the UK, ( and ) are round brackets, [ and ] are square
> > brackets, { and } are curly brackets, and < and > are angle brackets.
>>
>> See this explanation of round and square brackets, as used in writing
>> English: http://www.oxforddictionaries.com/words/brackets
>>
> That's nice I suppose, but it doesn't agree with what is commonly used in
> the IT industry...

Not in my experience (computing degree in the early 1980s and I worked in
mainframe sites after that). Maybe the UK's different from the US?

Jeremy Nicoll - news posts

unread,
Sep 3, 2014, 2:41:10 PM9/3/14
to
clackmannan <clack...@hotmail.com> wrote:

> You implied it's possible to have 1 external file contain multiple
> routines, so any hints on the magic that needs to happen to make that
> work?

At the end of your mainline program's file, after any functions/subroutines
it contains, you add a ::requires line which tells ooREXX that it must load
something else as well, eg you might have:

::requires "mylibrary.rex"

The ooREXX interpreter finds that statement and processes it before the code
in your mainline program starts to run.

In the file named "mylibrary.rex" you put all the separate routines, each
one introduced by eg

::routine "thefunctionname" public

and ending eg

return "whatever"

You will need to read the manual to find the significance of keywords like
"public".


When ooREXX loads a file that was specified by ::requires, it then 'calls'
it. Thus the code in that file that is between the start of the file and
the first of the defined ::routine sections will execute. In that section
you can do things like initialise structures that other routines may need to
have available.

clackmannan

unread,
Sep 3, 2014, 4:32:17 PM9/3/14
to
On Wednesday, September 3, 2014 2:35:09 PM UTC-4, Jeremy Nicoll - news posts wrote:
> > > What? In the UK, ( and ) are round brackets, [ and ] are square
> > > brackets, { and } are curly brackets, and < and > are angle brackets.
> >>
> >> See this explanation of round and square brackets, as used in writing
> >> English: http://www.oxforddictionaries.com/words/brackets
> >>
> > That's nice I suppose, but it doesn't agree with what is commonly used in
> > the IT industry...
>
> Not in my experience (computing degree in the early 1980s and I worked in
> mainframe sites after that). Maybe the UK's different from the US?

Very much so :)
I use the same terms Jeremy does since I'm from the right hand side of the Atlantic, but living on the left hand side I'm accustomed to my US friends using the term 'parenthesis' frequently, whereas I'd never heard of it back home.

clackmannan

unread,
Sep 3, 2014, 4:33:59 PM9/3/14
to
On Wednesday, September 3, 2014 2:41:10 PM UTC-4, Jeremy Nicoll - news posts wrote:
> clackmannan <clack...@hotmail.com> wrote:
> > You implied it's possible to have 1 external file contain multiple
> > routines, so any hints on the magic that needs to happen to make that
> > work?
>
> At the end of your mainline program's file, after any functions/subroutines
> it contains, you add a ::requires line which tells ooREXX that it must load
> something else as well, eg you might have:
>
<snip>

Thanks very much Jeremy! Now I know what I need to go read up on.

LesK

unread,
Sep 4, 2014, 10:25:22 AM9/4/14
to
On 9/3/2014 2:40 PM, Jeremy Nicoll - news posts wrote:
> clackmannan <clack...@hotmail.com> wrote:
>
>> You implied it's possible to have 1 external file contain multiple
>> routines, so any hints on the magic that needs to happen to make that
>> work?
>
> At the end of your mainline program's file, after any functions/subroutines
> it contains, you add a ::requires line which tells ooREXX that it must load
> something else as well, eg you might have:
>
> ::requires "mylibrary.rex"
>
> The ooREXX interpreter finds that statement and processes it before the code
> in your mainline program starts to run.
>
> In the file named "mylibrary.rex" you put all the separate routines, each
> one introduced by eg
>
> ::routine "thefunctionname" public
>
> and ending eg
>
> return "whatever"
>
> You will need to read the manual to find the significance of keywords like
> "public".
>
>
> When ooREXX loads a file that was specified by ::requires, it then 'calls'
> it. Thus the code in that file that is between the start of the file and
> the first of the defined ::routine sections will execute. In that section
> you can do things like initialise structures that other routines may need to
> have available.
>
I've never tried this because almost all my work is done with THE
macros. The few .rex things I have I simply put in C:\MyRexxStuff
folder, which is in the PATH so ooRexx can find it when THE doesn't.

Before starting down the ::requires path, would it be better to just use
a folder while thoroughly debugging my code?

Jeremy Nicoll - news posts

unread,
Sep 4, 2014, 4:57:12 PM9/4/14
to
LesK <5mr...@tampabay.rr.com> wrote:

>I've never tried this because almost all my work is done with THE
>macros. The few .rex things I have I simply put in C:\MyRexxStuff
>folder, which is in the PATH so ooRexx can find it when THE doesn't.

I have: C:\My Dropbox\JN_RexxPathLib

which is defined on PATH so execs contained in it are findable when one
executes them from a cmd window. I also (possibly not necessarily) have
ooREXX's REXX_PATH environment variable set to point at this folder.

Almost all of my rexx execs are standalone, though many of them contain
near-duplicate copies of nearly common code. My experiments in using a
::requires "something.rex" library file are not very well advanced, because
I decided to do the job 'properly' and design a better set of common
routines, taking the best bits of the various variants that the standalone
routines have.

Also my standalone execs mainly use classic rexx, but I decided to take
advantage of more ooREXX features in the shared routines. So for example
whereas standalone execs use an inconsistent set of stem arrays to hold
tables of data, I thought I'd use .local["_JN_.xxx.yyy"] - named variabels
for at least some of the new routines - if only to make sure that there's no
naming conflicts between new code and old stuff, and also to make it easy to
run a comparison set of functions in parallel if I want to try new ideas out
(eg my making a second set all use .local["_PQ_.xxx.yyy"] variables.

I imagine that code (eg for logging) that currently uses a hard-coded stem
name will end up using a parameterised stem name, but that name (for eg the
default log) will be stored in a .local["_JN_.xxx.yyy"] variable.


>Before starting down the ::requires path, would it be better to just use
>a folder while thoroughly debugging my code?

Unlike the OP, you know your way around rexx, so I wouldn't have thought so.
I'd think the easiest approach is to create a common-routines file, put
nearly nothing in it, then add ::requires to a handful of your mainline
programs, then start experimenting.

Swifty

unread,
Sep 7, 2014, 2:08:20 AM9/7/14
to
On 03/09/2014 21:33, clackmannan wrote:
> Now I know what I need to go read up on.

The ::Requires directive is the whole reason why I migrated all of my
code from Classic REXX to OORexx, years ago.

I used to write all my common subroutines/functions as simple external
files (so they could be shared). This way, a program called "loopy.rex"
could call an external routine Plural() if the code for plural() was in
the file plural.rex (with normal path considerations for accessing the
file).

The problem I was facing was that "loopy" would run very slowly if its
loop iterated more than a few times. The reason for this is that the
file "loopy.rex" was being read each time around the loop. Also,
"tokenisation" was occurring each time around, but we don't need to
worry about that.

I migrated to oorexx and merged all my external routines into
"subroutines.rex", adding a line such as:
::Routine Plural public
... at the start of each routine. This has the same effect as:
Plural: Procedure
... in Classic REXXX.

Now, when my programs run, the "subroutines.rex" code is read once,
during program initialisation (and that tokenisation runs just once).

Call to routines inside subroutines.rex are now handled entirely in
memory, so there's no penalty from calling the external routine many times.

--
Steve Swift
http://www.swiftys.org.uk/

LesK

unread,
Sep 7, 2014, 2:20:45 AM9/7/14
to
On 9/7/2014 2:08 AM, Swifty wrote:
> On 03/09/2014 21:33, clackmannan wrote:
>> Now I know what I need to go read up on.
>
> The ::Requires directive is the whole reason why I migrated all of my
> code from Classic REXX to OORexx, years ago.
>
> I used to write all my common subroutines/functions as simple external
> files (so they could be shared). This way, a program called "loopy.rex"
> could call an external routine Plural() if the code for plural() was in
> the file plural.rex (with normal path considerations for accessing the
> file).
>
> The problem I was facing was that "loopy" would run very slowly if its
> loop iterated more than a few times. The reason for this is that the
> file "loopy.rex" was being read each time around the loop. Also,
> "tokenisation" was occurring each time around, but we don't need to
> worry about that.
>
> I migrated to oorexx and merged all my external routines into
> "subroutines.rex", adding a line such as:
> ::Routine Plural public
> .... at the start of each routine. This has the same effect as:
> Plural: Procedure
> .... in Classic REXXX.
>
> Now, when my programs run, the "subroutines.rex" code is read once,
> during program initialisation (and that tokenisation runs just once).
>
> Call to routines inside subroutines.rex are now handled entirely in
> memory, so there's no penalty from calling the external routine many times.
>
I wish that ::REQUIRES had a 'global' option so it could be used just
once by the top level program.

I wonder if subroutines.rex could just be a list of ::requires ?

Swifty

unread,
Sep 7, 2014, 2:36:25 AM9/7/14
to
On 07/09/2014 07:20, LesK wrote:
> I wonder if subroutines.rex could just be a list of ::requires ?

It can be; ::Requires can be nested.

My subroutines.rex has become huge, as it has accumulated hundreds of
routines over the years. This by itself can make my main routines
somewhat slow to get started, because of the overheads of loading the
subroutines (I/O, tokenisation).

For example, the program:

Call Say 'Hello, World:'
::Requires subroutines.rex

... would hesitate before generating the output, whilst it reads and
tokenises my "subroutines.rex".

I keep my subroutines.rex on my C: drive, which is an SSD. But even so,
I wonder about the I/O overhead. Before I retired (and bought the
fastest PC I could find which ran near silently), I used to use one of
those "disk in storage" drivers, just for my subroutines.

I was never certain whether this was effective; the subroutines.rex file
would surely be cached in storage by the filesystem anyway.

LesK

unread,
Sep 7, 2014, 2:57:42 AM9/7/14
to
On 9/7/2014 2:36 AM, Swifty wrote:
> On 07/09/2014 07:20, LesK wrote:
>> I wonder if subroutines.rex could just be a list of ::requires ?
>
> It can be; ::Requires can be nested.
>
> My subroutines.rex has become huge, as it has accumulated hundreds of
> routines over the years. This by itself can make my main routines
> somewhat slow to get started, because of the overheads of loading the
> subroutines (I/O, tokenisation).
>
> For example, the program:
>
> Call Say 'Hello, World:'
> ::Requires subroutines.rex
>
> .... would hesitate before generating the output, whilst it reads and
> tokenises my "subroutines.rex".
>
> I keep my subroutines.rex on my C: drive, which is an SSD. But even so,
> I wonder about the I/O overhead. Before I retired (and bought the
> fastest PC I could find which ran near silently), I used to use one of
> those "disk in storage" drivers, just for my subroutines.
>
> I was never certain whether this was effective; the subroutines.rex file
> would surely be cached in storage by the filesystem anyway.
>
Put it in your Start folder and you won't notice the added time.
SSD drives scare me. They *will* fail sooner or later, with no warning!

Jeremy Nicoll - news posts

unread,
Sep 9, 2014, 8:17:34 PM9/9/14
to
LesK <5mr...@tampabay.rr.com> wrote:

> I wish that ::REQUIRES had a 'global' option so it could be used just once
> by the top level program.

When someone puts

::requires "subroutines.rex"

at the end of their mainline program file, it IS being used just once (by
that mainline program).

Or did you mean that one could define to ooREXX that every program it runs
should look in "subroutines.rex" for subroutine definitions?


>I wonder if subroutines.rex could just be a list of ::requires ?

Not if the mechanism I described earlier - that after loading any ::required
files ooREXX then 'call's them - is going to work. You'd need to put at
least a "return" statement at the start of such a file.

But what would you gain by having, say

::requires "masterlist.rex"

and then in that file:

return

::requires "subroutine1.rex"
::requires "subroutine2.rex"
...

rather than just putting the actual routines into the first-::required file?
You'd be doing lots more I/O to get all the separate files loaded, and
there'd be an initialisation 'call' of each one, as well.

LesK

unread,
Sep 10, 2014, 6:21:50 AM9/10/14
to
On 9/9/2014 8:11 PM, Jeremy Nicoll - news posts wrote:
> LesK <5mr...@tampabay.rr.com> wrote:
>
>> I wish that ::REQUIRES had a 'global' option so it could be used just once
>> by the top level program.
>
> When someone puts
>
> ::requires "subroutines.rex"
>
> at the end of their mainline program file, it IS being used just once (by
> that mainline program).
>
> Or did you mean that one could define to ooREXX that every program it runs
> should look in "subroutines.rex" for subroutine definitions?
>
Yes, that what I meant by 'global' and 'used just once by the top level
program.
>
>> I wonder if subroutines.rex could just be a list of ::requires ?
>
> Not if the mechanism I described earlier - that after loading any ::required
> files ooREXX then 'call's them - is going to work. You'd need to put at
> least a "return" statement at the start of such a file.
>
Are you sure about that? The manual says:

1.Processes the directives first, to set up the program's classes,
methods, and routines.

2.Runs any program code preceding the first directive. This code can use
any classes, methods, and routines set up by the directives.

'any program code' tell me that it's optional.
> But what would you gain by having, say
>
> ::requires "masterlist.rex"
>
> and then in that file:
>
> return
>
> ::requires "subroutine1.rex"
> ::requires "subroutine2.rex"
> ...
>
> rather than just putting the actual routines into the first-::required file?
> You'd be doing lots more I/O to get all the separate files loaded, and
> there'd be an initialisation 'call' of each one, as well.
>
The gain would be that I'd have individual files to edit, instead of one
big one. That lets me avoid any side effects of my editing.

Rony

unread,
Sep 10, 2014, 6:41:57 AM9/10/14
to
On 10.09.2014 02:11, Jeremy Nicoll - news posts wrote:
> LesK <5mr...@tampabay.rr.com> wrote:
>
>> I wish that ::REQUIRES had a 'global' option so it could be used just once
>> by the top level program.
>
> When someone puts
>
> ::requires "subroutines.rex"
>
> at the end of their mainline program file, it IS being used just once (by
> that mainline program).
>
> Or did you mean that one could define to ooREXX that every program it runs
> should look in "subroutines.rex" for subroutine definitions?
>
>
>> I wonder if subroutines.rex could just be a list of ::requires ?
>
> Not if the mechanism I described earlier - that after loading any ::required
> files ooREXX then 'call's them - is going to work. You'd need to put at
> least a "return" statement at the start of such a file.
>
> But what would you gain by having, say
>
> ::requires "masterlist.rex"
>
> and then in that file:
>
> return
>
> ::requires "subroutine1.rex"
> ::requires "subroutine2.rex"
> ...
>
> rather than just putting the actual routines into the first-::required file?
> You'd be doing lots more I/O to get all the separate files loaded, and
> there'd be an initialisation 'call' of each one, as well.
>

Maybe I am misunderstanding the explanations, but just to be sure:

- if you use the "::requires xyz" directive, then ooRexx will check whether the Rexx program/package
"xyz" was already required or not;

- if "xyz" was not required yet, it gets called by the interpreter and any public routines and
public classes are available to the Rexx program that contains the ::requires directive afterwards

- if "xyz" was already required, then the ooRexx interpreter does not call "xyz" anymore, but
merely makes it directly available such that its public routines and public classes are made available.

So in your example, where "masterlist.rex" requires "subroutine1.rex" and "subroutine2.rex",
"subroutine1.rex" and "subroutine2.rex" would be executed only once, no matter how many times
"masterlist.rex" will be required by other Rexx programs.

ooRexx maintains for each Rexx program individually which public routines and public classes it sees
depending on the sequence of requiring (and calling) other Rexx programs.

You can get access to this information by using e.g.

pkg=.context~package /* get the current program's package definitions */

Cf. the definitions of the fundamental class "Package" in the rexxref.pdf documentation.

HTH,

---rony

P.S.: If you have "rgf_util2.rex" and call or require it, you could easily dump your package's
content by issuing e.g.:

say ppPackage2(.context~package) -- show the current Rexx program's package definition


Jeremy Nicoll - news posts

unread,
Sep 10, 2014, 12:58:57 PM9/10/14
to
LesK <5mr...@tampabay.rr.com> wrote:

>On 9/9/2014 8:11 PM, Jeremy Nicoll - news posts wrote:
>> LesK <5mr...@tampabay.rr.com> wrote:

> > Not if the mechanism I described earlier - that after loading any
> > ::required files ooREXX then 'call's them - is going to work. You'd
> > need to put at least a "return" statement at the start of such a file.
>>
> Are you sure about that? The manual says:
>
> 1.Processes the directives first, to set up the program's classes,
> methods, and routines.
>
> 2.Runs any program code preceding the first directive. This code can use
> any classes, methods, and routines set up by the directives.
>
>'any program code' tell me that it's optional.

Which manual was that in? My 4.1.1 (admittedly not the most recent version)
Reference manual precedes what you quote by saying:

The ::REQUIRES directive specifies that the program requires access
to the classes and objects of the Rexx program programname.

>>-::REQUIRES--"programname"--+---------+-;--------------------><

...
The program programname is called as an external routine with no
arguments.
...
The main program code, which precedes the first directive
instruction, is run.

which seems to me to be a bit ambiguous. If "programname" is indeed
CALLed (by the interpreter) then surely that called code does need a
"return" (or an "exit")?

If one calls a normal (ie not defined via ::REQUIRES) external subroutine
which doesn't have a return/exit, does control come back to the caller?
Surely not. But maybe this is a special case?

Personally I'd rather place comments at the start of a ::REQUIRES-ed file to
remind myself that any initial code in it will be executed, and terminate
that with a return even if it isn't in fact strictly needed.


>> You'd be doing lots more I/O to get all the separate files loaded, and
>> there'd be an initialisation 'call' of each one, as well.
>>
> The gain would be that I'd have individual files to edit, instead of one
> big one. That lets me avoid any side effects of my editing.

Fair enough. I think I'd find that many of my common routines call other
common routines and a proportion of such edits will need changes made to
both routines and their users at the same time.

Being able to see all the relevant lines at once is useful - but I'm using
Kedit and tend to make great use of commands like ALL, MORE, LESS to show me
a subset of an entire file's lines. If I were using a text editor that
could load multiple files and then show me in one window a selection of
lines from any/all of the loaded data files, allowing me to navigate around
that set of files easily, I might do things differently.

LesK

unread,
Sep 10, 2014, 1:04:31 PM9/10/14
to
Think of a large project written in Rexx. It has 3 programmers, one of
which is the Chief programmer who did the original architecture and
assigned each of the 120 modules to the team members, keeping the
top-level code for himself.

Now management would like to move to ooRexx and take advantage of it's
added features. So the chief programmer looks at how to replace all that
code that checks to see that the other 119 modules are available, with a
simple ::REQUIRES statement in his top-level module. Since individual
modules may be passed from team member to team member to balance the
workload, he decides on the scheme I suggested earlier:

top-line contains a ::REQUIRES project_list_of_code_modules

and project_list_of_code_modules contains:

::REQUIRES module_1
::REQUIRES module_2
etc, through
::REQUIRES module_119

Nice idea, *but* since ::REQUIRES isn't global in nature, the CF must
now have each team member analyze the modules that are assigned to them
and provide him with a list of module inter-dependencies. He can then
analyze the information and come up with the 'best' structure of
::REQUIRES statements for the overall project, considering skills, time
off, separation of responsibilities, security clearance, experience, etc.

A basically simple task has become quite complicated because ooRexx was
developed on a blank sheet of paper, almost as an academic exercise,
without considering the Development Process, which may not be a bad
thing, but it inhibits easy transfer to ooRexx.

Rony

unread,
Sep 10, 2014, 1:21:01 PM9/10/14
to
.2014 19:04, LesK wrote:
> On 9/10/2014 6:41 AM, Rony wrote:
>> On 10.09.2014 02:11, Jeremy Nicoll - news posts wrote:
>>> LesK <5mr...@tampabay.rr.com> wrote:


... snip ...

>>
>>
> Think of a large project written in Rexx. It has 3 programmers, one of which is the Chief programmer
> who did the original architecture and assigned each of the 120 modules to the team members, keeping
> the top-level code for himself.
>
> Now management would like to move to ooRexx and take advantage of it's added features. So the chief
> programmer looks at how to replace all that code that checks to see that the other 119 modules are
> available, with a simple ::REQUIRES statement in his top-level module. Since individual modules may
> be passed from team member to team member to balance the workload, he decides on the scheme I
> suggested earlier:
>
> top-line contains a ::REQUIRES project_list_of_code_modules
>
> and project_list_of_code_modules contains:
>
> ::REQUIRES module_1
> ::REQUIRES module_2
> etc, through
> ::REQUIRES module_119
>
> Nice idea, *but* since ::REQUIRES isn't global in nature,

What do you mean by not "global in nature"?

If the master Rexx program is named "project_list_of_code_modules" which itself requires those 119
Rexx programs, then all these Rexx programs will be called by ooRexx and the public routines and
public classes in all of these Rexx programs become available to the Rexx program that required
"project_list_of_code_modules".

If you then call another Rexx program that itself requires "project_list_of_code_modules", then
ooRexx sets the context of that called Rexx program to get access to all of those required Rexx
programs, without calling them anymore. So this eases and speeds up things.

---

Besides, with the means ooRexx supplies in this context, you are free to inspect the packages
(required Rexx programs) for the current Rexx program, add addtional packages to it and the like.
Very flexible and powerful.

---rony




LesK

unread,
Sep 10, 2014, 1:22:29 PM9/10/14
to
No. called code does *not* have to Return a value, but Function code does!

> If one calls a normal (ie not defined via ::REQUIRES) external subroutine
> which doesn't have a return/exit, does control come back to the caller?
> Surely not. But maybe this is a special case?
>
> Personally I'd rather place comments at the start of a ::REQUIRES-ed file to
> remind myself that any initial code in it will be executed, and terminate
> that with a return even if it isn't in fact strictly needed.
>
>
>>> You'd be doing lots more I/O to get all the separate files loaded, and
>>> there'd be an initialisation 'call' of each one, as well.
>>>
>> The gain would be that I'd have individual files to edit, instead of one
>> big one. That lets me avoid any side effects of my editing.
>
> Fair enough. I think I'd find that many of my common routines call other
> common routines and a proportion of such edits will need changes made to
> both routines and their users at the same time.
>
Sure, that's always a possibility, but I still like to protect myself
from shooting my own foot!

> Being able to see all the relevant lines at once is useful - but I'm using
> Kedit and tend to make great use of commands like ALL, MORE, LESS to show me
> a subset of an entire file's lines. If I were using a text editor that
> could load multiple files and then show me in one window a selection of
> lines from any/all of the loaded data files, allowing me to navigate around
> that set of files easily, I might do things differently.
>
Sounds like an exercise for the student :-) Kedit does have SET SCREEN
that would allow you to split the screen N ways. It's more powerful than
THE, but wasted on me with my poor eyesight.

Rony

unread,
Sep 10, 2014, 1:28:14 PM9/10/14
to
On 10.09.2014 18:52, Jeremy Nicoll - news posts wrote:
> LesK <5mr...@tampabay.rr.com> wrote:
>
>> On 9/9/2014 8:11 PM, Jeremy Nicoll - news posts wrote:
>>> LesK <5mr...@tampabay.rr.com> wrote:

... snip ...

>
> If one calls a normal (ie not defined via ::REQUIRES) external subroutine
> which doesn't have a return/exit, does control come back to the caller?
> Surely not. But maybe this is a special case?
>
> Personally I'd rather place comments at the start of a ::REQUIRES-ed file to
> remind myself that any initial code in it will be executed, and terminate
> that with a return even if it isn't in fact strictly needed.

There is some misconception here.

If one calls an external Rexx program, control will return upon termination of the external Rexx
program, no matter whether it contains a return or an exit instruction. The same is true when you
call or require an external Rexx program.

In ooRexx routines (defined with ::requires directives) and methods (defined with ::method
directives) are seen as if they define their own Rexx program, such that control returns once the
last statement in the code representing the routine or method was executed. Of course you can always
use the return or exit instruction to make this explicit.

---

Maybe the term "directive" becomes important here: a directive is an instruction to the ooRexx
interpreter to carry out something on behalf of the programmer, *before* the Rexx program (the code
before the first directive) gets executed.

This way, whatever routines, classes, methods or required Rexx programs are defined, they get
carried out by the ooRexx interpreter, before the first Rexx instruction (the first line in the Rexx
program) gets interpreted. As a result, a Rexx program can rely on having all such routines,
classes, methods and public routines and public classes of the required Rexx programs available to it.



HTH,

---rony

LesK

unread,
Sep 10, 2014, 3:00:33 PM9/10/14
to
On 9/10/2014 1:20 PM, Rony wrote:
> ..2014 19:04, LesK wrote:
>> On 9/10/2014 6:41 AM, Rony wrote:
>>> On 10.09.2014 02:11, Jeremy Nicoll - news posts wrote:
>>>> LesK <5mr...@tampabay.rr.com> wrote:
>
>
> .... snip ...
In my scenario, I don't want other team members doing that! I want them
to collaborate with each other and me and I will control the list.
> ---rony
>
>
>
>
I guess my explicit example didn't adequately explain the use of the
word 'global', which is used throughout the ooRexx Reference document,
so let me try again:

If it were GLOBAL, then _only_ the top-level program would have to have
a ::REQUIRES statement and all child programs would inherit the same
statement WITHOUT MODIFICATION! Less work, less chance of error.

Gerard_Schildberger

unread,
Sep 10, 2014, 5:08:09 PM9/10/14
to
On Wednesday, September 10, 2014 11:58:57 AM UTC-5, Jeremy Nicoll - news posts wrote:
> LesK wrote:
> >On 9/9/2014 8:11 PM, Jeremy Nicoll - news posts wrote:
> >> LesK wrote:

---[---snipped---]---

> Being able to see all the relevant lines at once is useful - but I'm using
> Kedit and tend to make great use of commands like ALL, MORE, LESS to show me
> a subset of an entire file's lines. If I were using a text editor that
> could load multiple files and then show me in one window a selection of
> lines from any/all of the loaded data files, allowing me to navigate around
> that set of files easily, I might do things differently.
> --
> Jeremy C B Nicoll - my opinions are my own.

KEDIT does support editing a ring of file (multiple files at
once) with a QUERY RING --- It's easy to write a front-
end to that and have a menu (list) to choose from, even support
PF selection if that's what you want.

I do concur wholeheartedly, XEDIT's ALL (and it's derivatives)
is a godsend (thanks Xavier de Lamberterie!), and I couldn't
imagine editing programs (or most files) without 'em.

In addition, with the SET SCREEN command, and a decent
monitor (terminal), you could KEDIT multiple files on one
screen. Nothing beats having multiple screens, however.
________________________________________ Gerard Schildberger


Jeremy Nicoll - news posts

unread,
Sep 10, 2014, 8:04:19 PM9/10/14
to
LesK <5mr...@tampabay.rr.com> wrote:

> If it were GLOBAL, then _only_ the top-level program would have to have a
> ::REQUIRES statement and all child programs would inherit the same
> statement WITHOUT MODIFICATION! Less work, less chance of error.

If the 'top-level' program invokes the others as functions or classes or
methods or whatever, you only need the ::REQUIRES statement in the top-level
one.

When you say 'child programs' do you mean separate standalone programs each
of which could be run in isolation?

Jeremy Nicoll - news posts

unread,
Sep 10, 2014, 8:10:19 PM9/10/14
to
LesK <5mr...@tampabay.rr.com> wrote:

>On 9/10/2014 12:52 PM, Jeremy Nicoll - news posts wrote:

>> which seems to me to be a bit ambiguous. If "programname" is indeed
>> CALLed (by the interpreter) then surely that called code does need a
>> "return" (or an "exit")?
>>
>No. called code does *not* have to Return a value, but Function code does!

Indeed, but that doesn't preclude a subroutine ending with

return

(ie a return without an explicit returned value.)

Jeremy Nicoll - news posts

unread,
Sep 10, 2014, 8:22:21 PM9/10/14
to
Gerard_Schildberger <gera...@rrt.net> wrote:

>KEDIT does support editing a ring of file (multiple files at
>once) with a QUERY RING --- It's easy to write a front-
>end to that and have a menu (list) to choose from, even support
>PF selection if that's what you want.

Yes, one could, but the kedit macro is still going to have to explicitly
iterate through the various files in the ring locating lines that match some
condition and building the pick list. Then you'd need to write the pick
list into a temporary file (or build a menu). And then you need a separate
macro to be called when you position the cursor on some line in that list
and press a Fn key or click/double-click that line to cause the relevant
file to be displayed and have it scroll to the right place. If you
displayed the pick list as a menu rather than in a separate file, you'd need
to be clever to preserve the menu contents for arbitrary re-use for multiple
picks later on.

I've used a text editor (StrongED) where the facility was built-in; one
could get a 'ListOfFound' that produced a display somewhat like the effect
of an ALL in kedit, in a separate window. It could apply to one file or
many files, all at once, and it 'just worked'.

--
Jeremy C B Nicoll - my opinions are my own.

LesK

unread,
Sep 10, 2014, 9:05:22 PM9/10/14
to
On 9/10/2014 8:09 PM, Jeremy Nicoll - news posts wrote:
> LesK <5mr...@tampabay.rr.com> wrote:
>
>> On 9/10/2014 12:52 PM, Jeremy Nicoll - news posts wrote:
>
>>> which seems to me to be a bit ambiguous. If "programname" is indeed
>>> CALLed (by the interpreter) then surely that called code does need a
>>> "return" (or an "exit")?
>>>
>> No. called code does *not* have to Return a value, but Function code does!
>
> Indeed, but that doesn't preclude a subroutine ending with
>
> return
>
> (ie a return without an explicit returned value.)
>
That's true. It could also Exit or just fall off the end.

LesK

unread,
Sep 10, 2014, 9:26:53 PM9/10/14
to
On 9/10/2014 8:20 PM, Jeremy Nicoll - news posts wrote:
> Gerard_Schildberger <gera...@rrt.net> wrote:
>
>> KEDIT does support editing a ring of file (multiple files at
>> once) with a QUERY RING --- It's easy to write a front-
>> end to that and have a menu (list) to choose from, even support
>> PF selection if that's what you want.
>
> Yes, one could, but the kedit macro is still going to have to explicitly
> iterate through the various files in the ring locating lines that match some
> condition and building the pick list. Then you'd need to write the pick
> list into a temporary file (or build a menu). And then you need a separate
> macro to be called when you position the cursor on some line in that list
> and press a Fn key or click/double-click that line to cause the relevant
> file to be displayed and have it scroll to the right place. If you
> displayed the pick list as a menu rather than in a separate file, you'd need
> to be clever to preserve the menu contents for arbitrary re-use for multiple
> picks later on.
>
I have a THE macro (scanfile) that scans the files in the current DIR,
or a list of files, and builds a 'hit list' file (.scf) of where
'string' is found. For example (watch for line wraps):

C:\MyTHEstuff\helpxusermenu.the (HIT ampersand_vars - :164 1 ) -
'macro helpx_user_substitute_ampersand_vars' get.selection
C:\MyTHEstuff\helpx_user.the (HIT ampersand_vars - :147 1 ) - m
'helpx_user_substitute_ampersand_vars' infile

My Y macro (smart SOS EDIT) recognizes such a list and can take you to
the file & line selected or, optionally, just to the file. I suspect
they could easily be modified for Kedit, since they're so similar.

> I've used a text editor (StrongED) where the facility was built-in; one
> could get a 'ListOfFound' that produced a display somewhat like the effect
> of an ALL in kedit, in a separate window. It could apply to one file or
> many files, all at once, and it 'just worked'.
>


--

LesK

unread,
Sep 10, 2014, 9:30:05 PM9/10/14
to
On 9/10/2014 8:02 PM, Jeremy Nicoll - news posts wrote:
> LesK <5mr...@tampabay.rr.com> wrote:
>
>> If it were GLOBAL, then _only_ the top-level program would have to have a
>> ::REQUIRES statement and all child programs would inherit the same
>> statement WITHOUT MODIFICATION! Less work, less chance of error.
>
> If the 'top-level' program invokes the others as functions or classes or
> methods or whatever, you only need the ::REQUIRES statement in the top-level
> one.
>
> When you say 'child programs' do you mean separate standalone programs each
> of which could be run in isolation?
>
>
Yes, exactly. Use the bricks you have to build your house.

Rony

unread,
Sep 11, 2014, 6:38:05 AM9/11/14
to
On 10.09.2014 21:00, LesK wrote:> On 9/10/2014 1:20 PM, Rony wrote:
>> ..2014 19:04, LesK wrote:
>>> On 9/10/2014 6:41 AM, Rony wrote:
>>>> On 10.09.2014 02:11, Jeremy Nicoll - news posts wrote:
>>>>> LesK <5mr...@tampabay.rr.com> wrote:
>>
>>

... snip ...

>> ---
>>
>> Besides, with the means ooRexx supplies in this context, you are free
>> to inspect the packages (required Rexx programs) for the current Rexx
>> program, add addtional packages to it and the like. Very flexible and
>> powerful.
>>
> In my scenario, I don't want other team members doing that! I want them to collaborate with each
> other and me and I will control the list.
>> ---rony
>>
>>
> I guess my explicit example didn't adequately explain the use of the word 'global', which is used
> throughout the ooRexx Reference document, so let me try again:
>
> If it were GLOBAL, then _only_ the top-level program would have to have
> a ::REQUIRES statement and all child programs would inherit the same statement WITHOUT MODIFICATION!
> Less work, less chance of error.

O.K., you asked for it. ;)

ooRexx allows you to get to this kind of functionality with this (a little bit) advanced technique:
do not call the Rexx programs directly, instead create routine objects of them and send the call
message to the routine object.


Here are three Rexx programs, "test.rex", "test2.rex", "test3.rex":

test.rex:

--------------------- test.rex ----------------
parse source . . thisName
say "--->"
thisName=filespec("Name",thisName)
say "arrived in:" thisName

-- show all routines defined in this Rexx program/package
do r over .routines
say thisName":" r
end

-- create a routine object for the given Rexx program
rexxPgmName="test2.rex"
r=lkg(rexxPgmName) -- returns the executable routine
r~call -- invoke "test2.rex"
say "<---"


-- Les Koehler Global: pass context (all required Rexx programs/packages) on
::routine lkg public
use strict arg rexxPgmName

say "in >>> LKG()! <<<"
rexxPgmCode=charin(rexxPgmName,1,chars(rexxPgmName)) -- string
return .routine~new(rexxPgmName,rexxPgmCode)
--------------------- test.rex ----------------


test2.rex:
--------------------- test2.rex ---------------
parse source . . thisName
thisName=filespec("Name",thisName)
tab="09"x
say tab "--->"
say tab "arrived in:" thisName

-- show all routines defined in this Rexx program/package
-- do r over .routines
do r over .context~package~routines
say tab r
end

call from_test2 tab
say tab "now creating a new routine on the fly:"
-- create a routine object for the given Rexx program
r=lkg("test3.rex")
r~call

-- create a routine on the fly
r=.routine~new("hi", "say '09'x 'hi (created in a single statement)'")
r~call
say tab "<---"

::routine from_test2
use arg tab
say tab "in routine" .context~name
--------------------- test2.rex ---------------

test3.rex:
--------------------- test3.rex ---------------
say ' >>> in test3.rex <<<'
--------------------- test3.rex ---------------


Running "test.rex" yields the following output:

--------------------- output ---------------
F:\test\koehler\lkg>test
--->
arrived in: test.rex
test.rex: LKG
in >>> LKG()! <<<
--->
arrived in: test2.rex
FROM_TEST2
in routine FROM_TEST2
now creating a new routine on the fly:
in >>> LKG()! <<<
>>> in test3.rex <<<
hi (created in a single statement)
<---
<---
--------------------- output ---------------


As you can see, "test2.rex" is able to access the routine LKG() in "test.rex".

Also, "test2.rex" demonstrates how to create a routine on the fly (dynamically)

---

It is actually easy to do stunts like these in ooRexx, granted, one needs to become aware of this
functionality which adds a tremendeous amount of flexibility to Rexx.

HTH,

---rony


LesK

unread,
Sep 11, 2014, 10:31:36 AM9/11/14
to
On 9/11/2014 6:37 AM, Rony wrote:
... snip ....
>
> O.K., you asked for it. ;)
>
> ooRexx allows you to get to this kind of functionality with this (a little bit) advanced technique:
> do not call the Rexx programs directly, instead create routine objects of them and send the call
> message to the routine object.
>
>
... snip ...
> As you can see, "test2.rex" is able to access the routine LKG() in "test.rex".
>
> Also, "test2.rex" demonstrates how to create a routine on the fly (dynamically)
>
> ---
>
> It is actually easy to do stunts like these in ooRexx, granted, one needs to become aware of this
> functionality which adds a tremendeous amount of flexibility to Rexx.
>
> HTH,
>
> ---rony
>
>
That's an amusing solution to give to a team of novice ooRexx
programmers. Does it allow any routine to run any other routine?

Rony

unread,
Sep 11, 2014, 11:16:11 AM9/11/14
to
Yes, as long as you have a reference to that other routine. Just inspect the package and you see to
which routines you have references already.

---rony

LesK

unread,
Sep 11, 2014, 12:55:30 PM9/11/14
to
How does a package get created? What do you mean by 'reference'? Long
explanation offline please. The server won't accept long posts.

Jeremy Nicoll - news posts

unread,
Sep 11, 2014, 2:19:23 PM9/11/14
to
LesK <5mr...@tampabay.rr.com> wrote:

> How does a package get created? What do you mean by 'reference'? Long
> explanation offline please. The server won't accept long posts.

What server?

I've never seen a post to a newsgroup rejected.

Rony

unread,
Sep 11, 2014, 2:31:53 PM9/11/14
to
On 11.09.2014 18:55, LesK wrote:> On 9/11/2014 11:15 AM, Rony wrote:
>> On 11.09.2014 16:31, LesK wrote:
>>> On 9/11/2014 6:37 AM, Rony wrote:
>>> ... snip ....
>>>>
>>>> O.K., you asked for it. ;)

... snip ...


>>> That's an amusing solution to give to a team of novice ooRexx programmers. Does it allow any routine
>>> to run any other routine?
>>
>> Yes, as long as you have a reference to that other routine. Just inspect the package and you see to
>> which routines you have references already.
>>
>> ---rony
>>
> How does a package get created? What do you mean by 'reference'? Long explanation offline please.
> The server won't accept long posts.

The ooRexx interpreter maintains a package for each Rexx program. It uses it to resolve access to
routines, classes etc. The class is named "Package" :) and documented in the ooRexx reference,
builtin classes, fundamental classes.

One can get access to the current Rexx program's package by using the context environment variable
(a symbol that starts with a dot), i.e. ".context". This will return an instance of the
"RexxContext" class and is documented in the ooRexx reference, builtin classes, utility classes. As
you will see the RexxContext class defines a method named "package", therefore you can always get
the current's Rexx program package by issuing something like:

pkg=.context~package /* get current package */

Looking up the definition of the "Package" class you see methods like "routines" (all routines
defined in the Rexx program", "importedRoutines" (all public routines imported from other Rexx
program's packages), but also "addRoutine" or "addPublicRoutine" (to dynamically add a routine to
the package).

So, if you want to know which imported routines are available you would do something like:

do idx over pkg~importedRoutines /* iterate over the directory of imported routines */
say idx
end

If you know there is an imported routine named "HI" you could get a reference to it and then use it
at any time to call it (as many times as you see fit):

r=pkg~importedRoutines~HI /* fetch the executable routine object from the routine directory */
r~call /* call the routine */
r~call /* call the routine again */

HTH

---rony


LesK

unread,
Sep 11, 2014, 9:25:24 PM9/11/14
to
On 9/11/2014 2:13 PM, Jeremy Nicoll - news posts wrote:
> LesK <5mr...@tampabay.rr.com> wrote:
>
>> How does a package get created? What do you mean by 'reference'? Long
>> explanation offline please. The server won't accept long posts.
>
> What server?
>
> I've never seen a post to a newsgroup rejected.
>
The NNTP newsgroup server that Rony gave me a while back when the one I
was using went away. It sometimes says something like:

Posting refused: To many lines

Jeremy Nicoll - news posts

unread,
Sep 12, 2014, 11:57:29 AM9/12/14
to
Ah; from your headers that's 'aioe'; looking at http://www.aioe.org/ I see
there are some limits, but 32KB (of content) is a lot, when one considers
that you'd be posting plain text - it'd be around 400 lines even if every
line was 80 bytes long... Posts on this newsgroup seem usually to be around
the 3 - 8 KB size.

I use the NIN server at Freie Universitat, Berlin. Long ago it was free but
these days users pay 10 Euro per year. I see there's a size limit here too
but it's larger - 100 KB. See: https://news.individual.net/rules.php The
service is very reliable and technical support - not that it's often needed
- is good.

LesK

unread,
Sep 12, 2014, 1:07:50 PM9/12/14
to
On 9/12/2014 11:51 AM, Jeremy Nicoll - news posts wrote:
> LesK <5mr...@tampabay.rr.com> wrote:
>
>> On 9/11/2014 2:13 PM, Jeremy Nicoll - news posts wrote:
>>> LesK <5mr...@tampabay.rr.com> wrote:
>>>
>>>> How does a package get created? What do you mean by 'reference'? Long
>>>> explanation offline please. The server won't accept long posts.
>>>
>>> What server?
>>>
>>> I've never seen a post to a newsgroup rejected.
>>>
>> The NNTP newsgroup server that Rony gave me a while back when the one I
>> was using went away. It sometimes says something like:
>>
>> Posting refused: To many lines
>
> Ah; from your headers that's 'aioe'; looking at http://www.aioe.org/ I see
> there are some limits, but 32KB (of content) is a lot, when one considers
> that you'd be posting plain text - it'd be around 400 lines even if every
> line was 80 bytes long... Posts on this newsgroup seem usually to be around
> the 3 - 8 KB size.
>
> I use the NIN server at Freie Universitat, Berlin. Long ago it was free but
> these days users pay 10 Euro per year. I see there's a size limit here too
> but it's larger - 100 KB. See: https://news.individual.net/rules.php The
> service is very reliable and technical support - not that it's often needed
> - is good.
>
Sorry, but I mis-spoke. The error msg said: to many _quoted_ lines.
Looking at their Terms Of Use, I see:
---clip---
Each body line of an article must be shorter than 160 characters.
Quoted, blank and empty lines must be less than 80% of total body. A
quoted line begins with ">" or "|", a blank line contains only spaces an
empty one includes only a single newline ("\n") character.
---eclip---
So quoted lines is what I'm tripping over when I ask a short question to
a big program like Rony's.

At least now I know the rules!
0 new messages