The Museum of HP Calculators

HP Forum Archive 15

[ Return to Index | Top of Index ]

What's the difference? (RPN/RPL)
Message #1 Posted by Han on 22 Feb 2006, 1:43 a.m.

Hm.. I've only used the HP48(S/SX/G/GX/G+), so bear with me. But what exactly are the differenced between RPN and RPL?

      
Re: What's the difference? (RPN/RPL)
Message #2 Posted by Andreas Terzis on 22 Feb 2006, 2:16 a.m.,
in response to message #1 by Han

Han,

If you only have calculators of the HP-48 series then fairly you don't know the difference between RPN and RPL. RPN (Reverse Polish Notation) was used by earlier calculators up to the HP-18C or the HP-28C. RPL (Reverse Polish Lisp) is used in your calculator.

One of their main differences is that RPN uses a four-level stack with a fifth element being the LastX number used for intermediate calculations, when RPL uses a stack that has an depth that is dictated by memory only; in other words you can store multiple elements in the stack, limited only by the available memory, and use them for calculations.

Another difference is that RPN doesn't use a completely postfix notation - where you put the numbers in your stack first and then you perform the calculations (2 ENTER 5 +). In a lot of instances you use a prefix notation for functions, e.g. 7 STO 00, where you store the number 7 in register 00. In RPL you would store everything to the stack first and then perform operations on those objects, so the STO command would appear last. It is kind of a strict postfix notation language.

For more on this, you can check some excellent literature on the HP Museum like:

Link to RPN article, Link to RPL article.

I hope I summarized some of the differences correctly for you here. Andreas

Edited: 22 Feb 2006, 2:17 a.m.

            
Re: What's the difference? (RPN/RPL)
Message #3 Posted by Garth Wilson on 22 Feb 2006, 3:10 a.m.,
in response to message #2 by Andreas Terzis

As one who has never used or paid much attention to RPL myself, perhaps I can ask further, for the original poster. I understand RPL has strict program structures with no GOTO and, I assume, no labels either; and further, that an RPL program is compiled from text source code instead of being keyed directly in like you would do on an RPN programmable calc. I expect that variables can have names, and that you can probably make different kinds of variables, arrays, and data structures. Is this all correct? Does it compile "words" into a dictionary like Forth does? Perhaps these will bring to mind other things about it to describe briefly as well.

                  
Re: What's the difference? (RPN/RPL)
Message #4 Posted by Marcus von Cube, Germany on 22 Feb 2006, 3:20 a.m.,
in response to message #3 by Garth Wilson

Quote:
Does it compile "words" into a dictionary like Forth does?

An RPL program is an object that can reside on the stack or in a named variable. Once there, it can be 'evaluated'. Evaluating a variable is performed by just using its name. In that sense, an RPL program stored in a variable becomes part of the language.

I guess that's very similar to Forth.

Marcus

                        
Re: What's the difference? (RPN/RPL)
Message #5 Posted by Geir Isene on 22 Feb 2006, 6:31 a.m.,
in response to message #4 by Marcus von Cube, Germany

Quote:
I guess that's very similar to Forth.

Except the interactivity of the Forth environment is lost (which IMHO is one of the beauties of Forth and is one of the reasons why RPL is indeed inferior to Forth.)

                  
Re: What's the difference? (RPN/RPL)
Message #6 Posted by James M. Prange (Michigan) on 22 Feb 2006, 11:34 p.m.,
in response to message #3 by Garth Wilson

Quote:
As one who has never used or paid much attention to RPL myself, perhaps I can ask further, for the original poster. I understand RPL has strict program structures with no GOTO and, I assume, no labels either;

True, and no GOSUB either, thus indeed no use for labels.

But subprograms can be placed and manipulated on the stack and evaluated by the EVAL command, or stored as global variables and evaluated by name, or stored as local variables and evaluated by name followed by EVAL.

Quote:
and further, that an RPL program is compiled from text source code instead of being keyed directly in like you would do on an RPN programmable calc.

??? Well, ordinarily, I do key a program directly into the command line, within << and >> UserRPL program delimiters. Of course, you can always write a program (or most other object types) as source code in a text editor and transfer it to the calculator. If I happen to be at my PC, I'm more likely to use the larger screen and QWERTY keyboard to write all but the simplest programs. But for "real work", I'm not likely to be at my PC when I want to write an "ad hoc" program.

There are different ways to get the "words" into the command line editor; some can be placed there simply by pressing a primary or shifted key, most of the rest by pressing a menu key, and you can always just go into ALPHA mode and type out the command name. Personally, unless I know that I'm going to be using several commands from the same one or two menus, I normally just type out the command names instead of navigating through the menus.

In the 28 series, all of the commands are available through the CATALOG operation, and similarly, the 49 series has the CAT operation. These are perhaps best used if you don't remember the exact spelling of a command.

ENTER (or implicit ENTER) parses the command line, and assuming no syntax error, compiles it to a "secondary" (a SysRPL program) containing the object(s), and then executes it. In the case of a UserRPL program, we enclose the program within the << and >> delimiters, so "execution" simply places the UserRPL program on the stack, and it's decompiled for the stack display. To evaluate ("run") the program, you can use the EVAL command. Or with the program and a name on the stack, you can store them as a named global variable, in which case, executing the variable's name evaluates the program.

For that matter, you can write the object's source code, followed by the global name and the STO command, all in the command line, and then press ENTER to have them stored as a global variable without ever seeing them on the stack.

"Vectored ENTER" allows you to take additional actions before and/or after actually executing the command line.

Note that storing objects by name effectively extends the language for that particular calculator, and on all but the 28C, you can store quite a lot.

Note that RPL doesn't have "PROGRAM" and "RUN" modes. Perhaps the closest you can come to those is switching between "immediate", "PRG", "ALG", and "ALG PRG" entry modes, and "quoting" source code with delimiters for delayed execution.

You can write your source code within a character string, thus preserving all of your formatting and comments, and later "execute" the string with the STR\-> command, if you prefer.

Quote:
I expect that variables can have names,

Of course; an RPL "variable" amounts to a "named object". But there are some restrictions to names. For example, a global name can't duplicate a built-in "key word", or start with a numeric character, can't contain mathematical symbols, such as +, -, *, /, ^, <, and so on, can't contain any delimiter or separator character, and is limited to 127 characters. Note that in the 49 series, some of the restrictions are ignored by the Filer's "RENAME" operation and the S~N command in the "hacker's menu", but the "invalid" names can cause problems. Local names have fewer restrictions; for example, they can indeed duplicate built-in key words.

Quote:
and that you can probably make different kinds of variables,

Well, variables are either global or local, stored with a global or local name type object. A stored directory might be considered a sort of global variable, stored with a global name, that may contain other global variables. Global variables are stored until the user purges them. Local variables are stored in a local environment that exists only until the "defining procedure" (a program or algebraic object) is finished.

Quote:
arrays, and data structures.

There are various types of objects, depending on the model.

In the 28 series, the "user" object types are real number, complex number, character string, real array, complex array, list, global name, local name, program, algebraic object, and (user) binary integer. Of course the 28S can have directories, but you can't put a directory "on the stack" in that model.

The 48 series adds graphic object, tagged object, unit object, XLIB name, directory, library, backup object, built-in function, and built-in command to the "user" objects.

The 49 series adds user types (exact) integer, mini-font, symbolic array, and font.

There are also various "system" object types that the user wouldn't ordinarily see, such as system binary, extended real, extended complex, linked array, character object, code object, library data, and external objects.

Note that SysRPL uses different terminology for the object types.

Quote:
Is this all correct?

Well, I hope that I'm correcting any misconceptions.

Quote:
Does it compile "words" into a dictionary like Forth does? Perhaps these will bring to mind other things about it to describe briefly as well.

I'm not familiar with Forth.

