list.lisp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917
  1. "List manipulation functions.
  2. These include several often-used functions for manipulation of lists,
  3. including functional programming classics such as [[map]] and [[reduce]]
  4. and useful patterns such as [[accumulate-with]].
  5. Most of these functions are tail-recursive unless noted, which means
  6. they will not blow up the stack. Along with the property of
  7. tail-recursiveness, these functions also have favourable performance
  8. characteristics.
  9. ## Glossary:
  10. - **Constant time** The function runs in the same time regardless of the
  11. size of the input list.
  12. - **Linear time** The runtime of the function is a linear function of
  13. the size of the input list.
  14. - **Logarithmic time** The runtime of the function grows logarithmically
  15. in proportion to the size of the input list.
  16. - **Exponential time** The runtime of the function grows exponentially
  17. in proportion to the size of the input list. This is generally a bad
  18. thing."
  19. (import core/base (defun defmacro when unless let* set-idx! get-idx for gensym -or
  20. slice /= mod else print error tostring -and if n + - >= > =
  21. not with apply and progn .. * while <= < or values-list first list
  22. second for-pairs))
  23. (import core/base b)
  24. (import core/demand (assert-type!))
  25. (import core/method (pretty eq? neq?))
  26. (import core/type (nil? list? empty? exists? falsey? type))
  27. (import lua/math (min max huge))
  28. (import lua/string)
  29. (import lua/table)
  30. (defun car (x)
  31. "Return the first element present in the list X. This function operates
  32. in constant time.
  33. ### Example:
  34. ```cl
  35. > (car '(1 2 3))
  36. out = 1
  37. ```"
  38. (assert-type! x list)
  39. (b/car x))
  40. (define slicing-view
  41. "Return a mutable reference to the list LIST, with indexing offset
  42. (positively) by OFFSET. Mutation in the original list is reflected in
  43. the view, and updates to the view are reflected in the original. In
  44. this, a sliced view resembles an (offset) pointer. Note that trying
  45. to access a key that doesn't make sense in a list (e.g., not its
  46. `:tag`, its `:n`, or a numerical index) will blow up with an arithmetic
  47. error.
  48. **Note** that the behaviour of a sliced view when the underlying list
  49. changes length may be confusing: accessing elements will still work,
  50. but the reported length of the slice will be off. Furthermore, If the
  51. original list shrinks, the view will maintain its length, but will
  52. have an adequate number of `nil`s at the end.
  53. ```cl
  54. > (define foo '(1 2 3 4 5))
  55. out = (1 2 3 4 5)
  56. > (define foo-view (cdr foo))
  57. out = (2 3 4 5)
  58. > (remove-nth! foo 5)
  59. out = 5
  60. > foo-view
  61. out = (2 3 4 nil)
  62. ```
  63. Also **note** that functions that modify a list in-place, like
  64. `insert-nth!', `remove-nth!`, `pop-last!` and `push!` will not
  65. modify the view *or* the original list.
  66. ```cl :no-test
  67. > (define bar '(1 2 3 4 5))
  68. out = (1 2 3 4 5)
  69. > (define bar-view (cdr bar))
  70. out = (2 3 4 5)
  71. > (remove-nth! bar-view 4)
  72. out = nil
  73. > bar
  74. out = (1 2 3 4 5)
  75. ```
  76. ### Example:
  77. ```cl
  78. > (define baz '(1 2 3))
  79. out = (1 2 3)
  80. > (slicing-view baz 1)
  81. out = (2 3)
  82. > (.<! (slicing-view baz 1) 1 5)
  83. out = nil
  84. > baz
  85. out = (1 5 3)
  86. ```"
  87. (let* [(ref-mt { :__index (lambda (t k)
  88. (get-idx (get-idx t :parent) (+ k (get-idx t :offset))))
  89. :__newindex (lambda (t k v)
  90. (set-idx! (get-idx t :parent) (+ k (get-idx t :offset)) v)) })]
  91. (lambda (list offset)
  92. (cond
  93. [(<= (n list) offset) '()]
  94. [(and (get-idx list :parent)
  95. (get-idx list :offset))
  96. (b/setmetatable { :parent (get-idx list :parent)
  97. :offset (+ (get-idx list :offset) offset)
  98. :n (- (n list) offset)
  99. :tag (type list) }
  100. ref-mt)]
  101. [else (b/setmetatable { :parent list
  102. :offset offset
  103. :n (- (n list) offset)
  104. :tag (type list) }
  105. ref-mt)]))))
  106. (defun cdr (x)
  107. "Return a reference the list X without the first element present. In
  108. the case that X is nil, the empty list is returned. Note that
  109. mutating the reference will not mutate the
  110. ### Example:
  111. ```cl
  112. > (cdr '(1 2 3))
  113. out = (2 3)
  114. ```"
  115. (slicing-view x 1))
  116. (defun take (xs n)
  117. "Take the first N elements of the list XS.
  118. ### Example:
  119. ```cl
  120. > (take '(1 2 3 4 5) 2)
  121. out = (1 2)
  122. ```"
  123. (slice xs 1 (min n (b/n xs))))
  124. (defun drop (xs n)
  125. "Remove the first N elements of the list XS.
  126. ### Example:
  127. ```cl
  128. > (drop '(1 2 3 4 5) 2)
  129. out = (3 4 5)
  130. ```"
  131. (slice xs (+ n 1) nil))
  132. (defun snoc (xss &xs)
  133. "Return a copy of the list XS with the element XS added to its end.
  134. This function runs in linear time over the two input lists: That is,
  135. it runs in O(n+k) time proportional both to `(n XSS)` and `(n XS)`.
  136. ### Example:
  137. ```cl
  138. > (snoc '(1 2 3) 4 5 6)
  139. out = (1 2 3 4 5 6)
  140. ``` "
  141. `(,@xss ,@xs))
  142. (defun cons (&xs xss)
  143. "Return a copy of the list XSS with the elements XS added to its head.
  144. ### Example:
  145. ```cl
  146. > (cons 1 2 3 '(4 5 6))
  147. out = (1 2 3 4 5 6)
  148. ```"
  149. `(,@xs ,@xss))
  150. (defun reduce (f z xs)
  151. "Accumulate the list XS using the binary function F and the zero
  152. element Z. This function is also called `foldl` by some authors. One
  153. can visualise `(reduce f z xs)` as replacing the [[cons]] operator in
  154. building lists with F, and the empty list with Z.
  155. Consider:
  156. - `'(1 2 3)` is equivalent to `(cons 1 (cons 2 (cons 3 '())))`
  157. - `(reduce + 0 '(1 2 3))` is equivalent to `(+ 1 (+ 2 (+ 3 0)))`.
  158. ### Example:
  159. ```cl
  160. > (reduce append '() '((1 2) (3 4)))
  161. out = (1 2 3 4)
  162. ; equivalent to (append '(1 2) (append '(3 4) '()))
  163. ```"
  164. (assert-type! f function)
  165. (let* [(start 1)]
  166. (if (and (nil? xs)
  167. (list? z))
  168. (progn
  169. (set! start 2)
  170. (set! xs z)
  171. (set! z (car z)))
  172. nil)
  173. (assert-type! xs list)
  174. (let* [(accum z)]
  175. (for i start (n xs) 1
  176. (set! accum (f accum (nth xs i))))
  177. accum)))
  178. (defun map (fn &xss)
  179. "Iterate over all the successive cars of XSS, producing a single list
  180. by applying FN to all of them. For example:
  181. ### Example:
  182. ```cl
  183. > (map list '(1 2 3) '(4 5 6) '(7 8 9))
  184. out = ((1 4 7) (2 5 8) (3 6 9))
  185. > (map succ '(1 2 3))
  186. out = (2 3 4)
  187. ```"
  188. (let* [(ns (let* [(out '())]
  189. (for i 1 (n xss) 1
  190. (if (not (list? (nth xss i)))
  191. (error (.. "that's no list! " (pretty (nth xss i))
  192. " (it's a " (type (nth xss i)) "!)"))
  193. true)
  194. (push! out (n (nth xss i))))
  195. out))
  196. (out '())]
  197. (for i 1 (apply min ns) 1
  198. (push! out (apply fn (nths xss i))))
  199. out))
  200. (defun filter-map (fn &xss)
  201. "Iterate over all successive cars of XSS, producing a single list by
  202. applying FN to all of them, while discarding any `nil`s.
  203. ### Example:
  204. ```cl
  205. > (filter-map (lambda (x)
  206. . (if (even? x)
  207. . nil
  208. . (succ x)))
  209. . (range :from 1 :to 10))
  210. out = (2 4 6 8 10)
  211. ```"
  212. (let* [(lengths (let* [(out '())]
  213. (for i 1 (n xss) 1
  214. (if (not (list? (nth xss i)))
  215. (error (.. "that's no list! " (pretty (nth xss i))
  216. " (it's a " (type (nth xss i)) "!)"))
  217. true)
  218. (push! out (n (nth xss i))))
  219. out))
  220. (out '())]
  221. (for i 1 (apply min lengths) 1
  222. (let* [(vl (apply fn (nths xss i)))]
  223. (if (/= vl nil)
  224. (push! out vl)
  225. nil)))
  226. out))
  227. (defun flat-map (fn &xss)
  228. "Map the function FN over the lists XSS, then flatten the result
  229. lists.
  230. ### Example:
  231. ```cl
  232. > (flat-map list '(1 2 3) '(4 5 6))
  233. out = (1 4 2 5 3 6)
  234. ```"
  235. (flatten (apply map fn xss)))
  236. (defun partition (p xs)
  237. "Split XS based on the predicate P. Values for which the predicate
  238. returns true are returned in the first list, whereas values which
  239. don't pass the predicate are returned in the second list.
  240. ### Example:
  241. ```cl
  242. > (list (partition even? '(1 2 3 4 5 6)))
  243. out = ((2 4 6) (1 3 5))
  244. ```"
  245. (assert-type! p function)
  246. (assert-type! xs list)
  247. (let* [(passed '())
  248. (failed '())]
  249. (for i 1 (n xs) 1
  250. (with (x (nth xs i))
  251. (push! (if (p x) passed failed) x)))
  252. (values-list passed failed)))
  253. (defun filter (p xs)
  254. "Return a list with only the elements of XS that match the predicate
  255. P.
  256. ### Example:
  257. ```cl
  258. > (filter even? '(1 2 3 4 5 6))
  259. out = (2 4 6)
  260. ```"
  261. (first (partition p xs)))
  262. (defun exclude (p xs)
  263. "Return a list with only the elements of XS that don't match the
  264. predicate P.
  265. ### Example:
  266. ```cl
  267. > (exclude even? '(1 2 3 4 5 6))
  268. out = (1 3 5)
  269. ```"
  270. (second (partition p xs)))
  271. (defun any (p xs)
  272. "Check for the existence of an element in XS that matches the predicate
  273. P.
  274. ### Example:
  275. ```cl
  276. > (any exists? '(nil 1 \"foo\"))
  277. out = true
  278. ```"
  279. (assert-type! p function)
  280. (assert-type! xs list)
  281. (let* [(len (n xs))
  282. (fun nil)]
  283. (set! fun (lambda (i)
  284. (cond
  285. [(> i len) false]
  286. [(p (nth xs i)) true]
  287. [else (fun (+ i 1))])))
  288. (fun 1)))
  289. (defun none (p xs)
  290. "Check that no elements in XS match the predicate P.
  291. ### Example:
  292. ```cl
  293. > (none nil? '(\"foo\" \"bar\" \"baz\"))
  294. out = true
  295. ```"
  296. (not (any p xs)))
  297. (defun \\ (xs ys)
  298. "The difference between XS and YS (non-associative.)
  299. ### Example:
  300. ```cl
  301. > (\\\\ '(1 2 3) '(1 3 5 7))
  302. out = (2)
  303. ```"
  304. (filter (lambda (x)
  305. (not (elem? x ys)))
  306. xs))
  307. (defun nub (xs)
  308. "Remove duplicate elements from XS. This runs in linear time.
  309. ### Example:
  310. ```cl
  311. > (nub '(1 1 2 2 3 3))
  312. out = (1 2 3)
  313. ```"
  314. (let* ((hm {})
  315. (out '[]))
  316. (for-each elm xs
  317. (with (szd (pretty elm))
  318. (cond
  319. [(nil? (get-idx hm szd))
  320. (push! out elm)
  321. (set-idx! hm szd elm)]
  322. [else])))
  323. out))
  324. (defun union (&xss)
  325. "Set-like union of all the lists in XSS. Note that this function does
  326. not preserve the lists' orders.
  327. ### Example:
  328. ```cl
  329. > (union '(1 2 3 4) '(1 2 3 4 5))
  330. out = (1 2 3 4 5)
  331. ```"
  332. (let* [(set {})
  333. (out '())]
  334. (do [(xs xss)]
  335. (if (list? xs)
  336. (do [(x xs)]
  337. (set-idx! set x x))
  338. (set-idx! set xs xs)))
  339. (for-pairs (k v) set
  340. (push! out v))
  341. out))
  342. (defun all (p xs)
  343. "Test if all elements of XS match the predicate P.
  344. ### Example:
  345. ```cl
  346. > (all symbol? '(foo bar baz))
  347. out = true
  348. > (all number? '(1 2 foo))
  349. out = false
  350. ```"
  351. (assert-type! p function)
  352. (assert-type! xs list)
  353. (let* [(len (n xs))
  354. (fun nil)]
  355. (set! fun (lambda (i)
  356. (cond
  357. [(> i len) true]
  358. [(p (nth xs i)) (fun (+ i 1))]
  359. [else false])))
  360. (fun 1)))
  361. (defun elem? (x xs)
  362. "Test if X is present in the list XS.
  363. ### Example:
  364. ```cl
  365. > (elem? 1 '(1 2 3))
  366. out = true
  367. > (elem? 'foo '(1 2 3))
  368. out = false
  369. ```"
  370. (assert-type! xs list)
  371. (any (lambda (y) (eq? x y)) xs))
  372. (defun find-index (p xs)
  373. "Finds the first index in XS where the item matches the predicate
  374. P. Returns `nil` if no such item exists.
  375. ### Example:
  376. ```cl
  377. > (find-index even? '(3 4 5))
  378. out = 2
  379. > (find-index even? '(1 3 5))
  380. out = nil
  381. ```"
  382. (assert-type! p function)
  383. (assert-type! xs list)
  384. (let* [(len (n xs))
  385. (fun nil)]
  386. (set! fun (lambda (i)
  387. (cond
  388. [(> i len) nil]
  389. [(p (nth xs i)) i]
  390. [else (fun (+ i 1))])))
  391. (fun 1)))
  392. (defun element-index (x xs)
  393. "Finds the first index in XS where the item matches X. Returns `nil` if
  394. no such item exists.
  395. ### Example:
  396. ```cl
  397. > (element-index 4 '(3 4 5))
  398. out = 2
  399. > (element-index 2 '(1 3 5))
  400. out = nil
  401. ```"
  402. (assert-type! xs list)
  403. (find-index (lambda (y) (eq? x y)) xs))
  404. (defun prune (xs)
  405. "Remove values matching the predicates [[empty?]] or [[nil?]] from
  406. the list XS.
  407. ### Example:
  408. ```cl
  409. > (prune (list '() nil 1 nil '() 2))
  410. out = (1 2)
  411. ```"
  412. (assert-type! xs list)
  413. (filter (lambda (x) (and (not (nil? x)) (not (empty? x)))) xs))
  414. (defun traverse (xs f)
  415. :deprecated "Use [[map]] instead."
  416. "An alias for [[map]] with the arguments XS and F flipped.
  417. ### Example:
  418. ```cl
  419. > (traverse '(1 2 3) succ)
  420. out = (2 3 4)
  421. ```"
  422. (map f xs))
  423. (defun last (xs)
  424. "Return the last element of the list XS.
  425. Counterintutively, this function runs in constant time.
  426. ### Example:
  427. ```cl
  428. > (last (range :from 1 :to 100))
  429. out = 100
  430. ```"
  431. (assert-type! xs list)
  432. (get-idx xs (n xs)))
  433. (defun init (xs)
  434. "Return the list XS with the last element removed.
  435. This is the dual of LAST.
  436. ### Example:
  437. ```cl
  438. > (init (range :from 1 :to 10))
  439. out = (1 2 3 4 5 6 7 8 9)
  440. ```"
  441. (assert-type! xs list)
  442. (slice xs 1 (- (n xs) 1)))
  443. (defun nth (xs idx)
  444. "Get the IDX th element in the list XS. The first element is 1.
  445. This function runs in constant time.
  446. ### Example:
  447. ```cl
  448. > (nth (range :from 1 :to 100) 10)
  449. out = 10
  450. ```"
  451. (if (>= idx 0)
  452. (get-idx xs idx)
  453. (get-idx xs (+ (get-idx xs :n) 1 idx))))
  454. (defun nths (xss idx)
  455. "Get the IDX-th element in all the lists given at XSS. The first
  456. element is1.
  457. ### Example:
  458. ```cl
  459. > (nths '((1 2 3) (4 5 6) (7 8 9)) 2)
  460. out = (2 5 8)
  461. ```"
  462. (let* [(out '())]
  463. (for i 1 (n xss) 1
  464. (push! out (nth (nth xss i) idx)))
  465. out))
  466. (defun push! (xs &vals)
  467. "Mutate the list XS, adding VALS to its end.
  468. ### Example:
  469. ```cl
  470. > (define list '(1 2 3))
  471. > (push! list 4)
  472. out = (1 2 3 4)
  473. > list
  474. out = (1 2 3 4)
  475. ```"
  476. (assert-type! xs list)
  477. (let* [(nxs (n xs))
  478. (len (+ nxs (n vals)))]
  479. (set-idx! xs "n" len)
  480. (for i 1 (n vals) 1
  481. (set-idx! xs (+ nxs i) (get-idx vals i)))
  482. xs))
  483. (define push-cdr!
  484. "Mutate the list XS, adding VALS to its end.
  485. ### Example:
  486. ```cl
  487. > (define list '(1 2 3))
  488. > (push-cdr! list 4)
  489. out = (1 2 3 4)
  490. > list
  491. out = (1 2 3 4)
  492. ```"
  493. :deprecated "Use [[push!]] instead."
  494. push!)
  495. (defun pop-last! (xs)
  496. "Mutate the list XS, removing and returning its last element.
  497. ### Example:
  498. ```cl
  499. > (define list '(1 2 3))
  500. > (pop-last! list)
  501. out = 3
  502. > list
  503. out = (1 2)
  504. ``` "
  505. (assert-type! xs list)
  506. (with (x (get-idx xs (n xs)))
  507. (set-idx! xs (n xs) nil)
  508. (set-idx! xs "n" (- (n xs) 1))
  509. x))
  510. (defun remove-nth! (li idx)
  511. "Mutate the list LI, removing the value at IDX and returning it.
  512. ### Example:
  513. ```cl
  514. > (define list '(1 2 3))
  515. > (remove-nth! list 2)
  516. out = 2
  517. > list
  518. out = (1 3)
  519. ``` "
  520. (assert-type! li list)
  521. (set-idx! li "n" (- (get-idx li "n") 1))
  522. (lua/table/remove li idx))
  523. (defun insert-nth! (li idx val)
  524. "Mutate the list LI, inserting VAL at IDX.
  525. ### Example:
  526. ```cl
  527. > (define list '(1 2 3))
  528. > (insert-nth! list 2 5)
  529. > list
  530. out = (1 5 2 3)
  531. ``` "
  532. (assert-type! li list)
  533. (set-idx! li "n" (+ (get-idx li "n") 1))
  534. (lua/table/insert li idx val))
  535. (defmacro for-each (var lst &body)
  536. :deprecated "Use [[do]]/[[dolist]] instead"
  537. "Perform the set of actions BODY for all values in LST, binding the current value to VAR.
  538. ### Example:
  539. ```cl
  540. > (for-each var '(1 2 3)
  541. . (print! var))
  542. 1
  543. 2
  544. 3
  545. out = nil
  546. ```"
  547. `(do [(,var ,lst)]
  548. ,@body))
  549. (defmacro dolist (vars &stmts)
  550. "Iterate over all given VARS, running STMTS and collecting the results.
  551. ### Example:
  552. ```cl
  553. > (dolist [(a '(1 2 3))
  554. . (b '(1 2 3))]
  555. . (list a b))
  556. out = ((1 1) (1 2) (1 3) (2 1) (2 2) (2 3) (3 1) (3 2) (3 3))
  557. ```"
  558. (let* [(collect (gensym 'list))
  559. (arg (gensym 'val))
  560. (yield (gensym 'yield))
  561. (out `(,yield (progn ,@stmts)))]
  562. (for i (n vars) 1 -1
  563. (let* [(var (nth vars i))
  564. (cur-list (gensym))
  565. (i (gensym 'i))]
  566. (set! out
  567. `(let* [(,cur-list ,(cadr var))]
  568. (for ,i 1 (n ,cur-list) 1
  569. (let* [(,(car var) (get-idx ,cur-list ,i))]
  570. ,out))))))
  571. `(let* [(,collect '())
  572. (,yield (lambda (,arg)
  573. (when (/= ,arg nil)
  574. (push! ,collect ,arg))))]
  575. ,out
  576. ,collect)))
  577. (defmacro do (vars &stmts)
  578. "Iterate over all given VARS, running STMTS **without** collecting the
  579. results.
  580. ### Example:
  581. ```cl
  582. > (do [(a '(1 2))
  583. . (b '(1 2))]
  584. . (print! $\"a = ${a}, b = ${b}\"))
  585. a = 1, b = 1
  586. a = 1, b = 2
  587. a = 2, b = 1
  588. a = 2, b = 2
  589. out = nil
  590. ```"
  591. (let* [(out `(progn ,@stmts))]
  592. (for i (n vars) 1 -1
  593. (let* [(var (nth vars i))
  594. (cur-list (gensym))
  595. (i (gensym 'i))]
  596. (set! out
  597. `(let* [(,cur-list ,(cadr var))]
  598. (for ,i 1 (n ,cur-list) 1
  599. (let* [(,(car var) (get-idx ,cur-list ,i))]
  600. ,out))))))
  601. out))
  602. (defun append (xs ys)
  603. "Concatenate XS and YS.
  604. ### Example:
  605. ```cl
  606. > (append '(1 2) '(3 4))
  607. out = (1 2 3 4)
  608. ``` "
  609. `(,@xs ,@ys))
  610. (defun flatten (xss)
  611. "Concatenate all the lists in XSS. XSS must not contain elements which
  612. are not lists.
  613. ### Example:
  614. ```cl
  615. > (flatten '((1 2) (3 4)))
  616. out = (1 2 3 4)
  617. ```"
  618. (reduce append '() xss))
  619. (defun range (&args)
  620. "Build a list from :FROM to :TO, optionally passing by :BY.
  621. ### Example:
  622. ```cl
  623. > (range :from 1 :to 10)
  624. out = (1 2 3 4 5 6 7 8 9 10)
  625. > (range :from 1 :to 10 :by 3)
  626. out = (1 3 5 7 9)
  627. ```"
  628. (let* [(x (let* [(out {})]
  629. (when (= (mod (n args) 2) 1)
  630. (error "Expected an even number of arguments to range" 2))
  631. (for i 1 (n args) 2
  632. (set-idx! out (get-idx args i) (get-idx args (+ i 1))))
  633. out))
  634. (st (or (get-idx x :from) 1))
  635. (ed (or (+ 1 (get-idx x :to))
  636. (error "Expected end index, got nothing")))
  637. (inc (- (or (get-idx x :by) (+ 1 st)) st))
  638. (tst (if (>= st ed)
  639. > <))]
  640. (let* [(c st)
  641. (out '())]
  642. (while (tst c ed)
  643. (push! out c)
  644. (set! c (+ c inc)))
  645. out)))
  646. (defun reverse (xs)
  647. "Reverse the list XS, using the accumulator ACC.
  648. ### Example:
  649. ```cl
  650. > (reverse (range :from 1 :to 10))
  651. out = (10 9 8 7 6 5 4 3 2 1)
  652. ```"
  653. (let* [(out '())]
  654. (for i (n xs) 1 -1
  655. (push! out (nth xs i)))
  656. out))
  657. (defun accumulate-with (f ac z xs)
  658. "A composition of [[reduce]] and [[map]].
  659. Transform the values of XS using the function F, then accumulate them
  660. starting form Z using the function AC.
  661. This function behaves as if it were folding over the list XS with the
  662. monoid described by (F, AC, Z), that is, F constructs the monoid, AC
  663. is the binary operation, and Z is the zero element.
  664. ### Example:
  665. ```cl
  666. > (accumulate-with tonumber + 0 '(1 2 3 4 5))
  667. out = 15
  668. ```"
  669. (assert-type! f function)
  670. (assert-type! ac function)
  671. (reduce ac z (map f xs)))
  672. (defun sum (xs)
  673. "Return the sum of all elements in XS.
  674. ### Example:
  675. ```cl
  676. > (sum '(1 2 3 4))
  677. out = 10
  678. ```"
  679. (reduce + 0 xs))
  680. (defun prod (xs)
  681. "Return the product of all elements in XS.
  682. ### Example:
  683. ```cl
  684. > (prod '(1 2 3 4))
  685. out = 24
  686. ```"
  687. (reduce * 1 xs))
  688. (defun take-while (p xs idx)
  689. "Takes elements from the list XS while the predicate P is true,
  690. starting at index IDX. Works like `filter`, but stops after the
  691. first non-matching element.
  692. ### Example:
  693. ```cl
  694. > (define list '(2 2 4 3 9 8 4 6))
  695. > (define p (lambda (x) (= (mod x 2) 0)))
  696. > (filter p list)
  697. out = (2 2 4 8 4 6)
  698. > (take-while p list 1)
  699. out = (2 2 4)
  700. ```"
  701. (assert-type! p function)
  702. (assert-type! xs list)
  703. (unless (= (type idx) "number")
  704. (set! idx 1))
  705. (let* [(l '())
  706. (ln (n xs))
  707. (x (nth xs idx))]
  708. (unless (nil? x)
  709. (while (and (<= idx ln) (p x))
  710. (push! l x)
  711. (set! idx (+ idx 1))
  712. (set! x (nth xs idx))))
  713. l))
  714. (defun split (xs y)
  715. "Splits a list into sub-lists by the separator Y.
  716. ### Example:
  717. ```cl
  718. > (split '(1 2 3 4) 3)
  719. out = ((1 2) (4))
  720. ```"
  721. (assert-type! xs list)
  722. (let* [(l '())
  723. (p (lambda (x) (neq? x y)))
  724. (idx 1)
  725. (b (take-while p xs idx))]
  726. (while (not (empty? b))
  727. (push! l b)
  728. (set! idx (+ idx (n b) 1))
  729. (set! b (take-while p xs idx)))
  730. l))
  731. (defun groups-of (xs num)
  732. "Splits the list XS into sub-lists of size NUM.
  733. ### Example:
  734. ```cl
  735. > (groups-of '(1 2 3 4 5 6) 3)
  736. out = ((1 2 3) (4 5 6))
  737. ```"
  738. (assert-type! xs list)
  739. (let* [(result '())
  740. (group nil)]
  741. (for idx 1 (n xs) 1
  742. (when (= (mod (- idx 1) num) 0)
  743. (set! group '())
  744. (push! result group))
  745. (push! group (nth xs idx)))
  746. result))
  747. (defun sort (xs f)
  748. "Sort the list XS, non-destructively, optionally using F as a
  749. comparator. A sorted version of the list is returned, while the
  750. original remains untouched.
  751. ### Example:
  752. ```cl
  753. > (define li '(9 5 7 2 1))
  754. out = (9 5 7 2 1)
  755. > (sort li)
  756. out = (1 2 5 7 9)
  757. > li
  758. out = (9 5 7 2 1)
  759. ```"
  760. (let* [(copy (map (lambda (x) x) xs))]
  761. (lua/table/sort copy f)
  762. copy))
  763. (defun sort! (xs f)
  764. "Sort the list XS in place, optionally using F as a comparator.
  765. ### Example:
  766. > (define li '(9 5 7 2 1))
  767. out = (9 5 7 2 1)
  768. > (sort! li)
  769. out = (1 2 5 7 9)
  770. > li
  771. out = (1 2 5 7 9)
  772. ```"
  773. (lua/table/sort xs f)
  774. xs)
  775. ;; Auto-generate all `c[ad]r`/`c[ad]rs` methods.
  776. ,@(let* [(out '())
  777. (symb (lambda (x) { :tag "symbol" :contents x }))
  778. (depth-symb (lambda (idx mode) (symb (.. "c" mode (lua/string/rep "d" (- idx 1)) "r"))))
  779. (pair (lambda (x y) (list y x)))
  780. (generate nil)]
  781. (set! generate (lambda (name stack do-idx idx depth)
  782. (when (> (n name) 1)
  783. (with (head (if do-idx `(get-idx ,'xs ,idx) `(slicing-view ,'xs ,idx)))
  784. (push! out `(define ,(symb (.. "c" name "r"))
  785. (lambda (,'xs)
  786. (assert-type! ,'xs ,'list)
  787. ,(reduce pair head stack))))))
  788. (when (> (n name) 0)
  789. (push! out `(define ,(symb (.. "c" name "rs")) (lambda (,'xs) (map ,(symb (.. "c" name "r")) ,'xs)))))
  790. (cond
  791. [(<= depth 0)]
  792. [do-idx
  793. (generate (.. name "a") (cons (depth-symb idx "a") stack) true 1 (- depth 1))
  794. (generate (.. name "d") stack true (+ idx 1) (- depth 1))]
  795. [else
  796. (generate (.. name "a") (cons (depth-symb idx "d") stack) true 1 (- depth 1))
  797. (generate (.. name "d") stack false (+ idx 1) (- depth 1))])))
  798. (generate "a" '() true 1 3)
  799. (generate "d" '() false 1 3)
  800. out)