==

John Carter — 2001-08-07 06:03:43

There is one part of Joy that I'll admit I'm not comfortable with.

This is quitely likely a failure on my part to understand...

The == operator that assigns a name to "word" seems to stand apart and out
of the paradigm of joy.

Why is the == operator infix?

Instead of...
myword == this that the other;
have
[this that the other] myword ==

Postscript has the notion of a stack of dictionaries parallel to the
execution stack.

A "def" or == stores the word into the dictionary currently on top of the
dictionary stack.

A reference is resolved by looking in the topmost dictionary, if it
doesn't find it there, it looks in the next dictionary so on down until
the bottom most dictionary of system primitives.

So instead of the notion of a Joy word being a function of a stack
returning a stack, it becomes a function of a stack and a stack of
dictionaries returning a stack and a stack of dictionaries.

Please enlighten me as to why this curiosity out of paradigm == exists
within Joy, I'm confuzzled.


Thank you,

John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : john.carter@...
New Zealand

I'm becoming less and less convinced of humans as rational beings.
I suspect we are merely meme collectors, and the reason meme is only
kept on to help count our change.

Jack Waugh — 2001-08-08 13:27:13

Perhaps the answer is that == is not part of Joy proper, but part of
Metajoy.

Joy exists for discussion, not for practical programming, right?
When we say something like

copy-me == [dup cons] dup cons

we just mean that when we say copy-me in the ensuing discussion, we
mean [dup cons] dup cons.

If you added postfix == (or :=) to the language, you'd be introducing
something to the state besides the stack, which might destroy the
purity of the langauge (of course, the I/O already destroys it, but
we can ignore that for now and repair it if and when we want to make
such use or discussion of Joy as raises any need to get serious about
I/O).

John Carter — 2001-08-08 22:50:15

On Wed, 8 Aug 2001, Jack Waugh wrote:

> Perhaps the answer is that == is not part of Joy proper, but part of
> Metajoy.
>
> Joy exists for discussion, not for practical programming, right?

As yet perhaps, but I have deep plans and dark plotches....

Anything that has such a simple algebra on it has to, in the cosmic sense,
has to be eminently more practical than any current language.

> If you added postfix == (or :=) to the language, you'd be introducing
> something to the state besides the stack,

Yes, Postscript copes with this by having two stacks. The dict stack and
the ordinary stack.

The way I see the whole thing the primary value of Joy is that Algebra and
the Rewrite rules. Anything that destroys that would be a crying shame in
my view.

Now == stands outside of Joy and hence is cannot be made part of the
algebra and rewrite rules.

Now what if we took things a step further and made == within the paradigm
so we could have an algebra that operated on it?

For those fragments of code that do not operate on the dictionary stack we
are in exactly the state of innocence as in Joy code outside the LIBRA -
END.

Part of the reason for the simplicity of the Joy algebra compared to say an
algebra on Scheme, is that a lambda expression that binds arguments to
names becomes complex to reason about. Something deep within the stack (a
value) becomes bound to something at the top (a reference)

A stack machine and name binding free nature of Joy localises cause and
effect making it very simple to reason about small fragments of Joy.

Now introducing name binding into Joy on a seperate dict stack would
unfortunately reintroduce some, but not all of those complexities.

And alternate would be a word stack. So instead of saying
square == dup *;

Or postcriptish...
[dup *] "square" defun

To remain in a purely Joyish mode one could simply treat the dictionary
stack instead of as a stack of dictionaries as a stack of words.

[dup *] word (moves the top of the execution stack to the top of the
word stack.)

Thereafter the operator "invokeword" would invoke the word currently
on top of the word stack. You can add some primitives (dupword,
swapword,...) to manage the wordstack.

Still given the existence system primitives and the library functions
I suspect the Postscriptish "stack of dictionaries" approach is more
practical. (And is blessed by a an emminently pragmatic history of
being a working solution.)

I also suspect if the operators on the dictionaries are simple and
direct enough a reasonable algebra for their behaviour may also be
derived.


John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : john.carter@...
New Zealand

I'm becoming less and less convinced of humans as rational beings.
I suspect we are merely meme collectors, and the reason meme is only
kept on to help count our change.

Jack Waugh — 2001-08-10 13:56:39

In re

> Still given the existence system primitives and the library
functions
> I suspect the Postscriptish "stack of dictionaries" approach is more
> practical. (And is blessed by a an emminently pragmatic history of
> being a working solution.)
>
> I also suspect if the operators on the dictionaries are simple and
> direct enough a reasonable algebra for their behaviour may also be
> derived.

