Re: [stack] function/object ambiguity + quotation alternative

Stevan Apter <[email protected]>
Newsgroups gmane.comp.lang.concatenative
Message-ID <[email protected]>
> 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'.

i've always assumed that [dup swap] head is the function dup.  e.g. in XY:


  2 [dup swap] first i
2 2

that is, [dup swap] first leaves the function dup on the stack.
then i moves the top item of the stack to the head of the queue.

what am i missing?


----- Original Message ----- 
From: "John Nowak" <[email protected]>
To: "concatenative" <[email protected]>
Sent: Thursday, February 26, 2009 9:34 AM
Subject: [stack] function/object ambiguity + quotation alternative


> 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.