[翻译] hpmuseum - RPL

翻译自hpmuseum.org

当Pokecom大行其道时,各家老牌计算器厂终于意识到应该做些什么来取代掉落后的按键编程。各家都开始忙于研究新的计算器系统,而HP这次将自己的视野放到了其他公司难以企及的高度……
RPL是一个美丽、高效又实用的语言,虽然我们管它叫一门语言,但实际上它是HP后期几乎所有高端机型最核心的东西,其中的一些概念非常超前,以至于人们一时难以接受。
那么RPL是什么样的呢?

80年代末,HP正在开发一系列功能非常强大的计算器,它们需要一种新的编程语言。对于早期的计算器而言,内存是又贵又笨重的东西,把这么多科学函数放在如此小的空间里对早期的固件编写者而言是个大挑战。他们熟练地,仔细地运用汇编语言,一次又一次地提炼代码,直到它们合用。但是当内存不再那么昂贵和稀缺之后,主要的挑战就从节省空间变成了实现与测试为新型计算器设计的许多复杂的功能。
HP仔细审视了现存的语言如BASIC,但发现它们都不是很合适——它们的限制很多,同时它们很占用资源,尤其是对于手持设备而言。于是HP结合了RPN,Lisp和Forth的元素,制造出了一个新语言--Reverse Polish Lisp(RPL)。
RPL继承了Lisp中的一些理念,如元素和复合对象,临时变量(λ变量),垃圾回收,将未执行的对象作为参数传递等。同时RPL从Forth中继承了线程执行的概念,以及没有堆栈数量限制的RPN。
RPL即是为了HP内部的编程者设计的,也是为计算器用户设计的。第一台使用RPL的机器是HP-18C,尽管这是个不可编程的代数机,这台机器的RPL没有开放给用户。尽管大多数人不认为这是个“RPL计算器”,18C因为在内部编程使用了RPL,依然被当作是RPL计算器系列的一个“荣誉会员”

系统RPL和用户RPL

HP-28C是第一个将RPL开放给用户,内外均使用RPL编制的计算器。尽管两者的需求有重叠,依然有不同的部分:普通用户希望计算器跟“防弹衣”一样,许多用户在尝试中学习使用,程序错误应该被妥善处理,而不是对用户造成任何内容损失。
而内部编程者需要的是速度、效率,他们要做的是仔细地调试他们的程序,一旦发生错误就清除整个内存。因此HP的程序员可以使用RPL快速与强大的一边,那些普通用户无法使用的。
举个例子,用户可见的乘法指令会先确认栈上是否有两个对象,会检查它们的类型,然后调用该类型(实数?虚数?整数?)相对应的乘法指令。而一个确信这两个参数始终是正确的的HP程序员会选择直接调用对应该类型的内部乘法指令。而如果这种情况下程序员犯了错,计算器就可能工作的不正常,甚至需要复位或清空内存。
也有一些内部指令提供了组合操作,用以节约空间和时间。举一个不算少见的例子:#1+是在x栈的实数上加1,dup#1+是先复制(dup)一份,再加1,#-#2/是先从y中减去x再除以2。
总的来说,系统RPL是面向内部编程者的,用户RPL则是它的一个附带了类型检查的,安全的子集。用户RPL在计算器的使用手册里有详细描述,可以通过计算器的键盘输入。而系统RPL需要通过HP的RPL编译器编译,然后再下载到计算器中执行。

尽管原先是为HP自己的编程者设计的,HP通过'SYSEVAL'指令为系统RPL开了一扇窗。'SYSEVAL'指令会直接调用第一个栈中的地址(用户输入的二进制数)。勇敢的用户并没有惧怕内存丢失,他们通过自己不断的实验,破解了许多RPL计算器的秘密。不久一个HP-48开发者——James Donnelly 写了一本书《An Introduction to HP 48 System RPL and Assembly Language Programming.》,这本不是HP自己出版的书受到了HP的支持,并随书附送了HP-48开发套件CD。这本书将我们引向了更强大与快速的编程。

用户RPL

用户RPL在HP-28,HP-48和HP-49系列里可以用到。而HP-18C和HP-38G这种只有系统RPL的计算器并没有对用户开放太多的功能。
(用户)RPL有这些特点:

栈大小数量只受内存限制

RPN的栈会随着使用自动分配内存,用户可以自由地输入而不用特地优化输入顺序。同时,不受数量限制的栈内数据可以被当作参数传入函数中,这允许人们使用现代化的程序结构。增大的栈结构需要新的一套操作方式,以前的x栈被改名为'栈1',y栈被改名为'栈2'等等,'SWAP'替代了'x<>y','LAST'取代了'LAST x','DROP'以一种更有效的方式取代了'CLx',还有许多新的栈操作指令被加入了。

对数据和输入类型的统一(对象)

最早的RPN计算器只懂得数字和程序,通过设立“编程模式”和“运行模式”,这两类数据被分开放置。在进化过程中更多的“模式”被添加进来(alpha模式,复数模式等)
而RPL计算器不再含有“模式”这种东西,所有都被称作“对象”,计算机有指令来操作实数对象或复数对象。RPL计算器中的对象类型有:

  • 实数
  • 复数
  • 二进制(表示为二进制、八进制或十六进制)
  • 列表
  • 数组(实数或虚数,向量或矩阵)
  • 字符串
  • 代数式
  • 程序