RPL compiles "words" (source code) into "objects". Certain "built-in" objects are compiled simply as 5-nibble addresses, other than that, each object starts with a "prologue address" (usually referred to simply as the "prologue"), which is a 5-nibble pointer to the actual prologue, the code responsible for handling the particular type of object. Some object types contain information on the length of the object, or information that can be used to compute the length. Lists, programs, algebraic objects, unit objects, and symbolic matrices use the system object SEMI as a closing delimiter.

Note well that RPL never stores source code as such; the closest you can come to that is to force it to compile it as a character string object. For display, Kermit "ASCII" transfer, printing "via wire", and the \->STR command, objects are decompiled. But note that the object types library, backup object, mini-font, and font can't be decompiled by these methods.

Actually, having an object "on the stack" is a bit of indirection. The stack is really a stack of 5-nibble pointers to objects that exist elsewhere in memory, which are decompiled as needed for display. So the stack manipulation commands don't deal with objects per se, rather simply with 5-nibble pointers.

Note that an "algebraic object" could be regarded as a special kind of program. It's entered in algebraic syntax between single-quotation mark characters as the source code delimiters. It has its own prologue, but other than that it's compiled as an RPN sequence with SEMI as the closing object delimiter. For display and so on, it's decompiled to algebraic syntax. Of course, it can't use all of the "commands", only the "functions". That said, you can often write your own "user-defined functions", which can then be used within algebraic objects. All algebraic objects can be re-written as programs, but not all programs can be re-written as algebraic objects.

Regards,
James

                        
Re: What's the difference? (RPN/RPL)
Message #7 Posted by Eddie Shore on 26 Feb 2006, 11:23 a.m.,
in response to message #6 by James M. Prange (Michigan)

It does take some getting use to without having LBL and GTO commands to work with. The << sub program >> 'TEMPVAR' STO then TEMPVAR EVAL works.

                              
Re: What's the difference? (RPN/RPL)
Message #8 Posted by James M. Prange (Michigan) on 27 Feb 2006, 5:10 p.m.,
in response to message #7 by Eddie Shore

Quote:
It does take some getting use to without having LBL and GTO commands to work with.
Okay, I accept that for someone who's always had these available, learning to work without them may very well be difficult to get used to.
Quote:
The << sub program >> 'TEMPVAR' STO then TEMPVAR EVAL works.
Using subprograms in RPL is more like using GOSUBs in other languages, or in the case of named subprograms, rather like a CALL in some other languages. More likely substitutes for GOTOs would be conditional and looping program structures.

Unless a local variable named 'TEMPVAR' already exists,

<< sub program >> 'TEMPVAR' STO
makes a global variable. This makes sense if the intent is to make a utility program that will be called by various other programs, but isn't so good if the intent is to make a subprogram to be used more than once in a single program. For one thing, resolving a global name generally takes longer than resolving a local name or leaving the subprogram on the stack and using stack manipulation commands, and probably more importantly, the global variable will overwrite any global variable named 'TEMPVAR' in the current directory, and will be stored in the current directory until the user purges it.

With the subprogram stored in a global variable, executing its unquoted name, TEMPVAR, evaluates whatever's stored in the variable, so the EVAL is probably unneeded, although that depends on what evaluating << sub program >> returns.

We could do something like:

<<                      @ Begin program.
  << subprogram >>      @ Place the subprogram on the stack.
  'TEMPVAR'             @ Place the name on the stack.
  STO                   @ Store them as a global variable.
  ...                   @ Do some stuff.
  TEMPVAR               @ Evaluate subprogram.
  ...                   @ Do some more stuff.
  TEMPVAR               @ Evaluate subprogram.
  ...                   @ Do yet more stuff.
  TEMPVAR               @ Evaluate subprogram.
  'TEMPVAR'             @ Place the name on the stack.
  PURGE                 @ Discard the global variable.
  ...                   @ Finish up.
>>                      @ End program.
But that leaves the possibility of inadvertently purging an already existing variable named 'TEMPVAR', and of course it assumes that the program doesn't change directories.

