RE: HP-48 programming problem Lines: 52 > >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. It looks like all you are trying to do is pass the current value of 'a' in P1 to the 'a' in INC. If that is what you're doing whats wrong with P1: /<< /-> a /<< a INC />> removing the ''s around the a the 48 recalls the value of a to the stack where the second program picks it up. The problem is not that the machine thinks you are referring to the value of 'a' in P1 it thinks you are referring to the name 'a' you have put on the stack. Thus in the second program the machine sees 1: 'a' -> a thats like saying 'a' 'a' STO. Store 'a' into itself doesn't make much sense. Incidentally if you rename one of the two local variables its fine because the HP sees 1: 'b' -> a So 'b' gets stored into 'a' and the EVAL works down the chain and eventually recalls the value of 'b'. I hope that explains the problem. And I hope I've understood the problem If not (and since I'm kinda dense sometimes I probably haven't) just scream. And I or someone else will give another shot. ====================================================================== ___ I__) _ _I _ _ TIM STRONG I \ (_I (_I (_I I MICHIGAN TECH. HOUGHTON, MICHIGAN ====================================================================== Date: Tue, 9 Apr 1991 13:02 CST Subject: Re: HP-48 programming problem Lines: 50 >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 \>> \>> There is a way to do what you desire. My reversi program for the hp28 made extensive use of it. You have to trick the parser into thinking that the variable 'a' is a local variable without including '-> a' in the executable code. Write a Make_INC routine that looks like (I've labeled the double brakcets): Make_INC: \<< \-> a \<< \<< a INCR DROP \>> 'INC' STO \>> \>> A B C C B A Then run this program and you have a version of INC that binds 'a' to a local variable but it doesn't define 'a' itself. The reason that this works is that when the Make_INC routine is parsed 'a' is a local variable, because it is defined at block level A and it is permitted to be used at level B. The parser then processes level C and says that 'a' is local. When this is run, the block C is pushed onto the stack and then stored into the variable INC, without re-evalulating the bindings. This means that 'a' (inside block C) still binds to a local variable. When your program P1 calls INC, the locally bound 'a' refers the the 'a' defined inside of P1 !!! You can now have global, local variables. If you try to run the new INC routine and there is no 'a' defined by any context along the call chain then you get an error message (undefined local?). Try this, it doesn't do any harm. Cute feature isn't it. Pauli seeya Paul Dale | Internet/CSnet: grue@cs.uq.oz.au Dept of Computer Science| Bitnet: grue%cs.uq.oz.au@uunet.uu.net Uni of Qld | JANET: grue%cs.uq.oz.au@uk.ac.ukc Australia, 4072 | EAN: grue@cs.uq.oz | UUCP: uunet!munnari!cs.uq.oz!grue f4e6g4Qh4++ | JUNET: grue@cs.uq.oz.au -- Date: Tue, 9 Apr 1991 13:05 CST Subject: Re: HP-48 programming problem Organization: University of Oregon Chemistry Stores Lines: 93 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." Date: Wed, 10 Apr 1991 16:47 CST Subject: Re: HP-48 programming problem Lines: 53 Unfortunately, the technique you suggest won't do what I thought the original poster really wanted, which was to be able to make a subroutine that would apply INCR to an arbitrary variable. Another poster didn't notice that INCR was being called and thought that the original poster wanted to pass the value of a local name 'a' to the subroutine, not the name itself. You can pass local names into a subroutine to do operations that need a local name and not just its contents, but you cannot make the subroutine completely general because passing a local name which is also used in the subroutine will cause the subroutine to operate on its own local variable, not on the one in the caller. There is no way to pass a reference pointer to a variable so that a subroutine can operate on any variable in any scope in standard RPL. RPL has different scope rules for global names and local names, which I find very interesting. Global names are statically scoped based on the current PATH. Global name references are resolved by searching the current directory, then the parent of the current, then its parent, on up to HOME. The run-time nesting of functions has no effect on the resolution of global name references. Local names are dynamically scoped based on the run-time nesting of functions. A local name reference is resolved by searching the bindings of the current function, then in the function that called it, then in the function that called that, and so on. If a function passes a local name into another function, and the called function doesn't use the same local name, then references to that local name get its value in the calling function. A function that refers to a local name without first creating it, like the one you created with \<< \-> a \<< \<< 'a' INCR \>> 'INC' STO \>> \>> will end up being completely dependent on run-time function nesting to determine its effect. I don't want to say that this kind of dynamic scoping is bad, but it can produce some very counterintuitive behavior and the kinds of problems that the original poster reported. Generally nobody uses dynamic scoping any more in programming languages. I think that knowing it is used in RPL is very important because of the subtle effects it can have. -- 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." Date: Fri, 12 Apr 1991 00:00 CST Subject: A Way to pass variables? Something someone was trying to do with incrementing a local variable in one program in another got me to thinking about an old technique I used to use on the 28. Unfortunately I haven't found a way to make it do what he wanted but its still neat: Try the following: On the command line enter 0 -> a << HALT Then press return Next without KILLing the above HALT make another program or algebraic using 'a' for example: '2*a^3' 'EQT' STO STO it away then press KILL Now try a new program such as << -> a << EQT EVAL >> 'TRYIT' put a number on the stack an run it. Notice that the inner program EQT recognizes the local variable 'a' from the program that called it. If you don't understand what I mean just quickly VISIT 'EQT' and put it back unchanged and run 'TRYIT' again. Notice this time 'a' is no longer recognized in EQT. Somebody from HP showed this to us a year or so back. What happens is that as long as you are HALTed in a program that has a local variable, any program or algebraic you create will also be created using that name as a local, not a global variable. Maybe this could be used to pass variables << (some glorious operation with a) 'a' STO >> Make it as above with the HALTed program currently going then I believe you can pass the 'a' back to the orginal program. This seems like a solution to the problem of passing variables except one can only pass the variable of the same name (which stinks). Anyone think of a better way. Maybe you could check with an IF THEN. {Maybe I'm just babbling to myself and no one can understand a word of what I'm saying because I'm inept at saying it.} ====================================================================== ___ I__) _ _I _ _ TIM STRONG I \ (_I (_I (_I I MICHIGAN TECH. HOUGHTON, MICHIGAN ======================================================================