RE: [stack] [+] first: second thoughts

Tanksley, William D. Jr. — 2003-07-09 14:51:23

From: stevan apter [mailto:sa@...]

>i'm aware of three proposals:

>1. leaves + on the stack (joy)
>2. leaves [+] or '+ or .. on the stack
>3. evaluate the stack until no change (ck, naked = 1)

I guess this is a reasonable summary for Joy; but it's not complete for my
proposal, since I'm suggesting adding quotation, symbolised by an
apostrophe, and a quoted list is equal to the list of the quotations. Thus,
'[+] first == '+ by definition, since '[+] == ['+]. [+], on the other hand,
is an error -- the + tries to execute on an empty stack in order to build
the desired list.

>1 is joy

Sort of. I would say that Joy leaves '+ on the stack; leaving + on the stack
doesn't make much sense to me.

>3 can leave + or [x +] on the stack if it's short.

Leaving a program on the stack seems kind of risky. It makes programs appear
to run in error conditions, until some later type error breaks them. And if
you write a program that *depends* on that, it means that other functions
can't call your function.

>2 breaks some fundamental identities, to wit:
> x = x dup [first] dip rest cons

...where x is a list. Okay, yes. Again, I believe that this is an intrinsic
problem with confusing quotation with enlistment with programs. I don't
believe it should be possible to extract elements from programs; only
subsequences.

-Billy

stevan apter — 2003-07-10 11:25:36

i hope i'm not exhausting everyone's patience by nattering
on about this. i think i have a story which rationalizes
the presence of unquoted primitives on the stack.

i want to prove to you that in addition to integers, floats,
and characters, joy already contains function atoms.

[+] first [+] in
true

'in' takes x and y and returns true if x is in y. so x must
be first-class data. but x isn't an integer, a float, or a
character, so it must be something else. it's not a list, so
it must be an atom. i say it's a function.

if joy had a match primitive then we could say

[+] first dup match
true

since joy has no way to directly place a function on the stack,
we could add:

`+
+

which evaluates '+', gets the function as usual, but then,
pushes it onto the stack instead of applying it. but this
would just be a notational convenience, semantically identical
to '[+] first'.

----- Original Message -----
From: "Tanksley, William D. Jr." <william.d.tanksley.jr@...>
To: <concatenative@yahoogroups.com>
Sent: Wednesday, July 09, 2003 10:51 AM
Subject: RE: [stack] [+] first: second thoughts


> From: stevan apter [mailto:sa@...]
>
> >i'm aware of three proposals:
>
> >1. leaves + on the stack (joy)
> >2. leaves [+] or '+ or .. on the stack
> >3. evaluate the stack until no change (ck, naked = 1)
>
> I guess this is a reasonable summary for Joy; but it's not complete for my
> proposal, since I'm suggesting adding quotation, symbolised by an
> apostrophe, and a quoted list is equal to the list of the quotations. Thus,
> '[+] first == '+ by definition, since '[+] == ['+]. [+], on the other hand,
> is an error -- the + tries to execute on an empty stack in order to build
> the desired list.

so on your proposal, lists are eager and quotation is pervasive (all the
way down? i guess so, else [[+]] would fail. but even with eager lists,
[+] doesn't have to fail. say that, if a function tries to execute on a
short stack, it eats whatever's there, and evaluates to a function which
wants more input. this is how ck works:

+
+
2 +
[2 +]
2 3 +
5

e.g.

[2] [+ - *] [infra i] right
[[2 +] [2 -] [2 *]]

makes a list of programs which [adds 2, subtracts 2, multiplies by 2].

>
> >1 is joy
>
> Sort of. I would say that Joy leaves '+ on the stack; leaving + on the stack
> doesn't make much sense to me.

see my story above.

>
> >3 can leave + or [x +] on the stack if it's short.
>
> Leaving a program on the stack seems kind of risky. It makes programs appear
> to run in error conditions, until some later type error breaks them. And if
> you write a program that *depends* on that, it means that other functions
> can't call your function.
>
> >2 breaks some fundamental identities, to wit:
> > x = x dup [first] dip rest cons
>
> ...where x is a list. Okay, yes. Again, I believe that this is an intrinsic
> problem with confusing quotation with enlistment with programs. I don't
> believe it should be possible to extract elements from programs; only
> subsequences.
>
> -Billy
>
>
> To unsubscribe from this group, send an email to:
> concatenative-unsubscribe@egroups.com
>
>
>
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
>
>

Nick Forde — 2003-07-10 11:28:37

stevan apter writes:
> i want to prove to you that in addition to integers, floats,
> and characters, joy already contains function atoms.
>
> [+] first [+] in
> true
>
> 'in' takes x and y and returns true if x is in y. so x must
> be first-class data. but x isn't an integer, a float, or a
> character, so it must be something else. it's not a list, so
> it must be an atom. i say it's a function.

Internally the Joy C interpreter does indeed represent primitives and
user defined functions as discrete data types.

> if joy had a match primitive then we could say
>
> [+] first dup match
> true

Or,

[+] first dup = .
true
[+] first [-] first = .
false

Regards,

Nick.

John Cowan — 2003-07-10 11:25:37

stevan apter scripsit:

> since joy has no way to directly place a function on the stack,
> we could add:
>
> `+
> +
>
> which evaluates '+', gets the function as usual, but then,
> pushes it onto the stack instead of applying it. but this
> would just be a notational convenience, semantically identical
> to '[+] first'.

Or indeed to '"+" intern', as I pointed out before.

--
You let them out again, Old Man Willow! John Cowan
What you be a-thinking of? You should not be waking! jcowan@...
Eat earth! Dig deep! Drink water! Go to sleep! www.reutershealth.com
Bombadil is talking. www.ccil.org/~cowan

Tanksley, William D. Jr. — 2003-07-10 18:44:46

From: stevan apter [mailto:sa@...]
>i hope i'm not exhausting everyone's patience by nattering
>on about this. i think i have a story which rationalizes
>the presence of unquoted primitives on the stack.

I agree that function references belong on the stack, and can already be
placed there by Joy. The confusion is in the word "unquoted". In order to
get on the stack they were in fact quoted -- otherwise they would have been
executed. So "unquoted" isn't the right word; "unlisted" might be better.

>since joy has no way to directly place a function on the
>stack, we could add:
> `+
> +

I'd like that. This is essentially the same as my '+ proposal (' chosen for
similarity with Forth and Lisp), so I'm happy with it. It's not particularly
essential for Joy; I'm not sure what Joy needs to change, and I suspect it's
only documentation.

From: "Tanksley, William D. Jr." <william.d.tanksley.jr@...>
>>From: stevan apter [mailto:sa@...]
>>>i'm aware of three proposals:

>>>1. leaves + on the stack (joy)
>>>2. leaves [+] or '+ or .. on the stack
>>>3. evaluate the stack until no change (ck, naked = 1)

>>I guess this is a reasonable summary for Joy; but it's not complete
>>for my proposal, since I'm suggesting adding quotation,
>>symbolised by an apostrophe, and a quoted list is equal to the list
>>of the quotations. Thus, '[+] first == '+ by definition, since '[+]
>>== ['+]. [+], on the other hand, is an error -- the + tries to execute
>>on an empty stack in order to build the desired list.

>so on your proposal, lists are eager and quotation is
>pervasive (all the way down)?

Yes.

> i guess so, else [[+]] would
>fail. but even with eager lists, [+] doesn't have to fail.
>say that, if a function tries to execute on a short stack, it
>eats whatever's there, and evaluates to a function which wants
>more input. this is how ck works:

This actually works well if `[+] would otherwise have failed. It wouldn't
work in Joy, where executing functions always have full access to the stack.

> +
> +
> 2 +
> [2 +]
> 2 3 +
> 5

Right -- in a language based on my ideas they would return function objects,
possibly denoted by curly braces or something like that.

My initial language won't do that, because I won't do dynamic compilation or
self-modifying code, and I won't initially have any support for uncompiled
code (aside from text).

In other words, my language will be Forth-based, not Joy-based.

If I decide to add strong typing, then your idea will work perfectly even
with only static compilation, so I might add it then. But then, I'm not sure
that it's a good idea; it's perfectly easy to write a function, rather than
depending on the stack state to implicitly write one for you. And it's
easier to read.

>e.g.
> [2] [+ - *] [infra i] right
>[[2 +] [2 -] [2 *]]

>makes a list of programs which [adds 2, subtracts 2, multiplies by 2].

That won't work without strong typechecking either -- the list structure
will be `[[+ -] *] rather than your intended `[+ - *]. It seems easier in
this case to just make a (quoted) list of functions rather than depending on
the stack being the right depth (which, as you can see, it's not after the
first function's on the stack).

Oh, and in my system that wouldn't work anyhow, because the result would be
{{+ - } *} (i.e. a function object, not a list object).

>>>1 is joy
>>Sort of. I would say that Joy leaves '+ on the stack;
>>leaving + on the stack doesn't make much sense to me.

>see my story above.

This comment didn't make any sense to me until I realised that '+ meant
something different to you than it does to me. I don't know what it means to
you; to me, it's a reference to the function +, and unless you want to put
the entire code for + on the stack, it's the only way to manipulate the
function + as data.

I'm aware that Joy doesn't use that syntax yet, but honestly, that's because
Joy wasn't designed with the possibility of [+] first in mind.

-Billy

sa@dfa.com — 2003-07-10 19:55:03

> i guess so, else [[+]] would
>fail. but even with eager lists, [+] doesn't have to fail.
>say that, if a function tries to execute on a short stack, it
>eats whatever's there, and evaluates to a function which wants
>more input. this is how ck works:

This actually works well if `[+] would otherwise have failed. It wouldn't
work in Joy, where executing functions always have full access to the
stack.

in ck, + has access to the whole stack. it's defined:

S is empty -> +
S . x -> [x +]
S . x y -> S . x + y


> +
> +
> 2 +
> [2 +]
> 2 3 +
> 5

Right -- in a language based on my ideas they would return function
objects,
possibly denoted by curly braces or something like that.

My initial language won't do that, because I won't do dynamic compilation
or
self-modifying code, and I won't initially have any support for uncompiled
code (aside from text).

In other words, my language will be Forth-based, not Joy-based.

If I decide to add strong typing, then your idea will work perfectly even
with only static compilation, so I might add it then. But then, I'm not
sure
that it's a good idea; it's perfectly easy to write a function, rather than
depending on the stack state to implicitly write one for you. And it's
easier to read.

>e.g.
> [2] [+ - *] [infra i] right
>[[2 +] [2 -] [2 *]]

>makes a list of programs which [adds 2, subtracts 2, multiplies by 2].

That won't work without strong typechecking either -- the list structure
will be `[[+ -] *] rather than your intended `[+ - *]. It seems easier in
this case to just make a (quoted) list of functions rather than depending
on
the stack being the right depth (which, as you can see, it's not after the
first function's on the stack).

here's the way 'right' works: it expects at least three
items on the stack:

S x [y1 .. yn] [p] right

it returns

S [S x y1 p] .. [S x yn p]

p can eat more than just x and y:

10 20 30 [40 50 60] [+ * -] right
10 20 [-1390 -1590 -1790]

i.e.

10 20 30 40 + * -
10 20 30 50 + * -
10 20 30 60 + * -

are executed in parallel, and the results are appended to S.

Oh, and in my system that wouldn't work anyhow, because the result would be
{{+ - } *} (i.e. a function object, not a list object).

>>>1 is joy
>>Sort of. I would say that Joy leaves '+ on the stack;
>>leaving + on the stack doesn't make much sense to me.

>see my story above.

This comment didn't make any sense to me until I realised that '+ meant
something different to you than it does to me. I don't know what it means
to
you; to me, it's a reference to the function +, and unless you want to put
the entire code for + on the stack, it's the only way to manipulate the
function + as data.

well yes.

10 20 [+] first
10 20 +

if you look at the stack at this point, you see the list of three
items:

(10
20
{:[z~0 ;x / return valence if z = 0
z~1 ;y 1 / return body if z = 1
z~2 ;y 0 / return name if z = 2
~7=4:y ;E[z;y] / evaluate non-function
y z]}[`"+";{:[@z;(x;y)z;x>#z;pro[y
;z];{y,,dot[x;z]}[y]. cut[x;z]]}[2][+]])

that nasty thing in position 2 is the ck + function.

so yes, i think `+ (not the character quote - this is new syntax)
would
produce just this:

10 20 `+

but i don't actually think joy should add this notation.

I'm aware that Joy doesn't use that syntax yet, but honestly, that's
because
Joy wasn't designed with the possibility of [+] first in mind.

-Billy


To unsubscribe from this group, send an email to:
concatenative-unsubscribe@egroups.com



Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/

Martin Young — 2003-07-10 23:05:32

On Thu, 2003-07-10 at 19:44, Tanksley, William D. Jr. wrote:
> From: stevan apter [mailto:sa@...]
> >i hope i'm not exhausting everyone's patience by nattering
> >on about this. i think i have a story which rationalizes
> >the presence of unquoted primitives on the stack.
>
> I agree that function references belong on the stack, and can already be
> placed there by Joy. The confusion is in the word "unquoted". In order to
> get on the stack they were in fact quoted -- otherwise they would have been
> executed. So "unquoted" isn't the right word; "unlisted" might be better.

I'm suddenly confused again.

I don't understand the distinction between + (as it may appear on the
stack) and + (as it appears in a quotation in a Joy program). It is,
after all, just a symbol. The only time it become special is when it
appears at the head of the current program.

