Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

HP Function Design Critique

17 views
Skip to first unread message

John H Meyers

unread,
May 24, 1996, 3:00:00 AM5/24/96
to

I gingerly approach a topic about which I've kept quiet for over two years.

I haven't been "on the Net" that long, but I have looked both through
newsgroup archive indexes and various "bug" lists, and I just haven't
been able to spot any previous reference. It is hard to imagine it
escaping debate over all three years during which HP48G/GX's
have existed, but just in case, here goes:

Preface/disclaimer: I do think that HP is the world's best maker of
everything it makes, as folks who have heard me may have gathered;
all the same, if there's an occasional little oversight, shouldn't
your best friend tell you (as the TV ads once asked)?

Since the HP48 is a stack-oriented calculator, it is important for
the programmer to always know what is on the stack! It therefore
behooves every command either to leave a known number of objects
on the stack, or else to somehow indicate exactly how many objects
it has left on the stack, doesn't it?

Most commands operate on and/or return a fixed number of objects;
this obviously presents no problem.

Commands like LIST\-> , which return a variable number of objects,
return a count as one of the results, allowing the exact number of
other objects previously pushed to be known with certainty.

Commands like KEY and CHOOSE, which may or may not have any object
to return, also return a T/F indicator to reveal whether they did
or didn't push another object onto the stack.

Now, what if I were to tell you that I had just invented several new
HP48 commands which sometimes did and sometimes did not push a result
onto the stack, but never bothered to tell you whether they did or didn't?

Would you say that I had thereby made a slight design error, or that
I was awfully inconsiderate to create such a programming monstrosity?

Well, would you believe it, three of the commands introduced with the
HP48G/GX are of exactly that nature? (at least as of Rev "M")

Sure enough, and their names are: DOLIST, DOSUBS, and SEQ.

To illustrate:

Let's say I want to make a list of all the objects in HOME which are
directory objects. Here's one way I can do this:

\<< HOME 15 TVARS \>>

The TVARS command makes a list, containing all variable names in the
current directory whose VTYPE (type of object stored) is the given type
number (in this case, type 15, which means a directory). If no objects
are of this type, then TVARS returns an empty list, as it should.

Now, what would I do if there were no TVARS command?
Here's something which ought to do the job just as well:

\<< HOME VARS 1 \<< IF DUP VTYPE 15 \=/ THEN DROP END \>> DOLIST \>>

If there are any directories at all in HOME, this produces exactly the
same result as with TVARS, viz. a list, containing names of directories.

But what if NO variables happen to be directories? Is the result an empty
list, as it should be, just as in the case of TVARS? No, my friends, it
is not. If there happen to be no directories, what this program returns
instead is ... NOTHING! (not an empty list, but nothing returned at all).

Tell me, then, how am I supposed to be able to guess whether DOLIST has or
has not decided to return an answer? Is there a: flag? count? T/F ?

Someone might say: oh well, you could detect this by comparing the stack
depths before and after the command, then you could see when no result
was returned. Well, you could just as well compare the stack depths
before and after executing LIST\-> to see how many objects were pushed
onto the stack, so would it have been rational to omit the count
returned by LIST\-> because there exists a contorted and difficult way
to find out the count even if the command didn't give it to you?
Any other suggested work-around is also subject to the same objection.

Possibly in consequence of this first boo-boo, a second distressing anomaly
of DOLIST is that it won't accept as an argument a list that is empty
to begin with. Hey, if I can SORT and REVLIST an empty list, what's
wrong with DOLIST accepting it? Only this: the first boo-boo would
require that no answer be returned; so now we have a double boo-boo!

Okay, here's another rationalization of why DOLIST returns no answer
when all candidates for returned list elements have been eliminated:
some people just want to do the same thing to each and every name
or object in a list, and then want to forget about it; having DOLIST
automatically drop the result list, when empty, saves that programmer
all the work of having to say DROP to get rid of an empty useless result
list! (So who is saving me from having to say MEM DROP to force GC,
or SWAP DROP to get rid of the level 2 object, etc?) However, that
"saving" creates an unpredictability that requires all programmers
handling variable-size lists or doing conditional processing in DOLIST
to now have to go through contortions to trap the anomalous lack of
a result after DOLIST, and also to test and skip around DOLIST in the
first place if the input list happens to be empty.

After writing my first 20 programs which had to do these two things every
time they used DOLIST, I decided instead to just write myself a program
named DOLST which corrects the nasty anomalies of DOLIST, much as NASA put
"corrective specs" in front of the Hubble telescope to fix its distortion.
Thus, DOLST now both accepts an empty list (or lists) and always returns
a result, even if empty, making all my other programs simpler and
contortion-free, at last.

