# Author: Paul Fitzpatrick, paulfitz@alum.mit.edu
# Copyright (c) 2018 Paul Fitzpatrick
#
# This file is part of CosmicOS.
#
# CosmicOS is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# CosmicOS is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with CosmicOS; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
Here we count up from zero, go through some primes, that sort of
thing. Just like in the movies! There is some syntax around the
numbers, and a structure to the “lesson,” but it will be fine for the
listener to ignore all that for now. Hopefully what they will pick up
on is:
There are some repeating patterns.
Between those patterns, there’s a specific short unit repeating
a varying number of times (we count in unary).
The number of times it varies smells like math.
We’ll get to a more compact representation of numbers later, once
we’ve established the basics.
We’ve hopefully cued our listeners to be looking for mathematical
patterns. So let’s give them some more. It doesn’t matter so much
what patterns we give, as long as they are clear, and that there are
several of them. Eventually we’ll want the listener to start turning
things around, and use the parts of the message they understand (the
mathematical patterns) to learn something about the parts they don’t
(the message structure and syntax).
Let’s take a shot at introducing ways of comparing numbers.
No doubt we’re revealing a feudal, reductive mindset in which
all things must be ranked in a hierachy. ¯\_(ツ)_/¯.
Equality is introduced by a series of true statements of the form X=X
(the syntax is a little different than regular math, more like
=XX, but that isn’t important yet). The listener will hopefully
discern a number getting repeated twice within the “sentence”
structure they’ve been seeing, but won’t be sure yet what we are
driving at until we introduce non-equality and contrast with it.
Now introduce symbols for ‘greater than’ and ‘less than,’ and contrast with equality.
Hopefully the listener will start to understand what part of the sentences are numbers, what part is a function of the relationship between the numbers, and what parts are just meaningless (for now) scaffolding around all that.
There’s an ambiguity between the ‘greater than’ and ‘less than’ symbols, depending on how you interpret the sentences, but it doesn’t matter yet.
Even more random examples. We shouldn’t be shy about piling on examples at this early stage of the message. Even just the repetition of the sentence structure with many small variations could help guide the listener at a more fundamental level than what we’re ostensibly trying to communicate here.
At this point, the listener can find numbers in our sentences, and has some
idea of symbols related to equality and inequality. But the structure of the
sentences remains a mystery. Let’s introduce more math, so that we can show
different sentence structures. First, let’s introduce logical negation.
We construct some sentences the listener should know are wrong, and put “not”
in front of them.
Let’s introduce some arithmetic, to show off still more sentence structure.
We show sentences of the mathematical form X=Y+Z, which in our message look like
=X|+YZ. From this, and the negation lesson, the listener will hopefully
start picking up on how to chain operations.
If the listener didn’t already have a pretty clear idea of what = is,
then these sentences could just as easily be interpreted as being about subtraction.
Even having an idea of =, syntax is still fuzzy enough that this lesson may not
be unambiguous by itself.
While we’re at it, let’s introduce multiplication with =X|*YZ sentences.
As for addition and subtraction, there will be some ambiguity as to whether we are
presenting multiplication or division here, until syntax is clearly understood.
Switch from unary numbers to another representation. The best representation
will depend on the details of how the message is being transmitted, and the
rest of the message doesn’t depend on that choice for correctness (though the
choice will have implications for how easy the message will be to interpret).
As a base-line, imagine we use a binary representation.
It isn’t important for the listener to understand, but it might be worth explaining
at this point how the unary representation worked. In fact there’s no special
syntax used, just three objects:
The number 0.
The number 1.
A function (called unary in English) that takes a value and:
If passed 0, the function returns 0
If passed 1, the function returns another function, just like itself,
except with any ultimate return value increased by 1.
Using syntax defined later in the message, unary could be defined as:
If you know Lisp/Scheme/etc, just read @ as define, ? as
lambda, and | as opening a parenthesis that gets closed at the end
of the statement.
Anyway, all of this is a digression, but it is worth knowing that as much as possible
the message is built from itself, so that in the end everything dovetails nicely.
We’ve advanced enough that we’re starting to have choices about how
something is expressed. Let’s pause to acknowledge that, and
reinforce some syntactic equivalences so the listener can be confident
of them.
Parentheses play a role in grouping expressions, just like in regular
math. To reduce the mental burden of tracking nesting, we use a | shortcut
that means “add parentheses between this point and as far as you can go.” So for
example (=7|+34) is equivalent to (=7(+34)).
An expression starting with assign is a way to name values for use within that expression. To use the assigned value, simply place its name at the beginning of an expression. For example, a value assigned to x can be used by writing (x). The name is entirely arbitrary, and can be just an integer.
We are pretty ruthless about adding syntax to reduce parentheses. So let’s allow writing (x) as $x (or equivalent in other renderings). This and | are in fact global options for the message that you can turn off if they are not to your taste.
We’ve set up a way to name a value within an expression. Now let’s go beyond that,
and introduce a way to name a value in one sentence and use it in a later sentence.
In other words, a message-level memory. After this, we’ll be able to define new
symbols from existing ones, with less need for large numbers of examples.
We introduce a define symbol that works just like assign, except that it applies
to the rest of the message rather than the rest of the sentence.
A sentence of the form defineXY means that $X will evaluate to Y from that
point on (unless X is changed by another define).
The meaning-of-life-universe-everything symbol here is entirely arbitrary, and
won’t be encoded as anything particularly meaningful in the message.
Now that we have functions, we could introduce some clever definitions of true, false,
and conditionals, where:
if is ?x|?y|?z|x$y$z
true is ?y|?z|y
false is ?y|?z|z
This is a neat implementation, but maybe a bit confusing. So let’s
not actually commit to a type for truth values in the message yet,
but just equate them with the results of equality =.
Once we have truth values, we can introduce conditionals and build up to fun stuff.
One slightly sneaky thing we do is to code true and false as $1
and $0. This could be helpful, or confusing, I’m not sure. Nothing
else in the message depends on this so it can be adjusted to taste.
Now that we spent some time looking at true and false, let’s show
a way to build conditional expressions. We start with an if expression,
of the form ifCONDITIONE1E2, which evaluates to E1 if the CONDITION
is true, otherwise E2.
If the listener is trying to map the language we are describing onto
their own system of computation, it is pretty important that if be
“lazy,” and completely skip evaluating the branch not taken. That
should become clear fairly soon if they were to try an “eager” if.
We continue introducing symbols related to math and logic. Now we will often
be able to both define them and give examples, so the listener has multiple
paths to understanding.
Here is and, which evaluates to true if both its two arguments are true,
and false otherwise. We don’t talk about wbat happens if you pass it integers
or something funky. There’d be value in getting into talking about types, but
it might be a bit much just now.
Here is or, which evaluates to true if either of its arguments are true,
and false otherwise. Again, we just don’t talk about what happens if you
pass in any unexpected values, like integers or functions. The message is
constructed so that the problem never comes up.
Now we introduce our first data structure. The expression consXY stores X and Y
in a pair. We can then pull X out from the pair with car(consXY), and we can
get Y out from the pair with cdr(consXY). Apologies for the arcane names,
they are inherited from Lisp (and they’ll be encoded as something else in the
message anyway).
We give a definition of cons that is a bit funky. The consXY expression
constructs a function which takes a single argument, also a function. That
argument gets called with X and Y. That means to pull X back out, we
just need to call consXY with a function like ?a|?b$a. Likewise for
Y. That is exactly what car and cdr do.
Definitions like that can be a bit hard to think about. But the great
thing is that you can apply definitions like these without initially
understanding them. So if the listener wants to try them out, they
can there’s an element of interactivity beyond what a plain text
message could give.
With define, we showed that there is a global memory, where we can associate a
symbol with a value. That’s nice, but it can be handy to separate memory from
naming. In this section we introduce make-cellX, which creates a “cell”
of memory and puts X in it. The cell can be read with get!, like
get!|make-cellX, or written to with set!, like set!(make-cell-X)Y.
Lists are a handy data structure to have. We’d like to get to the point
in the message where we can make lists like this: vector145,
vector77$undefined(vector123)14, etc. But
vector can’t be a function in the language we’ve described up to now,
it just can’t work syntactically.
What we can do is make lists like this: (list3)145,
(list4)77$undefined((list3)123)14, where we manually
specify how many values are in the list.
And then we can introduce a way to transform the syntax of the language,
so that vector145 gets rewritten to (list3)145 prior to being
evaluated.
An alternative would be just to introduce some special new syntax for
lists, and give examples. If the listener finds our transformation approach
confusing, they can simply ignore it and pick the message up again once
vector is in place. But by giving the transformation, we offer a second
way to understand and experiment with the concepts being introduced.
# these definitions are not quite what we want
# since thinking of everything as a function requires headscratching
# it would be better to use these as a parallel means of evaluation
# ... for expressions