You perfectly describe the text file I/O aspects of my CUR and ObjectCUR
libraries.
http://www.lueckdatasystems.com/ and click on Solutions.
Read, Write, Search, Insert, Delete, Append..... All ready to go an bug
free every once and a while! *wink*
--
Michael Lueck
Lueck Data Systems
Remove the upper case letters NOSPAM to contact me directly.
"Admin Colocon" <ad...@colocon.f2s.com> wrote in message news:5ksu7.83105$6x5.18...@afrodite.telenet-ops.be...
"Jack Snodgrass" <jack...@cybermail.net> wrote in message news:10020682...@tivonet.cybermail.net...
[...]
% do while lines(myfile)\=0
% /* parse the file */
% array.1=linein(myfile);
% /* store the content into array.1*/
% /* SOMETHING IS MISSING HERE to store into array elements "auto
% incremented" ? ! ? ! */
% /* then do some manip*/
% if array.1="a fully white line including many spaces";
% then
% call testingproc
% say "ez no?";
% end
If all you want to do is have the array indices auto-incremented,
do can do that for you:
do i = 1 while lnies(myfile \= 0
array.i = linein(myfile)
/* ... */
end
--
Patrick TJ McPhee
East York Canada
pt...@interlog.com
: cmd = 'cat /etc/resolv.conf'
: rc = popen(cmd,"data.")
: fills data. with the result of the 'cat' command.
: data.0 is the lines that were returned in data.
: I use this popen() function a lot on linux with Regina Rexx.
Once you get Regina 3.0, you should start using the ANSI standard ADDRESS
extensions. The equivalent to the above is:
Address System 'cat /etc/resolv.conf' With Output Stem data.
: jack
: "Admin Colocon" <ad...@colocon.f2s.com> wrote in message news:5ksu7.83105$6x5.18...@afrodite.telenet-ops.be...
: hi,
: I'd like to parse a text file(each line), on every read of a line to store the content into an array element(independently of the nuber of lines), then access array elements, to manipulate then...
: ouffff...
: Any idea are welcome...
: Cheers
: B.M.
: arse arg infile .
: if myfile\='' then
: /* test exisiting file*/
: do while lines(myfile)\=0
: /* parse the file */
: array.1=linein(myfile);
: /* store the content into array.1*/
: /* SOMETHING IS MISSING HERE to store into array elements "auto incremented" ? ! ? ! */
: /* then do some manip*/
: if array.1="a fully white line including many spaces";
: then
: call testingproc
: say "ez no?";
: end
: ....
--
Cheers, Mark
---------------------------------------------------------------------------
* Mark Hessling, M.Hes...@qut.edu.au http://www.lightlink.com/hessling/
* Author of THE; a Free XEDIT/KEDIT editor, Rexx/SQL, Rexx/Curses, Rexx/Wrapper
* Maintainer of PDCurses: Public Domain Curses and, Regina Rexx interpreter
* Use Rexx? join the Rexx Language Association: http://www.rexxla.org
cmd = 'Type <filename-here>'
Call Popen cmd,'data.'
do i = 1,data.0
<make something with DATA.I>
end /* do i */
if Mark has written a good port to WINx (what I'm expect), this should
work...
-wolfram
On Wed, 3 Oct 2001, Admin Colocon wrote:
>
>jack,
>
>Sorry but I'm scripting under windoz, no cat available...
>
>thanks anyway
>
>Bob
> "Jack Snodgrass" <jack...@cybermail.net> wrote in message news:10020682...@tivonet.cybermail.net...
> What version of Rexx? Regina Rexx has the popen() function. It's one
> of my favorite functions.
>
> cmd = 'cat /etc/resolv.conf'
> rc = popen(cmd,"data.")
>
... lots of stuff cut ...
On 3 Oct 2001, Jack Snodgrass wrote:
>What version of Rexx? Regina Rexx has the popen() function. It's one
>of my favorite functions.
>
...
Hmm, is new to me. Can someone enlighten me ? It's not ANSI, is it ?
(I should read the source of Regina ?!?! :-))
-wolfram
On Wed, 3 Oct 2001, GerardS wrote:
>| Wolfram Fassbender wrote:
>| do i = 1,data.0 <===??? comma ??? <==== Gerard S.
sorry, of course, NO COMMA
please use
DO i = 1 TO data.0 /* I'm so sorry :-((( */
Watch out for DO OVER, it does NOT guarantee the order the data is given
out of the container! Unless you have some strange File I/O needs, then
I would think you want the file to stay in order. That made for some
interesting challenges when I changed the LDSTextFile class in ObjectCUR
over to an Array object vs a Stem object to hold the data.
% On 3 Oct 2001, Jack Snodgrass wrote:
%
% >What version of Rexx? Regina Rexx has the popen() function. It's one
% >of my favorite functions.
% >
% ...
%
% Hmm, is new to me. Can someone enlighten me ? It's not ANSI, is it ?
% (I should read the source of Regina ?!?! :-))
You could read the documentation. popen() precedes the ansi standard.
My implementation of rexxutil, which is finely honed to work with Regina,
but will work with other rexx implementations that support the rexxsaa
API, provides regstemread, which reads a file into a stem without
executing an external process.
For all those VM hacks out there, yes this functionality was available
with execio in the early '80s, but what I most remember about execio
was the nervous breakdown that closely followed reading the on-line help
for it.
infile='C:\MyRexx\MyFile.TXT' MyStrm=.Stream~New(infile)
MyArray=MyStrm~ArrayIn do FileLine over MyArray parse var FileLine
<insert your stuff here>
. . . end InStrm~Close
One thing I have found through testing is that reading a file line by
line is more efficient (speed wise) than reading the whole file into an
array from the outset.
And as previously stated there seems to be a problem with "Do Over"
where-by it doesn't necessarily read the entire array in order.
--
I don't have an attitude problem - you have a perception problem...
I don't have an attitude problem - you have a perception problem...
Posted via dBforums
http://dbforums.com
> If all you want to do is have the array indices auto-incremented,
> do can do that for you:
[obvious typos corrected]
> do i = 1 while lines(myfile) \= 0
> array.i = linein(myfile)
> /* ... */
> end
I'm uncertain (without trying it) whether that would work; surely without
a TO or BY clause, the repetitor (i) would remain with the initial value
(1) throughout. Whenever I've needed a loop along those lines, I've
included an explicit
i = 0
before it, and an explicit
i = i + 1
as the first line inside the loop (thus the counter is only incremented
from the initial zero if there ARE any "lines()")
Whilst that code will work, it's exceedingly ineffecient; typically (with
a 200MHz CPU) one will only achieve reading speeds of the order of a few
hundred lines per second.
By rewriting the loop such that it's all the subject of an INTERPRET
verb, one can achieve stupendous increases in efficiency. Here's one I
wrote a few years ago; as you'll see from the comment, this was TWENTY
times faster:
/***************************************************************************\
| |
| SUBROUTINE FileIn |
| |
| Parameters: |
| stem: a string naming a stem variable |
| filename: a string giving the path of the file to be read |
| count: interval between printing dots, to indicate progress |
| |
| Returns: |
| Number of lines read from the file, or -1 if error |
| |
| Notes: |
| |
| This procedure looks somewhat "hairy", and contains a long do loop |
| written as a single line (using ';' and continuations) which is then |
| interpreted just the once. This technique, whilst difficult to read, |
| achieves an input speed of 10,000 lines/s; using a simpler (clearer) |
| while loop, with an invocation of Interpret for each line of the file, |
| is much slower, roughly 500 lines/s. |
| |
| IMPORTANT: needs global access to any stems created: hence use of local |
| variables named _fi_i, etc., to avoid potential clashes with "obvious" |
| counters in calling routines, since all caller's variables "exposed". |
| |
\***************************************************************************/
FileIn:
parse arg stem, filename, count
if arg()<2 then return -1
if stem = '' | filename = '' then
do
SAY 'Error reading file' filename 'into stem' stem
return -1
end
_fi_i=0
interpret stem'=0' /* Clear out stem variable */
if Stream(filename,'C','OPEN READ') == 'READY:' then
do
interpret "do while Stream(filename,'S') = 'READY';",
"_fi_i = _fi_i+1;",
"if ( Arg() = 3 ) then;",
"if ( (_fi_i // count) = 0 ) then;",
"CALL CharOut , '.';",
stem'_fi_i = linein(filename);',
"end"
end
else
return -1
CALL Stream filename,'C','CLOSE'
/* Discard trailing blank line */
interpret 'if 'stem'_fi_i = "" then _fi_i = _fi_i-1;' stem'0 = _fi_i'
return _fi_i
--
Brian {Hamilton Kelly} b...@dsl.co.uk
"We have gone from a world of concentrated knowledge and wisdom to one of
distributed ignorance. And we know and understand less while being incr-
easingly capable." Prof. Peter Cochrane, formerly of BT Labs
John Seddon wrote:
>
> Hi. I must admit I have only skimmed the previous posts, but isn't the
> easiest way of converting a text file into an array to use the stream
> command ArrayIn? If someone has suggested this already I appologise for
> my laziness...
ArrayIn has a nasty bug in that it does not dimension the Array and is a
slow pig for performance. I do not suggest using ArrayIn for File I/O
until IBM has made a resolution to this bug, of which I have sent them a
suggestion and they have not gotten back to me with their review of the
suggestion.
[about do i=1 while condition auto-incrementing i]
% I'm uncertain (without trying it) whether that would work; surely without
% a TO or BY clause, the repetitor (i) would remain with the initial value
% (1) throughout.
I, on the other hand, am certain. TRL2, pg 47 defines DO like so:
DO [repetitor] [conditional];
[instructionlist]
END [symbol];
and provides 3 forms for repetitor:
name=expri [to exprt] [by exprb] [for exprb]
The default value for exprb is 1. Note that any and all of the
to, by, and for sub-clauses are optional (they can also be in
any order, which is news to me). If we skip over to pp 49-50, we
find that the the value of exprb is added to name on each iteration,
and that the loop terminates when name reaches exprt, unless the to
subclause is not specified, in which case it executes indefinitely.
The for clause provides a bound on the number times the loop can
execute. Another surprise for me is that you're allowed to alter
name, although MC considers it `suspect programming practice'. You
could do something like this, though:
do i=1 to 1024 by 0
i = i * 2
/* blah blah blah */
end
% Whenever I've needed a loop along those lines, I've
% included an explicit
% i = 0
% before it, and an explicit
% i = i + 1
% as the first line inside the loop (thus the counter is only incremented
% from the initial zero if there ARE any "lines()")
I would also do it this way, but only for clarity's sake, since
most people don't know all the details of the do loop.
% Whilst that code will work, it's exceedingly ineffecient; typically (with
% a 200MHz CPU) one will only achieve reading speeds of the order of a few
% hundred lines per second.
I put this in a file:
parse arg file .
do i=1 while lines(file) /* note -- not an ansi compliant use of lines! */
x.i = linein(file)
end
x.0 = i
and ran it on a PC with a P133, which was a pretty fast machine 6 years ago,
and time says it took 15.63 seconds real time to read 61,339 lines of
fairly dense text (2,500,646 bytes). That's 3900 lines per second.
% By rewriting the loop such that it's all the subject of an INTERPRET
% verb, one can achieve stupendous increases in efficiency. Here's one I
I ran your version, and it took 20.39 seconds. The call was
call filein 'x.', file, 70000
(70000 was chosen to prevent any progress dots from being printed).
To be fair, your version does more than mine, since it works as a
sub-routine. Suppose we had this:
filein:
?? = arg(1)
procedure expose (??)
parse arg stem,file
do i=1 while lines(file) > 0 /* Note -- ansi compliant use of lines! */
call value stem || i, linein(file)
end
call value stem || '0', i
return
that took 24.99 seconds, real time, which is not quite 20 times slower
than your version, but it's a bit.
Finally, using the regstemread function in regutil, it takes 11.66
seconds, which just goes to show you, you're probably better off
writing in C and using memory-mapped I/O if you want better performance.
> >b...@dsl.co.uk (Brian {Hamilton Kelly})
> >By rewriting the loop such that it's all the subject of an INTERPRET
> >verb, one can achieve stupendous increases in efficiency.
[snip my code, including the introductory comment block, which the
fuckwit Glatt obviously ignored totally]
> Ugh! The above has to be perhaps the most hideously inefficient REXX
> "coding" I've ever seen. It features a *totally unnecessary* use of
> INTERPRET, and far more instructions than should need to ever be used
> to read a file into a compound variable. Frankly, I don't think that
> anyone should model code after the above "example" -- it's that bad.
>
> I had always suspected that Brian Kelly knew almost squat about REXX
> and programming, and the above confirms it. (I guess that he doesn't
> even know about the PROCEDURE statement).
You show your total inattention with every word you write. The code I
presented was a function to be called; as such, the name of the stem
variable is apssed to it as a string. Hence the requirement for
INTERPRET, which could otherwise not assign the lines read into the
elements of the stem. Moreover, had I used PROCEDURE, it would not have
been possible for the function to have gained access to that stem
variable: hence the comment about the global variable used for counting
being given an identifier unlikely to have been used otherwise. One can
hardly include every potential stem that's likely to be used in a call of
the function into the EXPOSE clause, can one?
Granted it's easy to write the requisite code in-line, as you presented
it, without using INTERPRET; but that's not of much use in a program
that's reading hundreds of files into different stem variables (indeed,
I've used that to read into stems of stems).
Just go back to playing with your noddy windoze, Jeff: you know fuck all
about real-world programming.
> I'm uncertain (without trying it) whether that would work; surely without
> a TO or BY clause, the repetitor (i) would remain with the initial value
> (1) throughout. Whenever I've needed a loop along those lines, I've
> included an explicit
> i = 0
> before it, and an explicit
> i = i + 1
> as the first line inside the loop (thus the counter is only incremented
> from the initial zero if there ARE any "lines()")
As Jeff has pointed out with his inimitable competence, I glossed over a
leap in design philosophy between the above paragraph and the next...
> Whilst that code will work, it's exceedingly ineffecient; typically (with
> a 200MHz CPU) one will only achieve reading speeds of the order of a few
> hundred lines per second.
What had been meant to be in between there was something to the effect
that, in real-world programming, one most probably will not just want to
perform this operation just once on one file (and include the code for
reading the file into the array in-line within the main program). Good
principles of structured design should bring one to the point of using a
separate function to perform the reading in of the file to the stem
variable.
Now if there is only the single stem about which to concern ourselves,
one could conceivably make this a global, accessed within the function by
EXPOSE. However, I prefer to write code with genuine flexibility to be
deployed in programs as required (indeed, I am a great expouser of the
principle of code re-use). Therefore I came up with a general-purpose
function that can read a file into any stem variable, the variable's name
being passed (as a string, naturally) as one of the parameters.
It is that formulation of the problem into a function that leads one,
initially, to a design somewhat along these lines (ignoring, for the
nonce, error detection/correction):
> FileIn:
[Note that one cannot include a PROCEDURE statment, with or without an
EXPOSE clause, because the function does not know what name will be
passed in as the "stem" parameter, and the function needs access to the
actual stem whose name is given in that parameter.]
> parse arg stem, filename
> _fi_i=0
> interpret stem'=0' /* Clear out stem variable */
> if Stream(filename,'C','OPEN READ') == 'READY:' then
> do
> do while Stream(filename,'S') = 'READY'
> _fi_i = _fi_i+1
> INTERPRET stem'_fi_i = linein(filename)'
[This is where the content of the line is assigned to the next "element of
the array".]
> end
> end
> else
> return -1
> CALL Stream filename,'C','CLOSE'
> return _fi_i
Now the above is the simplistic approach (that might have been found by
the original enquirer, when he expanded his requirement so as to be able
to read a file into any stem variable). But as I originally wrote, it's
horribly inefficient; hence my presenting the rather curious looking:
> if Stream(filename,'C','OPEN READ') == 'READY:' then
> do
> interpret "do while Stream(filename,'S') = 'READY';",
> "_fi_i = _fi_i+1;",
> stem'_fi_i = linein(filename);',
> "end"
> end
> else
> return -1
> CALL Stream filename,'C','CLOSE'
which performs all the actions considerably faster, in that there is only
one INTERPRETation taking place, rather than one for every line of the
file.
Using INTERPRET in this fashion is also much faster than calling the
VALUE function repeatedly to perform the storage operation.
Anyway, this posting has mainly been to explain why I presented a
function that did so much more than the original enquirer had requested;
but remember the old adage about giving a man a fish.
> >b...@dsl.co.uk (Brian {Hamilton Kelly})
>
> >In article <oe0trto29fi6100ee...@4ax.com>
> > jgl...@spamgone-borg.com "Jeff Glatt" writes:
> >
> >> >b...@dsl.co.uk (Brian {Hamilton Kelly})
> >> >By rewriting the loop such that it's all the subject of an INTERPRET
> >> >verb, one can achieve stupendous increases in efficiency.
>
> >[snip my code, including the introductory comment block, which the
> >fuckwit Glatt obviously ignored totally]
>
> What happened to your "ignore filter", Brian? Too incompetent to get
> it working, I see. I'm not surprised.
{R} drew my attention, by posting, to the fact that you had responded to
me; I therefore explicitly fetched your article, which was already in my
newsbase, but as headers only. I have since turned off the killfile
rule, although I'm sure that this will be only a temporary measure, in
order to see your responses.
> You show your total inattention in every reply you write. The person
> did not ask for a function that takes the name of a stem variable
> assessed as a string.
Indeed; however "Give a hungry man a fish, and he will have a good meal;
teach a hungry man to fish, and he shall have a meal every day of his
life".
> >Hence the requirement for INTERPRET
>
> There was no requirement for INTERPRET, as I noted.
>
> Actually, there's no need for INTERPRET at all, although you seem to
> think otherwise. The VALUE() function is expressly designed to do what
> you're inefficiently trying to do with INTERPRET, You probably never
> heard of that, along with DIGITS().
I use VALUE many times in different situations; using it repeatedly
inside a WHILE loop to assign the lines read into different stem variable
tails is slower than using a SINGLE interpreted statement; the latter
achieves the same speed as the "raw" code which one can write
simplisitcally when working with only a single stem variable.
> That's irrelevant. The person didn't ask to include every potential
> stem. The other examples offered were more to the point, and more
> efficient
But they were not of general applicability.
Granted I missed out the reasoning that takes one from having a simple
iterative loop reading into a single stem variable, to the stage of
having a general-purpose function capable of reading into a different
stem variable for each call of the function; I have attempted to correct
that lacuna in my original posting. ISTR that at the time I was writing
that I suddenly realized that I had to go out, and therefore skipped part
of the exposition of why it's sensible to design a GP function.
If you are worried about efficiency then it's not a good idea to
call the LINES() function unless you do actually want to know
how many lines there are in the file. If you just want to
know whether there is any data left then it's more efficient
to call CHARS(); or, better, to check for end-of-file condition
in any of several ways (such as checking STREAM(filename)=="READY"
or using CALL ON NOTREADY to set an EOF variable or SIGNAL ON
NOTREADY to jump out of the reading loop).
--
---- Ian Collier : i...@comlab.ox.ac.uk : WWW page (including REXX section):
------ http://users.comlab.ox.ac.uk/ian.collier/imc.shtml
New to this group? Answers to frequently-asked questions can be had from
http://rexx.hursley.ibm.com/rexx/ .
>Now if there is only the single stem about which to concern
>ourselves, one could conceivably make this a global, accessed within
>the function by EXPOSE.
And if there are multiple stems one can do the same thing. Put the
name in a variable and put parentheses around the name of that
variable in the EXPOSE clause.
Of course, that still leaves the efficiency issue of calling INTERPRET
once versus calling VALUE multiple times.
--
-----------------------------------------------------------
Shmuel (Seymour J.) Metz, SysProg and JOAT
Atid/2
Team OS/2
Team PL/I
Any unsolicited commercial junk E-mail will be subject to legal
action. I reserve the right to publicly post or ridicule any
abusive E-mail.
I mangled my E-mail address to foil automated spammers; reply to
domain acm dot org user shmuel to contact me. Do not reply to
spam...@library.lspace.org
-----------------------------------------------------------
That would be the Lines method, not the function. The function returns
logical, 0 when at EOF. The Lines method will scan the file for the
number of remaining lines.
It depends on which interpreter you are using. You shouldn't count
on LINES() to only return 0 or 1 because some time it might stop
doing that.
Indeed; someone was complaining in one of the eCS newsgroups that
LINES() [the function] under eCS only returns 1 or 0, and he was used to
using it as a count of lines. He complained that this was at variance
with the behaviour under OS/2 Warp 4 FP12.
IIRC, the changeover to the current behaviour took place at FP13, so
it's not just something newly introduced in eCS. (Moreover, of course,
the function in Object Rexx has always only returned zero or one, hasn't
it?)
--
Brian {Hamilton Kelly} b...@dsl.co.uk
do while lines(infile) <> 0
...
end
It took some time to find and to reproduce the problem.
: Indeed; someone was complaining in one of the eCS newsgroups that
: LINES() [the function] under eCS only returns 1 or 0, and he was used to
: using it as a count of lines. He complained that this was at variance
: with the behaviour under OS/2 Warp 4 FP12.
Sounds like this behaviour was introduced to support the ANSI standard and
to make LINES() respond quicker; both of which were done to Regina a while
back.
You should expect LINES() to return 0 if there are no more lines in the
file, and >0 if there are lines remaining. If you always get 1 returned
from LINES(), then LINES() should also provide LINES( stream, 'C') which
MUST return the actual number of lines remaining.
: IIRC, the changeover to the current behaviour took place at FP13, so
: it's not just something newly introduced in eCS. (Moreover, of course,
: the function in Object Rexx has always only returned zero or one, hasn't
: it?)
: --
: Brian {Hamilton Kelly} b...@dsl.co.uk
: B.Hamilt...@rmcs.cranfield.ac.uk
--
> In <100245...@dsl.co.uk>, on 10/07/2001
> at 10:30 AM, b...@dsl.co.uk (Brian {Hamilton Kelly}) said:
>
> >Now if there is only the single stem about which to concern
> >ourselves, one could conceivably make this a global, accessed within
> >the function by EXPOSE.
>
> And if there are multiple stems one can do the same thing. Put the
> name in a variable and put parentheses around the name of that
> variable in the EXPOSE clause.
Which is messy, in that the operation of putting the name into the
variable has to be repeated on each call, /before/ the call itself.
(Moreover, if one's got the name in a variable, one hardly needs the
first parameter!)
I quite liked Patrick McPhee's code fragment:
FileIn:
?? = arg(1)
procedure expose (??)
parse arg stem,file
especially since I wasn't hitherto aware that one could have anything
intervening between the subroutine's entry label and the PROCEDURE
statement (I know that when I once did mistakenly get a PARSE ARG in
there first, the interpreter screamed that PROCEDURE could not appear in
that position).
But if the ARG() function can be called in that manner, and used to
squirrel the "global" stem's name away into the variable ??, and then
that latter alone is EXPOSEd, then obviously things are more neatly
compartmentalized, in that one doesn't need global variables at all.
However, the Object REXX Reference Manual, SH12-6222-03, that I have says
"If the PROCEDURE instruction is used, it must be the first instruction
processed after the CALL or function invocation, that is, it must be the
first instruction following the label". OTOH, from the tone of Patrick's
posting, I gathered that he had actually tried it, and so it must work,
at least on whatever implementation he is using.
> Of course, that still leaves the efficiency issue of calling INTERPRET
> once versus calling VALUE multiple times.
As I said originally, the overhead of the one invocation of INTERPRET has
minimal impact, probably less than the act of concating the stem
variable's name with the tail value and passing it into VALUE, instead of
applying it directly.
--
Brian {Hamilton Kelly} b...@dsl.co.uk
The following does not address reading a file, but is provided as a way of
passing a variable list of parameters to an internal function and demonstrating
expose using parenthesis. In this example the function is only referencing
variables, but the function could easily update the stem name it was passed.
parm1.1 = 'ABC'
parm1.2 = 'DEF'
parm1.3 = 'XYZ'
parm1.0 = 3
temp = myfunc(parm1.,parm2,parm3)
exit
myfunc:
result = arg(1) arg(2) arg(3)
return _myfunc(arg(1),arg(2),arg(3))
_myfunc: procedure expose (result)
say 'first arg 'arg(1)' has 'value(arg(1)||0)' elements'
return 0
The above code should produce the message
first arg PARM1. has 3 elements
% first instruction following the label". OTOH, from the tone of Patrick's
% posting, I gathered that he had actually tried it, and so it must work,
% at least on whatever implementation he is using.
It works with Regina. I didn't try it with OS/2 or Rexx/IMC. TRL
says that it is illegal, so I guess I'm a bad boy.
>I quite liked Patrick McPhee's code fragment:
I liked it also, but how portable and stable is it? Will it continue
to work if you install a fix pack, or if you move to a different
platform?
So far as I'm aware, it works with only one interpreter, and is,
strictly speaking, a bug. I would expect it to go away in some future
release (because I expect somebody will feel compelled to change the
way variables or arguments are handled), but in the mean time, I
reserve the right to use it if I feel like it.
Ditto with REXX/imc, although sometimes it can be useful as you point
out.
Such a function could instead be written:
function: parse arg _function_arg
return function2(_function_arg,arg(2),arg(3))
function2: procedure expose (_function_arg)
...
but it's a bit of a hack and the coding depends on how many arguments
the function takes and whether it returns a result.