# A question on joy syntax.

## Rahul — 2007-03-01 20:17:00

    I have been looking through the joy papers, and have

    this confusion:

    The help on ifte says:

    ifte     [B] [T] [F] -> ...

        Executes B. If that yields true, then executes T

        else executes F.

    Now the help on = says:

    =     X Y -> B

        Either both X and Y are numeric or both are strings

        or symbols. Tests whether X equal to Y. Also supports

        float.

    I assumed that '=' will consume two arguments off the stack,

    and leave the true or false on top.

    the joy interp seems to support this.

    1 2 = .

    false

    .

    Now, if I use the same inside an ifte

    1 5 [1 =] [dup *] [dup +] ifte .

    10

    The doubt I have is this:

    as soon as [1 =] is executed, I would expect '5' off the stack,

    so the [dup +] should have actually found '1' on the stack and given

    me 2.

    I checked this too: which seems to do fine.

    5 [true]  [dup *] [dup +] ifte .

    25

    Is there a reason for this? Is for some reason the stack

    invariant when executing ifte condition?

    The below seems to verify it.

    5 6 [pop 1 =]  [dup *] [dup +] ifte .

    12

    .

    5

    But I cant find any info on this.

    The other quoted programs does not seem to share the invariant stack

    behavior:

    ================================

    i     [P] -> ...

        Executes P. So, [P] i == P.

    1 2 [1 +] i .

    3

    .

    1

    Could some one please explain why this is so? or guide me to the

    docs that explains it?

                               rahul.

## William Tanksley, Jr — 2007-03-02 05:15:55

    Rahul <blufox@...> wrote:

     >      I have been looking through the joy papers, and have

    > this confusion:

    > 1 5 [1 =] [dup *] [dup +] ifte .

    > 10

    > The doubt I have is this:

    > as soon as [1 =] is executed, I would expect '5' off the stack,

    > so the [dup +] should have actually found '1' on the stack and given

    > me 2.

     Yup. Me too. But that's not what Joy does; some of Joy's combinators

    save the stack's state when they're performing certain types of

    actions. You simply have to learn which ones do it and which ones

    don't.

    Sometimes this is very handy. Sometimes it's annoying.

     >                            rahul.

     -Billy

## Taoufik Dachraoui — 2007-03-03 10:59:01

    I tried to define ifte as it is implemented in joy1 and I found this:

    [T] [A] [B]

    ifte == [[[stack] dip] dip

                   [dip swap] dip] dip    #save stack and run T

                choice [unstack] dip i; # restore stack and choose

    between A and B

    The stack is saved before the execution of [T] and restored before the

    execution of [A] or [B]. The test in this case is non destructive;

    the stack

    is unchanged before choosing between A and B.

    The way you implmented ifte is as follows:

    [T] [A] [B]

    ifte == [[i] dip] dip  #run T

                 choice i;     # choose between A and B

    Obviously your implementation is faster, but the test in this case

    is destructive; the stack can be modified greatly depending on T.

    Is it more difficult or easier to reason with destructive tests?

    Taoufik

     On Mar 1, 2007, at 9:17 PM, Rahul wrote:

    > I have been looking through the joy papers, and have

    > this confusion:

    >

    > The help on ifte says:

    >

    > ifte [B] [T] [F] -> ...

    > Executes B. If that yields true, then executes T

    > else executes F.

    >

    > Now the help on = says:

    > = X Y -> B

    > Either both X and Y are numeric or both are strings

    > or symbols. Tests whether X equal to Y. Also supports

    > float.

    >

    > I assumed that '=' will consume two arguments off the stack,

    > and leave the true or false on top.

    >

    > the joy interp seems to support this.

    >

    > 1 2 = .

    > false

    > .

    >

    > Now, if I use the same inside an ifte

    > 1 5 [1 =] [dup *] [dup +] ifte .

    > 10

    >

    > The doubt I have is this:

    > as soon as [1 =] is executed, I would expect '5' off the stack,

    > so the [dup +] should have actually found '1' on the stack and given

    > me 2.

    >

    > I checked this too: which seems to do fine.

    > 5 [true] [dup *] [dup +] ifte .

    > 25

    >

    > Is there a reason for this? Is for some reason the stack

    > invariant when executing ifte condition?

    > The below seems to verify it.

    >

    > 5 6 [pop 1 =] [dup *] [dup +] ifte .

    > 12

    > .

    > 5

    >

    > But I cant find any info on this.

    > The other quoted programs does not seem to share the invariant stack

    > behavior:

    > ================================

    > i [P] -> ...

    > Executes P. So, [P] i == P.

    >

    > 1 2 [1 +] i .

    > 3

    > .

    > 1

    >

    > Could some one please explain why this is so? or guide me to the

    > docs that explains it?

    >

    > rahul.

    >

    >

    >

    [Non-text portions of this message have been removed]

## Taoufik Dachraoui — 2007-03-03 11:37:08

    looking at the defintion of factorial:

    in Joy:

    fact == [0 =] [pop 1] [dup 1 - fact *] ifte

    in v:

    [fact

         [dup 0 =]

             [pop 1]

             [dup 1 - fact *]

         ifte].

    In the second definition we explicitly manipulate the stack (dup) so

    that the remaining code finds the stack in the expected state. In

    this case dup is certainly faster than saving and restoring the

    stack, but in other situations this may not be true.

    Taoufik

     On Mar 3, 2007, at 11:59 AM, Taoufik Dachraoui wrote:

    > I tried to define ifte as it is implemented in joy1 and I found this:

    >

    > [T] [A] [B]

    > ifte == [[[stack] dip] dip

    > [dip swap] dip] dip #save stack and run T

    > choice [unstack] dip i; # restore stack and choose

    > between A and B

    >

    > The stack is saved before the execution of [T] and restored before the

    > execution of [A] or [B]. The test in this case is non destructive;

    > the stack

    > is unchanged before choosing between A and B.

    >

    > The way you implmented ifte is as follows:

    >

    > [T] [A] [B]

    > ifte == [[i] dip] dip #run T

    > choice i; # choose between A and B

    >

    > Obviously your implementation is faster, but the test in this case

    > is destructive; the stack can be modified greatly depending on T.

    >

    > Is it more difficult or easier to reason with destructive tests?

    >

    > Taoufik

    >

    > On Mar 1, 2007, at 9:17 PM, Rahul wrote:

    >

    > > I have been looking through the joy papers, and have

    > > this confusion:

    > >

    > > The help on ifte says:

    > >

    > > ifte [B] [T] [F] -> ...

    > > Executes B. If that yields true, then executes T

    > > else executes F.

    > >

    > > Now the help on = says:

    > > = X Y -> B

    > > Either both X and Y are numeric or both are strings

    > > or symbols. Tests whether X equal to Y. Also supports

    > > float.

    > >

    > > I assumed that '=' will consume two arguments off the stack,

    > > and leave the true or false on top.

    > >

    > > the joy interp seems to support this.

    > >

    > > 1 2 = .

    > > false

    > > .

    > >

    > > Now, if I use the same inside an ifte

    > > 1 5 [1 =] [dup *] [dup +] ifte .

    > > 10

    > >

    > > The doubt I have is this:

    > > as soon as [1 =] is executed, I would expect '5' off the stack,

    > > so the [dup +] should have actually found '1' on the stack and given

    > > me 2.

    > >

    > > I checked this too: which seems to do fine.

    > > 5 [true] [dup *] [dup +] ifte .

    > > 25

    > >

    > > Is there a reason for this? Is for some reason the stack

    > > invariant when executing ifte condition?

    > > The below seems to verify it.

    > >

    > > 5 6 [pop 1 =] [dup *] [dup +] ifte .

    > > 12

    > > .

    > > 5

    > >

    > > But I cant find any info on this.

    > > The other quoted programs does not seem to share the invariant stack

    > > behavior:

    > > ================================

    > > i [P] -> ...

    > > Executes P. So, [P] i == P.

    > >

    > > 1 2 [1 +] i .

    > > 3

    > > .

    > > 1

    > >

    > > Could some one please explain why this is so? or guide me to the

    > > docs that explains it?

    > >

    > > rahul.

    > >

    > >

    > >

    >

    > [Non-text portions of this message have been removed]

    >

    >

    >

    [Non-text portions of this message have been removed]

