Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sdd.hp.com!mips!news.cs.indiana.edu!rsg1.er.usgs.gov!rsg1.er.usgs.gov!stevev From: stevev@greylady.uoregon.edu (Steve VanDevender) Newsgroups: comp.sys.handhelds Subject: Re: HP-48 programming problem Message-ID: Date: 9 Apr 91 06:06:19 GMT References: <1991Apr9.021224.27070@usenet.ins.cwru.edu> Sender: news@rsg1.er.usgs.gov Organization: University of Oregon Chemistry Stores Lines: 93 In-Reply-To: rkb@po.CWRU.Edu's message of 9 Apr 91 02: 12:24 GMT In article <1991Apr9.021224.27070@usenet.ins.cwru.edu> rkb@po.CWRU.Edu (Robert K. Brunner) writes: I had a problem debugging a program today, and I was wondering if anyone had encountered the same problem before. The problem isn't a bug, but it is annoying behavior. Suppose you have the following variables: P1: \<< \-> a \<< 'a' INC \>> \>> INC: \<< \-> a \<< a INCR DROP \>> \>> Executing 5 P1 gives INCR Error: Bad Argument Type. If you change the local variable in either of the programs to something different, you get 6, as you would expect. Apparently, INC thinks that the 'a' on the stack refers to the innermost local variable, rather than the one belonging to P1. If this behavior is documented in the manuals, I haven't seen it. The manuals attempt to document the scope rules of variables in pages 473 ff., but while they imply that local variables follow simple static scope rules, they only cite examples where static and dynamic scope rules are equivalent because none of their examples pass local names around as you did. By the way, I worked around the problem by using pass-by-value in the real program. Unfortunately, the reason I use a sub-program is that I need the routine in three places, so I've got three extra " 'a' STO " 's, one after each call of the routine. I may change the local variable in the routine, but it bothers me that subroutine calls are not transparent. Suppose someone writes a library that uses a local variable which I unwittingly use elsewhere. Robert You have discovered that RPL has dynamic scoping, not static scoping, which is important to know because it will definitely affect the way certain programs will work. Even worse, RPL doesn't support passing a reference token to a variable, which I think is what you were thinking it would do. Dynamic scoping means that you can't tell what variables are in scope (that is, which names refer to which values in which active functions) just by inspecting the program visually. A local name can refer to different local variables depending on which function is doing the calling. When you use the same local name 'a' in both P1 and INC, then when INC is called from P1, INC's local name 'a' is bound to the local name 'a'. Because RPL represents the local name 'a' the same in all scopes, when you evaluate the expression "a" to recall its contents, you get the local name 'a'. When INCR retrieves the value bound to 'a', it again gets the local name 'a', and generates the "Bad argument type" message because that isn't a real number. This isn't as telling as the behavior shown when you use the local name 'a' in P1 and 'b' in INC. Then, the value of "b" in INC is the local name 'a', so INCR is passed the local name 'a', and increments the value bound to local name 'a' _in the calling function_, P1. This is possible because RPL lets you put a local name on the stack, and because it clearly will attempt to resolve a local name which isn't bound in the current scope by looking for its binding in the function that called the current one, then the function that called the function that called the current one, and so on. While dynamic scoping will act like static scoping for the examples given in the manual, in this case it is different. In a statically scoped language, the variable would have to be defined in the current function, or in the environment that the current function is defined in, or in the environment global to that, etc., or you would get an error at the time you entered the statement. The run-time nesting of functions would not affect the resolution of binding of local names in any way. RPL therefore has two features that will bite people who are used to programming in most conventional programming languages. First, it uses dynamic instead of static scoping, which makes it far more difficult to predict what a name will refer to, because that depends on which functions have called which. Second, unlike most languages which allow you to pass arguments by value or by reference, RPL only allows you to pass arguments by value or by _name_, which if I recall correctly hasn't been done much since Algol faded from popularity. RPL therefore fully lives up to the name "Reverse Polish LISP", because the original LISP used dynamic instead of static scoping. Ironically, Common LISP now uses static scoping (although dynamic scoping is still available for backwards compatibility) and the popular LISP dialect Scheme uses static scoping exclusively. -- Steve VanDevender stevev@greylady.uoregon.edu "Bipedalism--an unrecognized disease affecting over 99% of the population. Symptoms include lack of traffic sense, slow rate of travel, and the classic, easily recognized behavior known as walking."