Login
7 branches 0 tags
Ben (X13/Arch) Improved comparisons of #nil e387db4 4 years ago 113 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]
	]
]]

[def 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]
	]
]]

[def 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]]]]
]]

[def 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]]
	]
]]

[def split [let*
	[def iter [λ [str separator separator-len start slen]
		    [let*
			[def pos [index-of str separator start]]
			[if [and [>= pos start] [< pos slen]]
			    [cons [substr str start [max [+ start 1] pos]] [iter str separator separator-len [max [+ pos 1] [+ pos [int separator-len]]] slen]]
			    [cons [substr str start slen]]]
		]
	]]

	[λ [str separator]
		"Split STR on every SEPARATOR"
		[iter str separator [max 1 [str/length separator]] 0 [str/length str]]
	]
]]

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

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

[def 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]]
]]

[def 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]
	]
]]

[def 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]]]
	]
]]

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

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

[def 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]]]
	]
]]

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

[def 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 ""]
	]
]]

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