Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!snorkelwacker!apple!portal!portal!cup.portal.com!Will From: Will@cup.portal.com (Will E Estes) Newsgroups: comp.lang.rexx Subject: Re: A Suggestion For Adding Function Pointers To REXX Message-ID: <26498@cup.portal.com> Date: 2 Feb 90 00:33:57 GMT References: <25545@cup.portal.com> <5344.25b20330@elroy.uh.edu> <25c5436f:31.2comp.lang.rexx;1@tronsbox.UUCP> Organization: The Portal System (TM) Lines: 195 A month ago I made a suggestion to this list that REXX needed a capability that approximates pointers in C in terms of its functionality. I suggested a mechanism for adding both function and data pointers that involved passing a reference to variable or function (but NOT the actual machine address). There were a lot of good responses to the original posting, and I want to summarize the responses and try to give answers. Be forewarned that this posting runs about 200 lines before you start reading. First, to review, my original suggestion for a modified syntax and semantics was as follows: (i) use & to mean that you are passing the name - not the physical address - of a variable or node and * to mean that you are receiving the name into a variable or stem. (ii) & in combination with () would mean that you are passing the name - not the physical address - of a function and * in combination with () would attempt to execute a function by reference. Function invocations through the *() mechanism could be through stems as well as variables (to allow for tables of function pointers). Why make these changes? There are several reasons: 1) to allow a way to pass variables, arrays, and arbitrary *portions* of arrays by reference to a subroutine. There is simply no other way to allow REXX to become a language where you can build general-purpose subroutines that act on a kind of data rather than hard-coding in the name of a *particular* data structure through EXPOSE. I dare anyone to write in REXX a general purpose binary sort routine that acts on *any* REXX array. Without some changes to the *language* it can't be done, and I think that should cause some serious concern to anyone who wants to use REXX as more than a shell language. 2) to allow a way to *return* arrays, and arbitrary *portions* of arrays by reference. There are some problems with the way I originally suggested doing this, and I'm not convinced of the utility of it, but it would give a way to return very complex subroutine results that can't be well-handled by something like: parse value MyFunction() with retcode1 retcode2 etc 3) to give you an *elegant* way to build tables of function pointers. (I don't count use of INTERPRET as elegant because of its overhead, its absence from the compiler, and because it can sometimes be difficult to read.) Here were the responses I received: Steve Bacher responds: < First of all, the & and * prefix syntax is fine for C, but won't < work in REXX. This is because, in REXX, abutment of expressions < is a feature of the language. That this means is that you would < be introducing an ambiguity. Consider the statement < say foo *bar &baz < Does this mean to display the value of foo concatenated with the < value of the expression [foo times bar] logical_and baz ??? That's a very good point. Can't argue with it. & and * will definitely have to go. But this is just a syntax ambiguity that can be easily resolved by choice of a different set of operators. For now put up with the incorrect symbolism just because of the fact that it looks familiar to C programmers and for purposes of this discussion will help out. < Second of all, exactly what would be the "address" of a REXX < variable? When you say "say &myvar", what gets displayed? < Depending on the implementation, there may not be a "machine < address" associated with the variable. In MVS/TSO, for example, < the REXX variables may get bumped around the tree from statement < to statement (this is all internal OCO stuff anyhow). Hold on now. I specifically said as part of the original suggestion that & did NOT reference a machine address of any sort. In fact, what & does reference is not defined at all, and you should never modify it in any way. Practically, saying &test would probably get you a handle. How that handle is used by the interpreter is implementation-dependent and is of no concern to the user. Ed Nilges responds: < The trouble here is that you are receiving this information into < a REXX procedure. This means that the dereferencing in the < parse arg statement conceptually takes place outside the "test" < procedure. But PARSE ARG currently grabs copies of variables "outside" the test procedure. What is so far-fetched about also having it grab handles to variables and stems at the same time? It's really a question of what the language semantics allow for. The variable environment that a subroutine works with is a function of the arguments to a subroutine call and the EXPOSE statement; that is true both before and after my suggested change, and I don't see how the new semantics I'm proposing involve a contradiction here. < While this is probably implementable, it is almost unexplainable < to all but the REXX aficiando. I have enough trouble getting < REXX programmers to use PROCEDURE for good information hiding < and disciplined use of variables. Well, I agree most programmers won't use the feature. The issue is what features need to be added to REXX to make it fully capable to do professional-quality applications. A professional-quality application assumes a professional-quality programmer, unfortunately ( :) ). I would hate to see someone take pointers out of C just because most programming students don't understand the concept! Let me put the problem a little differently and a little more emotionally: REXX as it stands today cannot be used to build commercial-quality applications unless you are willing to put up with some pretty crummy code (e.g., hard-coding array names into subroutines). That's a shame because I think REXX has the potential to become the application development language of choice, preferable even to C for most applications. But it "ain't gonna happen" without some serious changes to the language. < But a solution exists. This is to add the EXPOSE clause, < currently limited to procedures, as a new statement: < EXPOSE < where stuff would be a list of variables AND asterisk < representing everything. I hate to overstate, but here it goes: EXPOSE is grotesque. One of the key reasons for my suggested changes was to be able to do away with the need to use this facility. The idea that I should hard code in the name of global variables to my subroutine is, from a structured programming perspective, obscene. It gets programmers into very bad habits and it severely limits the power of the language. Now I understand that you are suggesting an extension to EXPOSE that would allow for dynamic EXPOSEs, but frankly I think that amounts to patching up something that is just wrong to begin with (a little like putting smooth edges on an ugly pipe sticking out the side of a house...I'd rather just cut off the pipe). An EXPOSE statement or function inside the procedure is also too wordy. Passing a reference is succinct. My own vote is to take Occam's razor to EXPOSE and do away with it. It is just about the only design in REXX that I think was poor (everything else is almost too good to believe!). Steve Bacher Responds: < Actually, "interpret" solves all the problems mentioned. INTERPRET can't do a call by reference for any REXX variable inside of a subroutine. But, beyond this, the REXX language just does not have a mechanism currently to support a call by reference to a STEM. And what about my examples that actually made calls by reference to an arbitrary node in a stem? You just can't do any of this with INTERPRET. The other issue is that INTERPRET makes for *ugly* code. Before it became illegal under SAA to use INTERPRET before the EXPOSE statement I had a friend who actually built a general-purpose sort routine that took as its argument a string that contained a STEM to EXPOSE. Every line of the sort involved using an INTERPRET on the variable that contained this string, and it was the most unreadable piece of code I have ever seen. INTERPRET has legitimate uses. Making up for a lack of call by reference is not one of them. < The return value could be captured as the variable "result". If < you want to retain the syntax of function calling, you need to < have a specialized function for this. And how do I return a structure from a function invocation except by changing the language? My suggestion was to allow calls like: *ReturnedStem. = test() ... test:procedure ... return &SomeStemIWantToReturn. Regarding specialized functions: how do I pass a stem by reference and point to an arbitrary location in that stem when I make a function call? I just don't see how adding any number of functions to the language is going to make up for an issue that has to do with its basic syntax and semantics. So, I think there are a few issues that need to be worked out here, but I'm more convinced now than ever that REXX needs a call by reference that supports both STEMS and portions of STEMS. A facility to have a subroutine return a STEM and some sort of function pointer capability (again, pointer does NOT mean a machine address in this context!) would both be nice, but neither is essential. To contrast, call by reference is essential if REXX is ever going to join the big leagues with C. Thanks, Will