As reported above, DOSUBS and SEQ perform similarly to DOLIST.

Naturally, I have my own DOSBS program as well, to correct DOSUBS,
just as I have DOLST to correct DOLIST;
as for SEQ, I just don't happen to use it.

Even if all the world agreed with my above sentiments, it would be much
too late to "correct" these functions in HP48's, since by now innumerable
programs already have come to depend on *not* having to DROP any result.

Finally, many people are saying "what do you mean, I use DOLIST, but
I have never seen this problem, what are you talking about?" -- that's
because you have not been doing any conditional processing or producing
variable-size result lists; you are either *always* getting a result
or *never* getting a result, so you never have had to deal with both
possibilities in the same program.

So what do you think of this? (HP design team members are welcome to
chime in here!). If you want to send me E-mail and have me summarize,
I'll be glad to do it.

-----------------------------------------------------------
With best wishes from: John H Meyers ( jhme...@mum.edu )

Mark Wilson

unread,
May 24, 1996, 3:00:00 AM5/24/96
to

John H Meyers wrote:

> Now, what if I were to tell you that I had just invented several new
> HP48 commands which sometimes did and sometimes did not push a result
> onto the stack, but never bothered to tell you whether they did or didn't?

> Sure enough, and their names are: DOLIST, DOSUBS, and SEQ.
>
> To illustrate:
>

> \<< HOME VARS 1 \<< IF DUP VTYPE 15 \=/ THEN DROP END \>> DOLIST \>>


>
> If there are any directories at all in HOME, this produces exactly the
> same result as with TVARS, viz. a list, containing names of directories.
>
> But what if NO variables happen to be directories? Is the result an empty
> list, as it should be, just as in the case of TVARS? No, my friends, it
> is not. If there happen to be no directories, what this program returns
> instead is ... NOTHING! (not an empty list, but nothing returned at all).

In the Advanced User's Reference Manual, under the description for
DOLIST, it states that for the nth iteration DOLIST leaves the results of
whatever operation it performs on the nth list item on the stack. "After
the final iteration, any new results are combined into a single list"
(AUR, pg 3-91).

Now, if I put this on the stack:
3:{ 1 1 1 1 1 }
2: 1
1: << 1 - >>

and execute DOLIST, I get {0 0 0 0 0}--a list of new results. Your
example above leaves nothing new on the stack (for non-directories). You
take the nth list item, DUP it, then test it. If it isn't a directory,
it is dropped. So when all is said and done, the stack is empty, and
there is no item count with which to construct a list of "new" results.
I would assume that DOLIST implements some form of ->LIST, and checks to
see whats on the stack (hence the caveot "new" results) before the list
construction. If nothing is there, it simply doesn't do anything, as
advertised.

>
> Tell me, then, how am I supposed to be able to guess whether DOLIST has or
> has not decided to return an answer?

Based upon "new" results. A dolist program can be syntaxially correct
and still produce absolutely nothing.


> Possibly in consequence of this first boo-boo, a second distressing anomaly

Sorry, but it really is a documented feature!

> of DOLIST is that it won't accept as an argument a list that is empty
> to begin with. Hey, if I can SORT and REVLIST an empty list, what's
> wrong with DOLIST accepting it? Only this: the first boo-boo would
> require that no answer be returned; so now we have a double boo-boo!

Not having dissassembled DOLIST yet, I think its name may answer that.
If DOLIST implements the SYSRPL DO command, it requires at least one
argument to run through. Unlike a FOR LOOP, which if given:

1
10

as input would run 10 times, the DO command stops when the counter
reaches its maximum, before the tenth iteration. So, 10 1 DO in SYSRPL
would execute nine times; 1 10 FOR would execute 10 times.

Price of tea in China? Glad you asked!

If you take apart an empty list in SYSRPL or USER, you get 0 for the
object count. If DOLIST has a built in zero for its starting counter,
then it is stopped before it can start.

Try this:

<< 0 0 FOR i 1 NEXT >>

Even though the start and stop are the same, it still runs through once.
DO, in SYSRPL, would not execute at all for the same counters. That is
the best guess I have.

This would also explain why REVLIST works and SORT works. As I
understand it, they are both terribly inefficient routines that
dissassemble a list than do some magic, and put it back together. You
can create an empty list; with a zero on the stack, hit ->LIST. You can
also decompose an empty list, which returns a zero to the stack. You
just can't "DO" anything with it;)