对象可以通过命令行被输入,被解释后保存在栈上。RPL栈上可能同时有各种数据和对象,并不需要切换到专门的“编程模式”,用户可以直接把程序输入到栈中,就像是其他对象一样。

变量的命名

与使用了数量有限的寄存器的计算器不同,RPL计算器允许使用任意字母名称命名变量。任何可以出现在栈上的对象都可以被保存为变量。需要把栈1上的对象保存下来,只需按下' ’ '键,输入一个名称,然后按下'STO',这是个典型的后缀表示法(RPN)(RPL不需要用户考虑引号是否闭合,“ 'NAME STO“和“ 'NAME' STO“是等效的),RPL计算器有'RCL'键,虽然不是很常用。用户可以直接输入变量名(不带')来回调一个变量,调出的同时会执行(evaluate)一次该变量,如果是一个数据,出现的就是这个数据,如果是程序,该操作就会运行这个程序。

RPN与代数逻辑的结合

RPL是基于堆栈的,但是用户也可以输入代数表达式比如'(A+B)*C'。举个例子,用户先给A、B两个变量赋值,他先输入“25 ENTER 'A' STO 10 ENTER 'B' STO”,然后再输入表达式'(A+B)*C',按下“EVAL”执行,计算器会“尽可能”地去计算这个式子,将结果'35*C'放在栈上,现在用户想要把它乘以10,得到的结果是'35*C*10',这时输入5 'C' STO然后EVAL,结果是1750。这种做法允许使用RPN的交互方式操作代数表达式。

符号代数

RPL可以把未赋值的变量带入计算,上面的例子中,'35*C'乘以10结果是'35*C*10',可以使用'COLLECT'指令化简为'350*C',另外也有分离、微分、积分等方面的指令。这使得一些非常复杂的问题在计算器上就可以得到完整的解答。

微积分

RPL计算器可以对许多式子进行积分或导数的符号运算,用户可以输入一个表达式如'TAN(X^2-1)+SIN(X)',输入'X'来指定自变量,然后按下'd/dx'来进行求导,结果是'(1+SQ(TAN(X^2-1)))*(2*X)+COS(X)'。HP-28C/S也可以进行有符号的积分运算(仅对多项式有效),其它的式子使用内带函数进行数值运算。后续RPL机型进一步发展了这方面的机能,更多的表达式可以进行符号积分运算。

RPL程序语言

为RPL计算器编写程序需要另一种不同的思路。在早期的计算器中,程序是被单独存放的,并遵循自己的一套规律,而RPL计算器中的程序只不过是由'< <'和'>>'作为开始和结尾的一个对象。需要输入程序的话,用户只需要按下'< <',并输入一系列指令,然后按下回车,按下'EVAL'来执行即可(进行这个操作的同时会把程序本身和任何它在操作中涉及的栈内数据从栈上“消耗”掉,不过有办法恢复(比如通过UNDO))
程序也可以像其他对象那样被保存在变量中,如果现在栈1上有一个程序,那么输入“ 'PROG1 STO”来保存,然后再输入“PROG1”就会执行这个程序,或者在VAR菜单里找到它,按下对应的快捷键也能运行。想要回调这个程序只需输入“ 'PROG1 RCL”,这时用户就可以通过'EDIT'键来修改它,或者用户也可以像修改其他变量那样通过“ 'PROG1 VISIT”来访问它
RPL程序可以使用变量(局部和全局都可以)来让程序更有可读性,当然,这里的变量是可以存储任何对象的,比如数组、表达式等等..,并非仅提供“skip”这样的指令,RPL支持完整的一套现代程序控制语句包括 IF/THEN/ELSE, FOR/NEXT, DO/UNTIL, WHILE/REPEAT,它也有错误处理。DISP指令可以让数据被显示在多行屏幕的任意一行上。

RPL的例子

下面这个程序计算1~10的平方和

下面这个修改版会从栈中读取数的范围
这个程序中使用了局部变量(此程序中命名为fst和lst),这些变量只有在定义它们的那段程序中可见。习惯上用小写字母表示局部变量(被FOR函数定义的那个变量也是局部变量)

将这个程序输入之后,可以通过“ 'SSQS STO”将其保存到“SSQS”这个变量中,将开始和结束值输入到栈中,再输入'SSQS'就可以运行了,或者用户也可以在USER菜单中找到它并执行。
下面这个修改版可以自动确认两个边界的顺序

这里是一个更加“后缀”的写法,比较操作会返回0或1,结果保存在栈上,中间输入如果真时要执行的操作(此时判断的结果移至栈2)然后使用IFT操作确认——如果栈2的内容为真,就执行栈1对应的内容

改进

HP-28S在上述基础上加入了目录和自定义菜单这两个功能。HP-48和HP-49在这个基础上继续得到发展。

Leave a Reply

Your email address will not be published. Required fields are marked *