(06-25-2021 10:51 AM)Giuseppe Donnini Wrote: [ -> ]This interpretation is solely based on the internal dispatch mechanism, which you described very well, but there remains the fact that IFT and IFTE are the only (!) commands on the HP-48 (besides EVAL itself) that treat lists as procedures, and that is significant enough.
Wouldn't this singularity alone be sufficient to say that lists are not to be used in place of programs?
Quote:Furthermore, IFT and IFTE are obviously designed to use stack arguments.
So my point is that, in the absence of any specific context, the standard approach should respect these two premises: it should not preclude the occasional use of lists as programs, and it should put the actual arguments on the stack, not their labels — because identifier objects do not distinguish between execution and evaluation. Hence my recommendation to use 'CALC' RCL.
I do agree that the actual arguments onto the stack (as opposed to references by variable names) is the least ambiguous method in light of the special behavior of list handling.
Quote:I never raised any speed argument.
My apologies; that wasn't meant to be directed at you but someone did mention speed differences and I should have been more careful to separate my repsonse.
Quote:A user program may add a lot more than just the \<< and \>> delimiters, which results in a number of subtle, but significant, differences at the User RPL level between the execution of a program and the evaluation of a list, that is, its execution as a program. (This is, by the way, one of the major reasons why there is no \->PRG / PRG\-> pair of commands for building and taking apart compiled program objects, as I mentioned earlier.)
** examples removed for the sake of brevity ***
Programs and lists are not executed differently at all by IFT (or more precisely, by the internal COMPEVAL command). Both object types are handled by the assembly command DOCOL. Therefore, they CANNOT behave differently... unless they are actually different. Seems silly of a statement, but allow me to explain.
The reason for the difference in the behavior is not how they are executed, but actually how they are
compiled. When one creates a list, such as in your example { 'A' }, the command line compiles it as { A }. Therefore, the program << A >> and the list { A } are executed the same way. On the other hand, entering the program << 'A' >> and the list { 'A' } result in two differently compiled objects. For << 'A' >>, the command line compiles the delimiters around the A into a pair of quote commands whereas the command line compiles { 'A' } into a container with a single element (a variable, but unquoted). It may seem like I'm nitpicking, but I do want to emphasize here that the behavior of the evaluation is exactly the same, provided that they are in fact the same. Your examples, on the other hand, are examples of how two similar objects (program vs list) are not parsed and compiled the same way by the command line even though they are typed in the exact same manner, excluding the containing delimiters << >> and { }. Thus the behavior is different because they are not actually compiled as the same sequence of objects, not because one is a program and the other is a list containing seemingly the same "things" inside (because they do not).
Said differently, on the SysRPL level, a program << 'A' >> would look like:
Code:
::
x<<
x'
ID A
xENDTIC
x>>
;
whereas a list typed as { 'A' } (but compiled as { A }) would look like:
in SysRPL code. On the other hand
Code:
{
x'
ID A
xENDTIC
}
would appear on the stack as { 'A' } and evaluate exactly as << 'A' >>. If it were feasible to create a list that contains the exact same contents of a program (as compiled by the command line), then they would behave the same way (excluding possibly your point #3, depending on whether you want to include the << and >> commands in your list, as they provide ON/HALT traps). However, it is actually not possible to create the last list without special tools. Thus, the idea that lists can be used as a program turns into an exercise of careful tip-toeing around the differences in how lists and programs are
compiled, and not how they are EVAL'd (via the user command EVAL).
EDIT: The same applies to your example #1 -- there is an invisible command xSILENT' that is not present in the list { 1 2 << 3 4 >> }
EDIT #2: Also, in the context of discussing IFT and EVAL (user commands), there is no difference between executing and evaluating. IFT calls EVAL, and EVAL eventually passes control over to DOCOL for lists, which is also the exact same behavior for programs (DOCOL is also used). As for the reason we do not have ->PRG and PRG->, it again has to do with how lists and programs are compiled. Lists get compiled without ever inserting "invisible" or even "similar-looking" objects like programs do (and programs do this by necessity). Thus, OBJ-> and ->LIST exist as commands because there are never instances of creating an invalid list from objects obtained by the OBJ-> commands. This is not true for programs. If one were able to "explode" a user program made from the ordinary command line, one could then put it back together in a manner that would cause the calculator to crash. This can never happen with lists created from a user-made list using only the ordinary command line.