Comments - 10
phimvt@lurac.latrobe.edu.au — 2000-08-10 02:59:55
Hi folks - I seem to be getting there, albeit slowly. Manfred
1. "function quotation or voracious evaluations"
Stevan Apter (26-JUN-2000) wrote of voracious evaluation.
I had been thinking about that some time ago. But I dropped it because
I could not think of any good use for it. The idea is that programs
write programs that write programs ... until there isn't anything left
to execute them.
One simple version:
[..some-program..] i i i ... i until it is pointless
Another version (using the stack instead of the top quotation):
start with empty stack, execute a program that leaves a stack
WHILE the stack is a program DO
(perhaps reverse the stack and then)
execute the stack
Example of the second version:
[+] first 3 2
leaves a stack with + at bottom, then 3, then 2 on top.
this is the same as the quotation [2 3 +]
it can be executed again to finally give 5
No doubt such a repeated executor can be written in Joy.
But I still cannot think of any real uses of that sort of thing,
apart from the (one-step) constructed programs that Joy uses a lot.
Can anyone think of real uses of two-step constructed programs?
Any ideas in general?
2. "generalised stack operations"
Stevan also introduced some neat generalisations of the
stack operators. For example "ndup" expects a number n and below
that at least n further items. It then duplicates the n-th item.
Then he defines dup == 1 dup. He suggests the generalisations
as new primitives.
I think we need to be clear on several notions here. One is
the view that the (short and lean) list of primitives is a logical
minmimum, from which the rest can be built. Another is that the
primitives are a good psychological base from which to define
the rest. A third is that the primitives are implemented directly,
and that everything else is in a library. [Compare all this with
the operations in Boolean algebra, and a good collection of
primitives in the three senses.]
Any thought on this?
3. "Three more proposals about Joy"
This started off with 3 proposals by Brent Kirby, and there was
a lot of interesting discussion about each of them and some others.
(1) 'Feel free to pile onto the stack'. I think this idea must
have its source in (what I take to be) an APL idea:
1 2 3 + 4 5 6
==> 5 7 9
It works well with infix notation for binary operators, but with postfix
there is a problem. How is one to compute one list, compute another list
and then concatenate them, for example? Or, taking the example above,
how is one to distinguish the first array 1 2 3 from the second 4 5 6 ?
I cannot see a way out.
(2) 'Eliminate inspection of quotations'. There are two reasons
why one might want to _forbid_ it: (a) the processor has optimised the
code in the quotation, so that it is no longer what the programmer
wrote. But in that case the processor will just have to leave two
versions available - one for inspection, the other for (fast) execution.
(b) quotation is opaque: even though e.g. dup + == 2 *,
[dup +] =/= [2 *], as may be seen by taking firsts or seconds on
both sides. This objection could be handled by distinquishing
function-body-quotations from list-quotations - e.g. by different
parentheses. To preserve "constructed programs", they can be build up
but not inspected. I am not sure whether all this is worth the trouble.
(3) Stevan prososed what I think of as a shuffle pattern -
a general device for rearranging the top few elements of the stack
in a way that is nice, visible, and immmediately intelligible.
(4) Louis Madon pointed out that in my prototype the program
1 [pop] nullary
produces a coredump. It should produce an error instead. I think I
know how to fix it - when I have time. Also, the Joy combinator
"while" is unfortunately called "whiledo" in several of the papers.
I like "whiledo" better since it suggests the two program parameters
that are required. So I'll add "whiledo" as a duplicate, change
the libraries, but continue to allow "while" as an alternative
that is to be eliminated in the long run.
(5) 'lambda' - I am not at all sure of this, but I got the
distinct impression that what was described was not lambda abstraction
(which introduce named formal parameters as in the lambda calculus),
but local definitions of function symbols (concatenative, i.e.
parameterless). Please correct me.
(6) 'string comparison' (this was for conk). I would have
thought that an obvious way to compare "abc" with "defgh" is to
padd the shorter with nulls: "abc.." < "abcd." < "abcde" < "defgh",
where the period indicated the null, chr(0) or ASCII 0. That
should be easy to implement, and it makes some sense. Then
max and min and so on become sensible automatically. This is how
it is done by C's strcmp( , ). That is a general purpose function
from which several comparison functions (and hence also max and min)
can be defined. Or did I miss something in the discussion?
There is another chain of reasoning, though. Strings are just
sequences of characters (_implemented_ in whatever way: as the content
of sequences of memory locations, i.e. as arrays, OR as linked lists).
Vectors in general are much the same, except that the contents do not
have to be characters, they can be other numbers or anything.
If it is a good idea to pad strings with nulls for comparisons,
then perhaps it is also a good idea to pad vectors of say numbers
with the appropriate unit element of binary operations, say 0 for
addition, 1 for multiplication. For example, to add the two vectors
(1 2) and (3 4 5) which are of unequal length, we think of adding
a trailing 0 to the first, to give (1 2 0). Then (1 2)+ (3 4 5) =
(4 6 5). Call this the "naive consistency requirement". Is it a good
idea?
One might argue that it eliminates many (compile- or run-time)
errors that could be annoying when developing programs. On the other
hand one might argue that an explicit error message, preferably at
compile-time, but at least at run-time, is better than a running
program that produces strange results. My preference is normally
for strong typing (yes, I know, I know, what about Joy ...).
I do not know what Forth and APL/J/K do with the example. But
it is a consideration relevant to the popular view that strings
are just vectors of numbers.
[Rather incidentally, Joy uses strcmp( , ), and hence pretends
null padding. Hence you can sort lists of strings of different lengths:
["Cassandra" "Di" "Bob" "Anastasia"] qsort ==
["Anastasia" "Bob" "Cassandra" "Di"]
as expected. On the other hand, zip does not do any padding because
there is no appopriate unit element, so zip produces a list of pairs
no longer than the shorter of the two parameter lists. It might be
worth going through Joy with a fine comb in search of cases where
there are suitable unit elements.]
4. "The Josephus problem" - I read it and was impressed by the
code given. But I cannot really comment on it.
Well - this catching up took a long time
Manfred
P.S. Zeno has been at it again - more concatenative mail on
"Another implementation of Joy" - I'll study that, but now now.