# 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