# a constructive-concatenative language

## John Nowak — 2008-12-07 12:52:02

    There are many nice things about concatenative languages: Good

    abstraction potential, easy handling of multiple value returns, simple

    left-to-right syntax, suitability for linear types[1], etc. There are,

    however, some things that I personally find problematic:

        - Because functions are of the type stack -> stack, and because the

          same stack is generally threaded throughout the entire program,

          reasoning (both formal and informal) becomes complicated. I see no

          reason at this point to think that concatenative languages are any

          easier to reason about than applicative languages, especially as

          "practical" concatenative languages end up adding variables and

          substitution anyway. (The fact that you can translate code that

          uses variables to a concatenative version full of quotation

          splicing and dips isn't that useful.)

        - It is difficult to compile concatenative languages efficiently,

          especially in the presence of separate compilation. The current

          technique I have requires extensive monomorphizing in order to be

          able to generate efficient C.

        - Interoperability with other languages is not as straightforward as

          it is when two languages share the same basic (applicative) model.

        - Typing concatenative languages requires row variables (or the

    rough

          equivalent of viewing the stack as unit-terminated list of pairs).

          Even languages with curried functions like Haskell typically have

          simpler types for "equivalent" functions. For example, here's

    'map'

          in Haskell: '(a -> b) -> List a -> List b'. Now here's the

          type of a Factor-like 'map' that does accumulation on the stack:

          'R (List x) [R x -> R y] -> R (List y)'.

        - The dataflow of a program is easily obscured. For example, the

          function '[+] dip' requires three values on the stack, but it only

          actually cares about two of them. Analysis is required to recover

          basic information that is explicit in applicative languages. This

          is an especially big problem for me as I'm interested in rendering

          concatenative code as a visual diagram for pedagogical purposes.

        - After working with concatenative languages for some time, I still

          occasionally  myself having to write the code first in another

          language so I can translate it to a concatenative version. This is

          unacceptable. Maybe it's just me, but I sometimes find it easier

    to

          think without a stack getting in the way. I don't think it's just

          me though: *Many* people agree.

    I think these problems are the result of one fundamental issue: The

    stack -> stack model, which requires that functions like '+' take the

    entire state of the program as an argument, is not ideal. From a type

    system perspective, you might say that functions that are row

    polymorphic are not ideal when it comes to reasoning ability,

    compilability, and interoperability. The stack is not such an issue in a

    first-order language like Forth, but once you add powerful combinators,

    things get much more difficult.

    The solution to this problem (if you agree it's a problem) is to drop

    the stack -> stack model. We can do this while still maintaining a

    predominately left-to-right syntax, multiple value returns, and the

    denotation of composition by concatenation. In other words, we can

    remain "concatenative" while ditching the stack.

    In place of the stack -> stack model, I substitute a model in which

    functions remain unary but can produce and consume any type of value. A

    good example of this is the 'square' function which squares a number. In

    a concatenative language, 'square' takes some stack R with a number on

    top and yields the same stack R with a new number on top. In the

    language I'm proposing (called a "constructive" languages for reasons to

    be explained later), 'square' simply takes a number and returns a

    number.

    An important question is how functions which produce or consume multiple

    values can be handled. I propose that this be done via tuples (as in

    Lisp) as opposed to currying (as in Haskell) or nested pairs (as in

    concatenative languages). For example, here are the types and semantics

    of the '+' function in a concatenative language (C), in a language with

    curried functions (λ), and in the language I'm proposing (?):

        C  + : R num num -> R num

           + = \(x, (y, r)) -> (x + y, r) -- 'r' for "rest" or "row"

        λ  + : num -> num -> num

           + = \x -> \y -> x + y

        ?  + : (num, num) -> num

           + = \(a, b) -> a + b

    As another example, here's the 'dup' function in both a concatenative

    language and the language I'm proposing. Note that in the second case,

    'dup' takes *any* value:

        C  dup : R x -> R x x

           dup = \(x, r) -> (x, (x, r))

        ?  dup : x -> (x, x)

           dup = x -> (x, x)

    In order to make such a language work, it is necessary to change the

    combining forms. I discard quotation, keep composition, and add the

    forms of application, construction, combination, and selection:

        - Composition is denoted via concatenation where 'f g' has the

          semantics '\x -> g (f x)'. This is the same as in a concatenative

          language.

        - Application of a function 'f' to an object 'x' is denoted 'f:x'.

        - Construction takes zero or more functions separated by commas

          within square brackets and has the following semantics (similar to

          'cleave' in Factor):

            []        = \x -> ()

            [f]       = \x -> f x

            [f, g]    = \x -> (f x, g x)

            [f, g, h] = \x -> (f x, g x, h x)

            ...

        - Combination takes zero or more functions separated by commas

    within

          curly braces and has the following semantics (similar to 'spread'

          in Factor):

            {}        = \x -> ()

            {f}       = \x -> f x

            {f, g}    = \(x, y) -> (f x, g y)

            {f, g, h} = \(x, y, z) -> (f x, g y, h z)

            ...

        - Selection has a syntax of the form 'M@N' yielding a function that

          selects the Nth element of a tuple of size M. For example,

          '4@2' has the semantics '\(x, y, z, w) -> y'. The reason for

          indicating M is that we're dealing with tuples, not nested pairs,

          and as such we can't operate on an arbitrary number of values.

    This

          is why we can get by without row polymorphism. I hope to come up

          with a better syntax for this shortly, although as I'll show

    later,

          you never really have to use this form directly.

    Here are a few simple examples that may help this make some sense. All

    of these are really roughly equivalent. For example, 'fold' does not get

    access to any sort of stack in a constructive language. Instead, the

    function resulting from an application of fold takes a tuple where the

    first element is a list and the second is the initial element.

        C  sq = dup *

        ?  sq = dup *

        C  hypot = [sq] bi@ + sqrt

        ?  hypot = {sq, sq} + sqrt

        C  +/- = [+] [-] 2bi

        ?  +/- = [+, -]

        C  avg = [sum, len] bi /

        ?  avg = [sum, len] /  -- or just 'sum / len' if we have infix ops

        C  swap = [] papply dip

        ?  swap = [2@2, 1@2]

        C  sum  = 0 [+] fold

        ?  sum  = [id, 0] (fold +)  -- HOFs are curried

        C  add3 = + +

        ?  add3 = [[3@1, 3@2] +, 3@3] +

    I should make a small note here with regard to literals. As in

    concatenative languages, they are really functions, but they have

    different semantics:

        C  42 = \r -> (42, r)

        λ  42 = 42

        ?  42 = \r -> 42

    In order to make the language more familiar and to avoid the need to use

    the form of selection, I allow the use of named variables. It is not

    legal to use variables in any other places than those which allow a

    trivial substitution for selection forms. For example:

        add3:<x, y, z> = [[x, y] +, z] +  -- x = 3@1, y = 3@2, z = 3@3

    Much of this syntactic noise is eased by adding infix operators which

    I'll use for the remainder of this document:

        add3:<x, y, z> = x + y + z  -- x + y = [x, y] +

    One more example; the quadratic formula in all its numerically unstable

    glory. We do this easily without defining any additional combinators:

        discrim:<a, b, c> = b sq - 4 * a * c

        <a, b> // c = [a / c, b / c]

        find-roots:<a, b, c> = [b neg, discrim sqrt] [+, -] // 2 * a

    Again, this is completely pointfree via a trivial translation:

        discrim = 3@2 sq - 4 * 3@1 * 3@3

        // = [2@1 2@1 / 2@2, 2@1 2@2 / 2@2]

        find-roots = [3@2 neg, discrim sqrt] [+, -] // 2 * 3@1

    And again as if we didn't have infix operators:

        discrim = [3@2 sq, [[4, 3@1] *, 3@3] *] -

        // = [[2@1 2@1, 2@2] /, [2@1 2@2, 2@2] /]

        find-roots = [[3@2 neg, discrim sqrt] [+, -], 2 * 3@1] //

    It seems perhaps that concatenative languages do not need a stack after

    all. That said, there are still some things that I have to consider:

        - Is it worth having composition read right-to-left instead? Doing

    so

          would let us write 'f[f[a, b], c]' instead of '[[a, b] f, c] f'.

    If

          you then change the square brackets to parentheses, you have a

    very

          familiar algol-like syntax.

        - Is the current selection form too painful? Can I really get away

          without allowing things like 'drop' and 'dip'? The answer is

          probably yes if we assume judicious use of named variables.

        - Will this approach scale up to real programs?

        - Does this language translate well to a visual programming context?

    Thanks for making it through. Any thoughts would be appreciated.

    P.S. I somehow forgot to mention this earlier: The language I'm

    proposing is *very* similar to Backus's FP, although FP used a nested

    pair model like concatenative languages do (e.g. the 'tail' function in

    FP is the same as 'drop' in Factor). As such, it suffers from some of

    the same problems I'm trying very hard to avoid.

    [1] http://home.pipeline.com/~hbaker1/ForthStack.html

## John Nowak — 2008-12-07 12:59:23

    Ow. Sorry for the line wrapping issues. Here's another copy. (Not sure

    if sending this again is more annoying than the line wrapping, but

    here we are.)

    - - -

    There are many nice things about concatenative languages: Good

    abstraction potential, easy handling of multiple value returns, simple

    left-to-right syntax, suitability for linear types[1], etc. There are,

    however, some things that I personally find problematic:

        - Because functions are of the type stack -> stack, and because the

          same stack is generally threaded throughout the entire program,

          reasoning (both formal and informal) becomes complicated. I see no

          reason at this point to think that concatenative languages are any

          easier to reason about than applicative languages, especially as

          "practical" concatenative languages end up adding variables and

          substitution anyway. (The fact that you can translate code that

          uses variables to a concatenative version full of quotation

          splicing and dips isn't that useful.)

        - It is difficult to compile concatenative languages efficiently,

          especially in the presence of separate compilation. The current

          technique I have requires extensive monomorphizing in order to be

          able to generate efficient C.

        - Interoperability with other languages is not as straightforward as

          it is when two languages share the same basic (applicative) model.

        - Typing concatenative languages requires row variables (or the

          rough equivalent of viewing the stack as unit-terminated list of

          pairs). Even languages with curried functions like Haskell

          typically have simpler types for "equivalent" functions. For

          example, here's 'map' in Haskell: '(a -> b) -> List a -> List b'.

          Now here's the  type of a Factor-like 'map' that does accumulation

          on the stack: 'R (List x) [R x -> R y] -> R (List y)'.

        - The dataflow of a program is easily obscured. For example, the

          function '[+] dip' requires three values on the stack, but it only

          actually cares about two of them. Analysis is required to recover

          basic information that is explicit in applicative languages. This

          is an especially big problem for me as I'm interested in rendering

          concatenative code as a visual diagram for pedagogical purposes.

        - After working with concatenative languages for some time, I still

          occasionally  myself having to write the code first in another

          language so I can translate it to a concatenative version. This is

          unacceptable. Maybe it's just me, but I sometimes find it easier

          to think without a stack getting in the way. I don't think it's

          just me though: *Many* people agree.

    I think these problems are the result of one fundamental issue: The

    stack -> stack model, which requires that functions like '+' take the

    entire state of the program as an argument, is not ideal. From a type

    system perspective, you might say that functions that are row

    polymorphic are not ideal when it comes to reasoning ability,

    compilability, and interoperability. The stack is not such an issue in

    a first-order language like Forth, but once you add powerful

    combinators, things get much more difficult.

    The solution to this problem (if you agree it's a problem) is to drop

    the stack -> stack model. We can do this while still maintaining a

    predominately left-to-right syntax, multiple value returns, and the

    denotation of composition by concatenation. In other words, we can

    remain "concatenative" while ditching the stack.

    In place of the stack -> stack model, I substitute a model in which

    functions remain unary but can produce and consume any type of value. A

    good example of this is the 'square' function which squares a number.

    In a concatenative language, 'square' takes some stack R with a number

    on top and yields the same stack R with a new number on top. In the

    language I'm proposing (called a "constructive" languages for reasons

    to be explained later), 'square' simply takes a number and returns a

    number.

    An important question is how functions which produce or consume

    multiple values can be handled. I propose that this be done via tuples

    (as in Lisp) as opposed to currying (as in Haskell) or nested pairs (as

    in concatenative languages). For example, here are the types and

    semantics of the '+' function in a concatenative language (C), in a

    language with curried functions (λ), and in the language I'm proposing

    (?):

        C  + : R num num -> R num

           + = \(x, (y, r)) -> (x + y, r) -- 'r' for "rest" or "row"

        λ  + : num -> num -> num

           + = \x -> \y -> x + y

        ?  + : (num, num) -> num

           + = \(a, b) -> a + b

    As another example, here's the 'dup' function in both a concatenative

    language and the language I'm proposing. Note that in the second case,

    'dup' takes *any* value:

        C  dup : R x -> R x x

           dup = \(x, r) -> (x, (x, r))

        ?  dup : x -> (x, x)

           dup = x -> (x, x)

    In order to make such a language work, it is necessary to change the

    combining forms. I discard quotation, keep composition, and add the

    forms of application, construction, combination, and selection:

        - Composition is denoted via concatenation where 'f g' has the

          semantics '\x -> g (f x)'. This is the same as in a concatenative

          language.

        - Application of a function 'f' to an object 'x' is denoted 'f:x'.

        - Construction takes zero or more functions separated by commas

          within square brackets and has the following semantics (similar to

          'cleave' in Factor):

            []        = \x -> ()

            [f]       = \x -> f x

            [f, g]    = \x -> (f x, g x)

            [f, g, h] = \x -> (f x, g x, h x)

            ...

        - Combination takes zero or more functions separated by commas

          within curly braces and has the following semantics (similar to

          'spread' in Factor):

            {}        = \x -> ()

            {f}       = \x -> f x

            {f, g}    = \(x, y) -> (f x, g y)

            {f, g, h} = \(x, y, z) -> (f x, g y, h z)

            ...

        - Selection has a syntax of the form 'M@N' yielding a function that

          selects the Nth element of a tuple of size M. For example,

          '4@2' has the semantics '\(x, y, z, w) -> y'. The reason for

          indicating M is that we're dealing with tuples, not nested pairs,

          and as such we can't operate on an arbitrary number of values.

          This is why we can get by without row polymorphism. I hope to come

          up with a better syntax for this shortly, although as I'll show

          later, you never really have to use this form directly.

    Here are a few simple examples that may help this make some sense. All

    of these are really roughly equivalent. For example, 'fold' does not

    get access to any sort of stack in a constructive language. Instead,

    the function resulting from an application of fold takes a tuple where

    the first element is a list and the second is the initial element.

        C  sq = dup *

        ?  sq = dup *

        C  hypot = [sq] bi@ + sqrt

        ?  hypot = {sq, sq} + sqrt

        C  +/- = [+] [-] 2bi

        ?  +/- = [+, -]

        C  avg = [sum, len] bi /

        ?  avg = [sum, len] /  -- or just 'sum / len' if we have infix ops

        C  swap = [] papply dip

        ?  swap = [2@2, 1@2]

        C  sum  = 0 [+] fold

        ?  sum  = [id, 0] (fold +)  -- HOFs are curried

        C  add3 = + +

        ?  add3 = [[3@1, 3@2] +, 3@3] +

    I should make a small note here with regard to literals. As in

    concatenative languages, they are really functions, but they have

    different semantics:

        C  42 = \r -> (42, r)

        λ  42 = 42

        ?  42 = \r -> 42

    In order to make the language more familiar and to avoid the need to

    use the form of selection, I allow the use of named variables. It is

    not legal to use variables in any other places than those which allow a

    trivial substitution for selection forms. For example:

        add3:<x, y, z> = [[x, y] +, z] +  -- x = 3@1, y = 3@2, z = 3@3

    Much of this syntactic noise is eased by adding infix operators which

    I'll use for the remainder of this document:

        add3:<x, y, z> = x + y + z  -- x + y = [x, y] +

    One more example; the quadratic formula in all its numerically unstable

    glory. We do this easily without defining any additional combinators:

        discrim:<a, b, c> = b sq - 4 * a * c

        <a, b> // c = [a / c, b / c]

        find-roots:<a, b, c> = [b neg, discrim sqrt] [+, -] // 2 * a

    Again, this is completely pointfree via a trivial translation:

        discrim = 3@2 sq - 4 * 3@1 * 3@3

        // = [2@1 2@1 / 2@2, 2@1 2@2 / 2@2]

        find-roots = [3@2 neg, discrim sqrt] [+, -] // 2 * 3@1

    And again as if we didn't have infix operators:

        discrim = [3@2 sq, [[4, 3@1] *, 3@3] *] -

        // = [[2@1 2@1, 2@2] /, [2@1 2@2, 2@2] /]

        find-roots = [[3@2 neg, discrim sqrt] [+, -], 2 * 3@1] //

    It seems perhaps that concatenative languages do not need a stack after

    all. That said, there are still some things that I have to consider:

        - Is it worth having composition read right-to-left instead? Doing

          so would let us write 'f[f[a, b], c]' instead of

          '[[a, b] f, c] f'. If you then change the square brackets to

          parentheses, you have a very familiar algol-like syntax.

        - Is the current selection form too painful? Can I really get away

          without allowing things like 'drop' and 'dip'? The answer is

          probably yes if we assume judicious use of named variables.

        - Will this approach scale up to real programs?

        - Does this language translate well to a visual programming context?

    Thanks for making it through. Any thoughts would be appreciated.

    P.S. I somehow forgot to mention this earlier: The language I'm

    proposing is *very* similar to Backus's FP, although FP used a nested

    pair model like concatenative languages do (e.g. the 'tail' function in

    FP is the same as 'drop' in Factor). As such, it suffers from some of

    the same problems I'm trying very hard to avoid.

    [1] http://home.pipeline.com/~hbaker1/ForthStack.html

## John Nowak — 2008-12-07 13:13:16

    On Dec 7, 2008, at 7:59 AM, John Nowak wrote:

     >    ?  sum  = [id, 0] (fold +)  -- HOFs are curried

     Sigh. That should read as follows:

        sum = [id, 0] fold:+

    I swear I proofread this thing before I sent it.

    - John

## William Tanksley, Jr — 2008-12-11 18:48:23

    I've been too busy to do any more than scan your message, but I did

    notice with interest your claim that you preserve concatenativity

    without using a stack. I might get some time to check that claim after

    the holidays.

    In the meantime, I fwd'ed this to a friend who's got more time, and

    this is what he said:

     > This is a near-complete re-invention of Backus' FL language, including

    > syntax.  The only things I can spot which are readily different are

    > the selection syntax and that you no longer need to use 'o' to

    > indicate composition.

    >

    > Not that this is anything wrong, of course -- FL has always been one

    > of those languages which has piqued my curiosity.  I've often pondered

    > how hard it'd be to write an interpreter for my own dialect of FL too.

     [...]

     > * In FP/FL, all functions consume one datum.  Passing multiple

    > arguments to a function occurs via tuples, expressed in <a,b,c>

    > syntax.

    >

    > * In FP/FL, integer literals are functions which return the nth item

    > of a tuple.  Thus, 3:<a,b,c> yields the value c (this is read "third

    > of <a,b,c>".  To actually specify a numeric literal, you prefix it

    > with some character (I cannot remember which: I think ~).

    >

    > * ID is used for the identity function -- it returns its argument.

    >

    > * [f,g,h] is the construction operator in FP/FL; hence:

    > [f,g,h]:<1,2,3> == <f:<1,2,3>, g:<1,2,3>, h:<1,2,3>>.  Hence,

    > computing the average of its parameter, a function can be written: avg

    > = /:[+,length].  Using substitution, avg:<1,2,3> =

    > /:[+,length]:<1,2,3> = /:[+:<1,2,3>, length:<1,2,3>] = /:<6, 3> = 2.

    >

    > I'm sure there are other attributes of FP/FL that I am missing or have

    > forgotten.

    >

    > The point is, however, that Nowak's language and FP/FL are extremely

    > similar.  I'm not sure to what extent that FP/FL have influenced his

    > thinking, but if it's an independent design, that speaks volumes for

    > Backus' ideas.  Perhaps traditional functional languages have it all

    > wrong -- perhaps functions of tuples of arguments solves the dataflow

    > problem when compiling to a stack architecture better than curried

    > functions.

    >

    > However, Nowak's language has a few innovations of its own, which must

    > not be ignored.  I do not recall seeing anything like {a,b,c} syntax

    > in FP/FL, for example.  The elimination of 'o' for function

    > composition perhaps forms the single biggest contribution.  That

    > _forces_ anything you program in it to be concatenative, by

    > definition.

    >

    > I'm not a fan of him using infix mathematics in his language, only

    > because it's nearly impossible to statically disambiguate postfix and

    > infix forms of operators.

    >

    > I do have to admit, however, that I've been considering a language

    > which is structured similarly to APL/J.  The idea that you read from

    > left to right, but evaluate from right to left is very appealing to

    > me, particularly from an applicative point of view.  So far as I can

    > tell, the only core primitives in the language would be function

    > definition (=), and the McCarthy conditional construct (a->b;c), and

    > function application (a(b)).  Everything else pretty much is

    > effectively "standard library" material.

    >

    > However, I'll need to re-evaluate my "toy" language idea to see how

    > making all functions operate on tuples of arguments changes it.

## Stevan Apter — 2008-12-11 20:30:53

    ----- Original Message -----

    From: "William Tanksley, Jr" <wtanksleyjr@...>

    To: <concatenative@yahoogroups.com>

    >> I do have to admit, however, that I've been considering a language

    >> which is structured similarly to APL/J.  The idea that you read from

    >> left to right, but evaluate from right to left is very appealing to

    >> me, particularly from an applicative point of view.  So far as I can

    >> tell, the only core primitives in the language would be function

    >> definition (=), and the McCarthy conditional construct (a->b;c), and

    >> function application (a(b)).

    what you've described is just iverson's "direct definition" restriction

    of APL.  a direct definition is an expression

        f = expression

    or

        f = condition:expression-if-true:expression-if-false

    "alpha" and "omega" are arguments to f.  using x and y for these:

        diff = x>y:x-y:y-x

    some large APL systems have been written using only direct definition.

## John Nowak — 2008-12-12 03:46:20

    On Dec 11, 2008, at 1:48 PM, William Tanksley, Jr wrote:

     > In the meantime, I fwd'ed this to a friend who's got more time, and

    > this is what he said:

     Very good. Thanks for passing it on.

     >> This is a near-complete re-invention of Backus' FL language,

    >> including

    >> syntax.  The only things I can spot which are readily different are

    >> the selection syntax and that you no longer need to use 'o' to

    >> indicate composition.

     This is essentially true. One more important thing that is different

    (that I think your friend realized but didn't mention here) is that

    you cannot write the equivalent of FP's 'hd' or 'tl' functions because

    they both operate on lists of arbitrary length. Here, selection only

    works on tuples of a specific length. The idea was that this would

    prevent some subtle errors and make reading easier, but it seems to be

    something of a burden in my early experiments.

     >> The point is, however, that Nowak's language and FP/FL are extremely

    >> similar.  I'm not sure to what extent that FP/FL have influenced his

    >> thinking, but if it's an independent design, that speaks volumes for

    >> Backus' ideas.

     It is not entirely independent. I was familiar with FP, although only

    in a cursory way. What really happened was that I enjoyed the clarity

    in which functions could written using the cleave and spread

    combinators in Factor. I ended up working backwards and arriving at

    something very much like FP. After realizing this, I lifted most of

    FP's syntax.

     >> I'm not a fan of him using infix mathematics in his language, only

    >> because it's nearly impossible to statically disambiguate postfix and

    >> infix forms of operators.

     I'm not a big fan of this either. The problem is that the verbosity is

    a little irritating if something like it isn't offered. FL offered a

    general infix syntax (the same as J's "fork", roughly '(f g h):x ==

    g:<f:x, h:x>') and 15 level of precedence, perhaps for this reason.

    I'm sure there are other syntactic approaches worth considering

    though. Switching to a right-to-left evaluation order seems to help.

     >> However, I'll need to re-evaluate my "toy" language idea to see how

    >> making all functions operate on tuples of arguments changes it.

     I'd be curious to hear the results of this experiment.

    One problem I've already run into with the language I proposed is that

    first class functions are hopelessly painful to work with. The simple

    example I had wanted to do was transform a binary operator (like '+')

    to one that works on 3 values and yields 2:

        foo(F) = [[3@1, 3@2] F, 3@3] F

    However, if I try to write a version of 'foo' that takes some function

    'F' as part of a tuple rather than as a constant, it becomes very

    painful. Looking at Backus's FL, it appears the problem is partially

    solved using "prime notation", but it's hardly elegant. Backus's

    Formal FP seems to take an approach similar to what I wrote above,

    although I'm not sure about that. In contrast, the concatenative code

    is trivial: '[dip] keep i'. It's not clear to what extent the problems

    I've run into are merely syntactic, but I suspect the syntax is not

    the fundamental issue.

    The other problem I quickly ran into is that rearranging values in

    nested tuples is very awkward. Some kind of shuffling form would be

    necessary to make this work. The addition of such a form may also do

    much to solve the issue with first class functions being too awkward

    to manipulate into a place where they can be properly applied.

    - John