(So who is saving me from having to say MEM DROP to force GC,
> or SWAP DROP to get rid of the level 2 object, etc?) However, that
> "saving" creates an unpredictability that requires all programmers
> handling variable-size lists or doing conditional processing in DOLIST
> to now have to go through contortions to trap the anomalous lack of
> a result after DOLIST, and also to test and skip around DOLIST in the
> first place if the input list happens to be empty.

Again, this is fully documented in the AUR, and is to be expected.
Granted, the one time you actually don't generate a list in DOLIST will
be the time you dig that nugget out of the AUR, but it is there:)

>
> After writing my first 20 programs which had to do these two things every
> time they used DOLIST, I decided instead to just write myself a program
> named DOLST which corrects the nasty anomalies of DOLIST,

You could also do a simple IF THEN ELSE after DOLIST; if no list on the
stack after DOLIST, pop an empty one up.

> Thus, DOLST now both accepts an empty list (or lists) and always returns
> a result, even if empty, making all my other programs simpler and
> contortion-free, at last.
>
> As reported above, DOSUBS and SEQ perform similarly to DOLIST.

I would assume for the same reason

> as for SEQ, I just don't happen to use it.

I really have tried to figure out some use for SEQ. I have also tried to
use "Dinosaur" in a personal perfomance report. Im both cases, I have
failed...:)


> Even if all the world agreed with my above sentiments, it would be much
> too late to "correct" these functions in HP48's, since by now innumerable
> programs already have come to depend on *not* having to DROP any result.
>
> Finally, many people are saying "what do you mean, I use DOLIST, but
> I have never seen this problem, what are you talking about?" -- that's
> because you have not been doing any conditional processing or producing
> variable-size result lists; you are either *always* getting a result
> or *never* getting a result, so you never have had to deal with both
> possibilities in the same program.

Again, I would try a IF THEN ELSE test after DOLIST, unless your
DOLST subroutine is faster already.

>
> So what do you think of this? (HP design team members are welcome to
> chime in here!). If you want to send me E-mail and have me summarize,
> I'll be glad to do it.
>
> -----------------------------------------------------------
> With best wishes from: John H Meyers ( jhme...@mum.edu )

Hope this clarifies,

--
Mark Wilson

"El Diablo sabe mas por viejo que por Diablo."

Andrew Jacob Brault

unread,
May 25, 1996, 3:00:00 AM5/25/96
to


[...]


>Now, what if I were to tell you that I had just invented several new
>HP48 commands which sometimes did and sometimes did not push a result
>onto the stack, but never bothered to tell you whether they did or didn't?

[..good discussion of DOLIST et al clipped..]

I agree with everything you said and I agree this can be seen as a
design flaw in the 3 discussed commands. However here are a few
reasons that may shed some light on the "rationale" behind these
commands:

1. DOLIST, DOSUBS, and SEQ only work on the G/GX series. Programs
that use them will not work on the S/SX.

2. The commands in question seem to be strongly oriented to
interactive use (as opposed to embedding them in a program).
When used interactively, the stack properties of commands do
not make nearly as much difference as they do when used inside
a program.

3. Their obviously inefficient implementation (along with reason 1)
indicates that HP did not spend a lot of time or effort on these
commands and just needed a quick hack so they could say their
calculator had "list processing" capabilities.

4. Like you said, if you are intent on using these commands in a
program, you can always do a DEPTH before and after and compare
results.

--

---
Andrew Brault (a...@wpi.edu)

John H Meyers

unread,
May 27, 1996, 3:00:00 AM5/27/96
to

I previously suggested that DOLIST, DOSUBS, and SEQ should have been
implemented to always return a result list, even if it turned out to
be an empty list.

This would have avoided creating the only HP48G/GX commands which
may or may not produce a result, but which give no indication of
whether they did or didn't do so -- a violation of a basic design
principle, a problem making difficult what would have been simple
whenever you need to do any conditional list processing, and thus
a slight blip in HP's otherwise luminous history of designing
the most perfect function imaginable for every task.

Mark Wilson and Andrew Jacob Brault have responded.

Mark Wilson said:

> In the Advanced User's Reference Manual, under the description for

> DOLIST, it states that...


> "After the final iteration, any new results are combined into a single list"

> ...


> Sorry, but it really is a documented feature!

I well know the AUR, where none of the stack diagrams shows "(no result)"
as the result, and where the quoted sentence is anything but clear;
however, what AUR says is just a "red herring" to the real issue:

AUR just announces what the implementor decided to implement;
it doesn't make the implementor's original choice a good one.