I've always seen Joy as an exercise in tree rewriting. It's clear that
any Joy program (which doesn't include implicit recursion) can be
written as a finite non-cyclical binary tree. For example: [ 2 3 + ] i
can be written as (where _|_ is bottom).

|
/\
/ \
/ /\
/ i _|_
/\
2 /\
3 /\
+ _|_

The act of execution is to apply rewrite rules to the tree. In this
case we'd start with the right-most branch and use the rule which says
that any tree of this form...

|
/\
/ /\
/ i <rest>
/\
p0 /\
p1 ...
\
_|_

...should be rewritten as...

|
/\
p0 /\
p1 ...
\
<rest>

...and rewriting continues at the lowest/rightmost level of change from
the previous rewrite so in this case 2 3 + would be rewritten as 5.

With this view quotation has no meaning. It's simply a convenience used
for discussing the concrete syntax of Joy. Wherever a symbol appears in
the program tree, it's just a symbol which may (or may not) become
subject to a rewrite at some point.

It seems to me that a distinction between quoted and unquoted operators
is an artifact of the language Manfred uses to talk about Joy.

Similarly I think to make a distinction between symbols (your '+, for
example) and functions (your +) it to move away from concatenative
programming (but perhaps this is not indeliberate?).

In Joy, anything, when encountered at the head of the current program
causes some effect on the stack. A literal may push its own value onto
the stack, just as "drop", for example, removes an item from the top of
stack. The point, as I see it, is that they're all the same - the
distinction between values and functions is entirely dissolved. One
simply concatenates "things", one does not invoke functions on values.

ISTM that the things you're adding to your language get around some
difficulties in Joy's concrete syntax. However, a better concatenative
language (than Joy) could yield the same benefits without introducing so
many new concepts.

--
Martin Young, at home.

stevan apter — 2003-07-11 00:28:29

----- Original Message -----
From: "Martin Young" <martin@...>
To: <concatenative@yahoogroups.com>
Sent: Thursday, July 10, 2003 7:05 PM
Subject: RE: [stack] [+] first: second thoughts


> On Thu, 2003-07-10 at 19:44, Tanksley, William D. Jr. wrote:
> > From: stevan apter [mailto:sa@...]
> > >i hope i'm not exhausting everyone's patience by nattering
> > >on about this. i think i have a story which rationalizes
> > >the presence of unquoted primitives on the stack.
> >
> > I agree that function references belong on the stack, and can already be
> > placed there by Joy. The confusion is in the word "unquoted". In order to
> > get on the stack they were in fact quoted -- otherwise they would have been
> > executed. So "unquoted" isn't the right word; "unlisted" might be better.
>
> I'm suddenly confused again.

isn't it great when that happens?

>
> I don't understand the distinction between + (as it may appear on the
> stack) and + (as it appears in a quotation in a Joy program). It is,
> after all, just a symbol. The only time it become special is when it
> appears at the head of the current program.
>
> I've always seen Joy as an exercise in tree rewriting. It's clear that
> any Joy program (which doesn't include implicit recursion) can be
> written as a finite non-cyclical binary tree. For example: [ 2 3 + ] i
> can be written as (where _|_ is bottom).
>
> |
> /\
> / \
> / /\
> / i _|_
> /\
> 2 /\
> 3 /\
> + _|_
>
> The act of execution is to apply rewrite rules to the tree. In this
> case we'd start with the right-most branch and use the rule which says
> that any tree of this form...
>
> |
> /\
> / /\
> / i <rest>
> /\
> p0 /\
> p1 ...
> \
> _|_
>
> ...should be rewritten as...
>
> |
> /\
> p0 /\
> p1 ...
> \
> <rest>
>
> ...and rewriting continues at the lowest/rightmost level of change from
> the previous rewrite so in this case 2 3 + would be rewritten as 5.
>
> With this view quotation has no meaning. It's simply a convenience used
> for discussing the concrete syntax of Joy. Wherever a symbol appears in
> the program tree, it's just a symbol which may (or may not) become
> subject to a rewrite at some point.
>
> It seems to me that a distinction between quoted and unquoted operators
> is an artifact of the language Manfred uses to talk about Joy.
>
> Similarly I think to make a distinction between symbols (your '+, for
> example) and functions (your +) it to move away from concatenative
> programming (but perhaps this is not indeliberate?).
>
> In Joy, anything, when encountered at the head of the current program
> causes some effect on the stack. A literal may push its own value onto
> the stack, just as "drop", for example, removes an item from the top of
> stack. The point, as I see it, is that they're all the same - the
> distinction between values and functions is entirely dissolved. One
> simply concatenates "things", one does not invoke functions on values.
>
> ISTM that the things you're adding to your language get around some
> difficulties in Joy's concrete syntax. However, a better concatenative
> language (than Joy) could yield the same benefits without introducing so
> many new concepts.

i assume that you're addressing billy here, so feel free to
disregard my comments.

i agree that the distinction between values and functions is
not the right one to draw. everything on the stack is a value:
integers, floats, characters, and functions are atomic values,
and lists and sets are non-atomic assemblies whose terminals
are atoms. + on the stack is not a "function-reference", or
a "symbol" - it's a first-class function.

i'm not sure i understand what you mean by "difficulties in
joy's concrete syntax". do you mean that joy only provides
sneaky means to get functions on the stack (first, unstack,
i &c.)

in any case, it would be interesting to hear what you have in
mind. (think of posting as a way of transferring confusion
to your readers.)


>
> --
> Martin Young, at home.
>
>
>
> To unsubscribe from this group, send an email to:
> concatenative-unsubscribe@egroups.com
>
>
>
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
>
>

John Cowan — 2003-07-11 04:16:50

Martin Young scripsit:

> In Joy, anything, when encountered at the head of the current program
> causes some effect on the stack. A literal may push its own value onto
> the stack, just as "drop", for example, removes an item from the top of
> stack. The point, as I see it, is that they're all the same - the
> distinction between values and functions is entirely dissolved. One
> simply concatenates "things", one does not invoke functions on values.

I don't agree there. 4 as a function pushes 4 on the stack, but the 4
that is on the stack is not a function, it's an integer.

--
Schlingt dreifach einen Kreis vom dies! John Cowan <jcowan@...>
Schliesst euer Aug vor heiliger Schau, http://www.reutershealth.com
Denn er genoss vom Honig-Tau, http://www.ccil.org/~cowan
Und trank die Milch vom Paradies. -- Coleridge (tr. Politzer)

Martin Young — 2003-07-11 06:56:11

On Fri, 2003-07-11 at 01:28, stevan apter wrote:
> i agree that the distinction between values and functions is
> not the right one to draw. everything on the stack is a value:
> integers, floats, characters, and functions are atomic values,
> and lists and sets are non-atomic assemblies whose terminals
> are atoms. + on the stack is not a "function-reference", or
> a "symbol" - it's a first-class function.

Yes. It's a first class function in the same way that "2" on the stack
is a first class function. They merely have different stack effects.

> i'm not sure i understand what you mean by "difficulties in
> joy's concrete syntax". do you mean that joy only provides
> sneaky means to get functions on the stack (first, unstack,
> i &c.)

I should probably have said "difficulties with Joy as an implementation
of conatenative programming", rather than just the syntax of Joy.

But yes, that's one example.

Here's another: Billy has stated that he wants to be able to iterate
over a heterogeneous list distinguishing between lists and functions.
To achieve this he's introduced a new type of data, the program,
distinct from lists, and some new semantics for quoting individual
values and compound values.

A more mature concatenative language might provide a means for tagging
lists with extra information without adding new types and semantics. In
this case the underlying implementation might be this:

Let's take the list [ [ 1 2 3 ] [ + ] [ foo ] [ 2 - ] ]. We want to
iterate over it doing something different for values than for
"functions" (although as I said earlier I believe this distinction to be
spurious).

I believe the essence of Billy's suggestion is that we introduce a new
type and render the list as [ [ 1 2 3 ] { + } [ foo ] { 2 - } ].

Instead the list could be written as

[ [ val [ 1 2 3 ] ] [ func [ + ] ] [ [ val [ foo ] ] [ func [ 2 - ] ] ]

and the iterator could programatically distinguish between lists of
values and "functions". It makes the program a little more complex to
write but doesn't require the language itself to be modified.

A different language than Joy might have a means for attaching tags to
lists such that on creation a list can be marked as either a value or a
function without altering the structure of the list itself.

For example:

[ 1 2 3 ] value tag

might tag the given list as a value. The tag is only seen again when a
word (maybe tagof) extracts the tag.

I believe this could be added to a concatenative language without
needing new types and semantics. It's down to the language offering
flexible primitives and a healthy does of syntactic sugar.

Now I'm not suggesting that Joy should use this type of tagging, or that
Billy should adopt it. I'm merely suggesting that one could achieve the
same goals without modifying the list==program paradigm of Joy.

P.S.

Just after writing this it occured to me that the list could also be
written as

[ [ [ 1 2 3 ] ] [ + ] [ [ foo ] ] [ 2 - ] ]

The iterator can take each top-level element of the list, and execute
each of it's elements. In the case of the double quoted "values" the
result of executing will be to push the value but the single quoted
"function" will be executed.

--
Martin Young, at home.

Martin Young — 2003-07-11 07:01:11

On Fri, 2003-07-11 at 05:16, John Cowan wrote:
> Martin Young scripsit:
>
> > In Joy, anything, when encountered at the head of the current program
> > causes some effect on the stack. A literal may push its own value onto
> > the stack, just as "drop", for example, removes an item from the top of
> > stack. The point, as I see it, is that they're all the same - the
> > distinction between values and functions is entirely dissolved. One
> > simply concatenates "things", one does not invoke functions on values.
>
> I don't agree there. 4 as a function pushes 4 on the stack, but the 4
> that is on the stack is not a function, it's an integer.

As I see it, talking about "4 as a function" is adding unnecessary
terminology. Or, rather, it's terminology that makes concatenative
programming easier to talk about but has no meaning in the language
itself.

A 4 at the front of the current program causes the tree to be rewritten
with a 4 on the stack and the 4 removed from the program. The nature of
the 4 doesn't change - it's merely moved.

--
Martin Young, at home.

stevan apter — 2003-07-11 12:30:34

----- Original Message -----
From: "Martin Young" <martin@...>
To: <concatenative@yahoogroups.com>
Sent: Friday, July 11, 2003 2:56 AM
Subject: Re: [stack] [+] first: second thoughts
:

>
> Just after writing this it occured to me that the list could also be
> written as
>
> [ [ [ 1 2 3 ] ] [ + ] [ [ foo ] ] [ 2 - ] ]
>
> The iterator can take each top-level element of the list, and execute
> each of it's elements. In the case of the double quoted "values" the
> result of executing will be to push the value but the single quoted
> "function" will be executed.

some thoughts:

somewhere manfred must have a canonical definition of "concatenative
programming language". meanwhile, my working definition is:

(1) lists are quotations (lazily evaluated)
(2) programs are lists (and lists are programs)
(3) program execution is disquotation
(4) program construction is concatenation
(5) every value is a map S -> S

in particular, i wouldn't refer to + or ifte as programs - they are
functions; or, if you prefer, "program atoms".

a few days ago, i tried to set out an argument for a different
semantics, in which all programs were atoms, not lists. my argument
was that, if you wanted to have program arrays (in addition to lists
of programs) then you'd wind up attributing contradictory properties
to e.g. [+ *]. is it a program which eats three items from the stack,
or a list, each of whose elements eats two items? in joy, it is both,
and that's ok, since e.g. [+ *] transpose doesn't produce an function:

2 3 [+ *] transpose
5 6

at this point, the argument from program arrays is the *only* rationale
i can come up with for program atoms. if you think program arrays are
too obscure, or not useful, then you won't be persuaded.

"concatenation" refers to how we build up a program from elements:

[2] [3] concat [+] concat [4] concat [*] concat
[2 3 + 4 *]

joy is not non-applicative because it is concatenative (property 4),
but rather because of property 5: no polyadic functions, no named
parameters. joy could be made applicative (without ceasing to be
concatenative) by requiring that programs have the structure:

[[args] [ress] body]

e.g.

[[x y z] [w] x y + x z + *]

disquoting a program causes elements from the stack to be mapped
to elements in the arg-list and substituted into the body, which is
then executed. the res-list specifies how the result is to be
mapped back to the truncated stack. for example, a program which
eats 3 args and returns 2 ress has the form

[[x y z][u v] ..]

and its stack effect is:

S x y z -> S u v

this would prevent being able to write things like:

[[first 10 =] [uncons] [cons] ifte]

since depending on its first arg, it either takes one arg and
returns two ress, or takes two args and returns one.

(how then could the interpreter tell the difference between the
list [[x y z] * +] and the program, written the same way? what
about [1 2 3]? would it have to be written [[] [x y z] 1 2 3]?
perhaps the arg and res lists aren't lists, but some other kind
thing - [{x y z} * +] - or programs aren't lists, but some other
kind of thing - {[x y z] * +} ...)


>
> --
> Martin Young, at home.
>
>
>
> To unsubscribe from this group, send an email to:
> concatenative-unsubscribe@egroups.com
>
>
>
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
>
>

Tanksley, William D. Jr. — 2003-07-11 16:11:26

From: stevan apter [mailto:sa@...]
>somewhere manfred must have a canonical definition of "concatenative
>programming language".

I'm pretty sure I've read it on his website. However, I suspect it wasn't in
a paper of its own. Manfred, let's come up with something and put it on the
website prominently.

> meanwhile, my working definition is:

Incorrect. Sorry :-). Manfred lists quite a few languages as concatenative
which lack all but one of your properties.

A concatenative language is one which is based on function concatenation
implying function composition. That's the only rule.

A purely concatenative language lacks features which make certain
consequences of concatenativity unreachable. For example, a purely
concatenative language won't access its own source, like Forth does.

> (1) lists are quotations (lazily evaluated)

Not at all. In fact, this is a non-concatenative subset of Joy.

> (2) programs are lists (and lists are programs)

This isn't true of Joy; although lists are programs, programs aren't always
lists.

Consider:

DEFINE mine == 3 4 +.
[mine] first first
?

> (3) program execution is disquotation

This is a consequence of concatenativity: dequoting is sufficient for
execution. It's not true for lambda-based languages, since you have to do
substitution as well.

> (4) program construction is concatenation

This is the core of the definition, although you forgot to mention how
concatenation affects functions: it composes them.

> (5) every value is a map S -> S

Yup.

>in particular, i wouldn't refer to + or ifte as programs - they are
>functions; or, if you prefer, "program atoms".

True.

>a few days ago, i tried to set out an argument for a different
>semantics, in which all programs were atoms, not lists.

I'm not sure that programs have to be atoms; I'm just not sure that they
have to be lists, either. Concatenativity does allow us to perform certain
manipulations on programs: any program may be split into two parts, and both
parts will be programs; and any two parts may be concatenated and the result
will be a program. There's no reason not to allow those operations (aside
from implementation complexity, but that can be designed around).

>at this point, the argument from program arrays is the *only* rationale
>i can come up with for program atoms.

In general being able to use functions as data makes it helpful to be able
to treat named functions and quotations equivalently. Right now they're not
very similar.

>joy is not non-applicative because it is concatenative (property 4),
>but rather because of property 5: no polyadic functions, no named
>parameters. joy could be made applicative (without ceasing to be
>concatenative) by requiring that programs have the structure:
> [[args] [ress] body]
>e.g.
> [[x y z] [w] x y + x z + *]

This actually does make it entirely non-concatenative, since no subset of
the language allows a valid function written using it to be split into two
parts, with both parts being valid functions.

This language violates what I called the core definition because your
parameters "magically" ferry data around; they're not functions from the
stack to the stack, but rather functions from the stack and some magical
place to the stack. This extra dependance is easy to rationalize when the
magical place is the only possible data source; but when it's the only way
to get parameters...

I have seen a concatenative or semi-concatenative (I'm not sure) language
that did something like what you're describing. The one difference is that
rather than having programs start with a list of named variables, they
started with a list of types of input and types of return. The compiler kept
track of input versus return on a "type stack", and thus staticly checked
the language at the same time as it compiled. Elegant.

>(how then could the interpreter tell the difference between the
>list [[x y z] * +] and the program, written the same way? what
>about [1 2 3]? would it have to be written [[] [x y z] 1 2 3]?
>perhaps the arg and res lists aren't lists, but some other kind
>thing - [{x y z} * +] - or programs aren't lists, but some other
>kind of thing - {[x y z] * +} ...)

It wouldn't have to -- in a Joy-like language those things would be
determined by who uses them. In a cK-like language it'd be determined by
syntax.

-Billy

sa@dfa.com — 2003-07-11 16:46:22

billy writes:

From: stevan apter [mailto:sa@...]
>somewhere manfred must have a canonical definition of "concatenative
>programming language".

I'm pretty sure I've read it on his website. However, I suspect it wasn't
in
a paper of its own. Manfred, let's come up with something and put it on the
website prominently.

> meanwhile, my working definition is:

Incorrect. Sorry :-). Manfred lists quite a few languages as concatenative
which lack all but one of your properties.

ok

A concatenative language is one which is based on function concatenation
implying function composition. That's the only rule.

ok

A purely concatenative language lacks features which make certain
consequences of concatenativity unreachable. For example, a purely
concatenative language won't access its own source, like Forth does.

i can't remember enough forth to comment.

> (1) lists are quotations (lazily evaluated)

Not at all. In fact, this is a non-concatenative subset of Joy.

ok

> (2) programs are lists (and lists are programs)

This isn't true of Joy; although lists are programs, programs aren't always
lists.

Consider:

DEFINE mine == 3 4 +.
[mine] first first
?

in ck, the answer is 3.


> (3) program execution is disquotation

This is a consequence of concatenativity: dequoting is sufficient for
execution. It's not true for lambda-based languages, since you have to do
substitution as well.

ok

> (4) program construction is concatenation

This is the core of the definition, although you forgot to mention how
concatenation affects functions: it composes them.

ok - right

> (5) every value is a map S -> S

Yup.

>in particular, i wouldn't refer to + or ifte as programs - they are
>functions; or, if you prefer, "program atoms".

True.

>a few days ago, i tried to set out an argument for a different
>semantics, in which all programs were atoms, not lists.

I'm not sure that programs have to be atoms; I'm just not sure that they
have to be lists, either. Concatenativity does allow us to perform certain
manipulations on programs: any program may be split into two parts, and
both
parts will be programs; and any two parts may be concatenated and the
result
will be a program. There's no reason not to allow those operations (aside
from implementation complexity, but that can be designed around).

right - i was thinking programs were either primitives or
constructed from lists, but in both cases, atomic. so if
you had

p = {+ *}
q = {first / -}

then to get, say,

r = {+ * first / -}

you would say

[p] disclose [q] disclose concat enclose

not "pure concatenation", although construction of r requires
concatenation. p q concat is a list of two function atoms.

>at this point, the argument from program arrays is the *only* rationale
>i can come up with for program atoms.

In general being able to use functions as data makes it helpful to be able
to treat named functions and quotations equivalently. Right now they're not
very similar.

i guess i still don't understand why [+ -] isn't a list of
two data objects (function atoms)

>joy is not non-applicative because it is concatenative (property 4),
>but rather because of property 5: no polyadic functions, no named
>parameters. joy could be made applicative (without ceasing to be
>concatenative) by requiring that programs have the structure:
> [[args] [ress] body]
>e.g.
> [[x y z] [w] x y + x z + *]

This actually does make it entirely non-concatenative, since no subset of
the language allows a valid function written using it to be split into two
parts, with both parts being valid functions.

i hadn't (haven't) thought through the consequences of
this, but your comments above and below seem quite correct.

This language violates what I called the core definition because your
parameters "magically" ferry data around; they're not functions from the
stack to the stack, but rather functions from the stack and some magical
place to the stack. This extra dependance is easy to rationalize when the
magical place is the only possible data source; but when it's the only way
to get parameters...

I have seen a concatenative or semi-concatenative (I'm not sure) language
that did something like what you're describing. The one difference is that
rather than having programs start with a list of named variables, they
started with a list of types of input and types of return. The compiler
kept
track of input versus return on a "type stack", and thus staticly checked
the language at the same time as it compiled. Elegant.

oh yes, i can see how that would work. nice.

>(how then could the interpreter tell the difference between the
>list [[x y z] * +] and the program, written the same way? what
>about [1 2 3]? would it have to be written [[] [x y z] 1 2 3]?
>perhaps the arg and res lists aren't lists, but some other kind
>thing - [{x y z} * +] - or programs aren't lists, but some other
>kind of thing - {[x y z] * +} ...)

It wouldn't have to -- in a Joy-like language those things would be
determined by who uses them. In a cK-like language it'd be determined by
syntax.

that last paragraph was written in a rush. i don't think
it makes much sense.

-Billy

thanks billy

Martin Young — 2003-07-11 17:52:24

On Fri, 2003-07-11 at 17:11, Tanksley, William D. Jr. wrote:
> > (2) programs are lists (and lists are programs)
>
> This isn't true of Joy; although lists are programs, programs aren't always
> lists.
>
> Consider:
>
> DEFINE mine == 3 4 +.
> [mine] first first
> ?

I've been thinking about this problem too. It disturbs me. I'm sure I
read somewhere on Manfred's site that a program can always be replaced
by its definition. Clearly this isn't true, but it would be nice if it
was.

As far as I'm concerned the definition of words is a little bit magical
- it's something that happens before the program is started, outwith the
language itself. Also, in Monkey at least, one can't (by design) define
new words during program execution (or redefine extant ones).

I've been pondering the consequences of making definitions atomic. I'm
already halfway there with Monkey's types (where a program is denoted as
{ ...} and is detectably different from a list). What happens if we
make a defined word exactly equivalent to its definition? That is (in
Monkey syntax, sorry):

mine == {{ 3 4 + }}
[ mine ] first

May leave either { 3 4 + } or mine. It doesn't matter which because
they're equivalent.

Thus...

[ mine ] first first

...wouldn't work because programs can't be deconstructed, only
concatenated.

OTOH...

{ 3 4 + } mine =
False

...because the first program just happens to have the same content as
mine. It's not actually the same.

With this in place any word can be replaced by its definition because
all the operations which previously caused problems are not allowed on
programs.

I suspect I may be have arrived (sometime later than others) at the
position you (Billy) were expounding previously re: programs as a
separate type.

> > (3) program execution is disquotation
>
> This is a consequence of concatenativity: dequoting is sufficient for
> execution. It's not true for lambda-based languages, since you have to do
> substitution as well.

This is interesting. I'm not certain that dequoting is always
sufficient for execution. One could build an odd concatenative language
which allows lists to be dequoted without executing them.

--
Martin Young, at home.

Martin Young — 2003-07-11 17:44:21

On Fri, 2003-07-11 at 13:30, stevan apter wrote:
> in particular, i wouldn't refer to + or ifte as programs - they are
> functions; or, if you prefer, "program atoms".

I'm happy to call them functions or program atoms. What's important to
me is that there is no dichotomy between things like + and ifte and what
might be called literal values like 6 and 'foo. I feel that these
denotations are aids only to human understanding of programs, not
aspects of the programs themselves.

> a few days ago, i tried to set out an argument for a different
> semantics, in which all programs were atoms, not lists. my argument
> was that, if you wanted to have program arrays (in addition to lists
> of programs) then you'd wind up attributing contradictory properties
> to e.g. [+ *]. is it a program which eats three items from the stack,
> or a list, each of whose elements eats two items? in joy, it is both,

To me, it's a list containing two symbols/program atoms/things (whatever
we want to call them). It's the combinator which uses such a list which
decides whether it's a program of length 2 or an array or programs of
length 1. Similarly the symbol/program atom/thing 2 may denote the
second natural number, or it might denote a state in a state machine.
The meaning of 2 is entirely dependent on the combinator which uses it.

If one wanted to write a polymorphic combinator which could iterate over
a list of these program/arrays, then each datum should describe it's own
intended type. That is, type information should become first class
data.

For instance, I've added n-ary tuples to Monkey. I write these as a
list of elements in round brackets. If I needed to distinguish between
a program of length N and an array (size N) of programs of length 1, I'd
use a tuple to hold the list and an atom/symbol/whatever denoting it's
type. E.g.

