# Remove-Function

# `remove` ¶

       [1 2 3 4] 5 remove
    ------------------------
          [1 2 3 4]

       [1 2 3 4] 2 remove
    ------------------------
          [1 3 4]

       [] a remove
    ------------------------
          []

## First attempt¶

First let's handle the case of an empty list:

    remove == [pop not] [pop] [remove'] ifte

For non-empty lists, the predicate and base case are easy:

    remove' == [swap first =] [pop rest] [R0] [R1] genrec

The recursive branch:

    [1 2 3 4] 3 R0 [remove'] R1

For `R0` use `[uncons] dip`:

    [1 2 3 4] 3 [uncons] dip [remove'] R1
    [1 2 3 4] uncons 3 [remove'] R1
    1 [2 3 4] 3 [remove'] R1

For `R1` let's try `i cons`:

    1 [2 3 4] 3 [remove'] i cons
    1 [2 3 4] 3 remove' cons
    ...
    1 2 [3 4] 3 remove' cons cons
    ...
    1 2 [4] cons cons
    ...
    [1 2 4]

Ergo:

    remove' == [swap first =] [pop rest] [[uncons] dip] [i cons] genrec
    remove  == [pop not] [pop] [remove'] ifte

In [1]:

    [remove' [swap first =] [pop rest] [[uncons] dip] [i cons] genrec] inscribe
    [remo [pop not] [pop] [remove'] ifte] inscribe

In [2]:

    [1 2 3 4] 3

    [1 2 3 4] 3

In [3]:

    remo

    [1 2 4]

So far so good but I made a mistake. The recursive part doesn't handle empty lists, so it's broken for the case of the item not being in the list:

In [4]:

    45

    [1 2 4] 45

In [ ]:

     remo

## Second attempt¶

    remove == [pop not] [pop] [R0] [R1] genrec
    remove == [pop not] [pop] [R0 [remove] R1] ifte

Non-empty:

    [a b c] item R0 [remove] R1

                       R0 [remove] R1
    -----------------------------------------------------
       [swap first =] [pop rest] [E1 [remove] E2] ifte

Recursive branch:

    [a b c] d E1 [remove] E2

With:

    E1 == [uncons] dip
    E2 == i cons

    [a b c] d [uncons] dip [remove] i cons
    a [b c] d [remove] i cons
    a [b c] d remove cons

How to make it?

    R0 == [swap first =] [pop rest]

Then we want:

    R1 == [[uncons] dip [remove] i cons] ifte

But of course `[remove]` can't appear in there like that, we have to package it up:

    R1 == [i cons] cons [[uncons] dip] swoncat ifte

Or better yet:

    [[uncons] dip remove cons] ifte

    R1 == [cons] concat [[uncons] dip] swoncat ifte

Clunky, but it works:

    remove == [pop not] [pop] [[swap first =] [pop rest]] [[cons] concat [[uncons] dip] swoncat ifte] genrec

In [6]:

    [remo2 [pop not] [pop] [[swap first =] [pop rest]] [[cons] concat [[uncons] dip] swoncat ifte] genrec] inscribe

    [1 2 4] 45

In [7]:

    remo2

    [1 2 4]

In [8]:

    2

    [1 2 4] 2

In [9]:

    remo2

    [1 4]

## Third attempt¶

What if we let `[remove]` be on the stack instead of building the else-part each iteration?:

    remove == [pop not] [pop] []        [[P] [THEN] [ELSE] ifte] genrec
    remove == [pop not] [pop] [ [remove] [P] [THEN] [ELSE] ifte] ifte

So:

    [a b c] item [remove] [P] [THEN] [ELSE] ifte

    P == pop swap first =

    THEN == popop rest

    ELSE == ...

Hmm...

    [a b c] item [remove] ELSE
    [a b c] item [remove] [uncons] dipd i cons
    a [b c] item [remove] i cons
    a [b c] item remove cons
    ...
    a [b c] cons
    [a b c]

So:

    ELSE == [uncons] dipd i cons

And:

    remove == [pop not] [pop] [] [[pop swap first =] [popop rest] [[uncons] dipd i cons] ifte] genrec

In [10]:

    [remo3 [pop not] [pop] [] [[pop swap first =] [popop rest] [[uncons] dipd i cons] ifte] genrec] inscribe

    [1 4]

In [11]:

    [5 6] concat

    [1 4 5 6]

In [12]:

    5

    [1 4 5 6] 5

In [13]:

    remo3

    [1 4 6]

In [14]:

    5

    [1 4 6] 5

In [15]:

    remo3

    [1 4 6]

In [16]:

    pop [] 5

    [] 5

In [17]:

    remo3

    []

In [ ]: