[stack] function/object ambiguity + quotation alternative

John Nowak <[email protected]>
Newsgroups gmane.comp.lang.concatenative
Message-ID <[email protected]>
I've hinted at this recently, but never properly explained it. It may  
be entirely uninteresting or even an incorrect observation, so I'd  
appreciate a whack on the hand if I'm off track. I think, however,  
that it may be important in letting us further develop a firm  
theoretical basis for concatenative languages.

In a concatenative language, all terms denote functions. I don't think  
this is too contentious to say. For example, '42' denotes the function  
that pushes the value 42 onto a stack. '[foo bar]' is a function that  
pushes the quotation/list [foo bar] onto the stack. Et cetera.

This seem to be a unique property. I have never seen a non- 
concatenative language in which every term denoted a function.

John Backus invented the term "function-level programming", of which  
his language FP is the canonical example. In FP however, the term '42'  
represents an object. You use the combining form '~', aka "constant",  
to produce a function that returns the object 42 when passed any  
value, e.g. '~42'.

Assume application is written ":", composition is written ".", a list  
is written in angle brackets, and construction is written with square  
brackets. Given this, the semantics of 'dup' in FP are as follows:

    dup:X   ->  <X, X>
    dup.~X  ==  [~X, ~X]

The former gives the semantics of applying 'dup' to some object X. The  
latter states an equivalence between composing 'dup' with the constant  
function '~X' and construction over two functions that are both the  
constant function '~X'.

With concatenative languages, we always use the second form for  
expressing the semantics of some function, e.g. 'X dup == X X'. We do  
this because we have no syntax for application and no way of  
expressing objects. There's something strange here though. Because all  
terms denote functions, 'X' must be a function. However, 'X' cannot be  
any function; it must be a function that pushes a value (and always  
the same value) onto a stack.

I'm now wondering if this function/object ambiguity in concatenative  
languages is really a good thing. Take the Joy expression '[1 2 3]'.  
We can say that '[1 2 3]' is a function that pushes the value [1 2 3]  
onto a stack, but we also have to say that the term '1' within the  
term '[1 2 3]' itself denotes a function. This seems strange because,  
if you gets the first element of the list, you certainly can't use it  
as a function; it's a number.

This strangeness is more evident in the following example. The  
expression '[dup swap] head' yields 'dup', but 'dup != [dup swap]  
head'! This is because the left side of the equality is the *function*  
'dup', but the right side gets reduced to the *object* 'dup'. You  
might think this problem is due to Joy's "open" quotations, but you  
have the same problem in Factor. For example, 'sq != { sq } first'  
despite the fact that '{ sq } first' yields sq!

I believe I know how to solve this problem: Get rid of the function/ 
object ambiguity.

To do this, we drop the requirement that all terms denote functions.  
'42' will now denote the *number* 42. To push 42 onto the stack, we'll  
write '`42', i.e. the push function '`' applied to the object 42.

The presence of '`' allows us to get rid of quotation. Instead of '[+]  
map', we would write '`+ map'; the '`' function applied to the '+'  
function yields a new function that pushes the '+' function onto a  
stack. We'd also need to add parentheses for grouping; you'd write  
'`(foo bar)' instead of '[foo bar]'.

This allows us a solution to the problem with Factor's array literals  
shown above: Array literals would only be allowed to contain terms  
representing objects. For example, '`{ 42 `42 }' would be a function  
that pushes an array onto a stack where the first element of the array  
is the number 42 and the second element is a function that pushes 42  
onto a stack.

I would also suggest adding an additional array syntax that takes  
*functions* that evaluate to single objects. If 'x' is defined as '1 2  
drop', then we could write '{| x |}' to push an array of one element  
containing the number 1 onto the stack. Alternatively, because we now  
have parentheses for grouping, we could replace 'x' with its  
definition and write '{| ( 1 2 drop ) |}' instead.

In Joy, where creating multiple "copies" of the stack is cheap, you  
could use my parallel "banana" combinator to construct lists. For  
example, you could write the function '2 3 (|+ -|)' which would be  
equivalent to the function '`{5 -1}' (assuming we also adopted closed  
quotations for Joy and added '{ }' as a list literal syntax).

Since we have lost the object/function ambiguity, we can now express  
the semantics of our functions in terms of application. I propose the  
syntax '<object>:<function>' to indicate an application. Assuming our  
concatenative language is stack-based, the object will always be a  
stack.

I represent the stack as a null-terminated list (using angle brackets)  
which is necessary to show how the function in question handles the  
"rest of the stack". The right-most element of a list is the "top"  
element. '<>' denotes the null list.

Here are the semantics of six functions in terms of application:

    R:`42  ->  <R, 42>
    <R,X>:dup  ->  <R,<X,X>>
    <R,<X,Y>>:swap  ->  <R,<Y,X>>
    <R,F>:i  ->  R:F
    <R,<X,F>>:dip  ->  <R:F, X>
    R:clear  ->  <>

Alternatively, we can express our semantics in terms of equivalencies.  
This isn't as generally useful as the application form above (e.g. you  
can't express 'clear' in this form), but it is perhaps a bit easier to  
read:

    `42  ==  `42
    `X dup  ==  `X `X
    `X `Y swap  ==  `Y `X
    `F i  ==  F
    `X `F dip  ==  F `X

If you made it this far, thank you. Any thoughts would be appreciated.

- John
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.