Re: [stack] function/object ambiguity + quotation alternative
William Tanksley <[email protected]>
| Newsgroups | gmane.comp.lang.concatenative |
|---|---|
| Message-ID | <1236204221.32020.2741.camel@tanksley> |
John Nowak wrote:
> 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.
I think you're dead-on, and your solution is something that I've
suggested in the past. However, I also admire the ambiguity between
functions and literals that you first described to us, so I'd like to
also think of a solution that might save it.
I'm not sure that I've succeeded, but I need to send this someday.
> This seem to be a unique property. I have never seen a non-
> concatenative language in which every term denoted a function.
Agreed.
> 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.
Yes. This is why Kerby always places his stack variable notations in
brackets:
[X] dup == [X] [X]
I've often suggested adding a notation to quote only a single symbol
(without enclosing it in a list). You follow this approach below.
> I believe I know how to solve this problem: Get rid of the function/
> object ambiguity.
I see your point.
The problem is, we both like the function/object ambiguity. (x) denotes
a function or an object, no real difference except that the object
always changes the stack in the exact same way -- so the object is like
a function.
> 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.
This is something I've proposed before. I didn't think of making it
apply to numbers; I only wanted it for functions, because:
[dip] first == `dip
Making it apply to groupings is an obvious enhancement which improves
the algebra:
[dip dup] == `(dip dup)
Making it apply to numbers and literals in general is needless; it'll
work, but it should be a noop.
> 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]'.
I'm quite happy with this. It makes sense to be able to distinguish
between grouping and quotation.
> 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.
Yes, I think I see why this is needed. It's nice to note that (`) is
distributive over grouping:
`(42 `42) == (`42 ``42) == `42 ``42 compose == 42 42 compose
> I would also suggest adding an additional array syntax that takes
> *functions* that evaluate to single objects.
Why only for arrays? It would make more sense to me to make a special
group syntax that forces the evaluation of the group at the time it's
constructed rather than the usual runtime. So an array might look like:
{ ,(2 1 drop) }
(I'm using , because it seems like the mirror of `.)
It's an ordinary array, with a dequoted group inside it. You can also
make an ordinary quoted group with a dequoted group (or even a dequoted
function) inside it, if you want.
> 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).
I agree that this would be a great way to structure the banana
combinator. I don't know why this would only work on Joy -- your banana
combinator doesn't ever copy the stack, or at least it doesn't require a
stack copy. Or perhaps I'm thinking of a slightly modified version that
I talked about -- I forget the details now. I'd say that copying the
stack is a really, really bad habit... or at best, a habit that there's
no good reason for and much good reason against.
> 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.
Wait, why couldn't this be done in the past? I don't see how this is any
different from what we'd done before. We didn't use that specific
notation, but we used similar notation.
> 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
Equivalencies have some nice properties of their own... A function which
can't be thus expressed has some usability problems.
Actually, that's kind of an interesting statement. I wonder why it seems
true to me? Nothing about the definition of a concatenative language
seem
> - John
-Wm