As a historical note: My HP34C came with a paper slipped into the manual
which said that whenever the limits of (numeric) integration were equal,
the HP34C would exit immediately, but with a meaningless, non-zero result;
it even gave suggestions for how to adjust for this in any user programs.
Needless to say, this "feature" was soon replaced with a ROM revision!

Suppose the HP48 manual had said that whenever you attempt to divide by zero,
a meaningless result (and no error trap) would occur; would you say that
printing this statement made a programmer's decision to ignore division
by zero, rather than detect it, a good decision? A new "feature"?

If Ford printed in their owner's manuals "Your ignition switch might
occasionally catch fire," would that turn this fault into a "feature"?

And what does this "feature" do for you? It (accidentally) saves
some programs a single DROP command, while costing many others a
substantial pain; commercial programmers can afford the time to do
work-arounds in their products, and even earn their commissions by
navigating these difficult waters, but for the individual user who is
the target audience for the product (according to HP), every little quick
program which would have been really simple is turned into a greater chore.

This is exactly the opposite of what we all want, both HP and us, so
why don't we all agree, instead of looking for rationalizations?

... and then avoid repeating this in the future!

> Not having dissassembled DOLIST yet, I think its name may answer that.
> If DOLIST implements the SYSRPL DO command, it requires at least one

> argument to run through... [as with a FOR loop]

You mean to say, that an HP internals programmer could not put in a test
to skip around some code when it should not be executed at all,
in order to make a built-in function do what it should?

Perhaps this explains why, in rev A, "KGET on a zero length file from
another machine will cause the calculator memory to be cleared"!
Would this have become a "feature" instead of a "bug" if it had been
printed in AUR instead of fixed?

I have been able to skip around a FOR loop when it should be
executed zero times, so come on, admit that HP could manage to do this
for an internal function when it is the correct thing to do. They could
do it once, and everyone else could then write simpler programs; isn't
that what everything in this calculator was developed for, and
the very thing which has made HP products superior?

> You could also do a simple IF THEN ELSE after DOLIST; if no list on the
> stack after DOLIST, pop an empty one up.

Not if there is *nothing* on the stack, and not if any previous object
which just happened to be on the stack was *also* a list! I devised a
contorted way to stick a useless real number behind my list(s) before doing
DOLIST and to adjust after DOLIST, somewhat as you have suggested above,
but my basic point is that one minor internal design correction
(to always return the result after list processing, even if it were an
empty list) would have eliminated the need for every user to have to go
through all this extra unnecessary work to make up for a design slip-up.

Had the original functionality been right, no "work-arounds" would ever
have been necessary, and we would not have needed to propose any now.

Andrew Jacob Brault responded:

> DOLIST, DOSUBS, and SEQ only work on the G/GX series. Programs
> that use them will not work on the S/SX.

