# Properties of Concatenative langauges and Forth

## Christopher Diggins — 2009-01-02 15:42:34

    In a concatenative language, I believe evaluation order should be unimportant.

    For example:

    f g h <=> (f g) h <=> f (g h)

    Does Forth have this property?

    Another property that I expect from a concatenative language is that

    any subsequence of terms can be replaced with a subroutine whose

    definition consists of that subsequence, without changing the meaning

    of the program. I believe this follows from the description of Joy

    that says that the syntax is a homomorphism to the semantics.

    For example:

    define sub { a b }

    a b c a b <=> sub c sub

    Does Forth have this property?

    What about Enchilada?

    FWIW: I like Steven Apter's informal definition a lot. Concatenative

    means Joy-like. I am really worrying so much about definitions because

    I am interested in trying to get at the heart of what makes Joy so

    darn interesting from a theoretical stand-point, so that I can talk to

    academics and say "see, Joy is not like your language!"

    - Christopher

## William Tanksley, Jr — 2009-01-02 16:50:46

    Christopher Diggins <cdiggins@...> wrote:

     > In a concatenative language, I believe evaluation order should be

    > unimportant.

    > For example:

    > f g h <=> (f g) h <=> f (g h)

     This is the associative property. You need to be careful calling it

    "evaluation order", though; evaluation order matters with respect to

    dataflow -- you can't fully evaluate an expression whose parameters

    aren't all known at evaluation time.

     > Does Forth have this property?

     Yes, except where you're using macros or other compiling words.

     > Another property that I expect from a concatenative language is that

    > any subsequence of terms can be replaced with a subroutine whose

    > definition consists of that subsequence, without changing the meaning

    > of the program.

     Yes; this is an important one for me. It's included in the new

    proposed "Concatenative" page. It's actually a direct consequence of

    the associative property.

     > I believe this follows from the description of Joy

    > that says that the syntax is a homomorphism to the semantics.

     I'm not familiar with that claim, but it is indeed important that the

    semantics and syntax have the same associative property. I don't know

    whether that makes it a homomorphism.

    I expressed this a while back by saying that "a concatenative language

    maps the associative operation of syntactic concatenation onto the

    semantics of an associative operation on functions." This isn't as

    good of a definition as the others we're considering, but it does say

    what you're examining here.

     > Does Forth have this property?

     Yes.

     > What about Enchilada?

     I believe so.

     > FWIW: I like Steven Apter's informal definition a lot. Concatenative

    > means Joy-like. I am really worrying so much about definitions because

    > I am interested in trying to get at the heart of what makes Joy so

    > darn interesting from a theoretical stand-point, so that I can talk to

    > academics and say "see, Joy is not like your language!"

     It's kind of odd to say that Postscript and Forth are Joy-like.

    But really, as long as you're just going by examples, you don't have a

    theory. That's okay; but it's not enough to make something interesting

    from a theoretical standpoint.

     > - Christopher

     -Wm

## Stevan Apter — 2009-01-02 16:59:41

    >

    >> FWIW: I like Steven Apter's informal definition a lot. Concatenative

    >> means Joy-like. I am really worrying so much about definitions because

    >> I am interested in trying to get at the heart of what makes Joy so

    >> darn interesting from a theoretical stand-point, so that I can talk to

    >> academics and say "see, Joy is not like your language!"

    >

    > It's kind of odd to say that Postscript and Forth are Joy-like.

    >

    > But really, as long as you're just going by examples, you don't have a

    > theory. That's okay; but it's not enough to make something interesting

    > from a theoretical standpoint.

     programming language inquiry does feel more like classifying beetles and

    orchids than it does like physics.

     >

    >> - Christopher

    >

    > -Wm

    >

## Christopher Diggins — 2009-01-02 19:36:59

    In Fri, Jan 2, 2009 at 11:50 AM, William Tanksley, Jr

    <wtanksleyjr@...> wrote:

     > Christopher Diggins <cdiggins@...> wrote:

    >> In a concatenative language, I believe evaluation order should be

    >> unimportant.

    >> For example:

    >> f g h <=> (f g) h <=> f (g h)

    >

    > This is the associative property. You need to be careful calling it

    > "evaluation order", though; evaluation order matters with respect to

    > dataflow

     Not necessarily. It depends on what the evaluation mechanism is.

    Talking about data-flow in the context of Joy is incorrect. A Joy

    program has no data, only functions. You'll see what I mean below.

     >  -- you can't fully evaluate an expression whose parameters

    > aren't all known at evaluation time.

     This is the difference between applicative and concatenative

    languages. An applicative language applies a function to a value to

    yield values. This continues until no more application is required and

    we are left with a final *value*. In a concatenative language (or at

    least in Joy and Cat) every program, subprogram, and expression is a

    function from stack to stack. Evaluation of a program consists of

    composing functions created by the terms to yield a final *function*

    on stacks.

    In a program "1 2 +", "1" and "2" are not parameters to a function

    "+". Manfred calls this out quite clearly in his essays. This is why

    he says Joy is not a postfix language. You are not applying the

    function "+" to values "1" and "2". To understand why this is, we have

    to resort to a formal exploration of the semantics in terms of the

    mathematical meanings of a Joy (or Cat) program.

    I'll use Cat, because I am afraid of making a mistake with the Joy

    syntax. Consider the Cat program "p":

    define p { 1 2 + }

    In Cat (like Joy) the program "p" is a function on stacks, that is

    created by composing the stack functions represented by "1", "2", and

    "+". The semantics (the meaning) of a valid program is a function on

    stacks. I represent this formally below using the symbol "::==" to

    mean "has the meaning of". The left side is a term in Cat, and the

    right side is the function on stacks. The notation [R, a, b] -> [R,

    a+b] means "the function which maps a stack containing two values on

    top and any number of values below, to a new stack containing which is

    a copy of the original stack with the top two values replaced with

    their sum".

    1 ::== [R] -> [R, 1]

    2 ::== [R] -> [R, 2]

    + ::== [R, a, b] -> [R, a+b]

    We know intuitively that the meaning of "p" is:

    p ::== [R] -> [R, 3]

    Which is equivalent to the program:

    3 ::== [R] -> [R, 3]

    Hence we can say that the evaluation of "p" is "3", because it has the

    same effect as the program 3. To get the function from a program (in

    other words to evaluate a program), we have to compose all of the

    functions corresponding to individual terms in the program. Formally:

    1 2 + ::== ([R] -> [R, 1]) . ([R] -> [R, 2]) . ([R, a, b] -> [R, a+b])

    To evaluate the expression "1 2 +", we compose the functions which

    result from performing the composition of the sub-terms. We can do it

    right to left:

    1 2 + ::== ([R] -> [R, 1]) . (([R] -> [R, 2]) . ([R, a, b] -> [R, a+b]))

    1 2 + ::== ([R] -> [R, 1]) . ([R, a] -> [R, a+2])

    1 2 + ::== ([R] -> [R, 3])

    Or left to right (obviously because composition is applicative):

    1 2 + ::== (([R] -> [R, 1]) . (([R] -> [R, 2])) . ([R, a, b] -> [R, a+b])

    1 2 + ::== ([R] -> [R, 1, 2]) . ([R, a, b] -> [R, a+b])

    1 2 + ::== ([R] -> [R, 3])

    So my statement about evaluation order is correct.

    The execution model of a Cat program may vary. Formally the stack

    function created by composing terms is applied to an input stack to

    yield an output stack. A naive implementation may apply terms

    sequentially to the input stack. While this is a helpful mental model

    for understanding a common implementation technique for executing Cat

    or Joy programs, it says nothing useful about the formal semantics.

    For those interested in semantics, the following books provide a good

    foundation in the study of the semantics of programming languages.

    * "Programming Languages Applications and Interpretation" (a,k.a.

    PLAI) by Shriram Krishnamurthi ( full text online at

    http://www.cs.brown.edu/~sk/Publications/Books/ProgLangs/2007-04-26/plai-2007-04-26.pdf

    )

    * "Structure and Interpretation of Programs" (a.k.a. SICP) by Ableman,

    Sussman, and Sussman. (full text online at

    http://mitpress.mit.edu/sicp/full-text/book/book.html )

    * "Types and Programming Languages" (a.k.a. TAPL) by Benjamin Pierce,

    unfortunately not free

    - Christopher

## John Nowak — 2009-01-02 22:02:50

    On Jan 2, 2009, at 10:42 AM, Christopher Diggins wrote:

     > In a concatenative language, I believe evaluation order should be

    > unimportant.

     Evaluation order is important in every concatenative language that

    currently exists as far as I know. In the Forth of Factor program '1 .

    2 .', it is a requirement that '1 .' be evaluated before '2 .'. The

    same sort of thing goes for Cat.

     > define sub { a b }

    > a b c a b <=> sub c sub

    >

    > Does Forth have this property?

     Forths without local variables have this property.

     > What about Enchilada?

     Enchilada does not seem to due to lambda abstractions.

    - John

## John Nowak — 2009-01-02 22:14:15

    On Jan 2, 2009, at 11:50 AM, William Tanksley, Jr wrote:

     > Christopher Diggins <cdiggins@...> wrote:

    >>

    >

    >> f g h <=> (f g) h <=> f (g h)

    >> Does Forth have this property?

    >

    > Yes, except where you're using macros or other compiling words.

     I think macros and compiling words get a pass. Saying they don't

    wouldn't be much different than saying Haskell isn't purely functional

    because top-level definitions can alter the meaning of other parts of

    the program. Forth's dynamic nature obscures this a bit, but I think

    it's essentially the same thing.

    The concatenative requirement is sensibly limited to expressions

    within the language. In certain cases, it might be required to expand

    the macros to get the concatenative expression. I think we can

    sensibly talk about a concatenative language "plus macros". Factor

    offers a good example; just because there exists a macro for locals

    doesn't make the language non-concatenative.

     > It's kind of odd to say that Postscript and Forth are Joy-like.

     Indeed.

    - John

## Christopher Diggins — 2009-01-02 22:50:39

    On Fri, Jan 2, 2009 at 5:14 PM, John Nowak <john@...> wrote:

     >

    > On Jan 2, 2009, at 11:50 AM, William Tanksley, Jr wrote:

    >

    >> Christopher Diggins <cdiggins@...> wrote:

    >>>

    >>

    >>> f g h <=> (f g) h <=> f (g h)

    >>> Does Forth have this property?

    >>

    >> Yes, except where you're using macros or other compiling words.

    >

    > I think macros and compiling words get a pass.

     Forth without compile-time words isn't Turing-complete as far as I can

    tell. I don't think you can just give it a pass. Can you even

    construct a conditional expression in Forth without compile-time

    words?

     > Saying they don't

    > wouldn't be much different than saying Haskell isn't purely functional

    > because top-level definitions can alter the meaning of other parts of

    > the program. Forth's dynamic nature obscures this a bit, but I think

    > it's essentially the same thing.

     I think this is an inaccurate comparison.

     > The concatenative requirement is sensibly limited to expressions

    > within the language. In certain cases, it might be required to expand

    > the macros to get the concatenative expression. I think we can

    > sensibly talk about a concatenative language "plus macros". Factor

    > offers a good example; just because there exists a macro for locals

    > doesn't make the language non-concatenative.

     Macros sure, but your earlier statement included compile-time words.

     >> It's kind of odd to say that Postscript and Forth are Joy-like.

    >

    > Indeed.

     I disagree. Joy is a nearly pure example of a special class of

    programming languages. If you remove the side-effects, you are left

    with a calculus of stacks. Forth and Postscript exhibit some of those

    properties, but not all, and contain a number of odd hacks and special

    constructs. IMO Joy is much more interesting to study formally than

    Forth and Postscript because of its purity.

    See my other post about the evaluation of a concatenative language, to

    get a sense of why Joy is special.

    - Christopher

## John Nowak — 2009-01-02 23:12:01

    On Jan 2, 2009, at 5:50 PM, Christopher Diggins wrote:

     >> I think macros and compiling words get a pass.

    >

    > Forth without compile-time words isn't Turing-complete as far as I can

    > tell. I don't think you can just give it a pass. Can you even

    > construct a conditional expression in Forth without compile-time

    > words?

     I was considering Forth's conditional as a functional form with the

    syntax 'IF <expr> THEN <expr> ELSE'. The expressions within the form

    are still completely concatenative. It's true that IF, THEN, and ELSE

    are not functions, but neither are [ and ] which are used for forming

    quotations. Furthermore, 'IF <expr> THEN <expr> ELSE' does indeed

    denote a function. I see no issue with a concatenative language

    offering the functional form of condition.

     >> The concatenative requirement is sensibly limited to expressions

    >> within the language. In certain cases, it might be required to expand

    >> the macros to get the concatenative expression.

    >

    > Macros sure, but your earlier statement included compile-time words.

     Nearly all languages have "compile-time" words, including Cat. Is Cat

    not concatenative because it has 'define'? Of course not, because

    'define' is not part of the expression language. The same goes for

    things in Forth like ':', ';', etc. There may be other examples in

    Forth that break this, but I'm not enough of a Forth programmer to know.

     > Joy is a nearly pure example of a special class of programming

    > languages. If you remove the side-effects, you are left with a

    > calculus

    > of stacks. See my other post about the evaluation of a concatenative

    > language, to get a sense of why Joy is special.

     That's a pretty big "if". Unfortunately, Joy is not pure enough to

    allow reduction in an arbitrary order in the sense you're describing.

    I agree that your description is correct if side-effects are barred.

    - John

## Stevan Apter — 2009-01-03 00:49:36

    ----- Original Message -----

    From: "Christopher Diggins" <cdiggins@...>

    [:]

    >

    >>> It's kind of odd to say that Postscript and Forth are Joy-like.

    >>

    >> Indeed.

    >

    > I disagree. Joy is a nearly pure example of a special class of

    > programming languages. If you remove the side-effects, you are left

    > with a calculus of stacks. Forth and Postscript exhibit some of those

    > properties, but not all, and contain a number of odd hacks and special

    > constructs. IMO Joy is much more interesting to study formally than

    > Forth and Postscript because of its purity.

    thanks, yes, i agree with this.

    since others have used the terms "interesting" and "uninteresting"

    as though they picked out objective properties (rather than just

    indicating preferences), i'll note that i find joy interesting, and

    forth not.

    >

    > See my other post about the evaluation of a concatenative language, to

    > get a sense of why Joy is special.

    well, it also emerged fully-formed and athena-like from the forehead of

    manfred von thun.

    >

    > - Christopher

    >

## John Cowan — 2009-01-03 03:20:43

    Christopher Diggins scripsit:

     > Talking about data-flow in the context of Joy is incorrect. A Joy

    > program has no data, only functions. You'll see what I mean below.

     Well, sort of.  5 is a number in Joy, even if it's a function too.

    As a function, it can be applied to the stack; but if it's on the stack,

    it can be added to another number by the function +.

    --

    Evolutionary psychology is the theory           John Cowan

    that men are nothing but horn-dogs,             http://www.ccil.org/~cowan

    and that women only want them for their money.  cowan@...

            --Susan McCarthy (adapted)

## John Nowak — 2009-01-03 03:52:58

    On Jan 2, 2009, at 10:20 PM, John Cowan wrote:

     > Christopher Diggins scripsit:

    >

    >> Talking about data-flow in the context of Joy is incorrect. A Joy

    >> program has no data, only functions. You'll see what I mean below.

    >

    > Well, sort of.  5 is a number in Joy, even if it's a function too.

    > As a function, it can be applied to the stack; but if it's on the

    > stack,

    > it can be added to another number by the function +.

     The fantastic thing about concatenative languages is that you can

    think about it both ways.

    Joy programs have data. If I take a Joy program and start it by

    passing it an empty stack, the stack that goes from function to

    function afterwards is the data.

    At the same time, they have no visible objects. The syntax doesn't

    allow me to write an object. If I define 'foo' to be '5', 'foo' is

    still a function (with type R -> R Int). If I have the expression '1 2

    +' and reduce it to '3', I still have a function.

    If there was an argument that concatenative languages must be stack

    based (or similar), you could base it on this point. A function that

    contains only functions which push elements onto the stack (e.g. '1 2

    3') "looks the same" as a stack itself. I can think of '1 2 +' as

    either "applying" the '+' operation to the stack '1 2' or composing

    the functions '1 2' and '+'.

    This is a duality you'd lose if you passed around a dictionary instead

    of a stack. I think that's a significant consequence. There are other

    data structures where I can see how have the same duality, but they

    are all ordered (tuples, lists, more-style vectors, etc). Are there

    others?

    Hm. I should probably add this duality do the "properties" section of

    the article...

    - John

## Christopher Diggins — 2009-01-03 04:57:05

    On Fri, Jan 2, 2009 at 10:20 PM, John Cowan <cowan@...> wrote:

     > Christopher Diggins scripsit:

    >

    >> Talking about data-flow in the context of Joy is incorrect. A Joy

    >> program has no data, only functions. You'll see what I mean below.

    >

    > Well, sort of. 5 is a number in Joy, even if it's a function too.

    > As a function, it can be applied to the stack; but if it's on the stack,

     As a syntactic phrase in the Joy language, the symbol "5" has one

    meaning: it is a function that takes a stack as input and returns a

    copy of the input stack, with a value "5" on top. Dually we can

    explain it is an instruction that pushes a value "5" on a shared

    stack. In either case the value "5" on a stack is distinct from the

    instruction "5".

    - Christopher

## John Nowak — 2009-01-03 05:09:02

    On Jan 2, 2009, at 11:57 PM, Christopher Diggins wrote:

     > On Fri, Jan 2, 2009 at 10:20 PM, John Cowan <cowan@...> wrote:

    >

    >> Christopher Diggins scripsit:

    >>

    >>> Talking about data-flow in the context of Joy is incorrect. A Joy

    >>> program has no data, only functions. You'll see what I mean below.

    >>

    >> Well, sort of. 5 is a number in Joy, even if it's a function too.

    >> As a function, it can be applied to the stack; but if it's on the

    >> stack,

    >

    > As a syntactic phrase in the Joy language, the symbol "5" has one

    > meaning: it is a function that takes a stack as input and returns a

    > copy of the input stack, with a value "5" on top.

     I agree.

     > Dually we can explain it is an instruction that pushes a value "5"

    > on a shared stack.

     Not necessarily in Joy, unless you also describe 'infra' as something

    which changes which stack is the "shared" stack until some particular

    quotation in finished being evaluated. I think that's pretty clumsy

    compared to '{S} [F] infra => {S F}'.

    - John

## John Cowan — 2009-01-03 07:46:08

    Christopher Diggins scripsit:

     > As a syntactic phrase in the Joy language, the symbol "5" has one

    > meaning: it is a function that takes a stack as input and returns a

    > copy of the input stack, with a value "5" on top. Dually we can

    > explain it is an instruction that pushes a value "5" on a shared

    > stack. In either case the value "5" on a stack is distinct from the

    > instruction "5".

     True, but one can be transformed into the other freely, since the

    currently executing Joy program is just another list object and can be

    manipulated as such.

    --

    John Cowan    http://www.ccil.org/~cowan   <cowan@...>

        "Any legal document draws most of its meaning from context.  A telegram

        that says 'SELL HUNDRED THOUSAND SHARES IBM SHORT' (only 190 bits in

        5-bit Baudot code plus appropriate headers) is as good a legal document

        as any, even sans digital signature." --me

## William Tanksley, Jr — 2009-01-04 19:16:57

    Christopher Diggins <cdiggins@...> wrote:

     > William Tanksley, Jr <wtanksleyjr@...> wrote:

    >> Christopher Diggins <cdiggins@...> wrote:

    >>> In a concatenative language, I believe evaluation order should be

    >>> unimportant.

    >>> For example:

    >>> f g h <=> (f g) h <=> f (g h)

    >> This is the associative property. You need to be careful calling it

    >> "evaluation order", though; evaluation order matters with respect to

    >> dataflow

    > Not necessarily. It depends on what the evaluation mechanism is.

    > Talking about data-flow in the context of Joy is incorrect. A Joy

    > program has no data, only functions. You'll see what I mean below.

     You're thinking of "values" as a syntactic element: Joy (and

    concatenative languages in general) do not have a special syntactic

    element for values. A value is nothing more than a function that takes

    no input and generates a single, constant output; not worth making a

    special syntactic category for.

    Data, on the other hand, is what programs consume and produce.

    Obviously, you can't evaluate a '+' if you don't know what 2 data

    items are on top of the stack. In that sense evaluation order is

    important.

     >>  -- you can't fully evaluate an expression whose parameters

    >> aren't all known at evaluation time.

    > This is the difference between applicative and concatenative

    > languages. An applicative language applies a function to a value to

    > yield values. This continues until no more application is required and

    > we are left with a final *value*. In a concatenative language (or at

    > least in Joy and Cat) every program, subprogram, and expression is a

    > function from stack to stack. Evaluation of a program consists of

    > composing functions created by the terms to yield a final *function*

    > on stacks.

     I totally agree right up to the last sentence -- building a program

    works that way, but evaluating it (i.e. running it) still requires

    data. Once you've built it, you can analyze it, refactor it, optimize

    it... But you can only evaluate the parts for which you have actual

    data.

     > In a program "1 2 +", "1" and "2" are not parameters to a function

    > "+". Manfred calls this out quite clearly in his essays.

     You're right; it took until now to see my mistake. I misspoke of

    parameters to a function, when as you explain, functions do not attach

    in any way to parameters, or anything else aside from other functions.

    I could have more accurately spoken of "data" applied to a "program".

    If "data" doesn't work for you, try "unknowns". You can't evaluate a

    program until all the unknowns are provided; you can't evaluate a

    portion of a program until all of the unknowns it depends upon have

    been computed or provided, and often that means you have to evaluate

    the leftmost part of a program earlier than the rightmost part. That's

    a rule of thumb, not a law; there are transformations that can

    rearrange program text; but it's a strong rule of thumb nonetheless.

     > Hence we can say that the evaluation of "p" is "3", because it has the

    > same effect as the program 3. To get the function from a program (in

    > other words to evaluate a program), we have to compose all of the

    > functions corresponding to individual terms in the program. Formally:

     Evaluating a program does not result in "getting the function from"

    it. Evaluating a program, given the data you wish to evaluate it at,

    produces the program's output for that data (if any, and if the

    program halts within your patience).

     > To evaluate the expression "1 2 +", we compose the functions which

    > result from performing the composition of the sub-terms. We can do it

    > right to left:

     You're actually simplifying "1 2 +" rather than evaluating it -- since

    it's a constant, the simplification is the same as the evaluation.

     > Or left to right (obviously because composition is applicative):

    > So my statement about evaluation order is correct.

     It's true that you can simplify in any order; and it's true that this

    is one of the big points in favor of concatenative languages. They

    beat even referentially transparent applicative languages, since

    applicative languages can only simplify a valid parse.

     > - Christopher

     -Wm

## William Tanksley, Jr — 2009-01-04 20:02:06

    Christopher Diggins <cdiggins@...> wrote:

     > Forth without compile-time words isn't Turing-complete as far as I can

    > tell. I don't think you can just give it a pass. Can you even

    > construct a conditional expression in Forth without compile-time

    > words?

     Sure, but you have to have some way of deferring a word inside a

    definition (i.e. getting a reference to a function rather than

    executing it). The "Furphy" language takes an approach like Joy's, by

    providing a quotation primitive and redesigning the control words to

    expect quotations on the stack rather than using compiling words...

    It's easier to treat the compiling words as syntax, which they are.

    And aside from that syntax, Forth is concatenative -- just as Joy,

    aside from its quotations and the inability to simplify inside

    quotations, is concatenative.

    The perfect concatenative language hasn't been invented. But the field is young.

    (Out of modesty, I haven't made the claim that the "oi" or "01"

    languages Kerby and I produced is fully associative and therefore

    perfectly concatenative. Well, modesty and a deep sense of shame at

    the horror that I produced by asking that fateful question.)

     >> The concatenative requirement is sensibly limited to expressions

    >> within the language. In certain cases, it might be required to expand

    >> the macros to get the concatenative expression. I think we can

    >> sensibly talk about a concatenative language "plus macros". Factor

    >> offers a good example; just because there exists a macro for locals

    >> doesn't make the language non-concatenative.

    > Macros sure, but your earlier statement included compile-time words.

     Macros are compile-time words that consume source code text. They're

    worse, not better, in terms of simplification.

     >>> It's kind of odd to say that Postscript and Forth are Joy-like.

    >> Indeed.

    > I disagree. Joy is a nearly pure example of a special class of

    > programming languages. If you remove the side-effects, you are left

    > with a calculus of stacks. Forth and Postscript exhibit some of those

    > properties, but not all, and contain a number of odd hacks and special

    > constructs. IMO Joy is much more interesting to study formally than

    > Forth and Postscript because of its purity.

     Joy was designed for that purpose. Forth and Postscript were designed

    before that purpose was even imagined. So yes, Joy is special; but

    it's not even close to the most specialized. 01 is stronger in that

    way, and it's a terrible language in all other ways.

     > See my other post about the evaluation of a concatenative language, to

    > get a sense of why Joy is special.

     Everything you said there applied to Forth and Postscript as well. I

    didn't notice anything that was special. Note that Joy has a similar

    disadvantage to Forth, since it has a quotation syntax -- it's better

    than Forth in one respect, since its quotation syntax is simple to

    recognise, while Forth's compile time words have to be recognized

    ad-hoc. OTOH, Joy's ability to treat quotations as lists means that

    quotations can't always be simplified, which is arguably much worse.

    The ideal Joy-like language would have quotations, but keep them

    distinct from lists.

     > - Christopher

     -Wm

## pml060912 — 2009-01-05 03:55:00

    --- In concatenative@yahoogroups.com, "William Tanksley, Jr"

    <wtanksleyjr@...> wrote:

     >

    > Christopher Diggins <cdiggins@...> wrote:

    > > Forth without compile-time words isn't Turing-complete as far as I can

    > > tell. I don't think you can just give it a pass. Can you even

    > > construct a conditional expression in Forth without compile-time

    > > words?

    >

    > Sure, but you have to have some way of deferring a word inside a

    > definition (i.e. getting a reference to a function rather than

    > executing it). The "Furphy" language takes an approach like Joy's, by

    > providing a quotation primitive and redesigning the control words to

    > expect quotations on the stack rather than using compiling words...

     No! I deliberately looked for an approach that did NOT need quotation

    for just this sort of reason, i.e. to keep the base small and

    extensible without making anything "special" so that higher level

    behaviour would also remain consistent etc. I eventually found one in

    the FREEZE and THAW matched pair of keywords (these can be implemented

    using return stack manipulation keywords like R> and >R and don't even

    need to be primitives). After that I provided quotation for code using

    [ and ] as syntactic sugar, but it is not fundamental (see

    http://users.beagle.com.au/peterl/furphy.html for more details).

    .

    .

    .

     > The ideal Joy-like language would have quotations, but keep them

    > distinct from lists.

     Furphy has a separate (and thus orthogonal) quotation system for data,

    using { and } to package up items that other stuff generate for them

    on the stack. There is also syntactic sugar to set up strings this way

    using quotation marks.

## pml060912 — 2009-01-05 04:10:41

    --- In concatenative@yahoogroups.com, "Christopher Diggins"

    <cdiggins@...> wrote:

    .

    .

    .

     > Forth without compile-time words isn't Turing-complete as far as I can

    > tell.

     Yes, it is (ignoring the fact that implementations are finite),

    because it's a TWO stack machine. (I'm assuming the memory addressing

    operators @ and ! aren't allowed for the purposes of this discussion.)

     I don't think you can just give it a pass. Can you even

     > construct a conditional expression in Forth without compile-time

    > words?

     Yes, actually. You can change the default compiler behaviour to close

    secondaries with a branch back to the beginning instead of a return,

    so the default is an infinite loop, and then use a conditional return

    ?R which consumes a true/false flag on the stack. If you get rigorous

    about not even allowing the compiler to have a compile time keyword to

    terminate it, you can do what I did with Furphy (for just that reason,

    to avoid making "special" words fundamental). That uses Reverse Polish

    naming, so that the first unrecognised token both terminates and names

    a secondary. I took that approach even further, to make Furphy

    modeless (more precisely, it has a single compile and go mode where

    Forth has distinct execution and compile modes).