We could make a utility program using argument checking and the SysRPL CREATE command as a variation on the UserRPL STO command. Given any object on level 2 and a global name on level 1, CREATE creates a new global variable at the beginning of the current directory, even if a same-named variable already exists in the directory. This would have the advantage of not overwriting anything, and since it would be at the beginning of the current directory, it would be resolved quickly. Of course, this assumes that the program doesn't change directories. As long as the variable exists, any same-named variable in the directory will be inaccessible. The variable will still be stored until the user purges it.

For a subprogram, I suggest using a local variable structure instead, such as:

<<                      @ Begin program.
  << subprogram >>      @ Place the subprogram on the stack.
  -> p                  @ Bind it in a local variable.
  <<                    @ Begin the defining procedure.
    ...                 @ Do some stuff.
    p                   @ Place the subprogram on the stack.
    EVAL                @ Evaluate subprogram.
    ...                 @ Do some more stuff.
    p                   @ Place the subprogram on the stack.
    EVAL                @ Evaluate subprogram.
    ...                 @ Do yet more stuff.
    p                   @ Place the subprogram on the stack.
    EVAL                @ Evaluate subprogram.
    ...                 @ Finish up.
  >>                    @ Abandon the local variable.
>>                      @ End program.
Of course, while a local variable named 'p' exists, nothing else named 'p' is accessible. Using the local variable has the advantage that creating it won't overwrite any already existing variable, and that it will be automatically discarded when its defining procedure ends.

Another approach is to leave the subprogram on the stack and use the stack manipulation commands, such as the following:

<<                      @ Begin program.
  << subprogram >>      @ Place the subprogram on the stack.
  ...                   @ Do some stuff.
  a PICK                @ Copy subprogram from level a to level 1.
    EVAL                @ Evaluate subprogram.
  ...                   @ Do some more stuff.
  b PICK                @ Copy subprogram from level b to level 1.
    EVAL                @ Evaluate subprogram.
  ...                   @ Do yet more stuff.
  c ROLL                @ Move subprogram from level c to level 1.
    EVAL                @ Evaluate subprogram.
  ...                   @ Finish up.
>>                      @ End program.
In the above, a PICK or b PICK could be some other command in the PICK family, such as DUP, OVER, or (in the 49 series) PICK3, and c ROLL could be some other command in the ROLL family, such as SWAP or ROT. This approach may well be a bit faster and/or smaller, but requires the user to keep track of which level the subprogram is in.

Regards,
James

      
Resourceful-Proficient-Natural vs. Re-Pe-Lent :-)
Message #9 Posted by Valentin Albillo on 22 Feb 2006, 11:28 a.m.,
in response to message #1 by Han

Best regards from V.

      
Literature suggestions (was: What's the difference? (RPN/RPL))
Message #10 Posted by Vieira, Luiz C. (Brazil) on 23 Feb 2006, 2:48 a.m.,
in response to message #1 by Han

Hi Han, all;

Bill Wickes' `HP41/HP48 Transitions` is one of the most concise sources of information for this very subject. Also, the single-volume version of the HP48 Owner's Manual (mine is January 1993 print, Edition 3) has an additional appendix comparing the HP48S/SX and the HP41. Sometime ago I digitized and converted it to a typeset PDF, available through this link. It's worth reading, only seven pages long.

Cheers.

Luiz (Brazil)

Edited: 23 Feb 2006, 2:49 a.m.

            
Re: Literature suggestions (was: What's the difference? (RPN/RPL))
Message #11 Posted by James M. Prange (Michigan) on 23 Feb 2006, 10:01 p.m.,
in response to message #10 by Vieira, Luiz C. (Brazil)

Quote:
Bill Wickes' `HP41/HP48 Transitions` is one of the most concise sources of information for this very subject.
Note that this book, along with his Insights books for the 28 and 48 series, is available on the Museum CD set / DVD. See: http://www.hpmuseum.org/cd/cddesc.htm.

Regards,
James

                  
Re: Literature suggestions (was: What's the difference? (RPN/RPL))
Message #12 Posted by Han on 23 Feb 2006, 10:25 p.m.,
in response to message #11 by James M. Prange (Michigan)

Luiz and James,

Thanks for the links to the information!

Han


[ Return to Index | Top of Index ]

Go back to the main exhibit hall