Yes, since the commands exist only in the G/GX, that's where the
design flaw is. S/SX owners may not be interested (curiously, "LISP"
on Goodies Disk #2 is the only "DOLIST-like" program I've encountered
for the S/SX, and it's not very general, in that it allows only one
input list, seems to require exactly one result for every original
object, and isn't intended to allow an empty input list. Did no
one write a full DOLIST equivalent for S/SX? It's fairly easy!)

> The commands in question seem to be strongly oriented to

> interactive use (as opposed to embedding them in a program),
> [ so the stack anomaly may not matter ].

I think they are extremely commonly used in programs (even in HP examples),
and that all functions should certainly be capable of easy use in programs.

> Their obviously inefficient implementation (along with reason 1)
> indicates that HP did not spend a lot of time or effort on these
> commands and just needed a quick hack so they could say their
> calculator had "list processing" capabilities.

Ouch! I think the list-processing extensions were a great addition,
and I believe that they were carefully implemented, but for that one
oversight I harp on here; DOLIST was generalized to N lists (somebody
uses that, don't they?), and DOSUBS is an ingenious functional addition,
something that would make one say "now why didn't I think of that?"

What makes "higher" functions of the HP48 "inefficient" is the same thing
that made it possible to develop HP48s at all and get them to market: the
functions are written in System RPL, rather than Machine Code.

Three years later (or six years, counting the S/SX), some ML code has
been written which could replace some SRPL (some of it even authored and
made available by HP's William Wickes). If another version or generation
is to come, it might use that code, if it originated with HP or has been
licensed by HP. The amount of ML development, processor speed, time and
cost are all tradeoffs; who knows what we'd have done if we were inside HP?

> As you said, if you are intent on using these commands in a program,


> you can always do a DEPTH before and after and compare results.

No, you should not have to; neither HP nor its users have ever wanted
functional design and use to be cumbersome, and you should not be
needing to write work-arounds for functions which do not behave well.

Most of HP's innovations in all its product lines have been ingenious and
simplifying, well thought out, the best engineering and design. I think
this was just a slight oversight, and I mentioned it so that it might be
fixed if possible, avoided in the future, and so that users could save
repeated efforts in individual programs by using a "once and for all" fix.

Mark Wilson

unread,
May 27, 1996, 3:00:00 AM5/27/96
to

John H Meyers wrote:
>
> I previously suggested that DOLIST, DOSUBS, and SEQ should have been
> implemented to always return a result list, even if it turned out to
> be an empty list.
>
> This would have avoided creating the only HP48G/GX commands which
> may or may not produce a result, but which give no indication of
> whether they did or didn't do so -- a violation of a basic design
> principle

Is this like the "Prime Directive", or Asimov's 3 "Laws of Robotics"?;)
Also, a result on the stack or not is pretty clear indication of what
happened.

> Mark Wilson and Andrew Jacob Brault have responded.
>
> Mark Wilson said:
>
> > In the Advanced User's Reference Manual, under the description for
> > DOLIST, it states that...
> > "After the final iteration, any new results are combined into a single list"
> > ...
> > Sorry, but it really is a documented feature!
>
> I well know the AUR, where none of the stack diagrams shows "(no result)"
> as the result, and where the quoted sentence is anything but clear;
> however, what AUR says is just a "red herring" to the real issue:
>
> AUR just announces what the implementor decided to implement;
> it doesn't make the implementor's original choice a good one.
>
>

> Suppose the HP48 manual had said that whenever you attempt to divide by zero,
> a meaningless result (and no error trap) would occur; would you say that
> printing this statement made a programmer's decision to ignore division
> by zero, rather than detect it, a good decision? A new "feature"?
>
> If Ford printed in their owner's manuals "Your ignition switch might
> occasionally catch fire," would that turn this fault into a "feature"?

I think you are blowing this a tad out of proportion. If HP had a little
note in the manual stating "if no list is produced by DOLIST, your
calculator may burst into flames" then maybe it would justify a bigger
response.

The simple fact is, like it or no, that the AUR very clearly spells out
what will happen when no new data is produced by DOLIST: no list is
returned. If HP hadn't bothered to mention this result, then maybe you
could argue it as a bug. Obviously, the HP programmers were very aware
of this, and had decided to keep things as they are as early a my edition
2, Jan 1994 AUR. That they haven't gone and released a bug notice or ROM
revision (similar to your HP-34C "bug" that actually was corrected)
doesn't imply it is great, it merely implies that it is. Besides, some
programmers may actually use that feauture as intended (I have in a
simple budget program). It is very easy a number of years down the road
to second guess the "nincompoop" who for some inscrutable reason did
whatever. Since, as you suggest, popping a null list on the stack is
simple for HP to do, then it is fair to assume that they implemented that
functionality for a reason. That they also point out the possibility of
no list returned by DOLIST implies they where aware of the consequences
of their design choice. Bugs by definition are unexpected or incorrect
results. This is neither.

>
> And what does this "feature" do for you? It (accidentally) saves ^^^^^^^^^^^^
See above; how can it be accidental when its clearly documented? Why
do you ignore the fact that it is clrearly documented, page 3-91 of
the AUR. Now, if Ford put a little note in the owner's manual about the
vehicle spontaneously combusting, that wouldn't excuse it. But the
implementation of DOLIST is not inherently good or evil; it simply is.
The astute programmer must be aware of its possible outcomes (clearly,
not accidentally, documented) and then figure out how to implement them.

You wouldn't randomly fire a handgun in any direction; you never know
what it will hit. Similarly, you wouldn't implement a piece of code
without knowing what it will or won't do all the time. The results are
far less dangerous, but as the programmer you must know what your program
will do. HP has told you exactly what it will do. What exactly is the
problem? DOLIST is not random; it is entirely predictable.

> some programs a single DROP command, while costing many others a
> substantial pain; commercial programmers can afford the time to do
> work-arounds in their products, and even earn their commissions by
> navigating these difficult waters, but for the individual user who is
> the target audience for the product (according to HP), every little quick
> program which would have been really simple is turned into a greater chore.

Even without the AUR, the user friendly debugging environment of the HP
shouldn't make this too bad. If I have a problem with a FOR LOOP that
normally goes to 100, I wouldn't step through the whole thing! After
two, three max, iterations whatever the problem is would appear. Now,
keep in mind, that's without the AUR. With the AUR, and a proper
understanding of DOLIST (or any function), whats the problem? You, as
the programmer, know what will happen if DOLIST has no new results: no
list. Very simple.

>
> This is exactly the opposite of what we all want, both HP and us, so
> why don't we all agree, instead of looking for rationalizations?

Ahem. speak for yourself. Vague generalities are neither fact nor true.
I could as easily say "quit your whining, you missed how to use DOLIST,
and deal with it". So far, I have refrained from emotional apeals or
outbursts. Please keep this discussion based in FACT.

>
> ... and then avoid repeating this in the future!
>
> > Not having dissassembled DOLIST yet, I think its name may answer that.
> > If DOLIST implements the SYSRPL DO command, it requires at least one
> > argument to run through... [as with a FOR loop]
>
> You mean to say, that an HP internals programmer could not put in a test
> to skip around some code when it should not be executed at all,
> in order to make a built-in function do what it should?

O.k., your dancing into the realm of opinion here (again). Why "should"
DOLIST do as you want? What basis in natural laws or physical constants
(i.e. Facts) do you have to support this? As I said before, HP could
have implemented DOLIST as you suggest. Instead, they consciously chose
the current implementation. Obviously DOLIST does some argument checking
if it returns an error on a null list. But, as I also postulated
earlier, a null list has no object count and can't be used to control a
DO list( FORLIST might work better;). Inputting a null list to DOLIST
is a completely different problem than DOLIST not returning a list; the
null list argument will kill DOLIST before it even has a chance to
operate; the "no list returned" result is a product of DOLIST after it
has run. Your car won't work? Is it stuck in the mud, or out of gas?
Two entirely seperate issues (or did the ignition switch explode? A third
seperate issue!)


>
> Perhaps this explains why, in rev A, "KGET on a zero length file from
> another machine will cause the calculator memory to be cleared"!
> Would this have become a "feature" instead of a "bug" if it had been
> printed in AUR instead of fixed?
>

Spurious argument, DOLIST causes no memory loss or ignition switch
explosions. It provides documented, predictable results. It is your
responsibility to implement it correctly. The beauty of HP's is that
when you don't like a command, its a piece of cake to work around it.



> I have been able to skip around a FOR loop when it should be
> executed zero times, so come on, admit that HP could manage to do this
> for an internal function when it is the correct thing to do. They could

Yes they could, but as I said above, the null input list error and the "
no list returned" output are seperate issues.

BTW, you can also infer a null list won't work from the AUR. DOLIST is
implemented l times, where l is the length of the list. A null list is 0
long, so DOLIST is implemented 0 times. If you put in some code that
isn't implemented, shouldn't that produce an error?

> do it once, and everyone else could then write simpler programs; isn't
> that what everything in this calculator was developed for, and
> the very thing which has made HP products superior?

Actually, I expect and demand my HP be capable of some hideously complex
stuff--that ability is what makes it superior. I like to think of it in
PC type terms; very few programs that are easy to use are very capable.
The HP-48 is about the easiest to use platform I've dealt with relative
to its power (to include Windoze based math software, DOS, OS/2 and LINUX
as platforms, and tossing in FORTRAN for functionality).

>
> > You could also do a simple IF THEN ELSE after DOLIST; if no list on the
> > stack after DOLIST, pop an empty one up.
>
> Not if there is *nothing* on the stack, and not if any previous object
> which just happened to be on the stack was *also* a list!

You seem like a very bright gentleman; I'm sure there is a way to
implement my above suggestion regardless of whats on (or not) the stack.
In every program I write, I know exactly what is on the stack, and when.
If I need an empty stack before execution, then I save or drop the
existing stack. At any point in a loop that is entirely based on stack
manipulation instead of local variables to execute a fairly complex
algebraic expression, I have to know where 'A" and 'B' are to PICK them
and add them together (assuming A and B aren't in level 1 & 2). I don't
see your problem as insurmountable. You must know what is on the stack
at all times in your program; use that information to accomplish your
logical testing. Why does the HP have error checking functions!?

>I devised a
> contorted way to stick a useless real number behind my list(s) before doing
> DOLIST and to adjust after DOLIST, somewhat as you have suggested above,
> but my basic point is that one minor internal design correction
> (to always return the result after list processing, even if it were an
> empty list) would have eliminated the need for every user to have to go
> through all this extra unnecessary work to make up for a design slip-up.
>
> Had the original functionality been right,

Why is it wrong? When given two possible outcomes (an empty list vs
nothing), why is one inherently better than the other? In the alternate
universe whre HP did as you asked, there is probably someone now
complaining about it!

> no "work-arounds" would ever
> have been necessary, and we would not have needed to propose any now.
>

> Andrew Jacob Brault responded:SNIP

(Concerning DOLIST, DOSUBS, etc)


> > Their obviously inefficient implementation (along with reason 1)
> > indicates that HP did not spend a lot of time or effort on these
> > commands and just needed a quick hack so they could say their
> > calculator had "list processing" capabilities.
>
> Ouch! I think the list-processing extensions were a great addition,
> and I believe that they were carefully implemented, but for that one
> oversight I harp on here;

Have to agree with Andrew here. I was a big fan of list processing and
parallel list procesing in USER RPL programs due to the ease of use.
That is, until I started dabbling in SYSRPL. The built in list
processing routines are written in SYSRPL, but even so, are ridiculuosly
slow compared to what can be written in SYSRPL. I won't speculate as to
why, but the argument checking overhead must be what kills them to a
crawl. I wrote a SYSRPL version of SUMLIST that is about five times
faster than the built in command. Of course, the new routine does
absolutely no argument checking....;)

Besides, if you really like list and parallel processing, check out
appendix G of the AUR. Under the heading "Commands that sometimes work
with parallel processing". Talk about commands with predictable results!
Here again are results not listed under the original command argument,
but are clearly documented. Caveout Emptor.

SNIP

> > As you said, if you are intent on using these commands in a program,
> > you can always do a DEPTH before and after and compare results.
>
> No, you should not have to; neither HP nor its users have ever wanted
> functional design and use to be cumbersome, and you should not be
> needing to write work-arounds for functions which do not behave well.

Then why do I have to press three buttons minimum to access library
commmands? Ease of use?

And again DOLIST behaves exactly as it is documented. Its results are
neither spurious nor random; they are entirely predictable. It is up to
you to implement it correctly.

>
> Most of HP's innovations in all its product lines have been ingenious and
> simplifying, well thought out, the best engineering and design. I think
> this was just a slight oversight,

A well documented and clearly stated "oversight"? Why do you refuse to
acknowledge that it is documented, implying HP was well aware of the
potential? You act as if this is something out of the blue, instead of
DIRECTLY OUT OF THE AUR, PAGE 3-91.

> and I mentioned it so that it might be
> fixed if possible, avoided in the future, and so that users could save
> repeated efforts in individual programs by using a "once and for all" fix.
>
> -----------------------------------------------------------
> With best wishes from: John H Meyers ( jhme...@mum.edu )

What this all boils down to is your particular personal preference. I
personally like the SYSRPL implementation of DO loops, where the counter
is finish start DO, instead of the USER start finish DO SYNTAX, which
always requires a SWAP if I already have the finish counter on the stack.
But HP implemented it one way for USER, one way for SYS. Big deal. I
adjust to the environment and commands I am using and press on. You
obviously have as well, but you don't like it. Noted.

John H Meyers

unread,
May 28, 1996, 3:00:00 AM5/28/96
to

In article <31AA06...@afit.af.mil>,
Mark Wilson <mwi...@afit.af.mil> wrote:

> John H Meyers wrote <...snip...>

Well, the Air Force ("El Diablo" ?) seems to be fighting mad! ;)

I should know better than to prolong this, but I'll try to keep it brief;
responders, please read once all the way through, check out the whole
perspective, and see whether there isn't a little agreement somewhere,
then commence firing if you must:

I'm starting with the most contentious thing, which I still maintain
is almost a non-issue, but it has some place in the whole perspective:

> [ AUR clearly spells out what DOLIST will do, page 3-91 ]

All of the following is based on my copy (Edition 1, July 1993):

Stack diagram: Every line shows -> { results }
NO line shows -> (e.g. nothing)

Similarly for DOSUBS (page 3-92) and SEQ (page 3-302).

Compare with page 3-90 (DOERR), where every stack diagram shows
... -> (e.g. nothing)

The only slight clue that any of the *three* functions might ever not
return anything at all is this single sentence, from DOLIST alone:

"After the final iteration, any new results are combined into a single list."

By the way, on page 3-93, it says "DOSUBS returns ... [an error] if the
level 1 argument is a user program that does not contain only one command
and does not have a [UDF] structure." Fortunately, the HP48 does not obey;
wording such as "If n is omitted, then ..." should have preceeded this text,
thus, the HP48 does the right thing, even though AUR got it wrong, as is
the case many, many other times throughout the entire AUR.

For the historical record, someone could ask Dan Coffin exactly what he
meant by the above, and whether the AUR was the specification for the HP48
or vice-versa; it might even be interesting to ask the HP developers
( privately, under non-disclosure ;) how they would do it if they had
a second chance, but we'll probably never find out. :)

Jim Donnelly's HP48 Handbook doesn't even hint at any such intention,
but we can say that this book was neither an official HP document nor
was it supposed to exhaustively explain the commands (but it did do a
better job at explaining what it covered than the internal publications).

What did William Wickes say in "Insights..." ? (my loss not to have it).

I've said elsewhere that I don't rely on manuals; they can't make the product
do what they say. I always ask the calculator what it actually does, since
the product is the final authority, and if the product does something that
could or should be better, then I may suggest adjusting it accordingly.

> Besides, some programmers may actually use that feature ... (I have ...)

That's why I said it is too late to correct it.

I use the "feature" myself (I have to: there is no result to DROP).

> The HP-48 is about the easiest to use platform I've dealt with relative

> to its power.

Yes, indeed. I whole-heartedly agree! That is why I love it and have
been "married" to it for 2.5 years (before that, it was other HP's),
and is why I want to see it (and whatever comes next) perfected.

> You seem like a very bright gentleman; I'm sure there is a way to
> implement my above suggestion regardless of whats on (or not) the stack.

Thanks for the compliment, and yes, the programs I posted elsewhere
(DOLST and DOSBS) constitute a fairly universal solution, using just about
what you suggested (I didn't say it was impossible, just that it was a
nuisance to have do over & over in every individual program).

> In every program I write, I know exactly what is on the stack, and when.

> ...


> At any point in a loop that is entirely based on stack
> manipulation instead of local variables to execute a fairly complex
> algebraic expression, I have to know where 'A" and 'B' are to PICK them

> and add them together (assuming A and B aren't in level 1 & 2)...
> You must know what is on the stack at all times in your program...

You said it! This perfectly summarizes why I suggested that no more commands
be created which leave you not knowing what is left on the stack afterwards.

I also said that the problem only surfaces when you do conditional
processing or use variable-length (possibly empty) lists, and that
everyone whose processing-object either *always* or *never* returns
results for each iteration might not have felt this to be an issue,
because they could predict which way it would go, but that it was a
pain in any programs where results could dynamically go either way.

> ... given two possible outcomes (an empty list vs nothing),


> why is one inherently better than the other?

As you said above, you must always be sure what is left on the stack.
To return one result sometimes, and no result other times, leaves you
in a pickle (there are probably more colorful Air Force expressions :)

Say, how'd you like VARS, TVARS, LIBS, RCLKEYS, TAIL, PUT, REPL, \->LIST ...
to all drop their result list if the list happened to be empty?
Wouldn't that make programming more fun?

Does anyone now have any kinder regards towards this perspective?

* Here come interesting comments:

> I was a big fan of list processing and parallel list procesing in USER RPL
> programs due to the ease of use. That is, until I started dabbling in SYSRPL.
> The built in list processing routines are written in SYSRPL, but even so,
> are ridiculuosly slow compared to what can be written in SYSRPL. I won't
> speculate as to why, but the argument checking overhead must be what kills
> them to a crawl. I wrote a SYSRPL version of SUMLIST that is about five
> times faster than the built in command. Of course, the new routine does
> absolutely no argument checking....;)

Yes, everyone agrees that many things can be speeded up; Dr. William Wickes
has contributed some things himself (e.g. XPURGE in GD#7), and I believe
Jim Donnelly created a toolkit full of fast ML routines.

If HP would only contract out some further development, I believe that you
(and many others) could do a lot for that old HP48 :)

BTW, here's a faster REVLIST in User RPL (good for HP48S/SX):

\<< LIST\-> \-> n \<< 0 n FOR i i ROLL NEXT n \->LIST \>> \>>

and even faster using some SysRPL functions:

:: INNERCOMP reversym {}N ; ( no arg checkin' )

Whoa! The above are dynamite when there's plenty of free memory, but
when memory gets low, a mysterious "crossover point" occurs, whereupon
REVLIST keeps on going, like the Energizer Bunny, while the above upstarts
slow down badly. I don't know REVLIST's secret, but you might pursue it,
and perhaps fix it up to be faster the rest of the time, as well.

<...remainder snipped...> [Thank Goodness!]

P.S. -- I'm not only a gentleman, but also a Scholar! :)

0 new messages