Re: [stack] adding construction to Joy-like languages
John Nowak <[email protected]>
| Newsgroups | gmane.comp.lang.concatenative |
|---|---|
| Message-ID | <[email protected]> |
On Dec 30, 2008, at 8:41 AM, Stevan Apter wrote:
>> 2. FP has functions which, given a list, return a single element from
>> that list. Factor has no way (that I know of) to index into a stack
>> returning only the element selected.
>
> why limit yourself to a single element, or to indexing only at the
> top level of a list?
The type system, mainly. For indexing within a vector within another
vector, you'd have to use something equivalent to Joy's "infra". For
example:
1 2 (3 (4 5)) [1st] infra 2nd
1 2 (3 (4 5) 1st) 2nd
1 2 (3 5) 2nd
1 2 3
It's possible that some additional special form could be introduced to
make such indexing a bit easier. For homogeneous vectors of
indeterminate length, things could be done a bit differently. It's
sort of like the difference between tuples and lists in something like
ML; The former is tracked much more closely on the type level while
the latter admits a much broader set of operations. Right now, I'm
only dealing with the former.
> i'm not sure what the problem is, so my suggestions might be off-
> target.
I apologize for not explaining it well.
Essentially what I'm trying to do is come up with something like
"cleave" for a concatenative language that behaves a bit better. To
illustrate the current problem with the cleave family, take this
example (where 'x' is an object and 'F' and 'G' are functions):
x [F] [G] bi
In a language like Factor, it's hard to say much about this. It's
unclear if 'F' or 'G' will need more values on the stack beyond the
'x' that is provided. It's unclear how many values will be returned as
a result. It's unclear if G will access any values produced by F. Etc.
What I want to be able to do for the above example is solve all of
those problems. I want it to be clear that the 'x' provided is all F
and G care about. I want it to be clear that F and G will not
interact. I want it to be clear that the result will be two values.
Finally, I want this all to be syntactically obvious; I do not want to
have to employ the type system to do it.
This is already a solved issue in FP. For example:
[F, G]:x -- the construction of 'F' and 'G' applied to 'x'
-- reduces to...
<F:x, G:x> -- the list of 'F' and 'G' each applied to 'x'
Essentially, I was trying to add this form of construction to a
concatenative language. My first attempt was as follows:
1. Limit the functions involved to only using the top element of the
stack
2. Return the result of each function in its own stack
As a trivial example (where braces denote a stack):
5 [sq] [dup] bi-construct
{5 sq} {5 dup}
{25} {5 5}
The problem with this is that I now have two stacks on the stack. To
get at the 25, I need to manually pull the value out of the second
stack. This makes the whole thing too awkward to use.
The solution I proposed was to replace the notion of a stack with the
notion of a vector where a vector containing a single element is
equivalent to the element it contains. Here's the same example using
vectors:
5 [sq] [dup] bi-construct
(5) [sq] [dup] bi-construct
(5 sq) (5 dup)
(25) (5 5)
25 (5 5)
Because '5 == (5)', I was able to use construction. Because '(25) ==
25', I can now access the value without manually pulling it out of the
stack. At the same time, the result of the other function which
yielded two values is still nicely bundled up. I get all the
guarantees I was after without the drudgery.
- John