What's the difference? (RPN/RPL)



#13

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?


#14

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.


#15

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.


#16

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


#17

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.)

#18

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


#19

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.


#20

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

#21

Best regards from V.

#22

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.


#23

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


#24

Luiz and James,

Thanks for the links to the information!

Han


Possibly Related Threads…
Thread Author Replies Views Last Post
  Writing RPL programs on OS X Sean Freeman 18 5,085 11-30-2013, 03:59 PM
Last Post: Sean Freeman
  48G vs 49G+ User RPL Speed Comparison John Colvin 7 2,559 11-16-2013, 10:07 PM
Last Post: Han
  RPL 32 David Hayden 4 2,047 11-11-2013, 11:34 AM
Last Post: David Hayden
  [PRIME] RPN: another attempt at returning more than one value to the RPN stack Marcus von Cube, Germany 5 2,427 11-05-2013, 02:44 AM
Last Post: Marcus von Cube, Germany
  HP Prime Collect/Factor difference bluesun08 3 1,473 10-29-2013, 09:36 AM
Last Post: Eddie W. Shore
  HHC / HP Museum Programming Contest for RPN and RPL machines Gene Wright 18 5,492 09-22-2013, 09:39 AM
Last Post: Miguel Toro
  wp34s Emulator (-Infinity Difference) Barry Mead 1 1,170 07-24-2013, 03:52 PM
Last Post: pascal_meheut
  RPL long vs. short names peacecalc 5 1,997 10-30-2012, 01:25 PM
Last Post: peacecalc
  Mini-challenge: HHC2012 RPL programming contest with larger input David Hayden 14 3,561 10-05-2012, 10:36 PM
Last Post: David Hayden
  HHC 2012 RPL Programming Contest Gene Wright 33 7,603 09-27-2012, 01:57 AM
Last Post: Werner

Forum Jump: