PreviousUpNext

15.4.1078  src/lib/std/src/list.pkg

## list.pkg

# Compiled by:
#     src/lib/std/src/standard-core.sublib


# The following are defined in
#
#     src/lib/core/init/pervasive.pkg
#
# and consequently available unqualified
# at top level:
#
#   type List
#   my NIL, ! , hd, tl, null, length, @, apply, map, fold_right, fold_left, reverse
#
# The following are defined in this file 
# and consequently not available unqualified
# at top level:
#
#   exception EMPTY
#   my last, nth, take_n, drop_n, cat, reverse_and_prepend, map_partial_fn, find, filter,
#       partition, exists, all, tabulate
#
# The following infix declarations will hold at top level:
#   infixr 60 ! @

# See also:
#     src/lib/src/list-fns.pkg



###                         "One can even conjecture that Lisp
###                          owes its survival specifically to
###                          the fact that its programs are lists,
###                          which everyone, including me,
###                          has regarded as a disadvantage."
###
###                                 -- John McCarthy, "Early History of Lisp"




package   list
: (weak)  List                                  # List          is from   src/lib/std/src/list.api
{                                               # inline_t      is from   src/lib/core/init/built-in.pkg
    my (+)  = inline_t::default_int::(+);
    my (-)  = inline_t::default_int::(-);
    my (<)  = inline_t::default_int::(<);
    my (<=) = inline_t::default_int::(<=);
    my (>)  = inline_t::default_int::(>);
    my (>=) = inline_t::default_int::(>=);

#     op =  = inline_t::(=) 

    List == List;                                                       # Import List into this package from   src/lib/core/init/pervasive.pkg

    exception EMPTY = EMPTY;

    null = null;
    head = head;
    tail = tail;

    fun last []      =>  raise exception EMPTY;                         # Return last element in list.                          Raise EMPTY if list is empty.
        last [x]     =>  x;
        last (_ ! r) =>  last r;
    end;

    fun get_item []      =>  NULL;
        get_item (x ! r) =>  THE (x, r);
    end;

    fun nth (l, n)                                                      # Return n-th    element  from list.  Raise SUBSCRIPT if list is not long enough.
        =
        {   fun loop ((e ! _), 0) => e;
                loop ([], _) => raise exception SUBSCRIPT;
                loop ((_ ! t), n) => loop (t, n - 1);
            end;

            if (n >= 0 ) loop (l, n); else raise exception SUBSCRIPT;fi;
        };

    fun take_n (l, n)                                                   # Return first N elements from list.  Raise SUBSCRIPT if list is not long enough.
        =
        if (n >= 0)   loop (l, n);
        else          raise exception SUBSCRIPT;
        fi
        where
            fun loop (l,       0) =>  [];
                loop ([],      _) =>  raise exception SUBSCRIPT;
                loop ((x ! t), n) =>  x ! loop (t, n - 1);
            end;
        end;

    fun drop_n (l, n)                                                   # Drop first N elements from list, return remainder.     Raise SUBSCRIPT if list is not long enough.
        =
        if (n >= 0)   loop (l, n);
        else          raise exception SUBSCRIPT;
        fi
        where
            fun loop (l,       0) =>  l;
                loop ([],      _) =>  raise exception SUBSCRIPT;
                loop ((_ ! t), n) =>  loop (t, n - 1);
            end;
        end;

    length  =  length;
    reverse =  reverse;

#    my op (@) = op (@);
#
# The above stopped working, so the below replicates the original definition XXX BUGGO FIXME
#
    fun l1 @ l2
        =
        fold_right (!) l2 l1;

    fun cat []      =>   [];
        cat (l ! r) =>   l @ cat r;
    end;

    fun reverse_and_prepend ([],     l) =>  l;
        reverse_and_prepend (h ! t,  l) =>  reverse_and_prepend (t, h ! l);
    end;

    apply   =  apply;
    map     =  map;

    apply'  =  apply';
    map'    =  map';


    fun map_partial_fn func l
        =
        mapp (l, [])
        where 
            fun mapp ([], l)
                    =>
                    reverse l;

                mapp (x ! r, l)
                    =>
                    case (func x)
                        #                      
                        THE y =>  mapp (r, y ! l);
                        NULL  =>  mapp (r, l);
                    esac;
            end;
        end;


    fun find predicate []
            =>
            NULL;

        find predicate (a ! rest)
            =>
            if (predicate a)   THE a;
            else               find predicate rest;
            fi;
    end;

    # Construct a return list
    # containing only elements of
    # given list satisfying given
    # predicate:
    #
    fun filter predicate []
            =>
            [];

        filter predicate (element ! rest)
            =>
            if (predicate element)   element ! (filter predicate rest); 
            else                               (filter predicate rest);
            fi;
    end;

    fun partition predicate l
        =
        loop (l,[],[])
        where
            fun loop ([], true_list, false_list)
                    =>
                   (reverse true_list, reverse false_list);

                loop (h ! t,  true_list,  false_list)
                    => 
                    if (predicate h)
                         #
                         loop (t,  h ! true_list,      false_list);
                    else loop (t,  true_list,      h ! false_list);
                   fi;
            end;
        end;

    fold_right =  fold_right;
    fold_left  =  fold_left;

    fun exists predicate
        =
        f
        where
            fun f []      =>  FALSE;
                f (h ! t) =>  predicate h or f t;
            end;
        end;

    fun all predicate
        =
        f
        where
            fun f []      =>  TRUE;
                f (h ! t) =>  predicate h and f t;
            end;
        end;

    fun tabulate (len, genfn)
        = 
        if (len < 0)
            #            
            raise exception SIZE;
        else
            loop 0
            where
                fun loop n
                    =
                    if (n == len)   [];
                    else            (genfn n) ! (loop (n+1));
                    fi;
            end;   
        fi;

    fun collate compare
        =
        loop
        where
            fun loop ([], []) =>  EQUAL;
                loop ([], _)  =>  LESS;
                loop (_, [])  =>  GREATER;

                loop (x ! xs,   y ! ys)
                    =>
                    case (compare (x, y))
                        #                       
                        EQUAL   =>  loop (xs, ys);
                        unequal =>  unequal;
                    esac;
            end;
        end;

    fun a in []            =>  FALSE;
        a in (this ! rest) =>  (a == this)  or  (a in rest);
    end;
        #
        # 2008-03-25 CrT:
        #    This function is inspired by the similar Python operator;
        #    I changed Mythryl syntax to make 'in' not be a reserved
        #    word specifically for this function.  :)
        #    I was originally going to put the above fun def in
        #        src/lib/core/init/pervasive.pkg
        #    but that resulted in
        #        bin/mythryl-runtime-intel32: Fatal error -- unable to find picklehash (compiledfile identifier) '[4500880824c70d26c741e5b186aad4c1]'
        #        sh/make-compiler-executable:   Compiler link failed, no mythryld executable
        #    which I didn't feel like trying to understand.
        #    So I settled for defining 'in' as infix in pervasive.pkg,
        #    defining it here, and exporting it as a scripting global in
        #        src/app/makelib/main/makelib-g.pkg
        #    I'd still rather have it in pervasive.pkg, though,
        #    or otherwise made generally available as a global:  XXX SUCKO FIXME.
        #
        # 2009-09-15 CrT:
        #    The core issue appears to be the attempt to use
        #    typeagnostic in/equality testing in pervasive.pkg.


}; #  package list 




Comments and suggestions to: bugs@mythryl.org

PreviousUpNext