( 'prog [ + * ] )
or
( 'array [ + * ] )

The combinator would then take a list of arity/2 tuples and
programatically do whatever was necessary in either case.

Thus the specifics of the problem being solved remain in the domain of
the program, not in the domain of the language itself. One could, for
example, use the list [ 2 + 3 + 4 + 5 + ] as an array of 4 programs of
length 2 without modifying the language again e.g. ( 'prog2 [ 2 + 3 + 4
+ 5 + ] ).

With regard to efficiency, I have some hope that I'll one day have time
to write an optimiser which can eliminate programatic type checking
using type inference and similar techniques. In any case, I believe
it's a problem for the language implementor to solve, not the language
designer.

> and that's ok, since e.g. [+ *] transpose doesn't produce an function:
>
> 2 3 [+ *] transpose
> 5 6
>
> at this point, the argument from program arrays is the *only* rationale
> i can come up with for program atoms. if you think program arrays are
> too obscure, or not useful, then you won't be persuaded.

To be honest I don't understand why they're necessary. That is not to
say I think they're not necessary, I just don't have enough knowledge
and experience to judge.

--
Martin Young, at home.

Tanksley, William D. Jr. — 2003-07-11 18:01:05

From: Martin Young [mailto:martin@...]
>...wouldn't work because programs can't be deconstructed, only
>concatenated.

That's one way to fix the problem, yes. It would also be permissible to
allow programs to be split into subprograms (but not allow their contents to
be extracted).

>>> (3) program execution is disquotation

>>This is a consequence of concatenativity: dequoting is sufficient for
>>execution. It's not true for lambda-based languages, since
>>you have to do substitution as well.

>This is interesting. I'm not certain that dequoting is always
>sufficient for execution. One could build an odd
>concatenative language which allows lists to be dequoted without
>executing them.

You're mixing up "dequoting" and "delisting". You can take all the things
out of a list and dump them on the stack without executing them; but if you
dequote, you're undoing the process of quotation, which _prevented_
execution. Therefore, you're allowing execution.

>Martin Young, at home.

-Billy

sa@dfa.com — 2003-07-11 18:37:07

[martin said:]

On Fri, 2003-07-11 at 17:11, Tanksley, William D. Jr. wrote:
> > (2) programs are lists (and lists are programs)
>
> This isn't true of Joy; although lists are programs, programs aren't
always
> lists.
>
> Consider:
>
> DEFINE mine == 3 4 +.
> [mine] first first
> ?

i was mistaken when i said the answer in ck was 3. here's a
transcript of the session, with comments:

[3 4 +] `mine def \ define mine
`mine \ returns a symbol of the definiens
mine \ evaluate mine
7 \ 3 4 +
[mine] first \ first of mine is ..
mine \ .. mine
first \ first of that is ..
mine \ .. you've hit bottom

I've been thinking about this problem too. It disturbs me. I'm sure I
read somewhere on Manfred's site that a program can always be replaced
by its definition. Clearly this isn't true, but it would be nice if it
was.

As far as I'm concerned the definition of words is a little bit magical
- it's something that happens before the program is started, outwith the
language itself. Also, in Monkey at least, one can't (by design) define
new words during program execution (or redefine extant ones).

i've never understood this restriction. what's the
rationale behind it?

Martin Young — 2003-07-11 19:08:28

On Fri, 2003-07-11 at 19:37, sa@... wrote:
> [martin said:]
>> As far as I'm concerned the definition of words is a little bit magical
>> - it's something that happens before the program is started, outwith the
>> language itself. Also, in Monkey at least, one can't (by design) define
>> new words during program execution (or redefine extant ones).
>
> i've never understood this restriction. what's the
> rationale behind it?

I think it allows better automatic manipulation of programs. I want a
word to always mean the same thing.

For example, take these definitions:

foo == {{ 1 2 }}
bar == {{ drop drop }}
boz == {{ foo bar }}

It's a simple optimisation to see the boz can be replaced by the empty
definition. I can therefore, assuming nobody tries to look inside
definitions, remove all instances of boz from my program. OTOH if I
allow foo or bar to be redefined my optimisation is invalid.

I don't have any other markedly different examples on-hand but, by
analogy to functional programming, it's referential transparency which
allows many of their clever optimisations. It feels to me that allowing
words to be redefined at runtime breaks Joy's equivalent of referential
transparency.

--
Martin Young, at home.

Tanksley, William D. Jr. — 2003-07-11 22:05:18

From: Martin Young [mailto:martin@...]
>Let's take the list [ [ 1 2 3 ] [ + ] [ foo ] [ 2 - ] ]. We want to
>iterate over it doing something different for values than for
>"functions" (although as I said earlier I believe this
>distinction to be spurious).

Actually, this doesn't capture the essence of what I wanted -- I want to be
able to iterate over a tree, treating data and programs alike (that is,
having them produce their stack effect).

>I believe the essence of Billy's suggestion is that we introduce a new
>type and render the list as [ [ 1 2 3 ] { + } [ foo ] { 2 - } ].
>Instead the list could be written as
>[ [ val [ 1 2 3 ] ] [ func [ + ] ] [ [ val [ foo ] ] [ func [ 2 - ] ] ]
>and the iterator could programatically distinguish between lists of
>values and "functions". It makes the program a little more complex to
>write but doesn't require the language itself to be modified.

If you plan to design many languages but write very few programs, that
tradeoff makes a LOT of sense. I think, however, that most language
designers admit at least a LITTLE bit of indebtedness to the programmers who
use their languages; they will therefore prefer to do a little more work so
that the programmers can do less.

>A different language than Joy might have a means for attaching tags to
>lists such that on creation a list can be marked as either a value or a
>function without altering the structure of the list itself.

Yes. Actually, my plan is to take a slightly different approach: my first
prototype for my language doesn't support types as such, only scalars and
arrays. Thus, my tag merely states the rank of the item; if the rank is 0,
the item's a scalar, and if the rank's more, the item is an array.

>I'm merely suggesting that one could achieve the
>same goals without modifying the list==program paradigm of Joy.

You can't apply the same manipulations to lists that you can to programs,
nor can you apply the same manipulations to programs that you can to lists.

>Just after writing this it occured to me that the list could also be
>written as
>[ [ [ 1 2 3 ] ] [ + ] [ [ foo ] ] [ 2 - ] ]
>The iterator can take each top-level element of the list, and execute
>each of it's elements. In the case of the double quoted "values" the
>result of executing will be to push the value but the single quoted
>"function" will be executed.

This is great for a list, but I want to be able to iterate through trees.

>Martin Young, at home.

-Billy

stevan apter — 2003-07-12 12:16:55

it would be interesting (and useful) to see specs for the various
joy-like languages (or is it more accurate to speak of "joy-
inspired languages"?) - monkey, toy, "tanksley". perhaps there
is a set of "benchmark problems" against which we can compare
these proposals? i get the impression that we're all circling
around a vaguely defined formal center, i just can't bring it
into focus.


----- Original Message -----
From: "Tanksley, William D. Jr." <william.d.tanksley.jr@...>
To: <concatenative@yahoogroups.com>
Sent: Friday, July 11, 2003 6:05 PM
Subject: RE: [stack] [+] first: second thoughts


> From: Martin Young [mailto:martin@...]
> >Let's take the list [ [ 1 2 3 ] [ + ] [ foo ] [ 2 - ] ]. We want to
> >iterate over it doing something different for values than for
> >"functions" (although as I said earlier I believe this
> >distinction to be spurious).
>
> Actually, this doesn't capture the essence of what I wanted -- I want to be
> able to iterate over a tree, treating data and programs alike (that is,
> having them produce their stack effect).
>
> >I believe the essence of Billy's suggestion is that we introduce a new
> >type and render the list as [ [ 1 2 3 ] { + } [ foo ] { 2 - } ].
> >Instead the list could be written as
> >[ [ val [ 1 2 3 ] ] [ func [ + ] ] [ [ val [ foo ] ] [ func [ 2 - ] ] ]
> >and the iterator could programatically distinguish between lists of
> >values and "functions". It makes the program a little more complex to
> >write but doesn't require the language itself to be modified.
>
> If you plan to design many languages but write very few programs, that
> tradeoff makes a LOT of sense. I think, however, that most language
> designers admit at least a LITTLE bit of indebtedness to the programmers who
> use their languages; they will therefore prefer to do a little more work so
> that the programmers can do less.
>
> >A different language than Joy might have a means for attaching tags to
> >lists such that on creation a list can be marked as either a value or a
> >function without altering the structure of the list itself.
>
> Yes. Actually, my plan is to take a slightly different approach: my first
> prototype for my language doesn't support types as such, only scalars and
> arrays. Thus, my tag merely states the rank of the item; if the rank is 0,
> the item's a scalar, and if the rank's more, the item is an array.
>
> >I'm merely suggesting that one could achieve the
> >same goals without modifying the list==program paradigm of Joy.
>
> You can't apply the same manipulations to lists that you can to programs,
> nor can you apply the same manipulations to programs that you can to lists.
>
> >Just after writing this it occured to me that the list could also be
> >written as
> >[ [ [ 1 2 3 ] ] [ + ] [ [ foo ] ] [ 2 - ] ]
> >The iterator can take each top-level element of the list, and execute
> >each of it's elements. In the case of the double quoted "values" the
> >result of executing will be to push the value but the single quoted
> >"function" will be executed.
>
> This is great for a list, but I want to be able to iterate through trees.
>
> >Martin Young, at home.
>
> -Billy
>
>
> To unsubscribe from this group, send an email to:
> concatenative-unsubscribe@egroups.com
>
>
>
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
>
>

stevan apter — 2003-07-12 14:31:02

----- Original Message -----
From: "Tanksley, William D. Jr." <william.d.tanksley.jr@...>
To: <concatenative@yahoogroups.com>
Sent: Friday, July 11, 2003 6:05 PM
Subject: RE: [stack] [+] first: second thoughts


>
> Actually, this doesn't capture the essence of what I wanted -- I want to be
> able to iterate over a tree, treating data and programs alike (that is,
> having them produce their stack effect).
[:]
> This is great for a list, but I want to be able to iterate through trees.

i've added the distinct category "function atom" to ck:

1 function

turns on the desired datatype:

2 3 4 5 [[{+ *} {- %}] {+ - %}]
2 3 4 5 [[{+ *} {- %}] {+ - %}] <- a tree of function-atoms
[i] treemap
2 3 4 5 [[27 -3.0] -0.3333333] <- tree-structure preserved

functions execute immediately:

2 3 4 {+ *}
14

a function is an atomic object of type 7:

[{+ *}] first @:
1

[{+ *}] first type
7

functions never match primitives:

[+] first [{+}] first
+ {+}
equal
0

the empty function applies to nothing, evaluates to nothing:

1 2 3 {}
1 2 3

[{}] first
{}



cf. www.nsl.com/papers/ck.htm, www.nsl.com/k/ck.k


>
> >Martin Young, at home.
>
> -Billy
>
>
> To unsubscribe from this group, send an email to:
> concatenative-unsubscribe@egroups.com
>
>
>
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
>
>

stevan apter — 2003-07-12 14:56:01

i forgot to say that this facility amounts *precisely* to the
capacity to manufacture new primitives from existing vocabulary.

that is,

[swap concat]

has the same effect as swoncat, but the first is a program - a
list, and the second a primitive:

[swap concat] first
swap
[swoncat] first
swoncat

whereas

{swap concat}

is a function-atom, implemented with the same machinery as swoncat.

this was the key implementation insight.


----- Original Message -----
From: "stevan apter" <sa@...>
To: <concatenative@yahoogroups.com>
Sent: Saturday, July 12, 2003 10:31 AM
Subject: Re: [stack] [+] first: second thoughts


>
> ----- Original Message -----
> From: "Tanksley, William D. Jr." <william.d.tanksley.jr@...>
> To: <concatenative@yahoogroups.com>
> Sent: Friday, July 11, 2003 6:05 PM
> Subject: RE: [stack] [+] first: second thoughts
>
>
> >
> > Actually, this doesn't capture the essence of what I wanted -- I want to be
> > able to iterate over a tree, treating data and programs alike (that is,
> > having them produce their stack effect).
> [:]
> > This is great for a list, but I want to be able to iterate through trees.
>
> i've added the distinct category "function atom" to ck:
>
> 1 function
>
> turns on the desired datatype:
>
> 2 3 4 5 [[{+ *} {- %}] {+ - %}]
> 2 3 4 5 [[{+ *} {- %}] {+ - %}] <- a tree of function-atoms
> [i] treemap
> 2 3 4 5 [[27 -3.0] -0.3333333] <- tree-structure preserved
>
> functions execute immediately:
>
> 2 3 4 {+ *}
> 14
>
> a function is an atomic object of type 7:
>
> [{+ *}] first @:
> 1
>
> [{+ *}] first type
> 7
>
> functions never match primitives:
>
> [+] first [{+}] first
> + {+}
> equal
> 0
>
> the empty function applies to nothing, evaluates to nothing:
>
> 1 2 3 {}
> 1 2 3
>
> [{}] first
> {}
>
>
>
> cf. www.nsl.com/papers/ck.htm, www.nsl.com/k/ck.k
>
>
> >
> > >Martin Young, at home.
> >
> > -Billy
> >
> >
> > To unsubscribe from this group, send an email to:
> > concatenative-unsubscribe@egroups.com
> >
> >
> >
> > Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
> >
> >
>
>
>
> To unsubscribe from this group, send an email to:
> concatenative-unsubscribe@egroups.com
>
>
>
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
>
>

stevan apter — 2003-07-12 16:07:18

a final note on this.

we want to be able to construct new functions from existing
functions programmatically -- "{}" is just notation. so i've
added

[P] enclose -> {P}
{P} disclose -> [P]

disclose of a primitive is an atom, viz. the primitive itself:

{+} disclose
+

enclose of the empty list is the empty function:

[] enclose
{}

to construct {+ * - /} from {+ *} and {- /}, disclose, concatenate,
and enclose:

[{+ *}] disclose [{- /}] disclose concat enclose
{+ * - /}


----- Original Message -----
From: "stevan apter" <sa@...>
To: <concatenative@yahoogroups.com>
Sent: Saturday, July 12, 2003 10:56 AM
Subject: Re: [stack] [+] first: second thoughts


> i forgot to say that this facility amounts *precisely* to the
> capacity to manufacture new primitives from existing vocabulary.
>
> that is,
>
> [swap concat]
>
> has the same effect as swoncat, but the first is a program - a
> list, and the second a primitive:
>
> [swap concat] first
> swap
> [swoncat] first
> swoncat
>
> whereas
>
> {swap concat}
>
> is a function-atom, implemented with the same machinery as swoncat.
>
> this was the key implementation insight.
>
>
> ----- Original Message -----
> From: "stevan apter" <sa@...>
> To: <concatenative@yahoogroups.com>
> Sent: Saturday, July 12, 2003 10:31 AM
> Subject: Re: [stack] [+] first: second thoughts
>
>
> >
> > ----- Original Message -----
> > From: "Tanksley, William D. Jr." <william.d.tanksley.jr@...>
> > To: <concatenative@yahoogroups.com>
> > Sent: Friday, July 11, 2003 6:05 PM
> > Subject: RE: [stack] [+] first: second thoughts
> >
> >
> > >
> > > Actually, this doesn't capture the essence of what I wanted -- I want to be
> > > able to iterate over a tree, treating data and programs alike (that is,
> > > having them produce their stack effect).
> > [:]
> > > This is great for a list, but I want to be able to iterate through trees.
> >
> > i've added the distinct category "function atom" to ck:
> >
> > 1 function
> >
> > turns on the desired datatype:
> >
> > 2 3 4 5 [[{+ *} {- %}] {+ - %}]
> > 2 3 4 5 [[{+ *} {- %}] {+ - %}] <- a tree of function-atoms
> > [i] treemap
> > 2 3 4 5 [[27 -3.0] -0.3333333] <- tree-structure preserved
> >
> > functions execute immediately:
> >
> > 2 3 4 {+ *}
> > 14
> >
> > a function is an atomic object of type 7:
> >
> > [{+ *}] first @:
> > 1
> >
> > [{+ *}] first type
> > 7
> >
> > functions never match primitives:
> >
> > [+] first [{+}] first
> > + {+}
> > equal
> > 0
> >
> > the empty function applies to nothing, evaluates to nothing:
> >
> > 1 2 3 {}
> > 1 2 3
> >
> > [{}] first
> > {}
> >
> >
> >
> > cf. www.nsl.com/papers/ck.htm, www.nsl.com/k/ck.k
> >
> >
> > >
> > > >Martin Young, at home.
> > >
> > > -Billy
> > >
> > >
> > > To unsubscribe from this group, send an email to:
> > > concatenative-unsubscribe@egroups.com
> > >
> > >
> > >
> > > Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
> > >
> > >
> >
> >
> >
> > To unsubscribe from this group, send an email to:
> > concatenative-unsubscribe@egroups.com
> >
> >
> >
> > Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
> >
> >
>
>
>
> To unsubscribe from this group, send an email to:
> concatenative-unsubscribe@egroups.com
>
>
>
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
>
>

stevan apter — 2003-07-13 00:28:22

>
> to construct {+ * - /} from {+ *} and {- /}, disclose, concatenate,
> and enclose:
>
> [{+ *}] disclose [{- /}] disclose concat enclose
> {+ * - /}
>

oops - that should be:

[{+ *}] first disclose [{- /}] first disclose concat enclose

or better:

[concat [first disclose] map [concat] infra enclose first] `fconcat def;
[{+ *}] [{- /}] fconcat
{[+ * - /]}

phimvt@lurac.latrobe.edu.au — 2003-07-14 05:53:52

On Fri, 11 Jul 2003, Tanksley, William D. Jr. wrote:

> From: stevan apter [mailto:sa@...]
> >somewhere manfred must have a canonical definition of "concatenative
> >programming language".
>
> I'm pretty sure I've read it on his website. However, I suspect it wasn't in
> a paper of its own. Manfred, let's come up with something and put it on the
> website prominently.

Yes, good idea, see below.
The term "concatenative language" is due to you, Billy.

[..]

> A concatenative language is one which is based on function concatenation
> implying function composition. That's the only rule.

I say about Joy that it maps the syntactic operation of
concatenation onto the semantic operation of function composition.
That seems to be the core of "concatenative language", too.
So here goes:

A language is concatenative if and only if all its programs
are concatenations of atomic programs, all programs compute
unary functions, and the concatenation of several programs
computes the composition of the functions computed by the
programs.

Concatenative languages do not use lambda abstraction and
do not use the operation of function application. Instead
their effects are obtained by other means.

In all the known concatenative languages most functions
take a stack as argument and yield a stack as value. But some
functions may also take as argument and value a stack together
with a file system. Other extensions are not excluded.

I suggest these three paragraphs should replace the two 3-line
and 4-line paragraphs currently on the concatenative page.
The references to Forth and Postscript in the one-line language
description should be enough.

Just a suggestion. So, let's wait for comments from the group
before you make the change, Billy.

- Manfred

Tanksley, William D. Jr. — 2003-07-14 15:58:34

From: sa@... [mailto:sa@...]
>From: Billy
>>This actually works well if `[+] would otherwise have failed.
>>It wouldn't
>>work in Joy, where executing functions always have full access to the
>>stack.

> in ck, + has access to the whole stack. it's defined:
> S is empty -> +
> S . x -> [x +]
> S . x y -> S . x + y

In Joy, + always has access to the top two items of the system stack. In one
of my ideas for my prototype, + always has access to the top two items of
the stack _for the program it's in_. There's a system stack, but most
combinators that execute their arguments don't give the resulting programs
access to it.

In that language, I would feel justified using your semantics, since a
library programmer would always know when it's safe to say + and expect the
function + to be pushed. In cK, I would almost never feel safe assuming that
+ would result in the function + being pushed, except when working
interactively.

The real problem is that even when I'm working in my hypothetical language
(where I feel safe with a bare + sometimes pushing itself), I still would
never use the ability for + to push itself; I'd rather explicitly say "push
+ on the stack", using a notation like `x or {x}. Otherwise it's just too
easy to hide my intention.

When would you use this feature of cK?

>so yes, i think `+ (not the character quote - this is new syntax)
>would produce just this:
> 10 20 `+
>but i don't actually think joy should add this notation.

I'm not sure about that syntax (I like it), but I do think Joy should do
something to formalise the existance of [+] first.

-Billy

sa@dfa.com — 2003-07-14 18:08:43

[billy wrote:]

In Joy, + always has access to the top two items of the system stack. In
one
of my ideas for my prototype, + always has access to the top two items of
the stack _for the program it's in_. There's a system stack, but most
combinators that execute their arguments don't give the resulting programs
access to it.

In that language, I would feel justified using your semantics, since a
library programmer would always know when it's safe to say + and expect the
function + to be pushed. In cK, I would almost never feel safe assuming
that
+ would result in the function + being pushed, except when working
interactively.

The real problem is that even when I'm working in my hypothetical language
(where I feel safe with a bare + sometimes pushing itself), I still would
never use the ability for + to push itself; I'd rather explicitly say "push
+ on the stack", using a notation like `x or {x}. Otherwise it's just too
easy to hide my intention.

When would you use this feature of cK?

thanks for forcing me to look at this again. i'd forgotten
that i meant to redefine how projection works now that defined
functions are part of ck:

+
+
2 +
{2 +}
2 3 +
5

instead of [stack f], i now build {stack f}.

in answer to your question, i haven't done enough application
programming in any of these languages to have examples at hand.

projection is used in one of my implementation of queues (see
the relevant section of
http://www.nsl.com/papers/ck.htm#Applications).
my feeling was that the potential benefits of projection outweigh
the known benefits of a "short stack" error (debugging). perhaps
i'm mistaken. my experience working with large-scale applications
is that when you need debugging tools, you wind up writing "bespoke"
software. "one-size-fits-all" errors less useful than the theorists
suggest.


>so yes, i think `+ (not the character quote - this is new syntax)
>would produce just this:
> 10 20 `+
>but i don't actually think joy should add this notation.

I'm not sure about that syntax (I like it), but I do think Joy should do
something to formalise the existance of [+] first.

i'm getting less and less bothered by the fact that there's
no "canonical" notation for this operation. i'm waiting to
hear what others have to say.

-Billy


To unsubscribe from this group, send an email to:
concatenative-unsubscribe@egroups.com



Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/

Tanksley, William D. Jr. — 2003-07-14 18:53:44

From: Martin Young [mailto:martin@...]
>Tanksley, William D. Jr. wrote:
>>From: stevan apter [mailto:sa@...]
>>>on about this. i think i have a story which rationalizes
>>>the presence of unquoted primitives on the stack.

>>I agree that function references belong on the stack, and
>>can already be placed there by Joy. The confusion is in
>>the word "unquoted". In order to get on the stack they
>>were in fact quoted -- otherwise they would have been
>>executed. So "unquoted" isn't the right word; "unlisted"
>>might be better.

>I'm suddenly confused again.

Excellent. A uniform state of confusion will serve my purposes quite well.
:-)

>I don't understand the distinction between + (as it may appear on the
>stack) and + (as it appears in a quotation in a Joy program).

There's no difference in these two instances, in theory. Both are quoted
functions. However, in practice Joy makes a distinction: + (as it appears in
a quotation in a Joy program) is a member of a list, ALWAYS. The list [0 +]
is of length 2; it's not equivalent to the list []. The program {0 +} is
equivalent to the program {}, though (when there's an integer on TOS).

>It is, after all, just a symbol.

Not good terminology, but close enough. It's more than a symbol -- it's a
reference to a function. Joy happens to implement that by means of symbols;
Forth does so by pointers. The symbol 'dkfjkdjkjkf, on the other hand, is
NOT a reference to a function (at least not on my computer!).

>The only time it become special is when it
>appears at the head of the current program.

I've never heard that expression before, so I can't answer.

>I've always seen Joy as an exercise in tree rewriting.

I suppose that's natural for someone educated using lambdas. Lambdas are,
after all, an exercise in tree rewriting. Concatenative languages in general
aren't; you can't always express a concatenative program as a static tree.

'ifte' and its relatives are examples in Joy of programs which can't be
treated as a static tree. 'swap' and 'dup' also provide tree effects which
are hard to illustrate simply (although they're still trees).

>It's clear that
>any Joy program (which doesn't include implicit recursion) can be
>written as a finite non-cyclical binary tree.

What about ternary operators?

>For example: [ 2 3 + ] i
>can be written as (where _|_ is bottom).
> |
> /\
> / \
> / /\
> / i _|_
> /\
> 2 /\
> 3 /\
> + _|_

Hmm. May I assume that a ternary operator 't would look like this:

/\
2 /\
3 /\
3 /\
t _|_

? If so, may I point out that a list is a much better data structure for
your purposes than a tree -- and in fact a list is natural for the
manipulations presupposed by concatenative theory, while a tree is not.

Trees are handy, but they aren't natural to concatenative languages.

>With this view quotation has no meaning. It's simply a
>convenience used for discussing the concrete syntax of Joy.
>Wherever a symbol appears in the program tree, it's just a
>symbol which may (or may not) become subject to a rewrite
>at some point.

This would be true if Joy's definition of quotation were single-purpose: a
quotation is a program, nothing else. But it's not. Joy uses quotations as
programs and lists. A program is subject to rewrites; a list certainly is
not. You can't tell the difference between them in Joy.

This means that Joy "quotation" is NOT semanticly meaningless. It has
special meaning to an optimiser, meaning that hinders analysis and
simplification.

My proposal is to split the two meanings so that they can be applied
independantly. Enlistment is handy, so give it brackets. Quotation is handy,
so give it a prefix operator (I think Apter's proposal of ` makes more sense
than my recycling of '). Something else has come of our discussion: some of
us also want a way to specify a true program, something that's open to
optimization but not executed immediately. Apter proposes the syntax {}. I
personally won't be implementing that, since I'm happy with static
definitions; but Joy has more of an emphasis on dynamically constructed
programs, and would probably benefit from this.

>It seems to me that a distinction between quoted and unquoted operators
>is an artifact of the language Manfred uses to talk about Joy.

Nope; it's fundamental. A quoted operator doesn't execute; an unquoted one
does.

>Similarly I think to make a distinction between symbols (your '+, for
>example) and functions (your +) it to move away from concatenative
>programming (but perhaps this is not indeliberate?).

I've not made that distinction in the past, but how could admitting the
truth move away from concatenative programming? It's a simple fact that not
all symbols are functions, and not all functions have symbols.

The distinction I'm trying to make is entirely different: an item which is
supposed to be put into a list, and an item which is supposed to be put into
a program. Either one may be a function.

>In Joy, anything, when encountered at the head of the current program
>causes some effect on the stack. A literal may push its own value onto
>the stack, just as "drop", for example, removes an item from the top of
>stack. The point, as I see it, is that they're all the same - the
>distinction between values and functions is entirely dissolved. One
>simply concatenates "things", one does not invoke functions on values.

There's no difference, indeed, between 6 as a function and 6 as data. There
is, however, a difference between + as a function and + as data.

>Martin Young, at home.

-Billy

phimvt@lurac.latrobe.edu.au — 2003-07-15 04:03:42

There has been a lot of interesting discussion on this topic,
and I have enjoyed it. But I have now changed the subject line
just a bit because I think what I am about to write will indeed
shed some new light. I should have written this much earlier.

IF you are willing to put up with me at my pedantic worst,
THEN please read on,
ELSE jump to the last two paragraphs.

PEDANTRY SWITCH ON

There is only one number seven. If you put it on your stack,
then I can't put it on mine. You cannot have it on your stack
at several different places in your stack either. So whatever
the program '7' does, it must be compatible with the fact
that there is only one number seven. Well, let us say that this
program puts a representation of the number seven on the stack.
There are as many representations as one might need, so you
can do as many pushes as you like, and so can I even at the
same time.

Similarly with other data values. For some, such as for strings,
it may be better to put a pointer to a representation on the
stack. But this is largely an implementation issue. An
implementation could decide never to use pointers to the
representation. Or it could always use a pointer to the
representation, even for representations of numbers. Or it
could, like the current implementation of Joy, use a mixture
of the two approaches, whichever is most efficient. Where
appropriate I'll put the optional 'pointer to' in parentheses.

Most functions are infinite objects, for example the addition
function consists of infinitely many triples of numbers:
the two summands and the resultant sum. You could not even
try to put an infinite object on a stack inside a finite
computer, not even once. Most other functions are infinite
too. So, the program '[+] first' cannot put the addition
function on the stack. We can take a lead from what we do with
the programs '7' and '[7] first', which push a (pointer to)
a representation of the number 7 onto the stack. So the answer
must be: the program '[+] first' pushes a (pointer to) a
representation of the addition function. By a Cantorian
argument, most functions cannot have a representation, but
there are infinitely many that can be given one or several
representations. The addition function is one of them, and
so are all the ones we need to consider, such as the squaring
function. It so happens that in Joy addition is a primitive
and squaring is (or can be) defined, but that is irrelevant.

In set theory one distinguishes very carefully between
a unit set and its sole member. Let me use ordinary math
notation for a while:
DEFINITION my-hands = { my-left-hand, my-right hand }
Now my-hands has two members, and {my-hands} has one. So
they are different things. The set {my-hands, {my-hands}} has
two members. A similar distinction has to be made for sequences
or ordered tuples. The ordered pair <Peter, Paul> has two
members, and so does <Peter, Peter>, simply because they are
pairs. Ordered tuples can be indexed, the first of <Peter, Paul>
is Peter. You can also have one-tuples such as <Peter>, and
this is different from Peter. Tuples can be concatenated,
and that turns out to be an associative operation. If one
also allows the empty tuple <> then that is the unit (or identity)
element for concatenation. A uniform reading for sequences
could be: <Peter, Paul> is the tuple of Peter, then Paul, and
then nothing. <Peter> is the tuple of Peter and then nothing.
<> is the tuple of nothing.

In many languages there are characters and strings of characters.
Some, like C (and Joy) distinguish between the character 'a'
(or 'a) and the string "a". Others, like Pascal, write "a" for both.
But strings are only first level tuples, because you cannot
have a string counterpart of <<Peter, Paul>, Mary>. So there
is little chance of deep confusion between 'a' and "a". However,
if a language allows nesting of tuples (or nesting of sets),
then the levels must be distinguished.

Lists in Joy are the same as ordered tuples in mathematics.
They can be nested to any level. Here are some programs and
what they push onto the stack:
program what gets onto the stack
7 a new representation of the number 7
"abc" a pointer to that same representation of the string
[Peter 7] a pointer to that same representation of the list
[7] first a new representation of the number 7
This is how the implementation works, others could do it differently.
(Just delete "pointer to" or "new" or "same"). But none of this is
controversial.

Since lists are just special cases of quotations, the same
sort of questions arise for quotations and their content when
the content is not a literal. The recent debate was not about
the difference between the programs '7' and '[7]', nor about
what they leave on the stack, nor about what '+' and '[+]' do
to the stack. Instead it was about what '[+] first' leaves
on the stack. We know that '[7] first' leaves a representation
of the number seven on the stack. By parity of reasoning, the
program '[+] first' must leave a representation of the addition
function on the stack. And that must be different from what is
left by '[+]', which is one-tuple. Here is the pronounciation
of what is left on the stack:
program: how to say what gets pushed onto the stack:
[7] first a representation of the number seven
[7] the tuple consisting of the above and then nothing
[+] first a representation of the addition function
[+] the tuple consisting of the above and then nothing

INDUSTRIAL STRENGTH PEDANTRY SWITCH ON

The last and third last lines should not say 'the tuple', since
numbers, sets and tuples are abstract objects, each one existing
"only once". The phrase should be 'a representation of the tuple'.

ALL PEDANTRY SWITCHES OFF

The program '7' pushes the number seven.
The program '[7]' pushes the tuple of the number seven and then nothing
The program '[7 8]' pushes the tuple of seven, then eight, then nothing
The program '[7] first' pushes the number seven
The program '[+]' pushes the tuple of addition and then nothing
The program '[+] first' pushes addition
The program '+' performs addition
The program '+ *' performs addition and then multiplication
The program '[+] i' performs addition
The program '[+] first [] cons i' performs addition

Any comments? Hated the pedantry? As I sometimes tell my students,
I get paid to be pedantic - and they think that is funny. But it
is not always necessary.

- Manfred

stevan apter — 2003-07-15 11:53:15

i think several topics have gotten mixed together in
this thread. billy wants to distinguish quotations
and lists, but until i see the spec for his language,
i'm neutral. on the other hand, i think there's an
asymmetry in how we describe what we type into joy
and what winds up on the stack, which is obscured by
how the joy language is defined and how joy displays
the contents of the stack. not that that's a bad
thing in my opinion.

you're sitting at the console and typing joy into the
interpreter. as you type, you say what you're typing:

you type you say
-------- -------
7 push 7
3 push 3
+ add
[7 3 +] push the list containing 7, 3, addition, or
push the quotation "push 7, push 3, add"
i evaluate, or disquote
[+] push the list containing addition, or
push the quotation "add"
first take the first

everything you type is a verb or verb-phrase.

if you're asked to say what happens when you evaluate/disquote
[7 3 +], you might say:

7 gets pushed
3 gets pushed
7 and 3 are added

instead of "the list containing 7, 3, addition" we could
say (in fact, we are encouraged to say) "the quotation
"push 7, push 3, add", and instead of "evaluate" we should
then say "disquote".

now suppose you're asked to say what the stack is following
each bit of typing:

you type stack is
-------- --------
7 7
3 7 and 3
+ 10
[+] 10 and the list containing addition, or
10 and the quotation "add"
first addition

everything on the stack is a noun or noun-phrase.

as i see it, we know what joy typings mean, and we know
how to describe the stack-states which result. although
we may quibble about which terminology to use, we know
that when we type '7' it means "push 7" and when we type
'+' it means "add". and when 7 is on the stack, 7 is on
the stack, not "push 7"; and when + is on the stack,
addition is on the stack, not "add". and whether we
describe [7 3 +] as a list containing 7, 3, and addition,
or as the quotation "push 7, push 3, add", it means "push
(whatever)" when we type it, and when it's on the stack,
it's on the stack, not "push (whatever)".

for anything except +, joy lets us put that thing on the
stack by typing it. but the only way to get addition on
the stack is by first quoting it, then disquoting it. we
can't say "addition", we can only say "add". we don't
have a way to turn verbs into nouns.

as noted, that crack can be filled in by adding a special
quotation mark, which turns a verb into a noun:

you type you say the stack is
-------- ------- ------------
`+ push addition addition
`7 push 7 7
`[2 3 +] etc.

`x pushes x.

in k, the expression "2 + 3" has the syntactic structure
noun-verb-noun, but the list (2;+;3) is a noun containing
three pieces of data: 2, addition, and 3. A verb on its
own can be turned into a noun by enclosing it in parens: (+).

2(+)3 has the syntactic structure noun-noun-noun, and if you
type it, you'll get an error - it is not equivalent to 2 + 3.

k has the same display ambiguity as joy: *(+;2;3) displays
as a naked +. but what's on display is addition, not the
verb "add".

----- Original Message -----
From: <phimvt@...>
To: <concatenative@yahoogroups.com>
Sent: Tuesday, July 15, 2003 12:03 AM
Subject: RE: [stack] [+] first: final(?) thoughts


>
> There has been a lot of interesting discussion on this topic,
> and I have enjoyed it. But I have now changed the subject line
> just a bit because I think what I am about to write will indeed
> shed some new light. I should have written this much earlier.
>
> IF you are willing to put up with me at my pedantic worst,
> THEN please read on,
> ELSE jump to the last two paragraphs.
>
> PEDANTRY SWITCH ON
>
> There is only one number seven. If you put it on your stack,
> then I can't put it on mine. You cannot have it on your stack
> at several different places in your stack either. So whatever
> the program '7' does, it must be compatible with the fact
> that there is only one number seven. Well, let us say that this
> program puts a representation of the number seven on the stack.
> There are as many representations as one might need, so you
> can do as many pushes as you like, and so can I even at the
> same time.
>
> Similarly with other data values. For some, such as for strings,
> it may be better to put a pointer to a representation on the
> stack. But this is largely an implementation issue. An
> implementation could decide never to use pointers to the
> representation. Or it could always use a pointer to the
> representation, even for representations of numbers. Or it
> could, like the current implementation of Joy, use a mixture
> of the two approaches, whichever is most efficient. Where
> appropriate I'll put the optional 'pointer to' in parentheses.
>
> Most functions are infinite objects, for example the addition
> function consists of infinitely many triples of numbers:
> the two summands and the resultant sum. You could not even
> try to put an infinite object on a stack inside a finite
> computer, not even once. Most other functions are infinite
> too. So, the program '[+] first' cannot put the addition
> function on the stack. We can take a lead from what we do with
> the programs '7' and '[7] first', which push a (pointer to)
> a representation of the number 7 onto the stack. So the answer
> must be: the program '[+] first' pushes a (pointer to) a
> representation of the addition function. By a Cantorian
> argument, most functions cannot have a representation, but
> there are infinitely many that can be given one or several
> representations. The addition function is one of them, and
> so are all the ones we need to consider, such as the squaring
> function. It so happens that in Joy addition is a primitive
> and squaring is (or can be) defined, but that is irrelevant.
>
> In set theory one distinguishes very carefully between
> a unit set and its sole member. Let me use ordinary math
> notation for a while:
> DEFINITION my-hands = { my-left-hand, my-right hand }
> Now my-hands has two members, and {my-hands} has one. So
> they are different things. The set {my-hands, {my-hands}} has
> two members. A similar distinction has to be made for sequences
> or ordered tuples. The ordered pair <Peter, Paul> has two
> members, and so does <Peter, Peter>, simply because they are
> pairs. Ordered tuples can be indexed, the first of <Peter, Paul>
> is Peter. You can also have one-tuples such as <Peter>, and
> this is different from Peter. Tuples can be concatenated,
> and that turns out to be an associative operation. If one
> also allows the empty tuple <> then that is the unit (or identity)
> element for concatenation. A uniform reading for sequences
> could be: <Peter, Paul> is the tuple of Peter, then Paul, and
> then nothing. <Peter> is the tuple of Peter and then nothing.
> <> is the tuple of nothing.
>
> In many languages there are characters and strings of characters.
> Some, like C (and Joy) distinguish between the character 'a'
> (or 'a) and the string "a". Others, like Pascal, write "a" for both.
> But strings are only first level tuples, because you cannot
> have a string counterpart of <<Peter, Paul>, Mary>. So there
> is little chance of deep confusion between 'a' and "a". However,
> if a language allows nesting of tuples (or nesting of sets),
> then the levels must be distinguished.
>
> Lists in Joy are the same as ordered tuples in mathematics.
> They can be nested to any level. Here are some programs and
> what they push onto the stack:
> program what gets onto the stack
> 7 a new representation of the number 7
> "abc" a pointer to that same representation of the string
> [Peter 7] a pointer to that same representation of the list
> [7] first a new representation of the number 7
> This is how the implementation works, others could do it differently.
> (Just delete "pointer to" or "new" or "same"). But none of this is
> controversial.
>
> Since lists are just special cases of quotations, the same
> sort of questions arise for quotations and their content when
> the content is not a literal. The recent debate was not about
> the difference between the programs '7' and '[7]', nor about
> what they leave on the stack, nor about what '+' and '[+]' do
> to the stack. Instead it was about what '[+] first' leaves
> on the stack. We know that '[7] first' leaves a representation
> of the number seven on the stack. By parity of reasoning, the
> program '[+] first' must leave a representation of the addition
> function on the stack. And that must be different from what is
> left by '[+]', which is one-tuple. Here is the pronounciation
> of what is left on the stack:
> program: how to say what gets pushed onto the stack:
> [7] first a representation of the number seven
> [7] the tuple consisting of the above and then nothing
> [+] first a representation of the addition function
> [+] the tuple consisting of the above and then nothing
>
> INDUSTRIAL STRENGTH PEDANTRY SWITCH ON
>
> The last and third last lines should not say 'the tuple', since
> numbers, sets and tuples are abstract objects, each one existing
> "only once". The phrase should be 'a representation of the tuple'.
>
> ALL PEDANTRY SWITCHES OFF
>
> The program '7' pushes the number seven.
> The program '[7]' pushes the tuple of the number seven and then nothing
> The program '[7 8]' pushes the tuple of seven, then eight, then nothing
> The program '[7] first' pushes the number seven
> The program '[+]' pushes the tuple of addition and then nothing
> The program '[+] first' pushes addition
> The program '+' performs addition
> The program '+ *' performs addition and then multiplication
> The program '[+] i' performs addition
> The program '[+] first [] cons i' performs addition
>
> Any comments? Hated the pedantry? As I sometimes tell my students,
> I get paid to be pedantic - and they think that is funny. But it
> is not always necessary.
>
> - Manfred
>
>
>
> To unsubscribe from this group, send an email to:
> concatenative-unsubscribe@egroups.com
>
>
>
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
>
>

Tanksley, William D. Jr. — 2003-07-16 19:18:25

From: phimvt@... [mailto:phimvt@...]
>There has been a lot of interesting discussion on this topic,
>and I have enjoyed it. But I have now changed the subject line
>just a bit because I think what I am about to write will indeed
>shed some new light. I should have written this much earlier.

I've spent a while going over this, and I apologise, but I don't get it.
Everything seems to make sense and be true (and if there's any pedantry it's
my own fault for being pedantic first), but it doesn't seem to be about
anything I've been talking about. Is it?

I'm proposing that functions need their own type, and possibly their own
literal syntax as well. I don't really object to functions, such as all of
Joy's combinators, that execute lists, but I think it's more useful to have
a special function type, and that type, not lists, should be used normally
to denote functions when functions are intended.

> - Manfred

-Billy

phimvt@lurac.latrobe.edu.au — 2003-07-25 06:47:19

On Wed, 16 Jul 2003, Tanksley, William D. Jr. wrote:

[..]

> I've spent a while going over this, and I apologise, but I don't get it.
> Everything seems to make sense and be true (and if there's any pedantry it's
> my own fault for being pedantic first), but it doesn't seem to be about
> anything I've been talking about. Is it?

Well, no, I wasn't answering anything specifically written by you.
I just thought it might provide some background needed for any such
discussion. What follows now is also more background rather than
what you are proposing, but see the end of this posting too.

Recall that in the syntax of Joy a factor is anything that can be
a component of a term. Most factors are atomic factors: numbers,
truth values, characters, inbuilt or defined operators such as dup
+ and square, inbuilt or defined combinators such i, linrec, ifte,
sequand.. There are a few non-atomic factors: quotations (including
lists), strings and sets.

FOR ALL FACTORS X, Y, ... the following hold:
1. the program '[X] first' pushes X onto the stack
2. If X is on top of the stack, then 'put' will write it
3. If X is the next thing in input, then 'get' will push X
4. If X is on top of the stack then '[] cons i' will execute X
5. [X Y Z ..] first [] cons == [X]
6. [X] first stack first == [X] first dup
7. [X] i == X

A lot of things follow from just these principles, and there are
probably a few others that don't follow but nevertheless are true.
So this is by no means a complete axiomatisation, not even for
the few things such as first, put, get, cons, i, stack. But the
important point is that they hold for ALL factors. Moreover, they
just about characterise what Joy is.

I will concede that maybe it would be a good idea to have what
might be called a "factor quoter", a unary operator Q which satisfies
Q X == [X] first, but note that so far there are no syntactic
unary operators at all. (We need to distinguish Q from the semantically
unary atomic factors like dup, succ, first - some better terminology
might be needed). We would also have Q Q X == [Q X] first, which leaves
Q X on the stack. But you could not have Q alone on top of the stack.
However, I would need to be persuaded that such an addition to the
syntax of the language is really useful.

I will also concede that maybe there should be a primitive exe,
to execute a single factor on the stack, which currently would
have to be defined by DEFINE exe == [] cons i. But that would be an
inessential addition.

> I'm proposing that functions need their own type, and possibly their own
> literal syntax as well.

I am still unclear about what you mean by functions having their own
type. Maybe you mean in the same way that integers have their own
type, floats have their own, and so on. And in a way of course
addition + has its own type, namely the type function from two
integers-or-floats to .. well, that depends. Subtraction has the
same type. Functions like dup are harder to even specify, and on
the whole Joy has not bothered about using a formal notation for
types in this sense - we just get runtime errors when the wrong type
of argument is encountered.

But this might be marginally relevant: I recently revived an old
atom 'sametype' which got lost I don't quite know when. It is back
in my version, but not yet on the web page.
111 222 sametype ==> true
111 2.2 sametype ==> false
"ab" "c" sametype ==> true
"a" 'a sametype ==> false
[+] first [-] first sametype ==> false
As you can see, + and - when on top of the stack have different
types, and similarly for all primitive functions. But all
user defined functions like 'sort' have the same type in this
sense. Incidentally, the joy-in-joy interpreter used 'opcase'
with similar semantics for stuff like this, and it worked well.

See below for literal syntax.

> I don't really object to functions, such as all of
> Joy's combinators, that execute lists, but I think it's more useful to have
> a special function type, and that type, not lists, should be used normally
> to denote functions when functions are intended.

What you wrote here makes me think that your concern is not so much
about what gets on top of the stack by, say, '[+] first' but what
a quotation like [+] or like [+ *] on top of the stack means, and
what should be permitted operations on quotations. Any language
which allows higher order functions like ifte, map, filter, fold
will need a notation for the parameters, and it should be the same
as when the parameter function is used on its own, not as a parameter.
In a concatenative language the parameter will have to be a term,
a sequence of one or more factors.

Let's use another kind or bracket, |[ and ]| for the literal
syntax. Then a bit of program might look like this:
[1 2 3 4] |[ dup *]| map ==> [1 4 9 16]
But I take it you want the list brackets to be different from
the function brackets. Maybe you want to prohibit using the
list operations on parameters:
[1 2 3] rest ==> [2 3]
[1 2 3] first ==> 1
|[dup *]| rest ==> error
|[dup *]| first ==> error
So, one might think of the | to mean: locked up, can't look.
I have a vague recollection that I have discussed the pros
and (mainly) cons of this proposal in the group a year or two ago.
But I am only guessing that this is what you mean.

It would help the discussion if you could give a few examples
of what you have in mind.

- Manfred

John Cowan — 2003-07-25 19:05:44

phimvt@... scripsit:

> I will concede that maybe it would be a good idea to have what
> might be called a "factor quoter", a unary operator Q which satisfies
> Q X == [X] first, but note that so far there are no syntactic
> unary operators at all.

In effect, the existing sequenc

"X" intern

does this.

> So, one might think of the | to mean: locked up, can't look.
> I have a vague recollection that I have discussed the pros
> and (mainly) cons of this proposal in the group a year or two ago.

I think that is indeed what he means. In historic Lisp systems, functions
were lists. Nowadays in both Common Lisp and Scheme, functions are a
disjoint type from lists: a function is *made from* a list which is its
source code, but you can't (without explicitly using "eval", which is
reflective) construct a list and treat it as code.

--
John Cowan jcowan@... www.ccil.org/~cowan www.reutershealth.com
"If he has seen farther than others,
it is because he is standing on a stack of dwarves."
--Mike Champion, describing Tim Berners-Lee (adapted)

stevan apter — 2003-07-25 22:44:40

----- Original Message -----
From: "John Cowan" <cowan@...>
To: <concatenative@yahoogroups.com>
Sent: Friday, July 25, 2003 3:05 PM
Subject: Re: [stack] [+] first: final(?) thoughts


> phimvt@... scripsit:
:
>
> > So, one might think of the | to mean: locked up, can't look.
> > I have a vague recollection that I have discussed the pros
> > and (mainly) cons of this proposal in the group a year or two ago.
>
> I think that is indeed what he means. In historic Lisp systems, functions
> were lists. Nowadays in both Common Lisp and Scheme, functions are a
> disjoint type from lists: a function is *made from* a list which is its
> source code, but you can't (without explicitly using "eval", which is
> reflective) construct a list and treat it as code.

did things move in this direction for reasons of performance (i.e.
functions are compiled lists-as-programs), or expressive power (i.e.
simpler programming)? if the latter, can you give an example?

stevan apter — 2003-07-26 13:02:19

----- Original Message -----
From: <phimvt@...>
To: <concatenative@yahoogroups.com>
Sent: Friday, July 25, 2003 2:47 AM
Subject: RE: [stack] [+] first: final(?) thoughts


>
> What you wrote here makes me think that your concern is not so much
> about what gets on top of the stack by, say, '[+] first' but what
> a quotation like [+] or like [+ *] on top of the stack means, and
> what should be permitted operations on quotations. Any language
> which allows higher order functions like ifte, map, filter, fold
> will need a notation for the parameters, and it should be the same
> as when the parameter function is used on its own, not as a parameter.
> In a concatenative language the parameter will have to be a term,
> a sequence of one or more factors.
>
> Let's use another kind or bracket, |[ and ]| for the literal
> syntax. Then a bit of program might look like this:
> [1 2 3 4] |[ dup *]| map ==> [1 4 9 16]
> But I take it you want the list brackets to be different from
> the function brackets. Maybe you want to prohibit using the
> list operations on parameters:
> [1 2 3] rest ==> [2 3]
> [1 2 3] first ==> 1
> |[dup *]| rest ==> error
> |[dup *]| first ==> error
> So, one might think of the | to mean: locked up, can't look.
> I have a vague recollection that I have discussed the pros
> and (mainly) cons of this proposal in the group a year or two ago.
> But I am only guessing that this is what you mean.
>
> It would help the discussion if you could give a few examples
> of what you have in mind.

i think billy has given the example where you have a tree of
programs, and you want to recurse (or have treemap recurse for
you) to the programs and execute them. if programs are lists,
and lists also provide structure for the tree, you can't know
where the structuring ends and the program begins. if the
recursion is explicit, then you can choose an element e which
never occurs in programs and replace each program in the tree
(if you can find it!) with [e prog], but if the recursion is
implicit (i.e. with treemap) then you can't, and you'll sail
right past, and into, prog. the boundary between tree-structure
and program is wholly in the mind of the programmer.

it seems odd to have both programs-as-lists (quotations) and
programs-as-atoms (functions), but in a sense we already have
that in joy: [2 +] and +. in ck, i've added notation for
function-atoms {2 +}, as well as operators which make a function
from a list ([2 +] enclose) and a list from a function ({2 +}
disclose). since {2 +} is a function like +, it executes
immediately - it's not a quotation. since it's an atom,
treemap can find it. since it's a function, it's an appropriate
argument to higher-order functions like map and i.

>
> - Manfred
>
>
>
> To unsubscribe from this group, send an email to:
> concatenative-unsubscribe@egroups.com
>
>
>
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
>
>

John Cowan — 2003-07-28 04:23:59

stevan apter scripsit:

> did things move in this direction for reasons of performance (i.e.
> functions are compiled lists-as-programs), or expressive power (i.e.
> simpler programming)? if the latter, can you give an example?

In the original consensus Common Lisp (documented in the 1st edition
of _Common Lisp: The Language_), the function "functionp" returned
true of any symbol, any list whose first element was the symbol
"lambda", the implementation-dependent closures generated by the
pseudo-function "function" (which does not interpret its argument), and
the implementation-dependent results of calling the "compile" function.
This made it difficult to write code that did different things when passed
a symbol, a list, or a function, since all symbols and some lists were
also functions.

The second edition and the ANSI Common Lisp standard that it approximates
changed "functionp" to be true only of the last two cases: no symbol or
list is ever a function. This is also the rule for the corresponding
Scheme predicate "procedure?" which is never true of anything that
"pair?" or "symbol?" is true of. I don't know the exact history in
Scheme.

--
Overhead, without any fuss, the stars were going out.
--Arthur C. Clarke, "The Nine Billion Names of God"
John Cowan <jcowan@...>

Tanksley, William D. Jr. — 2003-07-28 19:26:14

From: phimvt@... [mailto:phimvt@...]
>On Wed, 16 Jul 2003, Tanksley, William D. Jr. wrote:
>Well, no, I wasn't answering anything specifically written by you.
>I just thought it might provide some background needed for any such
>discussion.

I assumed that "final thoughts" had a little more finality to them :-).
Okay.

>Recall that in the syntax of Joy a factor is anything that can be
>a component of a term. Most factors are atomic factors: numbers,
>truth values, characters, inbuilt or defined operators such as dup
>+ and square, inbuilt or defined combinators such i, linrec, ifte,
>sequand.. There are a few non-atomic factors: quotations (including
>lists), strings and sets.

I belive that you're examining factors from a syntactic point of view, very
appropriate. Then I'd like to point out that one major category of factors,
function names, are by themselves neither atomic nor non-atomic; rather than
leaving data on the stack, they process data. All of the other factors have
a constant meaning; function names, however, mean different things depending
on context (stack contents).

>FOR ALL FACTORS X, Y, ... the following hold:

Agreed.

>I will concede that maybe it would be a good idea to have what
>might be called a "factor quoter", a unary operator Q which satisfies
>Q X == [X] first, but note that so far there are no syntactic
>unary operators at all.

It might be indeed. I'm not pushy about it :-). The main reason my language
will have it is that I'm not going to initially implement inline quotations;
my language will be built for small size and speed, after the model of
Forth. Thus, if you want to pass a block of code to a combinator, you'll
have to define that block of code as a function, and therefore you'll have
to quote the function name in order to pass it.

Joy's priorities are quite the other way around, so it's natural that you
might not care to implement the quotation mark. However, my concern about a
function type remains, and I think that Apter's stated it best: if you have
the capability of implicit iteration into trees, you need an atomic function
type.

> (We need to distinguish Q from the semantically
>unary atomic factors like dup, succ, first - some better terminology
>might be needed). We would also have Q Q X == [Q X] first, which leaves
>Q X on the stack. But you could not have Q alone on top of the stack.
>However, I would need to be persuaded that such an addition to the
>syntax of the language is really useful.

The syntactic quote would have to be purely syntactic; you can no more push
it on the stack than you can push an open-brace on the stack. Note, by the
way, that your [] is a syntactically unary operator, and it has a meaning
when expressed by itself; the empty quotation operator could also have a
meaning, for example it could push the no-operation function (I'm not
recommending that, but it's possible).

Taking Apter's syntax, which I very much like because it meets my need while
still being fully Joy-compatible, I would state:

For all words x and sequences X,Y:
``x == `x -- idempotence
`x i == x -- unquoting
`[X] == [X] -- lists are already quoted
`X == X implies [X] i == X -- literals ignore quotation and
dequotation
[x Y] first == `x -- quotation is distributive
[{X} Y] first == `{X} -- functions are a unit

Furthermore, and very importantly, all semantic-preserving translations
would be possible within curly braces. This is only of theoretical
importance to Joy, since it isn't intended as a study in optimization;
however, the strong theoretical emphasis of Joy should make it obvious that
more precise language results in more precise ability to express thoughts.

>I will also concede that maybe there should be a primitive exe,
>to execute a single factor on the stack, which currently would
>have to be defined by DEFINE exe == [] cons i. But that would be an
>inessential addition.

The only language for which it would be essential would be one with implicit
iteration as part of the language. Of course, this is what I'm designing.

>>I'm proposing that functions need their own type, and
>>possibly their own literal syntax as well.

>I am still unclear about what you mean by functions having their own
>type. Maybe you mean in the same way that integers have their own
>type, floats have their own, and so on.

Yes.

> And in a way of course
>addition + has its own type, namely the type function from two
>integers-or-floats to .. well, that depends. Subtraction has the
>same type. Functions like dup are harder to even specify, and on
>the whole Joy has not bothered about using a formal notation for
>types in this sense - we just get runtime errors when the wrong type
>of argument is encountered.

Static typing in this sense is also possible; strongForth does this
brilliantly. The same basic notation has been used informally for Forth
comments for years, and of course could be done dynamicly.

>>I don't really object to functions,
>>such as all of Joy's combinators, that execute lists,
>>but I think it's more useful to have
>>a special function type, and that type, not lists, should be
>>used normally to denote functions when functions are intended.

>What you wrote here makes me think that your concern is not so much
>about what gets on top of the stack by, say, '[+] first' but what
>a quotation like [+] or like [+ *] on top of the stack means,

Yes.

>and what should be permitted operations on quotations.

Sort of. Keep in mind that I consider the term "quotation" to be very vague
language. I think that the operations available for function quotations
should be different from the options available for list quotations.

Whether those operations are overloaded is a different matter to me.

>Any language
>which allows higher order functions like ifte, map, filter, fold
>will need a notation for the parameters, and it should be the same
>as when the parameter function is used on its own, not as a parameter.
>In a concatenative language the parameter will have to be a term,
>a sequence of one or more factors.

Agreed.

>Let's use another kind or bracket, |[ and ]| for the literal
>syntax.

I'll use your syntax for the rest of this post, but I think Apter's syntax
has many merits. In particular, his syntax can also express unquoted
functions, which is handy for the sake of terseness inside already-quoted
material.

>Then a bit of program might look like this:
> [1 2 3 4] |[ dup *]| map ==> [1 4 9 16]

Yes. And then,

[1 2 3 4] [ |[dup *]| |[2 *]| ] treemap
==> [[1 4 9 16] [2 4 6 8]]

>But I take it you want the list brackets to be different from
>the function brackets. Maybe you want to prohibit using the
>list operations on parameters:
> [1 2 3] rest ==> [2 3]
> [1 2 3] first ==> 1
> |[dup *]| rest ==> error
> |[dup *]| first ==> error

Not certainly. It would be reasonable to assign the list operation some
meaning based on similar program operations. For example, the 'first' of a
program might be a non-'id' chunk of code that when concatenated with the
'rest' of the program produces identical results to the program. In other
words, for all code X there exists code Y,Z such that Y is not id and:

`{X} first == Y
`{X} rest == Z
{Y Z} == X

Note, of course, that Z may be id (but in a useful implementation wouldn't
always be). Also note that for this to be useful, the length of Z must be
smaller than the length of X; but I haven't defined length for programs. I
leave that to you. For Joy, the implementation of this is obvious once we
have the syntax and functions as a type, and the length operator simply
returns the length of the underlying list.

For the first version of my Forthlike language, for all code X:

`{X} length == 1
`{X} first == `{X}
`{X} rest == `{}

But this is only laziness.

>So, one might think of the | to mean: locked up, can't look.
>I have a vague recollection that I have discussed the pros
>and (mainly) cons of this proposal in the group a year or two ago.
>But I am only guessing that this is what you mean.

Not really correct -- but I definitely would say that it's not the same as a
list.

>It would help the discussion if you could give a few examples
>of what you have in mind.

Does the above make anything clearer?

> - Manfred

-Billy

stevan apter — 2003-07-29 14:15:17

----- Original Message -----
From: "Tanksley, William D. Jr." <william.d.tanksley.jr@...>
To: <concatenative@yahoogroups.com>
Sent: Monday, July 28, 2003 3:26 PM
Subject: RE: [stack] [+] first: final(?) thoughts


> From: phimvt@... [mailto:phimvt@...]
> For the first version of my Forthlike language, for all code X:
>
> `{X} length == 1
> `{X} first == `{X}
> `{X} rest == `{}
>
> But this is only laziness.
>
> >So, one might think of the | to mean: locked up, can't look.
> >I have a vague recollection that I have discussed the pros
> >and (mainly) cons of this proposal in the group a year or two ago.
> >But I am only guessing that this is what you mean.
>
> Not really correct -- but I definitely would say that it's not the same as a
> list.

i would say: atoms have no parts. if you want a piece of {X}, turn
it into something which has parts, then get the piece you want from
that. for example, if you want the first digit in 123, turn it into
a list of characters, then get "1" and turn it back into an integer.
if you want the first element of {A B}, turn it into a list [A B],
then get A (and turn it back into a function? maybe, maybe not).
lists are the lingua franca of things-with-parts-at-position talk.

i'm still troubled over `. it doesn't "fit" the way i'm used to
thinking about programming. if you've got function atoms, and you've
got lists, then why isn't [{X}] an adequate way to quote a function,
i.e. to keep it from executing?

i'm picturing that automatic quotation is going to get in my way.
[+ *] first leaves `+ on the stack, but `+ isn't a part of [+ *].
the type of each of [+ *] is [function function], but the type
of `+ is .. quotation?

let me point out that i've made some "experimentation space" in
cK to test the practicability of a "third way". with the immediate
execution flag set to 0, 2 3 + still leaves 5 on the stack, but
2 3 {+} leaves 2 3 {+}. the behavior of primitives is unaffected,
but {} serves as both function definition and quotation. my thought
here is that the alternate interpretation could be justified by
observing that [+] first is +, but that [+] first enclose is {+}.
under this alternate regime, you pass functions to higher-order
functions without bothering to enlist; e.g. {+} map instead of
[+] map. but then you have to use 'i' to do simple executions:
2 3 4 plustimes i, which seems like a high price to pay.

Tanksley, William D. Jr. — 2003-07-29 16:04:01

From: stevan apter [mailto:sa@...]
>From: "Tanksley, William D. Jr." <william.d.tanksley.jr@...>
>> From: phimvt@...
>> For the first version of my Forthlike language, for all code X:
>> `{X} length == 1
>> `{X} first == `{X}
>> `{X} rest == `{}
>> but this is just laziness.

>i would say: atoms have no parts. if you want a piece of {X}, turn
>it into something which has parts, then get the piece you want from
>that. for example, if you want the first digit in 123, turn it into
>a list of characters, then get "1" and turn it back into an integer.
>if you want the first element of {A B}, turn it into a list [A B],
>then get A (and turn it back into a function? maybe, maybe not).
>lists are the lingua franca of things-with-parts-at-position talk.

That's true, but I'm not totally convinced that I want to be able to turn
programs into lists. Programs have parts too, and extracting those parts
isn't always the same as it is with lists. In Joy it would be, but in a
compiled native language it wouldn't be. So I would rather, as I specified,
define dissection operations for programs (but no indexing), but define them
loosely enough that they can be implemented even if the author's too lazy to
actually compute the "first" operation in a program.

>i'm still troubled over `. it doesn't "fit" the way i'm used to
>thinking about programming. if you've got function atoms, and you've
>got lists, then why isn't [{X}] an adequate way to quote a function,
>i.e. to keep it from executing?

It's more than adequate -- it's overkill. It definitely quotes the function,
but it also enlists it.

>i'm picturing that automatic quotation is going to get in my way.
>[+ *] first leaves `+ on the stack, but `+ isn't a part of [+ *].

Why would you say that? If [+] first leaves `+ on the stack, then `+ IS the
first element of [+]. Remember how I said that quotation was idempotent?

[`+] == [+]

Enlistment automatically quotes. It has to in order to act like Joy.

>the type of each of [+ *] is [function function], but the type
>of `+ is .. quotation?

Its type is function. Quotation isn't a type; it's syntax designed to allow
you to place types that otherwise couldn't be expressed.

>let me point out that i've made some "experimentation space" in
>cK to test the practicability of a "third way". with the immediate
>execution flag set to 0, 2 3 + still leaves 5 on the stack, but
>2 3 {+} leaves 2 3 {+}. the behavior of primitives is unaffected,
>but {} serves as both function definition and quotation. my thought
>here is that the alternate interpretation could be justified by
>observing that [+] first is +, but that [+] first enclose is {+}.
>under this alternate regime, you pass functions to higher-order
>functions without bothering to enlist; e.g. {+} map instead of
>[+] map.

This was my first instinctive response to your {} syntax (the immediately
executing one); but I've come to like how it works. All we need is a way to
tell the parser to not execute this function immediately; and ` seems almost
ideal for that, since it has the same meaning for named functions.

Can you tolerate having to type things like `{+}map instead of {+}map?

>but then you have to use 'i' to do simple executions:
>2 3 4 plustimes i, which seems like a high price to pay.

I don't see why you should have to do that; defining a function should also
provide for its execution whenever the function's name is mentioned without
a backtick.

-Billy

stevan apter — 2003-07-29 21:29:09

----- Original Message -----
From: "Tanksley, William D. Jr." <william.d.tanksley.jr@...>
To: <concatenative@yahoogroups.com>
Sent: Tuesday, July 29, 2003 12:04 PM
Subject: RE: [stack] [+] first: final(?) thoughts


> From: stevan apter [mailto:sa@...]
> >From: "Tanksley, William D. Jr." <william.d.tanksley.jr@...>
> >> From: phimvt@...
> >> For the first version of my Forthlike language, for all code X:
> >> `{X} length == 1
> >> `{X} first == `{X}
> >> `{X} rest == `{}
> >> but this is just laziness.
>
> >i would say: atoms have no parts. if you want a piece of {X}, turn
> >it into something which has parts, then get the piece you want from
> >that. for example, if you want the first digit in 123, turn it into
> >a list of characters, then get "1" and turn it back into an integer.
> >if you want the first element of {A B}, turn it into a list [A B],
> >then get A (and turn it back into a function? maybe, maybe not).
> >lists are the lingua franca of things-with-parts-at-position talk.
>
> That's true, but I'm not totally convinced that I want to be able to turn
> programs into lists. Programs have parts too, and extracting those parts
> isn't always the same as it is with lists. In Joy it would be, but in a
> compiled native language it wouldn't be. So I would rather, as I specified,
> define dissection operations for programs (but no indexing), but define them
> loosely enough that they can be implemented even if the author's too lazy to
> actually compute the "first" operation in a program.

ok

>
> >i'm still troubled over `. it doesn't "fit" the way i'm used to
> >thinking about programming. if you've got function atoms, and you've
> >got lists, then why isn't [{X}] an adequate way to quote a function,
> >i.e. to keep it from executing?
>
> It's more than adequate -- it's overkill. It definitely quotes the function,
> but it also enlists it.

ah - so what you want is a quotation that is atomic. got it.

>
> >i'm picturing that automatic quotation is going to get in my way.
> >[+ *] first leaves `+ on the stack, but `+ isn't a part of [+ *].
>
> Why would you say that? If [+] first leaves `+ on the stack, then `+ IS the
> first element of [+]. Remember how I said that quotation was idempotent?
>
> [`+] == [+]
>
> Enlistment automatically quotes. It has to in order to act like Joy.
>
> >the type of each of [+ *] is [function function], but the type
> >of `+ is .. quotation?
>
> Its type is function. Quotation isn't a type; it's syntax designed to allow
> you to place types that otherwise couldn't be expressed.

you mean, "expressed directly", right?

ok - i think i'm finally getting it.

>
> >let me point out that i've made some "experimentation space" in
> >cK to test the practicability of a "third way". with the immediate
> >execution flag set to 0, 2 3 + still leaves 5 on the stack, but
> >2 3 {+} leaves 2 3 {+}. the behavior of primitives is unaffected,
> >but {} serves as both function definition and quotation. my thought
> >here is that the alternate interpretation could be justified by
> >observing that [+] first is +, but that [+] first enclose is {+}.
> >under this alternate regime, you pass functions to higher-order
> >functions without bothering to enlist; e.g. {+} map instead of
> >[+] map.
>
> This was my first instinctive response to your {} syntax (the immediately
> executing one); but I've come to like how it works. All we need is a way to
> tell the parser to not execute this function immediately; and ` seems almost
> ideal for that, since it has the same meaning for named functions.
>
> Can you tolerate having to type things like `{+}map instead of {+}map?

sure.

>
> >but then you have to use 'i' to do simple executions:
> >2 3 4 plustimes i, which seems like a high price to pay.
>
> I don't see why you should have to do that; defining a function should also
> provide for its execution whenever the function's name is mentioned without
> a backtick.

ok, this is starting to make sense now. i'm not sure i *like* it,
but it's definitely starting to make sense. :)

for what it's worth, here's how i would incorporate this into ck.
i've used up all the ascii symbols, but "\" is the line comment.
i can say that \xyz is a comment if x is a blank, else it's
a quotation. i kind of like "\", since in ck (as in k) it's
used as the escaper in a string, and quotation is sort of like
escape (from execution). i'm not sure how hard it would be to
make this change, but it's definitely upwards compatible.

thanks.

>
> -Billy
>
>
> To unsubscribe from this group, send an email to:
> concatenative-unsubscribe@egroups.com
>
>
>
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
>
>

Tanksley, William D. Jr. — 2003-07-29 22:22:22

From: stevan apter [mailto:sa@...]
>for what it's worth, here's how i would incorporate this into ck.
>i've used up all the ascii symbols, but "\" is the line comment.
>i can say that \xyz is a comment if x is a blank, else it's
>a quotation. i kind of like "\", since in ck (as in k) it's
>used as the escaper in a string, and quotation is sort of like
>escape (from execution). i'm not sure how hard it would be to
>make this change, but it's definitely upwards compatible.

Interesting. Okay, that's cool.

I was incorrectly assuming that ` (backtick) was usable for this; but \
works fine.

>thanks.

You're welcome!

-Billy

stevan apter — 2003-07-29 23:28:17

>
> >
> > >let me point out that i've made some "experimentation space" in
> > >cK to test the practicability of a "third way". with the immediate
> > >execution flag set to 0, 2 3 + still leaves 5 on the stack, but
> > >2 3 {+} leaves 2 3 {+}. the behavior of primitives is unaffected,
> > >but {} serves as both function definition and quotation. my thought
> > >here is that the alternate interpretation could be justified by
> > >observing that [+] first is +, but that [+] first enclose is {+}.
> > >under this alternate regime, you pass functions to higher-order
> > >functions without bothering to enlist; e.g. {+} map instead of
> > >[+] map.
> >
> > This was my first instinctive response to your {} syntax (the immediately
> > executing one); but I've come to like how it works. All we need is a way to
> > tell the parser to not execute this function immediately; and ` seems almost
> > ideal for that, since it has the same meaning for named functions.

i've removed the option to NOT execute functions. (the word 'immediate'
has been removed.) i think you're right - it's not a useful path to explore.

> for what it's worth, here's how i would incorporate this into ck.
> i've used up all the ascii symbols, but "\" is the line comment.
> i can say that \xyz is a comment if x is a blank, else it's
> a quotation. i kind of like "\", since in ck (as in k) it's
> used as the escaper in a string, and quotation is sort of like
> escape (from execution). i'm not sure how hard it would be to
> make this change, but it's definitely upwards compatible.

well, it turned out not to be very hard at all.

2 3 \+ -> 2 3 +
2 3 \{+} -> 2 3 {+} \ this is a comment

\ is just another operator, but given a list of tokens

2 3 \ {+}

i now look one token ahead. if the current token is \, i
push the succeeding token on the stack. obviously,

\2

has no effect other than to push 2.

to get idempotence, i just squeeze out redundant occurrences
of \.

i might have overlooked some edges in the implementation, but
i'm reasonably confident the extension doesn't break the model.
(wish i had a nickel for every time i thought that.)

it's up there: www.nsl.com/k/ck.k

thanks - at worst, i think this feature does no harm.

stevan apter — 2003-07-29 23:33:42

----- Original Message -----
From: "Tanksley, William D. Jr." <william.d.tanksley.jr@...>
To: <concatenative@yahoogroups.com>
Sent: Tuesday, July 29, 2003 6:22 PM
Subject: RE: [stack] [+] first: final(?) thoughts


> From: stevan apter [mailto:sa@...]
> >for what it's worth, here's how i would incorporate this into ck.
> >i've used up all the ascii symbols, but "\" is the line comment.
> >i can say that \xyz is a comment if x is a blank, else it's
> >a quotation. i kind of like "\", since in ck (as in k) it's
> >used as the escaper in a string, and quotation is sort of like
> >escape (from execution). i'm not sure how hard it would be to
> >make this change, but it's definitely upwards compatible.
>
> Interesting. Okay, that's cool.
>
> I was incorrectly assuming that ` (backtick) was usable for this; but \
> works fine.

i'm trying to keep ck consistent with k2. `X is a symbol if X
is a k name, where a k name begins with a-zA-Z and follows with
a-zA-Z0-9._ since many ck/joy operators are words, you couldn't
quote e.g. treemap, since `treemap is a symbol. there was some
unused syntactic space in the comment symbol (comments? who needs
comments?), and "escape" has enough iconicity to justify the
overload.


>
> >thanks.
>
> You're welcome!
>
> -Billy
>
>
> To unsubscribe from this group, send an email to:
> concatenative-unsubscribe@egroups.com
>
>
>
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
>
>

stevan apter — 2003-07-29 23:59:48

>
> it's up there: www.nsl.com/k/ck.k
>

forgot to extend the display code:

[10 20 \+]

e.g. lists containing quotations.

fixed.

Ivan Tomac — 2003-07-30 00:24:45

I think there's another alternative to adding constructs like `.
This only occured to me today so I haven't had time to think through
this completely but it sounds interesting.

What if we get rid of first? So that you can't get the first element
of a list. Or any element of a list. In fact what if we literally
treat all lists as functions so the only operation we can perform on
them is execution, nevermind implementation details, complexity, etc.

This requires some changes in the design of a language. For example
a function thats about to get executed takes all the parameters from
the main stack, removes them and puts them onto it's own local stack
(in a way this is like having stack frames but it's still a bit
different and it's all transparent to the programmer). When the
function finishes execution it's output remains on that local stack.
There would be a small number of functions designed specifically to
manipulate that local stack and transfer the values to the main
stack so basically local stacks would replace lists (for example
first could be used right after a function is executed to copy the
first element from the temporary stack onto the main stack and then
destroy the temporary stack).

The main problem here is that you don't want to have to write
something like [2 3 +] i first to copy 5 to the main stack. So a
solution would be to automatically merge contents of the temporary
stack with the main stack right before the next function is executed
but do so only if the next function isn't one of those functions
like first that deals with temporary stacks.

Basically this is like taking lists out of the syntax of the
language. There is no way to define a list, only a way to define a
function. Functions however generate lists.

Now I'm not completely sure how automatic merging of local stacks
with the main stack should work. For example you could postpone
merging of any of the local stacks until its absolutely necessary.
Or even postpone the execution or perform partial execution of the
functions that are meant to generate those stacks effectively
turning the language into a lazy functional language. I'm not sure
whether this language would stop being concatenative due to that - I
haven't had enough time to think about this.

Another problem with this is what if we want to preserve the local
stacks/lists rather then merge them with the main stack. Maybe we
could somehow write a temporary function to contain that list.

I remember starting a big discussion about laziness in concatenative
languages when I first joined the board and I've been convinced that
laziness doesn't make sense in a language like Joy (basically
execution in concatenative languages is sequential so delaying
execution is pointless while in applicative languages execution is
more like a tree so delaying execution of some of the branches of
the tree makes sense).

However with the changes I'm proposing it might make sense to make a
lazy language although the final language might not be concatenative.

phimvt@lurac.latrobe.edu.au — 2003-07-30 03:28:43

On Mon, 28 Jul 2003, Tanksley, William D. Jr. wrote:

[..very long response to some questions..]

Dear Billy

Thank you very much for your very detailed response. It is all
very clear now, even after only a brief reading. I shall reply in
detail as soon as time permits.

- Manfred

phimvt@lurac.latrobe.edu.au — 2003-08-08 02:27:53

Hi Billy, sorry this took longer than I would have liked.

On Mon, 28 Jul 2003, Tanksley, William D. Jr. wrote:

> From: phimvt@... [mailto:phimvt@...]

> >Recall that in the syntax of Joy a factor is anything that can be
> >a component of a term. Most factors are atomic factors: numbers,
> >truth values, characters, inbuilt or defined operators such as dup
> >+ and square, inbuilt or defined combinators such i, linrec, ifte,
> >sequand.. There are a few non-atomic factors: quotations (including
> >lists), strings and sets.
>
> I belive that you're examining factors from a syntactic point of view, very
> appropriate.

Yes, I use it as a syntactic category of factors.

> Then I'd like to point out that one major category of factors,
> function names, are by themselves neither atomic nor non-atomic; rather than
> leaving data on the stack, they process data.

That is now a different use of the word atomic.

> All of the other factors have
> a constant meaning; function names, however, mean different things depending
> on context (stack contents).

Well, it depends on their definition - consider
DEFINE one-two-three == 1 2 3 .

[..]

> >I will concede that maybe it would be a good idea to have what
> >might be called a "factor quoter", a unary operator Q which satisfies
> >Q X == [X] first, but note that so far there are no syntactic
> >unary operators at all.

I think I was wrong in what I assumed you want. See below.

[..]

> Thus, if you want to pass a block of code to a combinator, you'll
> have to define that block of code as a function, and therefore you'll have
> to quote the function name in order to pass it.

Suddenly I do understand. When you spoke of functions, you meant
those that have a name (primitive or defined, it does not matter).
For later, let's assume we have defined
DEFINE square == dup *; cube = dup dup * *; positive == 0 > .
I'll use the map combinator because it is simple, any other would do.
Now Joy allows:
[1 2 3] [dup *] map
[1 2 3] [square] map
You allow
[1 2 3] `square map
Joy allows, if next factor in input is [square] or [dup *],
[1 2 3] get map
You allow, if next factor in input is `square but not if [dup *],
[1 2 3] get map
Joy allows
[1 2 3] [dup *] dup put map
[1 2 3] [square] dup put map
You allow
[1 2 3] `square dup put map
Am I right so far?

Summarising, it seems you use `X for Joy's [X], where X is a function
name which is to be used as one of the arguments for a combinator.
Or, to use the |[ and ]| brackets, you use `X for |[X]|, but you
disallow |[X Y]|. Well, yes, the backslash notation forces you to
do that. But one wants a good argument for disallowing it.
(I used to think that you use `X for Joy's [X] first, but I don't know
what caused my confusion.)

> Joy's priorities are quite the other way around, so it's natural that you
> might not care to implement the quotation mark. However, my concern about a
> function type remains, and I think that Apter's stated it best: if you have
> the capability of implicit iteration into trees, you need an atomic function
> type.

Or, perhaps, the |[ and ]| brackets, which might allow |[X Y Z]| also.

[.. stuff based on my misunderstanding..]

> The syntactic quote would have to be purely syntactic; you can no more push
> it on the stack than you can push an open-brace on the stack.

Note, by the
> way, that your [] is a syntactically unary operator,

No, its a syntactically a pair of mixfix operators, (like in some
languages the mixfix IF .. THEN .. ELSE ..ENDIF)

[..]

> Taking Apter's syntax, which I very much like because it meets my
need while
> still being fully Joy-compatible, I would state:
>
> For all words x and sequences X,Y:
> ``x == `x -- idempotence
> `x i == x -- unquoting
> `[X] == [X] -- lists are already quoted
> `X == X implies [X] i == X -- literals ignore quotation and
> dequotation
> [x Y] first == `x -- quotation is distributive
> [{X} Y] first == `{X} -- functions are a unit

I see. That helps a lot. Very clear. (Good notation, too, especially
distinguishing words and sequences by lower/upper case.)
Except for the second last: Now I'm confused again back to where
I was before. Which is it:
[cube] == `cube or [cube] first == `cube
and hence [cube] map == `cube map or [cube] first map == `cube map

Joy allows
-3 [[dup *][dup dup * *][0 >]] [i] map ==> -3 [9 -27 false]
-3 [[square][cube][positive]] [i] map ==> -3 [9 -27 false]
Do you allow
-3 [`square `cube `positive] `i map ==> -3 [9 -27 false] ?

[...]

> The only language for which it would be essential would be one with implicit
> iteration as part of the language. Of course, this is what I'm designing.

I'm not so sure I understand whatyou mean by implicit iteration.
A few examples would help. Will it be similar to APL/J/K ?

[...]

> >>I don't really object to functions,
> >>such as all of Joy's combinators, that execute lists,
> >>but I think it's more useful to have
> >>a special function type, and that type, not lists, should be
> >>used normally to denote functions when functions are intended.
>
> >What you wrote here makes me think that your concern is not so much
> >about what gets on top of the stack by, say, '[+] first' but what
> >a quotation like [+] or like [+ *] on top of the stack means,
>
> Yes.
>
> >and what should be permitted operations on quotations.
>
> Sort of. Keep in mind that I consider the term "quotation" to be very vague
> language.

Nothing vague. A quotation factor consists of a term mixfixed by [ ]
to form a factor. See the grammar.

> I think that the operations available for function quotations
> should be different from the options available for list quotations.

And you don't just mean that e.g. the cons operator should
be split into say Lcons and Fcons which are identical except
that they insist that the top element of the stack is a list
quotation or a function quotation. Even here the difference
is hard to tell e.g. for [42].

But if its not a matter of having two symbols Lcons and Fcons,
what should the difference be? Disallowing too much would
make it impossible to use programs as data. Of course some
would say that this would not be a loss at all. Others would say
that it is important to be able to use a language for its
own metaprogramming: interpreter, compiler, optimiser, editor,
pretty printer and probably a few others.

[...]

> >Let's use another kind or bracket, |[ and ]| for the literal
> >syntax.
>
> I'll use your syntax for the rest of this post, but I think Apter's syntax
> has many merits. In particular, his syntax can also express unquoted
> functions, which is handy for the sake of terseness inside already-quoted
> material.

[..]

> Does the above make anything clearer?

Yes, thank you.

I did not bring my mind reading machine to work today, so this
is only conjecture about why you want your language to be different
from Joy:

1. You are aiming at a compiled implementation. You believe that
not allowing quotations as parameters to combinators will make
the implementation easier. I think that will be true somewhat,
but not all that much. I also think that the proliferation of
the necessary definitions might become annoying to the programmer
(although I know that Forth programmers think otherwise). Should
one trade ease of programming for ease of compilation?

2. You are aiming to implement the stack not as a linked structure
(as Joy does), but as an array of consecutive memory locations
(as Forth does). You have said nothing in particular about this,
but somehow I thought that this is part of your motivation.
From time to time I have thought about an implementation of
Joy using such an array, but abandoned the idea because of all
sorts of difficulties. Your language might overcome those.
I welcome experiments like this.

Anyhow, best wishes for the design and implementation of your language.

Thanks for the discussion.

- Manfred

Tanksley, William D. Jr. — 2003-08-08 19:28:02

From: phimvt@... [mailto:phimvt@...]
>Hi Billy, sorry this took longer than I would have liked.

That's okay -- we know you have a real job.

>On Mon, 28 Jul 2003, Tanksley, William D. Jr. wrote:
>> From: phimvt@...

>That is now a different use of the word atomic.

I apologise; I see what you meant. I misunderstood.

>>Thus, if you want to pass a block of code to a
>>combinator, you'll have to define that block of
>>code as a function, and therefore you'll have
>>to quote the function name in order to pass it.

>Suddenly I do understand. When you spoke of functions, you meant
>those that have a name (primitive or defined, it does not matter).

Yes. Sorry for the ambiguity. Actually, I'm using the phrase "defining as a
function" to mean "defining a name which will invoke the given function."

Note also that I'm not proposing this limitation for Joy, nor for any
concatenative language aside from my own; I'm merely doing it because it's
easier for my specific implementation. In the current version of cK you can
pass any function to a combinator, whether it's named or literal.

>For later, let's assume we have defined
> DEFINE square == dup *; cube = dup dup * *; positive == 0 > .
>I'll use the map combinator because it is simple, any other would do.

Yes.

>Now Joy allows:
> [1 2 3] [dup *] map
> [1 2 3] [square] map
>You allow
> [1 2 3] `square map

Yes. In the future, may we use cK's new notation, \square? I'd like to keep
notation consistent whenever possible, and cK has good reason to use \.

>Joy allows, if next factor in input is [square] or [dup *],
> [1 2 3] get map
>You allow, if next factor in input is `square but not if [dup *],
> [1 2 3] get map

Yes, athough I'm not allergic to making map polymorphic, so that [dup *]
would do the same as \square. My language can't do that, since [dup *] map
will have an existing meaning; but Joy could.

>Joy allows
> [1 2 3] [dup *] dup put map
> [1 2 3] [square] dup put map
>You allow
> [1 2 3] `square dup put map
>Am I right so far?

Precisely.

>Summarising, it seems you use `X for Joy's [X], where X is a function
>name which is to be used as one of the arguments for a combinator.

No; I use \X (or `X) as a syntactic expression for the semantic meaning of
Joy's [X] first.

>Or, to use the |[ and ]| brackets, you use `X for |[X]|, but you
>disallow |[X Y]|.

Yes, my language will initially disallow |[X Y]|. But this is only for the
sake of expediency; I will define brackets to do that and add them to the
language when it seems good to me. (Note that I prefer single-character
brackets, so I'll be using {}, as cK does.)

>Well, yes, the backslash notation forces you to
>do that. But one wants a good argument for disallowing it.

Yes. I have none, aside from personal temporary convenience. I don't wish to
disallow it for other languages, only for mine; and the disallowal will last
only as long as it remains convenient. It may be permanently disallowed, if
I find that the added complexity of allowing it is greater than the ease
allowed by it.

It's very definite that there's no _need_, per se, for a multiword function
literal.

>(I used to think that you use `X for Joy's [X] first,

I was and am.

>but I don't know what caused my confusion.)

Left to myself, I realise: I am the maker of my own demise.
-- DC Talk, "The Hardway", speaking for William Tanksley

In other words, I accept all responsibility for any confusion in readers of
my words.

In this case, I believe that the confusion comes because I am attempting to
correct what I believe is a fundamental ambiguity, an error, in Joy's
description of the world. When I use the word "quotation", I mean precisely
and ONLY the operation of quotation, not to include the operation of
enlistment or anything else. When Joy uses the word, it sometimes includes
the idea of enlistment.

>>Joy's priorities are quite the other way around, so it's
>>natural that you might not care to implement the quotation
>>mark. However, my concern about a function type remains,
>>and I think that Apter's stated it best: if you have
>>the capability of implicit iteration into trees, you need an
>>atomic function type.

>Or, perhaps, the |[ and ]| brackets, which might allow |[X Y Z]| also.

By "atomic function type" I was talking about the data, not the literal.
Atomic functions are not lists (although they may not be TRULY atomic, in
that there may be ways to disassemble them).

>>Note, by the way, that your [] is a syntactically unary
>>operator,

>No, its a syntactically a pair of mixfix operators, (like in some
>languages the mixfix IF .. THEN .. ELSE ..ENDIF)

This can't be correct. Either [] is a unary operator, or the characters "
[]" are a set of _three_ mixfix operators: one to delimit the beginning of a
list, one to delimit entries in the list, and one to delimit the end of a
list.

I choose to view [] as a unary operator, taking a single argument: the text
it contains; and producing a single result: a list containing the results of
quoting and parsing the contained text. (Actually, I view it as a lexical
literal rather than an operator, but same thing. The reason I do that is so
that I can claim that Joy meets my definition of "concatenative", which
includes the ability to split any program on lexical boundaries to produce
two valid programs).

>>Taking Apter's syntax, which I very much like because it meets my
>>need while still being fully Joy-compatible, I would state:

>> For all words x and sequences X,Y:
>> ``x == `x -- idempotence
>> `x i == x -- unquoting
>> `[X] == [X] -- lists are already quoted
>> `X == X implies [X] i == X -- literals ignore quotation and
>> dequotation
>> [x Y] first == `x -- quotation is distributive
>> [{X} Y] first == `{X} -- functions are a unit

>I see. That helps a lot. Very clear. (Good notation, too, especially
>distinguishing words and sequences by lower/upper case.)

I stole that from you, of course. Thank you, and thank YOU.

Note that the ability to use notation like this is, I believe, a major
advantage of this quotation as syntax. Consider the excellent page
http://tunes.org/~iepos/joy.html, in which we see that [A] [B] swap == [B]
[A]. This is true, but hardly general since it speaks only of lists; a truly
general statement is that \a \b swap == \b \a.

>Except for the second last: Now I'm confused again back to where
>I was before. Which is it:
> [cube] == `cube or [cube] first == `cube
>and hence [cube] map == `cube map or [cube] first map ==
>`cube map

The second in each pair.

>Joy allows
> -3 [[dup *][dup dup * *][0 >]] [i] map ==> -3 [9 -27 false]
> -3 [[square][cube][positive]] [i] map ==> -3 [9 -27 false]
>Do you allow
> -3 [`square `cube `positive] `i map ==> -3 [9 -27 false] ?

Emphatically yes -- but by the first and fifth rule you quote above, I can
equivalently write that as:

-3 [square cube positive] \i map ==> -3 [9 -27 false]
The only difference is that I've eliminated the redundant quotation
operators.

>>The only language for which it would be essential would be
>>one with implicit iteration as part of the language. Of
>>course, this is what I'm designing.

>I'm not so sure I understand whatyou mean by implicit iteration.
>A few examples would help. Will it be similar to APL/J/K ?

Yes, it'll be very similar to K (and therefore to cK). You'll get a VERY
strong taste of my language by playing with cK, especially now that Steve
has implemented \quotation.

"Implicit iteration" is like the "treemap" function -- iteration over items
in a list, or in a tree, that's controlled by the shape of the list or tree.
"Implicit iteration as part of the language" means that this can happen
without an explicit function; using a list where an atom was expected means
that the function will iterate over the list.

>>Sort of. Keep in mind that I consider the term "quotation"
>>to be very vague language.

>Nothing vague. A quotation factor consists of a term mixfixed by [ ]
>to form a factor. See the grammar.

There's nothing vague about "quotation factor in Joy". There's much
ambiguity when we use the word "quotation" on this list, though. Do we mean
a Joy quotation factor, or a Joy list, or a function which isn't executed
because it was somehow quoted?

>>I think that the operations available for function quotations
>>should be different from the options available for list quotations.

>And you don't just mean that e.g. the cons operator should
>be split into say Lcons and Fcons which are identical except
>that they insist that the top element of the stack is a list
>quotation or a function quotation. Even here the difference
>is hard to tell e.g. for [42].

Actually, that would be a valid operation, so you could do that if you
wanted. Personally, I would be tempted to overload cons so that it operated
on both lists and functions.

>But if its not a matter of having two symbols Lcons and Fcons,
>what should the difference be? Disallowing too much would
>make it impossible to use programs as data.

Well, what operations make sense on lists but fail to make sense on
programs? I would claim that "first" and "rest" are poorly defined for
functions; not every non-empty function has a first in the same sense that
every nonempty list does. However, every nonempty function can be defined to
have a first operation, which is itself a nonempty function, and a 'rest' of
its operations, which is a possibly empty function. It would make sense to
give these operations different names, since they produce different results,
but I wouldn't mind if you used the same names.

Cons of two functions makes some sense (but don't expect {cons uncons} ==
{id} in that case). I would rather use concat for functions, and leave cons
for lists, because concat's operation is natural for functions while cons'
operation isn't.

>Of course some
>would say that this would not be a loss at all. Others would say
>that it is important to be able to use a language for its
>own metaprogramming: interpreter, compiler, optimiser, editor,
>pretty printer and probably a few others.

I'm deifnitely one of the second group.

>I did not bring my mind reading machine to work today, so this
>is only conjecture about why you want your language to be different
>from Joy:

>1. You are aiming at a compiled implementation. You believe that
>not allowing quotations as parameters to combinators will make
>the implementation easier. I think that will be true somewhat,
>but not all that much.I also think that the proliferation of
>the necessary definitions might become annoying to the programmer
>(although I know that Forth programmers think otherwise). Should
>one trade ease of programming for ease of compilation?

Yes and no.

To explain, let's discard the word "quotation" for now; we'll use "list
literals" and "function literals". I will disallow the use of lists as
parameters to combinators, since I want lists to have a specific meaning
there; I will allow functions to be passed. This will not have any impact on
the verbosity of the language.

I will also, as a completely separate decision, NOT include syntax for a
function literal. This will force programmers to define a named function
whenever they wish to pass a block of code to a combinator; this will
proliferate definitions. I don't know whether it'll become annoying, because
Forth doesn't use very many combinators in the way Joy does. ColorForth
does, but it's much newer. The reason I'm doing this is, indeed, because
it's easier to implement; but it's also because it's not harder to use.

Much more traumatic is the fact that I won't be initially providing
combinators to take apart functions at runtime. If I do wind up providing an
equivalent to 'unconcat' for functions (i.e. a function that given a
function argument returns the first "operation" of that function and then
the rest of that function), it'll be initially defined as follows:

: UNCONCAT ( function -- function function )
\NOP ;

(In other words, this claims that the "first operation" of any function does
the entire task of the function, and the rest of the function does nothing.)

This choice of functionality allows me to be entirely compatible with
smarter implementations (that is, if someone is attempting to iterate over a
function, the iteration will work but finish quickly), but allows me to not
have to implement any of that smartness.

>2. You are aiming to implement the stack not as a linked structure
>(as Joy does), but as an array of consecutive memory locations
>(as Forth does).

That's true.

>You have said nothing in particular about this,
>but somehow I thought that this is part of your motivation.

It's not. Or at least, it would have no effect that I'm aware of.

I'm not aware of the limitations of an array-based stack, aside from the
obvious depth restrictions; perhaps my experience with arrays has blinded me
to the uses of lists?

However, my refusal to promise inline function literals is caused by an
implementation detail: I'm building a VERY simple and quick compiler, and
right now I don't want it to manage memory.

>From time to time I have thought about an implementation of
>Joy using such an array, but abandoned the idea because of all
>sorts of difficulties. Your language might overcome those.

I'd like to hear more about these.

>I welcome experiments like this.
>Anyhow, best wishes for the design and implementation of your language.

Thank you!

>Thanks for the discussion.

> - Manfred

-Billy

stevan apter — 2003-08-10 01:24:44

----- Original Message -----
From: "Tanksley, William D. Jr." <william.d.tanksley.jr@...>
To: <concatenative@yahoogroups.com>
Sent: Friday, August 08, 2003 3:28 PM
Subject: RE: [stack] [+] first: final(?) thoughts


> From: phimvt@... [mailto:phimvt@...]
:
>
> >Summarising, it seems you use `X for Joy's [X], where X is a function
> >name which is to be used as one of the arguments for a combinator.
>
> No; I use \X (or `X) as a syntactic expression for the semantic meaning of
> Joy's [X] first.

i prefer to think of syncategorematic \ as fulfilling the promise that any stack

s1 .. sn

can be directly created by saying

\s1 .. \sn

as you say, \ has no independent semantic meaning - it's just syntax for escaping execution.

>
> >Or, to use the |[ and ]| brackets, you use `X for |[X]|, but you
> >disallow |[X Y]|.
>
> Yes, my language will initially disallow |[X Y]|. But this is only for the
> sake of expediency; I will define brackets to do that and add them to the
> language when it seems good to me. (Note that I prefer single-character
> brackets, so I'll be using {}, as cK does.)

in cK, {X} is shorthand for [X] enclose. enclose takes a list and turns it into an atomic function. (and disclose takes a function
and turns it back into the underlying list.) {X} and + are both functions, and so, to get {+} on the stack non-functionally (i.e.
other than by e.g. [{+}] first) you quote it:

\{+}


> >Anyhow, best wishes for the design and implementation of your language.
>
> Thank you!
>
> >Thanks for the discussion.

i too have found this discussion stimulating - thanks to both of you.

>
> > - Manfred
>
> -Billy

phimvt@lurac.latrobe.edu.au — 2003-08-14 07:16:48

On Fri, 8 Aug 2003, Tanksley, William D. Jr. wrote:

> From: phimvt@... [mailto:phimvt@...]

[.. apropos my mystification about what `foo corresponds to in Joy..]

> >Except for the second last: Now I'm confused again back to where
> >I was before. Which is it:
> > [cube] == `cube or [cube] first == `cube
> >and hence [cube] map == `cube map or [cube] first map ==
> >`cube map
>
> The second in each pair.

Mystery solved: it is your combinators that are different from Joy.

In concatenative languages a term is a sequence of zero or more
factors. In Joy terms occur
1. in definitions as bodies of defined functions,
2. as the bodies of nameless quotations -
as lists or as parameters for combinators
3. as requests to interpret/evaluate a program.
In your language 1. and 3. are the same, maybe 2. also, but not
as parameters for combinators. Your combinators are different from
the ones in Joy, as the following shows.

In the current implementation of Joy, in the file interp.c
the principal workhorse function is exterm() which executes all
terms. It is a loop enclosing a conditional:
WHILE there is another factor in this term
IF the factor is a literal, push it,
ELSE IF it is a primitive, execute it,
ELSE (it is defined), execute its body by recursive
call to exeterm.
Apart from the recursion for 1. above, exeterm() is also used for
2. in all combinators, and in 3. for the main request. Any other
implementation of Joy would have to do essentially the same.

In your language combinators do not execute the term in a quotation
[foo bar baz], but instead they execute a single factor foo.
So for combinators you have something like the conditional above
but without the enclosing loop. Let me write mapterm for what
is normally called map in Joy, and also define:
DEFINE mapfactor == [] cons mapterm
Allowing `square for [square] first, we have the equivalent programs
[dup *] mapterm
[square] mapterm
[square] first [] cons mapterm
[square] first mapfactor
`square mapfactor
Your language has mapfactor but not mapterm, and similarly for all
other combinators. So, in the implementation of your language you
need something like exeterm() for 1. and 3., but you need some kind
of exefactor() (i.e. without the enclosing loop) for use by your
combinators. (Quite possibly you might decide not to make the
conditional a separate function but to have it in every combinator.)

If you ever decide to allow combinators to execute arbitrary terms
rather than single factors, then they will need to use some kind
of exeterm(). BUT also: you will need to introduce duplicate
combinators such as mapterm in addition to mapfactor. This duplication
is a worry - and you should be aware of it now, before you invest
a lot of time in your implementation.

[..lots of good stuff..]

> >From time to time I have thought about an implementation of
> >Joy using such an array, but abandoned the idea because of all
> >sorts of difficulties. Your language might overcome those.
>
> I'd like to hear more about these.

I'll have to leave that for another posting very soon.

- Manfred

Tanksley, William D. Jr. — 2003-08-14 17:24:09

From: phimvt@... [mailto:phimvt@...]
>Mystery solved: it is your combinators that are different from Joy.

Hmm. Yes, they are; because my threading is different from Joy.

>In concatenative languages a term is a sequence of zero or more
>factors. In Joy terms occur
>1. in definitions as bodies of defined functions,
>2. as the bodies of nameless quotations -
> as lists or as parameters for combinators
>3. as requests to interpret/evaluate a program.
>In your language 1. and 3. are the same, maybe 2. also, but not
>as parameters for combinators. Your combinators are different from
>the ones in Joy, as the following shows.

I'm not sure what #3 means, unless you're saying that it represents direct
text input into the compiler/interpreter. In my language #1 is present as
CPU-native code; #3 is present as text input, and #2 isn't present (yet).
When and if it gets added, I will implement it by treating it as a literal,
but still compiling to CPU native code; in other words, my { operator will
compile a CALL to the end of the literal, and my } operator will compile a
pop of the return address onto the data stack.

In other words, in the final analysis, #1 and #2 are treated identically,
both for compiling and executing. I'm still not sure what you meant by #3.

>In the current implementation of Joy, in the file interp.c
>the principal workhorse function is exterm() which executes all
>terms. It is a loop enclosing a conditional:

Obviously, my code won't have this at all, since it's native code.

>In your language combinators do not execute the term in a quotation
>[foo bar baz], but instead they execute a single factor foo.

Yes, currently; but they do this simply by CALLing the address of the
factor, and they could execute a term in the exact same way.

> - Manfred

-Billy

phimvt@lurac.latrobe.edu.au — 2003-08-15 02:31:58

On Thu, 14 Aug 2003, Tanksley, William D. Jr. wrote:

> From: phimvt@... [mailto:phimvt@...]

[..]

> >In concatenative languages a term is a sequence of zero or more
> >factors. In Joy terms occur
> >1. in definitions as bodies of defined functions,
> >2. as the bodies of nameless quotations -
> > as lists or as parameters for combinators
> >3. as requests to interpret/evaluate a program.

> I'm not sure what #3 means, unless you're saying that it represents direct
> text input into the compiler/interpreter.

DEFINE square == dup *. #1
7 square. #3

[..]

> >In the current implementation of Joy, in the file interp.c
> >the principal workhorse function is exterm() which executes all
> >terms. It is a loop enclosing a conditional:
>
> Obviously, my code won't have this at all, since it's native code.

Well, yes, instead of exeterm() and exefactor() you would have
compileterm() and compilefactor(), the first with a loop enclosing
a conditional, the second with just the conditional.

- Manfred

phimvt@lurac.latrobe.edu.au — 2003-08-15 03:27:41

On Fri, 8 Aug 2003, Tanksley, William D. Jr. wrote:

> From: phimvt@... [mailto:phimvt@...]

[..]

> >2. You are aiming to implement the stack not as a linked structure
> >(as Joy does), but as an array of consecutive memory locations
> >(as Forth does).
>
> That's true.

[..]

> >From time to time I have thought about an implementation of
> >Joy using such an array, but abandoned the idea because of all
> >sorts of difficulties. Your language might overcome those.
>
> I'd like to hear more about these.

OK, here it is. In Joy, consider
[if-part] [then-part] [else-part] ifte
or anything like that in which the three parts are on the top
of the stack and now the ifte combinator gets to work. Joy does
1. Remove the three parts from the top of the stack.
2. Save as much of the remainder of the stack as needed for 5.
3. execute the if-part ( and note that typically this will
use up parts of the stack to get a truth value.
4. note whether top of stack is true or false
5. Restore stack to what it was in step 3
6. If the saved top of stack was true/false,
execute the if-part/then-part.
In a linked list implementation step 2 is easy: just save the whole
stack, as a link. In step 5, forget about the stack that was mangled
in step 3, just restore the link from step 2.

Pretty much the same thing happens in recursion combinators such
as linrec, binrec, tailrec, while, nestrec and so on. Also the
aggregate combinators map, filter and fold need something very
similar, although they do not have an explicit if-part. Finally,
the innocent looking nullary, unary and binary combinators also
have to save and later restore the stack. It is all very easy
with a linked list implementation of the stack.

Another case: the operators stack and unstack and the infra combinator
are easiest with linked implementations for the stack and the lists
(quotations).

With arrays, i.e. consecutive memory locations, for the stack it
is all much harder. Consider ifte again: somehow the effects of
the test in step #3 have to be undone. One possibility is to give
the responsibility to the programmer, and that is cumbersome and
error prone. (I know that Forth programmers don't mind it.)
The other possibility is to let the tests in step #3 do their
own saving for each stack element that they use up. Thus the
tests in ifte and all the recusion combinators will be different
from ordinary predicate evaluations. Yes, one could do it, but
it makes the implementation just a lot harder. Same with the
nullary, unary and binary combinators. And finally, the stack,
unstack and infra will turn out to be difficult.

The upshot: yes, an array stack for Joy can probably be implemented,
but it will be difficult to do for all of Joy.

On the other hand, there may well be a very useful subset of Joy
that can be implemented as an array stack with reasonable effort.
Quite likely it is more efficient that the linked stack, at least for
a substantial proportion of programming tasks. My guess is that
an array stack will work best when sequences such as [1 2 3] are
also implemented as arrays.

And finally, maybe there is a possible hybrid implementation
which uses both arrays and linked structures. I do not know.

I take it some of these vague hunches will be confirmed or refuted
by your implementation. Your Forth background will be a source
of usefule ideas. I look forward to seeing more as you go along.

Best wishes

- Manfred

Tanksley, William D. Jr. — 2003-08-15 16:25:19

From: phimvt@... [mailto:phimvt@...]
>On Thu, 14 Aug 2003, Tanksley, William D. Jr. wrote:
>> From: phimvt@...

>> >In concatenative languages a term is a sequence of zero or more
>> >factors. In Joy terms occur
>> >1. in definitions as bodies of defined functions,
>> >2. as the bodies of nameless quotations -
>> > as lists or as parameters for combinators
>> >3. as requests to interpret/evaluate a program.

>>I'm not sure what #3 means, unless you're saying that it
>>represents direct text input into the compiler/interpreter.

>DEFINE square == dup *. #1
>7 square. #3

Ah! I see. Yes, to my compiler #3 and #1 are the same thing. In Forth
they're distinct, because Forth doesn't have the concept of "terms"; factors
in the body of a definition are compiled one at a time, and factors outside
of a definition are executed one at a time, and that's all there is to it.
This means that in Forth, some words can act strangely when used outside of
their intended environment -- although I can't explain why or how without
explaining some of the hardest concepts in Forth.

>>>In the current implementation of Joy, in the file interp.c
>>>the principal workhorse function is exterm() which executes all
>>>terms. It is a loop enclosing a conditional:

>>Obviously, my code won't have this at all, since it's native code.

>Well, yes, instead of exeterm() and exefactor() you would have
>compileterm() and compilefactor(), the first with a loop enclosing
>a conditional, the second with just the conditional.

Not really -- everything's part of a term; a factor only appears inside of a
term. So whenever you see a factor, you automatically know that you must be
in a term.

You mentioned recursive parsing for quotations. I don't even have to do
that; here's my code for a function-quotation (this is less optimised than
what I'll generate, but it's optimised just a bit):

Input: "4 {5 +} drop 6 -."
Output:
mov EAX,4 \ push a literal
push EAX
call end_of_quotation1 \ push address of next instruction, jump to label
pop EAX
mov EBX,5 \ literal
add EAX, EBX
push EAX
ret
end_of_quotation1:
LEA ESP,[ESP+4] \ drop

pop EAX
mov EBX, 6
sub EAX, EBX
push EAX
ret

Can you see what's happening here? Each word is translated to machine code
one at a time; the open brace translates to a "call end_of_quotation1", and
the close brace translates to a return and the label that the assembler will
use to resolve that call. The result is that a return address, pointing to
the POP instruction, is left on the stack, and it could be used to call the
function (but in this case it's simply dropped).

Sorry for the assembler; I hope the meaning is clear in spite of my use of a
somewhat obscure (but neccesary) language.

> - Manfred

-Billy

Tanksley, William D. Jr. — 2003-08-15 18:26:27

From: phimvt@... [mailto:phimvt@...]
>On Fri, 8 Aug 2003, Tanksley, William D. Jr. wrote:
>> From: phimvt@...

>>>From time to time I have thought about an implementation of
>>>Joy using such an array, but abandoned the idea because of all
>>>sorts of difficulties. Your language might overcome those.
>>I'd like to hear more about these.

>OK, here it is. In Joy, consider
> [if-part] [then-part] [else-part] ifte
>or anything like that in which the three parts are on the top
>of the stack and now the ifte combinator gets to work. Joy does
> 1. Remove the three parts from the top of the stack.
> 2. Save as much of the remainder of the stack as needed for 5.
> 3. execute the if-part ( and note that typically this will
> use up parts of the stack to get a truth value.
> 4. note whether top of stack is true or false
> 5. Restore stack to what it was in step 3
> 6. If the saved top of stack was true/false,
> execute the if-part/then-part.

This isn't needed. Instead, I have the ifte combinator take a flag and the
two alternate functions; it simply drops one of the quotations from the
stack and executes the other. There's no need to take the if-part as a
quotation, since it's executed unconditionally; therefore there's no need to
preserve the stack in any special way.

But consider the other combinators, map and unary and app11 and app12. Here
you NEED to play with the stack, and by Joy's rules you HAVE to save the
stack. But when do you save it, and when do you merge it? There are no clear
guidelines. It's simply up to the person who implements each combinator.

>In a linked list implementation step 2 is easy: just save the whole
>stack, as a link. In step 5, forget about the stack that was mangled
>in step 3, just restore the link from step 2.

But skipping step 2 is even easier! And step 5, while you're at it.

>Another case: the operators stack and unstack and the infra combinator
>are easiest with linked implementations for the stack and the lists
>(quotations).

Now this is true: using a temporary stack is easy with a linked list. It's
much harder with an array implementation, since expanding an array is harder
than expanding a list (and stacks can be expected to expand).

>Consider ifte again: somehow the effects of
>the test in step #3 have to be undone. One possibility is to give
>the responsibility to the programmer, and that is cumbersome and
>error prone. (I know that Forth programmers don't mind it.)

The fact is that effects _don't_ have to be undone. If a programmer's
creating effects that will be undone, he's wasting time. Don't do that.

Furthermore, by choosing to NOT restore the stack, I remove the need for
combinators like app12, and the disctinction between '2 times' and 'unary2'.
In short, your scheme requires combinators to know stack effects, and
therefore requires one combinator for each type of stack effect (and the
programmer has to select from all the different combinators); my scheme
allows combinators to be ignorant of stack effects, thus making combinator
selection much simpler.

However, my scheme does require the functions passed to combinators to
produce the correct input and output. So what? Those functions by definition
are quotations in Joy; the programmer had to write them for this purpose,
none other. So there's no special knowledge involved, nothing new to learn:
simply the one rule, "clean up after yourself," a rule which applies to all
situations in and out of concatenative languages.

Try a mental exercise. Assume that Joy's combinators didn't clean up the
stack for you; how would you have to write some of the existing programs?
Since so many of the combinators are now redundant, how many of the existing
programs could be written in a much simpler way?

>it makes the implementation just a lot harder. Same with the
>nullary, unary and binary combinators. And finally, the stack,
>unstack and infra will turn out to be difficult.

Again, these are true problems. There are some solutions: for example, I can
simulate a new stack by moving the "bottom of the stack" marker up, so that
"stack underflow error" gets signalled before the old elements get touched.
If I'm using static typechecking (and I plan to), this will be detected and
handled at compile time.

>I take it some of these vague hunches will be confirmed or refuted
>by your implementation. Your Forth background will be a source
>of usefule ideas. I look forward to seeing more as you go along.

I hope I can produce something soon... I have a list implementation sitting
on top of semi-standard Forth, but I haven't had any spare time lately,
since I just lost my current contract and I have my first child due November
(gotta work to keep the family fed!).

> - Manfred

-Billy

phimvt@lurac.latrobe.edu.au — 2003-08-21 06:35:45

On Fri, 15 Aug 2003, Tanksley, William D. Jr. wrote:

[...]

> but I haven't had any spare time lately,
> since I just lost my current contract and I have my first child due November
> (gotta work to keep the family fed!).

From all of us: best wishes to mother and baby,
and good luck with a new contract.

- Manfred

Tanksley, William D. Jr. — 2003-11-11 19:56:12

From: phimvt@... [mailto:phimvt@...]
>On Fri, 15 Aug 2003, Tanksley, William D. Jr. wrote:
>>but I haven't had any spare time
>>lately, since I just lost my current contract and I have my first
>>child due November (gotta work to keep the family fed!).

>From all of us: best wishes to mother and baby,
>and good luck with a new contract.

Due date still November 26th; as you can tell from my email address, I
managed to find a new contract at the same company (a relief -- I like this
place a lot).

Things are, however, very busy, so should this list spring into action with
a flurry of activity and posts, don't expect me to be at the forefront :-).

On topic: during my little "vacation" I looked at a derivative of Ada called
"SPARK" (www.sparkada.com). Spark is a subset of Ada plus comment
annotations which does a few interesting things:

1. eliminates all ambiguity: a valid SPARK program will do the exact same
thing on all ceritfied Ada compilers.
2. allows certification of lack of runtime: a valid, fully annotated, and
proven SPARK program will never throw an exception or otherwise use the
services of the Ada runtime. There are now a few no-runtime Ada packages.
This can be handy for tight embedded systems as well as life-critical
systems where the runtime would cost too much to certify.
3. profoundly increases the power of static typechecking, including the
ability to establish upper bounds for resource (and time) consumption.
4. Can be checked as fast as an Ada compiler can run, so rather than running
the compiler to check for syntax errors, it's always worthwhile to run
SPARK's verifier (although the theorem prover takes longer, and can require
human intervention).

So what?

Well, it's interesting to me that my current design for my cKlike Forth
language looks a little like Spark in many ways. I would find it amusing to
have the first version of the language be a verifiable subset, and even
perhaps to see what aspects of verification I can perform in linear time.

Keep in mind that I'm already planning to perform static polymorphic
typechecking, so I have some part of what I need already. In addition, all
the code SPARK uses to perform dataflow analysis is ENTIRELY unneeded in a
concatenative language -- unless, of course, I allow certain uses of global
variables. Imagine my newfound hesitation to allow those globals...

> - Manfred

-Billy

phimvt@lurac.latrobe.edu.au — 2003-11-13 04:45:50

On Tue, 11 Nov 2003, Tanksley, William D. Jr. wrote:

> From: phimvt@... [mailto:phimvt@...]

[..]
> >From all of us: best wishes to mother and baby,
> >and good luck with a new contract.

Well, I'll repeat this verbatim.

> Due date still November 26th; as you can tell from my email address, I
> managed to find a new contract at the same company (a relief -- I like this
> place a lot).
>
> Things are, however, very busy, so should this list spring into action with
> a flurry of activity and posts, don't expect me to be at the forefront :-).

I have been very busy myself, with my last semester of teaching before
retirement. In addition the mailing software on the old DEC Alpha under
VMS got badly hit by something (at least that is what they tell me), and
my old mailing address did not work at all for ages. So my apologies to
anyone who has sent me anything - as far as I know the software just
swallowed it, no delivery, no bounce. BAD. The only person who knows
anything about it was overseas and administration did not want to invest
in outside help for the two or three humans who still use this hardware.
I have been advised to move my stuff to another machine because the
old one will be scrapped in the middle of next year. Oh what tedium !

My new email address will be: M.Vonthun@...
But for the purposes of the concatenative group I am still with
my old email. I still have not found a way to re-join the group
with the new email, but I'll get it right eventually. In the mean-
time, both the old and the new work for ordinary email.

I hope the recent low traffic on the concatenative group is only
a temporary phenomenon.

[..about Ada and Spark..]

> Well, it's interesting to me that my current design for my cKlike Forth
> language looks a little like Spark in many ways. I would find it amusing to
> have the first version of the language be a verifiable subset, and even
> perhaps to see what aspects of verification I can perform in linear time.
>
> Keep in mind that I'm already planning to perform static polymorphic
> typechecking, so I have some part of what I need already. In addition, all
> the code SPARK uses to perform dataflow analysis is ENTIRELY unneeded in a
> concatenative language -- unless, of course, I allow certain uses of global
> variables. Imagine my newfound hesitation to allow those globals...

You sound all fired up - so my best wishes for this project.

- Manfred