Login
7 branches 0 tags
Ben (X13/Arch) Added support for adding marker passes to the GC 370d602 4 years ago 174 Commits
nujel / stdlib / lists.nuj
; Put all the LISt Processing stuff in here

[def except-last-pair [let*
        [def iter [λ [list rest]
                     [if [nil? [cdr list]]
                         [reverse rest]
                         [iter [cdr list] [cons [car list] rest]]]
        ]]

        [λ [list]
                "Return a copy of LIST without the last pair"
                [iter list #nil]
        ]
]]

[defun last-pair [list]
        "Return the last pair of l"
        [if [cdr list]
            [last-pair [cdr list]]
            list]
]

[def make-list [let*
        [def iter [λ [number value l]
                     [if [<= number 0]
                         l
                         [iter [- number 1] value [cons value l]]]
        ]]

        [λ [number value]
                "Return a list of NUMBER elements containing VALUE in every car"
                [iter number value #nil]
        ]
]]

[defun reduce [o l s]
        "Combine all elements in l using operation o and starting value s"
        [if [nil? l]
            s
            [reduce o [cdr l] [o s [car l]]]]
]

[defun list-ref [l i]
        "Returns the the element of list l at location i"
        [cond [[nil? l] #nil]
              [[<= i 0] [car l]]
              [#t [list-ref [cdr l] [-- i]]]
        ]
]

[def join [let*
        [def iter [λ [str l glue]
                [cond [[nil? l] [substr str 0 [- [str/length str] [str/length glue]]]]
                      [#t [iter [cat str [car l] glue] [cdr l] glue]]
                ]
        ]]

        [λ [l glue]
                "Join LIST into a string with GLUE in between each element"
                [iter "" l [string glue]]
        ]
]]

[defun split [str separator]
       [def separator-len [str/length separator]]
       [def slen [str/length str]]
       [def start 0]
       [def ret #nil]
       [while [< start slen]
              [def pos-found [index-of str separator start]]
              [if [>= pos-found 0]
                  [do [def pos-found [max pos-found [+ start 1]]]
                      [set! ret [cons [substr str start pos-found]
                                      ret]]
                      [set! start [+ separator-len pos-found]]
                  ]
                  [do [set! ret [cons [substr str start slen]
                                      ret]]
                      [set! start slen]
                  ]]
       ]
       [reverse ret]
]

[defun reverse [l r]
        "Return the list l in reverse order"
        [if [nil? l]
            r
            [reverse [cdr l] [cons [car l] r]]]
]

[defun list-length [a t]
        "Returns the length of list a"
        [if [nil? a]
            t
            [list-length [cdr a] [++ t]]]
]

[defun filter [p l]
        "Runs predicate p over every item in list l and returns a list consiting solely of items where p is true"
        [def ret #nil]
        [if l
            [if [p [car l]]
                [cons [car l] [filter p [cdr l]]]
                [filter p [cdr l]]
            #nil]]
]

[defun for-each [f l]
        "Runs f over every item in list l and returns the resulting list"
        [while l
               [f [car l]]
               [set! l [cdr l]]
        ]
]

[defun map [f l]
        "Runs f over every item in list l and returns the resulting list"
        [if [nil? l]
            l
            [cons [f [car l]] [map f [cdr l]]]]
]

[def append [let*
        [def iter [λ [a b]
                     [if [nil? a]
                         b
                         [iter [cdr a] [cons [car a] b]]]
        ]]

        [λ [a b]
                "Appends to two lists a and b together"
                [iter [reverse a] b]
        ]
]]

[defun sublist [l start end ret]
        "Returns a new list containing all elements of l from start to end"
        [cond [[nil?    l] [reverse ret]]
              [[neg?  end] [sublist      l      start  [+ [length l] end]]]
              [[zero? end] [reverse ret]]
              [[> start 0] [sublist [cdr l] [-- start] [-- end] #nil]]
              [[> end   0] [sublist [cdr l] 0          [-- end] [cons [car l] ret]]]
        ]
]

[defun list-head [l k]
        "Returns the first k elemnts of list l"
        [sublist l 0 k]
]

[defun list-tail [l k]
        "Returns the sublist of l obtained by omitting the first l elements"
        [sublist l k [length l]]
]

[defun member [m l]
        "Returns the first pair of list l whose car is equal to m"
        [cond [[nil? l] #f]
              [[eq? [car l] m] l]
              [#t [member m [cdr l]]]
        ]
]

[defun delete [e l]
        "Returns a filtered list l with all elements equal to e omitted"
        [filter [λ [a] [not [eq? a e]]] l]
]

[defun arg-list [f]
        "Return the Argument list of f which can be a Native Function or a Lambda"
        [cond [[lambda? f] [reduce cat [map [λ [a] [" " [car a]]] [cl-data f]]]]
              [[native? f] [reduce cat [map [λ [a] [" " a]] [car [cl-data f]]]]]
              [#t ""]
        ]
]

[defun getf [l key]
       "Return the value in LIST following KEY"
       [cond [[nil? l] #nil]
             [[eq? key [car l]] [cadr l]]
             [#t [getf [cdr l] key]]
       ]
]