Joy State
Jack Waugh — 2001-05-30 19:36:20
I just encountered Joy and find it breathtakingly elegant. Kudos in
particular for synthesizing the concepts of list and program. Of
course, Lisp regards a list as the source code for a program, but the
unification seems to go deeper in Joy.
I wonder if Haskell programmers might enjoy Reverse Joy, the language
you get by keeping Joy's semantics but reversing the order of the
juxtaposition in the syntax for function composition.
One could also propose JOOy, or Joy 1 +, by extending Joy's primitive
data types to include an "object" type. A further extension would
give a functional meaning to all possible words, over the domain of
states where the stack has an "object" on top. Objects would contain
mappings of words to functions. Applying a word to a state would
mean popping the object from the top of the stack, looking up in the
object the function to which the word maps, and applying that
function to a state having the remaining stack (resulting from having
popped off the object) and with the rest of the state being the same
as the nonstack part of the original state. There would have to be
means of literally specifying and/or constructing an object. Hmm, it
would be necessary to decide what happens when a word occurs that has
a primitive nillary meaning -- should it get its primitive
interpretation, or should it be "sent" to any object on the stack?
Are there any nillary words in Joy besides the literals? The
interpretation of the literals should be obvious -- always the
primitive meaning. Anyway it's a moot question unless someone thinks
a JOOy would be worth using. (Another way to go is to say that a
word consisting of an underline concatenated in front of a Joy
function name has the meaning that that name has in Joy, but all
words that don't begin with the underline get the OO treatment. Non-
objects treated as objects would effectively add the underline.)
As soon as someone comes along and praises the elegance of your
language, he up and suggests ways to make it less elegant, eh?
I have two questions about Joy. Question 1 is my real reason for
writing this message, hence the subject line "Joy State".
1. What are the other components of the state besides the stack?
2. Please simplify:
1 2 [swap swap] nullary
I guess the answer is
1 2 1 2
therefore nullary, unlike other combinators, doesn't create a context
in which one can substitute equivalent programs within quoting. E.
g.,
1 2 [id] nullary =/= 1 2 [swap swap] nullary
even though
swap swap == id
.
I think Joy is really cool as an addition to the spectrum of
programming languages one can refer to for their purity in the
expression of useful ideas, like Scheme or Self. Kudos for coming up
with it, Professor!
Manfred von Thun — 2001-06-15 08:23:18
My apologies for not responding earlier
On Wed, 30 May 2001, Jack Waugh wrote:
> I just encountered Joy and find it breathtakingly elegant. Kudos in
> particular for synthesizing the concepts of list and program. Of
> course, Lisp regards a list as the source code for a program, but the
> unification seems to go deeper in Joy.
Yes, it is deeper. This is because in Joy there is no environment
of name/value pairs to worry about. Hence after the definition
foo == bar baz zonk
it is true that
F foo G == F bar baz zonk G
for all F and G.
> I wonder if Haskell programmers might enjoy Reverse Joy, the language
> you get by keeping Joy's semantics but reversing the order of the
> juxtaposition in the syntax for function composition.
Yes, one could. But little is gained from that. In particular
one would need to append to the END of a list quite often
to get the effect of partial evaluation. Currently, after the
definition
f3 == * +
any use of f3 requires three number on the stack,
and hence after the definition of
f2 == 42 f3
any use of f2 requires two numbers.
Quite often a combinator takes a quoted program as a parameter,
but only part of the required program is known at the time
something is being defined. Suppose we quite often have
a list (of, say, numbers) on the stack and on top of that
another number. We want to add that number to every element
of the list to get a list of the same length.
This is what you do:
[+] cons map
The cons will insert the unkown number at the START of the
quotation, and the map will used this slightly longer quotation
to do its work. If one used reverse notation, the unknown
number would have to be inserted at the END of the quotation.
For singly liked list this requires copying all the old list
(and hence is inefficient). For a doubly linked list it does
not matter. I had in fact toyed with doubly linked list originally.
> One could also propose JOOy, or Joy 1 +, by extending Joy's primitive
> data types to include an "object" type. A further extension would
> give a functional meaning to all possible words, over the domain of
> states where the stack has an "object" on top.
With the dip combinator you can keep anything on top of the
stack and later look at it -- it has not changed.
make-something [do-all-sorts-of-things] dip
now the something is still on top of the stack.
> Objects would contain
> mappings of words to functions. Applying a word to a state would
> mean popping the object from the top of the stack, looking up in the
> object the function to which the word maps, and applying that
> function to a state having the remaining stack (resulting from having
> popped off the object) and with the rest of the state being the same
> as the nonstack part of the original state.
Yes, as the "something-object" you could have anything expressible
in Joy. For the sort of state that you have in mind it might be
a list of name/value pairs:
[ [foo 42] [bar 1234] ... ]
[some more about OO for Joy]
I got the impression you are thinking that OO must mean
state change ("send a message to object O which says: change yourself
in such ans such a way"). But changes cannot be had in functional
languages. There is no state.
> As soon as someone comes along and praises the elegance of your
> language, he up and suggests ways to make it less elegant, eh?
Many years ago (1979 ?) I went to a conference in Sydney mostly
about C and Pascal which were still quite new then. Ritchie and
Wirth were there. Somebody gave a paper called "Design of a successor
to Pascal", wanting a better Ascii set mong others.
> I have two questions about Joy. Question 1 is my real reason for
> writing this message, hence the subject line "Joy State".
>
> 1. What are the other components of the state besides the stack?
Joy is purely functional. It has no state. The stack does not change.
There is no stack. All of Joy can be handled with rewriting,
in the same way as in lambda calculus languages (Lisp,Scheme,ML,
Haskell) everything can be handled with lambda reduction.
Read all about it in "A rewriting system for Joy".
A stack CAN be used to make the rewriting more efficient,
so execution consists not of rewriting just a program but
a program/stack pair. And, very importantly, a stack helps in
thinking about Joy. Oh, yes: what does a program denote?
a function from stacks to stacks. I know it all sounds a bit
paradoxical.
> 2. Please simplify:
> 1 2 [swap swap] nullary
> I guess the answer is
> 1 2 1 2
I think it should be
1 2 2
In fact, I did not trust myself sufficiently, so I interrupted
writing this reply, and indeed this is what I got.
But I also found that there is something weird about the
implementation of nullary: when the quotation is [] or [id]
or [dup pop] I got nonsense. Is this what prompted your
question? At any rate, I must go back to nullary and
its siblings unary and binary. Thanks.
> therefore nullary, unlike other combinators, doesn't create a context
> in which one can substitute equivalent programs within quoting. E.g.,
> 1 2 [id] nullary =/= 1 2 [swap swap] nullary
> even though
> swap swap == id
You are quite right, if the result were 1 2 1 2 then the substitution
of equivalents in quotation _used_by_a_combinator_ would not work.
But the substitution principle must be preserved.
> I think Joy is really cool as an addition to the spectrum of
> programming languages one can refer to for their purity in the
> expression of useful ideas, like Scheme or Self. Kudos for coming up
> with it, Professor!
Thanks for the promotion. Our Department has not had a professor
for 6 years, I think. And with the squeeze that will not improve
for a while.
- Manfred
John Cowan — 2001-06-15 12:08:22
Manfred von Thun scripsit:
> But I also found that there is something weird about the
> implementation of nullary: when the quotation is [] or [id]
> or [dup pop] I got nonsense. Is this what prompted your
> question? At any rate, I must go back to nullary and
> its siblings unary and binary. Thanks.
I posted about this earlier: the N_ARY implementation in Joy0
and in Joy1 versions prior to 30 May is definitely broken:
it alters a stack element rather than properly calling newnode.
Try 1 2 [id] nullary stack, which prints 2 2 2 2 2 2 2 2 2 ...
The current Joy1 is fixed.
> > Kudos for coming up with it, Professor!
> Thanks for the promotion. Our Department has not had a professor
> for 6 years, I think. And with the squeeze that will not improve
> for a while.
It's conventional in the U.S. to use "professor" informally for all
tertiary educators, whatever their formal titles.
--
John Cowan
cowan@...
One art/there is/no less/no more/All things/to do/with sparks/galore
--Douglas Hofstadter
Manfred von Thun — 2001-06-17 04:05:06
On Fri, 15 Jun 2001, John Cowan wrote:
> Manfred von Thun scripsit:
>
> > But I also found that there is something weird about the
> > implementation of nullary: when the quotation is [] or [id]
> > or [dup pop] I got nonsense. Is this what prompted your
> > question? At any rate, I must go back to nullary and
> > its siblings unary and binary. Thanks.
>
> I posted about this earlier: the N_ARY implementation in Joy0
> and in Joy1 versions prior to 30 May is definitely broken:
> it alters a stack element rather than properly calling newnode.
> Try 1 2 [id] nullary stack, which prints 2 2 2 2 2 2 2 2 2 ...
> The current Joy1 is fixed.
Oops, sorry, your fix got buried deep inside the stack of my brain.
Your fix is correct, of course.
In Joy0 the fix would be:
in file interp.c
in macro
#define N_ARY(...
... 6 lines down:
replace
stk->next = TOP \
by
stk = newnode(stk->op,stk->u.num,TOP) \
(Note the "\", of course.)
I'll fix Joy0 on the web page, and also the missing check for
the quotation.
Thanks Jack, and thanks John.
Independently of that: has the time come to let Joy0 fade away yet?
In that case I'll put Joy0 into an "old" directory, and replace
the C-files for Joy0 with the corresponging C-files for Joy1.
This will make it possible for non-unix users to build a Joy
as before. For unix there would be the joy.tar.gz
Any thoughts?
- Manfred
Jack Waugh — 2001-06-18 14:05:34
(Responding to
http://groups.yahoo.com/group/concatenative/message/693).
>> Of course, Lisp regards a list as the source code for a
>> program, but the unification seems to go deeper in Joy.
> Yes, it is deeper. This is because in Joy there is no environment
> of name/value pairs to worry about. Hence after the definition
> foo == bar baz zonk
> it is true that
> F foo G == F bar baz zonk G
> for all F and G.
I don't see what your example has to do with lists; none appear in it.
I was thinking more along these lines: When we look at lists in Lisp
that can be interpreted as software, we see numbers and symbols and
sublists as the elements of the lists. I think a Lisp system can't
express the list any other way and have it still available for
examination via the list operations such as car and cdr (first and
rest). But in Joy, a list can be a program and all its elements can
be functions. Nothing has to be done with the functions but to apply
them. So in Lisp, you have source code, but in Joy, lists can
contain code compiled down as much as desired.
Jack Waugh — 2001-06-18 14:19:00
(Re
http://groups.yahoo.com/group/concatenative/message/693):
I'm not particularly advocating reverse notation, but the problem you
point out could be solved by saying we are only reversing the syntax,
without reversing the sense in which conses denote composition (under
interpretation by combinators). Of course, this could look funny
(relative to conventional "left"/"right" visualisation) when the
programmer intends the list literal to denote some "data" rather than
code. We would have
[3 4 5] == cons [3 4] 5
in reverse notation, corresponding to, in Joy notation,
[5 4 3] == 5 [4 3] cons
.
Jack Waugh — 2001-06-18 14:46:00
http://groups.yahoo.com/group/concatenative/message/693
> [some more about OO for Joy]
> I got the impression you are thinking that OO must mean
> state change ("send a message to object O which says: change
> yourself in such and such a way"). But changes cannot be had
> in functional languages. There is no state.
No, I was not thinking that way about the "objects". I see them as
values containing mappings of selectors into functions. The nearest
thing to a Smalltalk-like state change of an object would be a
function whose result would contain a stack with a new object on top
of the stack (the rest of the stack equal to the stack in the
argument), where the new object substantially resembles the old
object but differs in some mapping. Of course this differs from the
traditional definition of OO.
I was not thinking that the "object" would consist of data
expressible in Joy. I was suggesting a language differing from Joy
by the addition of a data type for "objects". That is, I was
thinking of an OO extension to Joy, not an OO style of programming in
Joy.
Jack Waugh — 2001-06-18 14:53:52
In
http://groups.yahoo.com/group/concatenative/message/693, Manfred
von Thun writes:
> In fact, I did not trust myself sufficiently, so I interrupted
> writing this reply, and indeed this is what I got.
> But I also found that there is something weird about the
> implementation of nullary: when the quotation is [] or [id]
> or [dup pop] I got nonsense. Is this what prompted your
> question?
No, in fact, I have not downloaded any Joy interpreter. I was just
probing to understand the meaning of nullary because the description
of it seemed ambiguous.
Jack Waugh
Jack Waugh — 2001-06-18 15:23:22
http://groups.yahoo.com/group/concatenative/message/693
> > 1. What are the other components of the state besides the stack?
> Joy is purely functional. It has no state. The stack does not
change.
> There is no stack. All of Joy can be handled with rewriting,
I thought it would be obvious that by "state" I only mean the
arguments and results, and that when I write words that sound as
though I am talking about state change, I am only abbreviating the
concept of a function that produces a result that differs from the
argument in a defined way. For example, if someone says "dup"
duplicates the top element of the stack, that sounds imperative, but
we read it to mean just that dup maps from some stack
A As cons
where A is any stackable value and As is a list of stackable values,
into
A A As cons cons
if I may use Joy-like notation for describing the mathematical
concept of the stack. Here I'm ignoring the part of the argument and
result besides the stack (which part you deny the existence of below).
> Oh, yes: what does a program denote?
> a function from stacks to stacks.
John Cowan, at
http://groups.yahoo.com/group/concatenative/message/680, seems to
assert that the argument or result consists of more than just a
stack. There are some open files, etc. Which is it?
Manfred von Thun — 2001-06-19 05:55:04
On Mon, 18 Jun 2001, Jack Waugh wrote:
[In reply to what I thought was his view of objects]
> No, I was not thinking that way about the "objects". I see them as
> values containing mappings of selectors into functions.
Maybe this is the sort of thing you want - here in a fantasy extension
to Joy:
OBJECT-DEFINITIONS
numeric ==
[ square == dup *;
cube == dup dup * *
..]
graphic
[ square == something quite different;
..]
END-OBJECT-DEFINITIONS
now some possible notations for using the objects:
1. 42 numeric.square simply call the squaring function
2. 42 numeric .square push the object, call the function
3. 42 numeric .square i push object, select body, call body
Notation 1 is just like module notation (not even classes, since
there can only be one member of the class).
Notation 2 allows manipulation of the numeric object between pushing
the object but before the selector .square is called.
Notation 3 would even allow combinators other than i to use the body
(which of course is [dup *]).
I think notation 3 would be the most general.
But something like that can already done in Joy using the data type
"dictionary" - a list of name/value pairs. See the "typlib.joy" library
from the main Joy page under "Type library".
An object would look like this:
DEFINE
numeric ==
[ ["square" [dup *] ]
["cube" [dup dup * *]
..]
To use it you would say
numeric "square" d_lookup i
numeric "square" d_lookup dip
"squ" numeric swap "are" concat d_lookup i
or whatever. Maybe at least the first two come close to what
you want.
> I was not thinking that the "object" would consist of data
> expressible in Joy. I was suggesting a language differing from Joy
> by the addition of a data type for "objects". That is, I was
> thinking of an OO extension to Joy, not an OO style of programming in
> Joy.
The best you could do is to invent some fantasy notation that you like
and write some sample programs in that notation.
- Manfred
Manfred von Thun — 2001-06-19 06:23:26
On Mon, 18 Jun 2001, Jack Waugh wrote:
> http://groups.yahoo.com/group/concatenative/message/693
> > > 1. What are the other components of the state besides the stack?
> > Joy is purely functional. It has no state. The stack does not
> change.
> > There is no stack. All of Joy can be handled with rewriting,
>
> I thought it would be obvious that by "state" I only mean the
> arguments and results, and that when I write words that sound as
> though I am talking about state change, I am only abbreviating the
> concept of a function that produces a result that differs from the
> argument in a defined way.
By state I mean the collection of assignable variables - if the
language has them at all.
But I may well have used the word state improperly in some contexts
elsewhere. I should be more consistent, I know,
> For example, if someone says "dup"
> duplicates the top element of the stack, that sounds imperative, but
> we read it to mean just that dup maps from some stack
I think someting got lost either in the transmission or I inadvertently
deleted it from your message. The following does not fit:
> A As cons
>
> where A is any stackable value and As is a list of stackable values,
> into
>
> A A As cons cons
Maybe you had in mind one of the following:
A As cons == [A As]
A dup As cons cons == A A As cons cons == A [A As] cons == [A A As]
> if I may use Joy-like notation for describing the mathematical
> concept of the stack. Here I'm ignoring the part of the argument and
> result besides the stack (which part you deny the existence of below).
> John Cowan, at http://groups.yahoo.com/group/concatenative/message/680,
> seems to assert that the argument or result consists of more than just a
> stack. There are some open files, etc. Which is it?
John is right, of course.
If you are not using get and put, then the argument and result
are just a stack. If you are using get and put then the argument and
result are stack/inputfile/outputfile, let's call it a complex "entity",
and if I have elsewhere called it state, then that was misleading.
Joy programs denote unary functions from entities to entities.
But the entities do not change. When you compute the square of 3,
which gives you 9, the number 3 does not change.
Hope this helps
-Manfred
Jack Waugh — 2001-06-19 09:39:31
I wrote
> > For example, if someone says "dup"
> > duplicates the top element of the stack, that sounds imperative,
but
> > we read it to mean just that dup maps from some stack
[and at this point I wrote something in an inappropriate notation
that looked like Joy]
> > into
[more inappropriate notation].
Let me try again. I was saying that more than one of us in this
group have been abbreviating functional concepts with imperative
sounding metalanguage. So someone might say, for example, for
brevity, that "dup" duplicates the top element of "the stack", as
though there were a stack that could be changed. Ha, ha! Of course
we don't really mean there is a stack that can be changed; that would
make Joy an imperative language, and we can't really mean such a
thing. What a statement like that abbreviates is that dup is a
function that takes an argument containing a stack consisting of a
top element A and the rest of the stack, As, and produces a result
containing a stack where the top element is A, the second element is
also A, and the remaining elements after the first two constitute the
same collection I mentioned as As before.
If you were going to write a Joy interpreter in Joy, you could
simulate a stack using a list.