You're proposing to have an environment where names get mapped to
functions. You would do that with a stack of dictionaries in
addition to the operand stack. Elsewhere participants in the forum
spoke for polymorphism. I see these things as relatable to each
other, the environment and polymorphism. In the imperative
programming language Self, the application of a procedure to the
system state involves setting up an environment, where names get
mapped to operations (it is easy to imagine a functional subset of
Self, in which we would say the environment maps function names to
functions). Environments in Self consist of _slots_. Each slot maps
from a name to an operation or a value. A slot can be marked as
_inheriting_. If the interpreter does not find the name it's looking
for in a given environment, it tries to delegate the operation to the
definition in some ancestor that it finds by looking at the
environments (objects) pointed to by the original environment's
inheriting slots. The current environment for execution inherits
from the _receiver_ of the message currently being interpreted. This
inheritance between the receiver and the environment gives Self its
namesake feature, that "foo" at the beginning of a command is
equivalent to "self foo"; "self" is effectively implicit (as compared
to Smalltalk, where it would have to be explicit). I see similarity
between Self's looking in the environment for a mapping, then in the
receiver, then in its parents, and so on, and the stack of
dictionaries in Postscript, where the interpreter looks in the top
dictionary, then the next deeper dictionary in the stack, and so on.
Of course Forth achieves a similar effect quite elegantly using its
linked vocabularies.

Would Joy have the algebraic properties you want if we extended it to
permit programmable polymorphism, and a current envirionment, along
lines such as the following? There would be a way to cobble up a
polymorphic value. Such a value would contain _two_ mappings from
names to functions. I call them the _external map_ and the _internal
map_. Functions found in these maps we can call _methods_, borrowing
from the jargon of object-oriented programming.

When the interpreter sees a word in the stream it is executing, it
wants to look up a function from the word. There is a current
environment in which the matching definition might appear. Also, if
the operand stack is not empty, the interpreter looks at the external
map of the top element. This may supply a match for the word the
interpreter is trying to map. In case both mappings supply matches,
I'm not sure which should take precedence.

Suppose the decision is to execute a method found in the external map
of the polymorphic value found on top of the stack. In that case,
the interpreter must push the current environment on a separate stack
for the purpose and make the _internal map_ of the top element of the
operand stack become the current environment. At this point we
should or should not pop the top element off the operand stack; I'm
not sure. It's a matter of style. If the convention is to pop it,
it is not necessarily lost; it may be recoverable from its own
internal map. Now the interpreter executes the method using the new
environmnet. When the method finishes, the interpreter pops back the
old environment from the environment stack. Although this proposal
and yours both involve a stack of dicitonaries, they differ in that
yours would look down the stack on failing to find a match in the top
dictionary. Mine instead would look to the external map of the top
stack element, so as to implement polymorphism.

Typical values would inherit from (or be partly copied from) a root
value that would provide in one or both of its maps the mappings from
standard names such as "dup", to the interpreter primitives to
provide the default behaviors for those names. As in Smalltalk or
Self, a special form would tell the compiler to compile in an
invocation of an interpreter primitive. Smalltalk uses numbers for
these; Self uses names beginning with underlines. Some values,
intended to be _linear_, might override "dup" and "pop" (externally)
in order to disallow them. Hmm, either they'd also have to be
jimmied to disallow the primitive dup and pop, or we'd have to give
the external methods of the top stack element priority over the
environment. But I'm sure the environment should have priority for
functions that don't use up the top stack element, at least, because
an engineer would like to be able to design the interactions internal
to a polymorphic value without fear of a name clash with some
interlocutor's external baggage.

Manfred von Thun — 2001-08-13 08:31:57

On Fri, 10 Aug 2001, Jack Waugh wrote:

> You're proposing to have an environment where names get mapped to
> functions. You would do that with a stack of dictionaries in
> addition to the operand stack. Elsewhere participants in the forum
> spoke for polymorphism. I see these things as relatable to each
> other, the environment and polymorphism. In the imperative
> programming language Self, the application of a procedure to the
> system state involves setting up an environment, where names get
> mapped to operations (it is easy to imagine a functional subset of
> Self, in which we would say the environment maps function names to
> functions). Environments in Self consist of _slots_. Each slot maps
> from a name to an operation or a value.

I do not know anything about the Self language, but environments
of course occur in any language in which there are named formal
parameters and which on call take on the value of the actual
parameter. See the Joy FAQ for why Joy does not have them.

Note also that environments are different from the dictionary
of name / body associations set up by definitions of functions
and procedures, and different again from the state in imperative
languages which is changed by assignment.

[Other remarks about Self, Forth and Postscript]

> Would Joy have the algebraic properties you want if we extended it to
> permit programmable polymorphism, and a current envirionment, along
> lines such as the following? There would be a way to cobble up a
> polymorphic value. Such a value would contain _two_ mappings from
> names to functions. I call them the _external map_ and the _internal
> map_. Functions found in these maps we can call _methods_, borrowing
> from the jargon of object-oriented programming.

Joy would no longer be functional if it had a state.
All functional languages have the substitutional property.
But Joy does not even have an environment as the other
functional languages do. Hence substitution does not involve
complicated beta-reduction but simple textual substitution.

I'll look at Self some time soon.

- Manfred

Jack Waugh — 2001-08-13 15:49:22

So Manfred von Thun and John Carter are in disagreement about whether
having a stack of dictionaries in addition to the operand stack would
remove desirable mathematical properties?

John Carter — 2001-08-14 03:05:00

