Hi all, Yesterday I discovered that using these three words together with 'call', any stack shuffle can be expressed.
Let's recap: - cleave takes one value, and an array of quotations. It applies each quotation to the value; the value is removed from the stack afterwards. - 2cleave takes two values, and an array of quotations. it applies each quotation to the two values; the two values are removed from the stack afterwards. - spread takes n values and an array of n quotations; it applies the nth quotation to the nth value in turn. Now, we can define : drop { } cleave ; This works because cleave always consumes one input value, and the number of outputs is the sum of the number of outputs of each quotation in the array. The array is empty, so it has one input and no outputs. We need a way to duplicate values. This does the trick: : dup { [ ] [ ] } cleave ; We need to be able to swap values: : swap { [ nip ] [ drop ] } 2cleave ; But what about nip? : nip { [ drop ] [ ] } spread ; Now we only need one more combinator, dip: : dip swap { [ call ] [ ] } spread ; Once you have drop, dup, swap and dip, you can express any stack permutation. While this doesn't have much practical value, it does show that there is something fundamental about these combinators. The reason they can replace stack shufflers in so many cases is because they're equivalent in a sense. However they capture something that stack shufflers don't, and that is explicit one-to-many, one-to-one and many-to-one dataflow. Slava ------------------------------------------------------------------------- Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source. http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace _______________________________________________ Factor-talk mailing list Factor-talk@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/factor-talk