## Rahul — 2007-03-03 12:18:17

    Taoufik Dachraoui <taoufik.dachraoui@...> wrote:

     > I tried to define ifte as it is implemented in joy1 and I found this:

    >

    > [T] [A] [B]

    > ifte == [[[stack] dip] dip

    >                [dip swap] dip] dip    #save stack and run T

    >             choice [unstack] dip i; # restore stack and choose

    > between A and B

    >

    > The stack is saved before the execution of [T] and restored before the

    > execution of [A] or [B]. The test in this case is non destructive;

    > the stack

    > is unchanged before choosing between A and B.

    >

    > The way you implmented ifte is as follows:

    >

    > [T] [A] [B]

    > ifte == [[i] dip] dip  #run T

    >              choice i;     # choose between A and B

    >

    > Obviously your implementation is faster, but the test in this case

    > is destructive; the stack can be modified greatly depending on T.

       The speed is probably not important in this case. I had not

    expected a change in behavior for a quote when it is inside an 'ifte'

    and when it is evaluted outside by an 'i'. This behavior gives the

    last param to 'ifte' a kind of special status (The stack and unstack

    are quite meta compared to the rest of the words).

     > Is it more difficult or easier to reason with destructive tests?

     You are right here. My contention was that it did not seem to fit

    nicely with the rest of joy.

    Looking at it again, I like the way the Cat language has taken.

    It expects a boolean rather than a quote at the top of the stack,

    The result is not different from what we get in joy, though it avoids

    the meta operations.

    [snip..]

     > > The help on ifte says:

    > >

    > > ifte [B] [T] [F] -> ...

    > > Executes B. If that yields true, then executes T

    > > else executes F.

     [snip..]

     > > I assumed that '=' will consume two arguments off the stack,

    > > and leave the true or false on top.

     [snip..]

     > > Now, if I use the same inside an ifte

    > > 1 5 [1 =] [dup *] [dup +] ifte .

    > > 10

    > > The doubt I have is this:

    > > as soon as [1 =] is executed, I would expect '5' off the stack,

    > > so the [dup +] should have actually found '1' on the stack and given

    > > me 2.

## Rahul — 2007-03-03 13:20:22

    Taoufik Dachraoui <taoufik.dachraoui@...> wrote:

     > in Joy:

    > fact == [0 =] [pop 1] [dup 1 - fact *] ifte

    > in v:

    > [fact

    >      [dup 0 =]

    >          [pop 1]

    >          [dup 1 - fact *]

    >      ifte].

    > In the second definition we explicitly manipulate the stack (dup) so

    > that the remaining code finds the stack in the expected state. In

    > this case dup is certainly faster than saving and restoring the

     ---

     > stack, but in other situations this may not be true.

       Would there be situations when this is less efficient?

      If we are modifying n members in the stack in the condition, then

      we may need to save only that n members rather than the entire

      stack. This we can do any way because the programmer is aware of

      the changes in stack. so that instead of above it might look like

      [dup_last_5

         do_stuff_on_these

         pop_these_out

      ] ... ifte

      But in case of ifte in joy, the interp has to reason about the

      quotation and figure out the amount of stack effect, if it has

      to do the same. I am not sure if it is possible.

## John Cowan — 2007-03-03 16:10:19

    Rahul scripsit:

     > Looking at it again, I like the way the Cat language has taken.

    > It expects a boolean rather than a quote at the top of the stack,

     Joy also provides that operator, under the name of "choice".

    --

    John Cowan    cowan@...    http://ccil.org/~cowan

    Half the lies they tell about me are true.

            -- Tallulah Bankhead, American actress

## John Cowan — 2007-03-03 16:08:36

    Taoufik Dachraoui scripsit:

     > In the second definition we explicitly manipulate the stack (dup) so

    > that the remaining code finds the stack in the expected state. In

    > this case dup is certainly faster than saving and restoring the

    > stack, but in other situations this may not be true.

     In fact, for Joy the stack is just another linked list in the heap,

    so saving and restoring it is just a matter of storing the stack pointer

    in a local variable.  So both operations are approximately O(1).

    --

    Andrew Watt on Microsoft:                       John Cowan

    Never in the field of human computing           cowan@...

    has so much been paid by so many                http://www.ccil.org/~cowan

    to so few! (pace Winston Churchill)

## rahul — 2007-03-03 19:43:00

    > In fact, for Joy the stack is just another linked list in the heap,

    > so saving and restoring it is just a matter of storing the stack pointer

    > in a local variable.  So both operations are approximately O(1).

     Thanks,

       I should have looked at the source first :).