On Mon, 13 Aug 2001, Jack Waugh wrote:

> So Manfred von Thun and John Carter are in disagreement about whether
> having a stack of dictionaries in addition to the operand stack would
> remove desirable mathematical properties?

Firstly, I am fully in agreement that having operators that change the
definitions of the words destroys the algebra for fragments including that
operator.

Before and after dictionary fiddling operators you are in _exactly_ the
same state of grace as on either side of a LIBRA..END block.

In Joy the process of fiddling the environment (LIBRA...END), and the
process of execution is kept seperated.

However, an algebra including operations on a dictionary would be
considerably more complex, but not undoable.

My point then is if LIBRA..END and == destroy the algebra for fragments
crossing them anyway, why not make == fit uniformly with the postfix
paradigm?

In dynamic languages like Scheme and postscript defun's can be created at
run time.

Joy is fish and fowl. The LIBRA..END creates a compile time
definition of the defun's.

Unfortunately a large part of the appeal (to me at least) of a language
like Joy is the reflexiveness of it. Creating/Analysing Joy programs with
Joy programs is truly easy. Having crafted a complex word with a Joy
program, one is permitted the convenience of saving for later use.

Note the difference.

Defuns (==) name words.

Scheme like lambda's name parameters.

Both destroy the Joy algebra.

Scheme-like lambda's irredeemably complexify the algebra at a fine level.

Defun's change the algebra when they occur, but one can deduce the
properties of the defun and and there after use those proerties within the
algebra.

John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : john.carter@...
New Zealand

I'm becoming less and less convinced of humans as rational beings.
I suspect we are merely meme collectors, and the reason meme is only
kept on to help count our change.

Manfred von Thun — 2001-08-14 09:57:21

On Tue, 14 Aug 2001, John Carter wrote:

> Firstly, I am fully in agreement that having operators that change the
> definitions of the words destroys the algebra for fragments including that
> operator.
Exactly so.

> In Joy the process of fiddling the environment (LIBRA...END), and the
> process of execution is kept seperated.
"fiddlinng the _definitions_" yes. In the technical sense of
"environment", lambda calculus based languages have it,
but Joy does not. (See the FAQ "What is an environment")

> However, an algebra including operations on a dictionary would be
> considerably more complex, but not undoable.
If "dictionary" means environment (binding of formals to actuals)
then any lambda calculus based language does it, and
the algebra is well known - it is beta reduction in the lambda calculus.
As you say, it is considerably more complex than the simple
textual substitution in Joy.

> My point then is if LIBRA..END and == destroy the algebra for fragments
> crossing them anyway, why not make == fit uniformly with the postfix
> paradigm?
At the end of the FAQ, see "Further Frequently Asked Questions"
which I have added only a couple of hours ago.

> In dynamic languages like Scheme and postscript defun's can be created at
> run time.
I don't know much about Postscript, but I know a bit about
Scheme even if I have written next to nothing in it. If I read you
correctly, you are saying that I can define (in the ordinary way)
a function which, when called will define (in an extraordinary way)
a function which when called do what it was defined to be?
Excuse the exact syntax, but it would be something like
(defun ordinary (x)
(if (< x 5)
(defun extraordinary (a b) (+ a b))
(defun extraordinary (a b) (* a b)) ) )
Now after the call (ordinary 10)
as the body of ordinary is executed at run time,
the second definition of extraordinary should be entered.
Now the further call (extraordinary 3 4) should produce 12
I have never seen anything like that in Scheme programs
(or in Lisp programs). Is this what you meant? If so,
can you give a reference, because I must then clear up my
misunderstanding of Scheme (or Lisp).
>
> Joy is fish and fowl. The LIBRA..END creates a compile time
> definition of the defun's.
Exactly so. I thought that it is like almost all other languages
in that respect.

> Unfortunately a large part of the appeal (to me at least) of a language
> like Joy is the reflexiveness of it. Creating/Analysing Joy programs with
> Joy programs is truly easy. Having crafted a complex word with a Joy
> program, one is permitted the convenience of saving for later use.
I think that the reflectiveness is quite orthogonal to the ability
to define things ("words", literals, operators, combinators).
A language without definitions would be difficult to use.

> Note the difference.
>
> Defuns (==) name words.
>
> Scheme like lambda's name parameters.
> Both destroy the Joy algebra.
The environment (formal/actual parameter correspondence or association)
created at call makes beta reduction in Scheme and other lambda calculus
languages hard. None of that in Joy.
But ordinary definitions in Joy do not destroy the algebra at all.
If anything, they create extensions to the algebra of the primitives.
See below.

> Scheme-like lambda's irredeemably complexify the algebra at a fine level.
Exactly so.

> Defun's change the algebra when they occur, but one can deduce the
> properties of the defun and and there after use those proerties within the
> algebra.
I would not have said "change", but what you then continue to say is
exactly right: After the definition (or: within the scope of the
definition)
name == b o d y (* that is the body *)
for any programs P and Q,
P name Q == P b o d y Q
That's Joy for you.

- Manfred