srfi-1.scm 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962
  1. ;;; srfi-1.scm --- List Library
  2. ;; Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010, 2011 Free Software Foundation, Inc.
  3. ;;
  4. ;; This library is free software; you can redistribute it and/or
  5. ;; modify it under the terms of the GNU Lesser General Public
  6. ;; License as published by the Free Software Foundation; either
  7. ;; version 3 of the License, or (at your option) any later version.
  8. ;;
  9. ;; This library is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;; Lesser General Public License for more details.
  13. ;;
  14. ;; You should have received a copy of the GNU Lesser General Public
  15. ;; License along with this library; if not, write to the Free Software
  16. ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. ;;; Some parts from the reference implementation, which is
  18. ;;; Copyright (c) 1998, 1999 by Olin Shivers. You may do as you please with
  19. ;;; this code as long as you do not remove this copyright notice or
  20. ;;; hold me liable for its use.
  21. ;;; Author: Martin Grabmueller <mgrabmue@cs.tu-berlin.de>
  22. ;;; Date: 2001-06-06
  23. ;;; Commentary:
  24. ;; This is an implementation of SRFI-1 (List Library).
  25. ;;
  26. ;; All procedures defined in SRFI-1, which are not already defined in
  27. ;; the Guile core library, are exported. The procedures in this
  28. ;; implementation work, but they have not been tuned for speed or
  29. ;; memory usage.
  30. ;;
  31. ;; This module is fully documented in the Guile Reference Manual.
  32. ;;; Code:
  33. (define-module (srfi srfi-1)
  34. :export (
  35. ;;; Constructors
  36. ;; cons <= in the core
  37. ;; list <= in the core
  38. xcons
  39. ;; cons* <= in the core
  40. ;; make-list <= in the core
  41. list-tabulate
  42. list-copy
  43. circular-list
  44. ;; iota ; Extended.
  45. ;;; Predicates
  46. proper-list?
  47. circular-list?
  48. dotted-list?
  49. ;; pair? <= in the core
  50. ;; null? <= in the core
  51. null-list?
  52. not-pair?
  53. list=
  54. ;;; Selectors
  55. ;; car <= in the core
  56. ;; cdr <= in the core
  57. ;; caar <= in the core
  58. ;; cadr <= in the core
  59. ;; cdar <= in the core
  60. ;; cddr <= in the core
  61. ;; caaar <= in the core
  62. ;; caadr <= in the core
  63. ;; cadar <= in the core
  64. ;; caddr <= in the core
  65. ;; cdaar <= in the core
  66. ;; cdadr <= in the core
  67. ;; cddar <= in the core
  68. ;; cdddr <= in the core
  69. ;; caaaar <= in the core
  70. ;; caaadr <= in the core
  71. ;; caadar <= in the core
  72. ;; caaddr <= in the core
  73. ;; cadaar <= in the core
  74. ;; cadadr <= in the core
  75. ;; caddar <= in the core
  76. ;; cadddr <= in the core
  77. ;; cdaaar <= in the core
  78. ;; cdaadr <= in the core
  79. ;; cdadar <= in the core
  80. ;; cdaddr <= in the core
  81. ;; cddaar <= in the core
  82. ;; cddadr <= in the core
  83. ;; cdddar <= in the core
  84. ;; cddddr <= in the core
  85. ;; list-ref <= in the core
  86. first
  87. second
  88. third
  89. fourth
  90. fifth
  91. sixth
  92. seventh
  93. eighth
  94. ninth
  95. tenth
  96. car+cdr
  97. take
  98. drop
  99. take-right
  100. drop-right
  101. take!
  102. drop-right!
  103. split-at
  104. split-at!
  105. last
  106. ;; last-pair <= in the core
  107. ;;; Miscelleneous: length, append, concatenate, reverse, zip & count
  108. ;; length <= in the core
  109. length+
  110. ;; append <= in the core
  111. ;; append! <= in the core
  112. concatenate
  113. concatenate!
  114. ;; reverse <= in the core
  115. ;; reverse! <= in the core
  116. append-reverse
  117. append-reverse!
  118. zip
  119. unzip1
  120. unzip2
  121. unzip3
  122. unzip4
  123. unzip5
  124. count
  125. ;;; Fold, unfold & map
  126. fold
  127. fold-right
  128. pair-fold
  129. pair-fold-right
  130. reduce
  131. reduce-right
  132. unfold
  133. unfold-right
  134. ;; map ; Extended.
  135. ;; for-each ; Extended.
  136. append-map
  137. append-map!
  138. map!
  139. ;; map-in-order ; Extended.
  140. pair-for-each
  141. filter-map
  142. ;;; Filtering & partitioning
  143. ;; filter <= in the core
  144. partition
  145. remove
  146. ;; filter! <= in the core
  147. partition!
  148. remove!
  149. ;;; Searching
  150. find
  151. find-tail
  152. take-while
  153. take-while!
  154. drop-while
  155. span
  156. span!
  157. break
  158. break!
  159. any
  160. every
  161. ;; list-index ; Extended.
  162. ;; member ; Extended.
  163. ;; memq <= in the core
  164. ;; memv <= in the core
  165. ;;; Deletion
  166. ;; delete ; Extended.
  167. ;; delete! ; Extended.
  168. delete-duplicates
  169. delete-duplicates!
  170. ;;; Association lists
  171. ;; assoc ; Extended.
  172. ;; assq <= in the core
  173. ;; assv <= in the core
  174. alist-cons
  175. alist-copy
  176. alist-delete
  177. alist-delete!
  178. ;;; Set operations on lists
  179. lset<=
  180. lset=
  181. lset-adjoin
  182. lset-union
  183. lset-intersection
  184. lset-difference
  185. lset-xor
  186. lset-diff+intersection
  187. lset-union!
  188. lset-intersection!
  189. lset-difference!
  190. lset-xor!
  191. lset-diff+intersection!
  192. ;;; Primitive side-effects
  193. ;; set-car! <= in the core
  194. ;; set-cdr! <= in the core
  195. )
  196. :re-export (cons list cons* make-list pair? null?
  197. car cdr caar cadr cdar cddr
  198. caaar caadr cadar caddr cdaar cdadr cddar cdddr
  199. caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr
  200. cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr
  201. list-ref last-pair length append append! reverse reverse!
  202. filter filter! memq memv assq assv set-car! set-cdr!)
  203. :replace (iota map for-each map-in-order list-copy list-index member
  204. delete delete! assoc)
  205. )
  206. (cond-expand-provide (current-module) '(srfi-1))
  207. ;; Load the compiled primitives from the shared library.
  208. ;;
  209. (load-extension (string-append "libguile-" (effective-version))
  210. "scm_init_srfi_1")
  211. ;;; Constructors
  212. (define (xcons d a)
  213. "Like `cons', but with interchanged arguments. Useful mostly when passed to
  214. higher-order procedures."
  215. (cons a d))
  216. ;; internal helper, similar to (scsh utilities) check-arg.
  217. (define (check-arg-type pred arg caller)
  218. (if (pred arg)
  219. arg
  220. (scm-error 'wrong-type-arg caller
  221. "Wrong type argument: ~S" (list arg) '())))
  222. (define (out-of-range proc arg)
  223. (scm-error 'out-of-range proc
  224. "Value out of range: ~A" (list arg) (list arg)))
  225. ;; the srfi spec doesn't seem to forbid inexact integers.
  226. (define (non-negative-integer? x) (and (integer? x) (>= x 0)))
  227. (define (list-tabulate n init-proc)
  228. "Return an N-element list, where each list element is produced by applying the
  229. procedure INIT-PROC to the corresponding list index. The order in which
  230. INIT-PROC is applied to the indices is not specified."
  231. (check-arg-type non-negative-integer? n "list-tabulate")
  232. (let lp ((n n) (acc '()))
  233. (if (<= n 0)
  234. acc
  235. (lp (- n 1) (cons (init-proc (- n 1)) acc)))))
  236. (define (circular-list elt1 . elts)
  237. (set! elts (cons elt1 elts))
  238. (set-cdr! (last-pair elts) elts)
  239. elts)
  240. (define* (iota count #:optional (start 0) (step 1))
  241. (check-arg-type non-negative-integer? count "iota")
  242. (let lp ((n 0) (acc '()))
  243. (if (= n count)
  244. (reverse! acc)
  245. (lp (+ n 1) (cons (+ start (* n step)) acc)))))
  246. ;;; Predicates
  247. (define (proper-list? x)
  248. (list? x))
  249. (define (circular-list? x)
  250. (if (not-pair? x)
  251. #f
  252. (let lp ((hare (cdr x)) (tortoise x))
  253. (if (not-pair? hare)
  254. #f
  255. (let ((hare (cdr hare)))
  256. (if (not-pair? hare)
  257. #f
  258. (if (eq? hare tortoise)
  259. #t
  260. (lp (cdr hare) (cdr tortoise)))))))))
  261. (define (dotted-list? x)
  262. (cond
  263. ((null? x) #f)
  264. ((not-pair? x) #t)
  265. (else
  266. (let lp ((hare (cdr x)) (tortoise x))
  267. (cond
  268. ((null? hare) #f)
  269. ((not-pair? hare) #t)
  270. (else
  271. (let ((hare (cdr hare)))
  272. (cond
  273. ((null? hare) #f)
  274. ((not-pair? hare) #t)
  275. ((eq? hare tortoise) #f)
  276. (else
  277. (lp (cdr hare) (cdr tortoise)))))))))))
  278. (define (null-list? x)
  279. (cond
  280. ((proper-list? x)
  281. (null? x))
  282. ((circular-list? x)
  283. #f)
  284. (else
  285. (error "not a proper list in null-list?"))))
  286. (define (not-pair? x)
  287. "Return #t if X is not a pair, #f otherwise.
  288. This is shorthand notation `(not (pair? X))' and is supposed to be used for
  289. end-of-list checking in contexts where dotted lists are allowed."
  290. (not (pair? x)))
  291. (define (list= elt= . rest)
  292. (define (lists-equal a b)
  293. (let lp ((a a) (b b))
  294. (cond ((null? a)
  295. (null? b))
  296. ((null? b)
  297. #f)
  298. (else
  299. (and (elt= (car a) (car b))
  300. (lp (cdr a) (cdr b)))))))
  301. (or (null? rest)
  302. (let lp ((lists rest))
  303. (or (null? (cdr lists))
  304. (and (lists-equal (car lists) (cadr lists))
  305. (lp (cdr lists)))))))
  306. ;;; Selectors
  307. (define first car)
  308. (define second cadr)
  309. (define third caddr)
  310. (define fourth cadddr)
  311. (define (fifth x) (car (cddddr x)))
  312. (define (sixth x) (cadr (cddddr x)))
  313. (define (seventh x) (caddr (cddddr x)))
  314. (define (eighth x) (cadddr (cddddr x)))
  315. (define (ninth x) (car (cddddr (cddddr x))))
  316. (define (tenth x) (cadr (cddddr (cddddr x))))
  317. (define (car+cdr x)
  318. "Return two values, the `car' and the `cdr' of PAIR."
  319. (values (car x) (cdr x)))
  320. (define take list-head)
  321. (define drop list-tail)
  322. (define (take! lst i)
  323. "Linear-update variant of `take'."
  324. (if (= i 0)
  325. '()
  326. (let ((tail (drop lst (- i 1))))
  327. (set-cdr! tail '())
  328. lst)))
  329. (define (drop-right! lst i)
  330. "Linear-update variant of `drop-right'."
  331. (let ((tail (drop lst i)))
  332. (if (null? tail)
  333. '()
  334. (let loop ((prev lst)
  335. (tail (cdr tail)))
  336. (if (null? tail)
  337. (if (pair? prev)
  338. (begin
  339. (set-cdr! prev '())
  340. lst)
  341. lst)
  342. (loop (cdr prev)
  343. (cdr tail)))))))
  344. (define (split-at lst i)
  345. "Return two values, a list of the elements before index I in LST, and
  346. a list of those after."
  347. (if (< i 0)
  348. (out-of-range 'split-at i)
  349. (let lp ((l lst) (n i) (acc '()))
  350. (if (<= n 0)
  351. (values (reverse! acc) l)
  352. (lp (cdr l) (- n 1) (cons (car l) acc))))))
  353. (define (split-at! lst i)
  354. "Linear-update variant of `split-at'."
  355. (cond ((< i 0)
  356. (out-of-range 'split-at! i))
  357. ((= i 0)
  358. (values '() lst))
  359. (else
  360. (let lp ((l lst) (n (- i 1)))
  361. (if (<= n 0)
  362. (let ((tmp (cdr l)))
  363. (set-cdr! l '())
  364. (values lst tmp))
  365. (lp (cdr l) (- n 1)))))))
  366. (define (last pair)
  367. "Return the last element of the non-empty, finite list PAIR."
  368. (car (last-pair pair)))
  369. ;;; Miscelleneous: length, append, concatenate, reverse, zip & count
  370. (define (zip clist1 . rest)
  371. (let lp ((l (cons clist1 rest)) (acc '()))
  372. (if (any null? l)
  373. (reverse! acc)
  374. (lp (map cdr l) (cons (map car l) acc)))))
  375. (define (unzip1 l)
  376. (map first l))
  377. (define (unzip2 l)
  378. (values (map first l) (map second l)))
  379. (define (unzip3 l)
  380. (values (map first l) (map second l) (map third l)))
  381. (define (unzip4 l)
  382. (values (map first l) (map second l) (map third l) (map fourth l)))
  383. (define (unzip5 l)
  384. (values (map first l) (map second l) (map third l) (map fourth l)
  385. (map fifth l)))
  386. ;;; Fold, unfold & map
  387. (define (fold kons knil list1 . rest)
  388. "Apply PROC to the elements of LIST1 ... LISTN to build a result, and return
  389. that result. See the manual for details."
  390. (if (null? rest)
  391. (let f ((knil knil) (list1 list1))
  392. (if (null? list1)
  393. knil
  394. (f (kons (car list1) knil) (cdr list1))))
  395. (let f ((knil knil) (lists (cons list1 rest)))
  396. (if (any null? lists)
  397. knil
  398. (let ((cars (map car lists))
  399. (cdrs (map cdr lists)))
  400. (f (apply kons (append! cars (list knil))) cdrs))))))
  401. (define (fold-right kons knil clist1 . rest)
  402. (if (null? rest)
  403. (let loop ((lst (reverse clist1))
  404. (result knil))
  405. (if (null? lst)
  406. result
  407. (loop (cdr lst)
  408. (kons (car lst) result))))
  409. (let loop ((lists (map reverse (cons clist1 rest)))
  410. (result knil))
  411. (if (any1 null? lists)
  412. result
  413. (loop (map cdr lists)
  414. (apply kons (append! (map car lists) (list result))))))))
  415. (define (pair-fold kons knil clist1 . rest)
  416. (if (null? rest)
  417. (let f ((knil knil) (list1 clist1))
  418. (if (null? list1)
  419. knil
  420. (let ((tail (cdr list1)))
  421. (f (kons list1 knil) tail))))
  422. (let f ((knil knil) (lists (cons clist1 rest)))
  423. (if (any null? lists)
  424. knil
  425. (let ((tails (map cdr lists)))
  426. (f (apply kons (append! lists (list knil))) tails))))))
  427. (define (pair-fold-right kons knil clist1 . rest)
  428. (if (null? rest)
  429. (let f ((list1 clist1))
  430. (if (null? list1)
  431. knil
  432. (kons list1 (f (cdr list1)))))
  433. (let f ((lists (cons clist1 rest)))
  434. (if (any null? lists)
  435. knil
  436. (apply kons (append! lists (list (f (map cdr lists)))))))))
  437. (define* (unfold p f g seed #:optional (tail-gen (lambda (x) '())))
  438. (define (reverse+tail lst seed)
  439. (let loop ((lst lst)
  440. (result (tail-gen seed)))
  441. (if (null? lst)
  442. result
  443. (loop (cdr lst)
  444. (cons (car lst) result)))))
  445. (let loop ((seed seed)
  446. (result '()))
  447. (if (p seed)
  448. (reverse+tail result seed)
  449. (loop (g seed)
  450. (cons (f seed) result)))))
  451. (define* (unfold-right p f g seed #:optional (tail '()))
  452. (let uf ((seed seed) (lis tail))
  453. (if (p seed)
  454. lis
  455. (uf (g seed) (cons (f seed) lis)))))
  456. (define (reduce f ridentity lst)
  457. "`reduce' is a variant of `fold', where the first call to F is on two
  458. elements from LST, rather than one element and a given initial value.
  459. If LST is empty, RIDENTITY is returned. If LST has just one element
  460. then that's the return value."
  461. (if (null? lst)
  462. ridentity
  463. (fold f (car lst) (cdr lst))))
  464. (define (reduce-right f ridentity lst)
  465. "`reduce-right' is a variant of `fold-right', where the first call to
  466. F is on two elements from LST, rather than one element and a given
  467. initial value. If LST is empty, RIDENTITY is returned. If LST
  468. has just one element then that's the return value."
  469. (if (null? lst)
  470. ridentity
  471. (fold-right f (last lst) (drop-right lst 1))))
  472. (define map
  473. (case-lambda
  474. ((f l)
  475. (let map1 ((hare l) (tortoise l) (move? #f) (out '()))
  476. (if (pair? hare)
  477. (if move?
  478. (if (eq? tortoise hare)
  479. (scm-error 'wrong-type-arg "map" "Circular list: ~S"
  480. (list l) #f)
  481. (map1 (cdr hare) (cdr tortoise) #f
  482. (cons (f (car hare)) out)))
  483. (map1 (cdr hare) tortoise #t
  484. (cons (f (car hare)) out)))
  485. (if (null? hare)
  486. (reverse! out)
  487. (scm-error 'wrong-type-arg "map" "Not a list: ~S"
  488. (list l) #f)))))
  489. ((f l1 . rest)
  490. (let ((len (fold (lambda (ls len)
  491. (let ((ls-len (length+ ls)))
  492. (if len
  493. (if ls-len (min ls-len len) len)
  494. ls-len)))
  495. (length+ l1)
  496. rest)))
  497. (if (not len)
  498. (scm-error 'wrong-type-arg "map"
  499. "Args do not contain a proper (finite) list: ~S"
  500. (list (cons l1 rest)) #f))
  501. (let mapn ((l1 l1) (rest rest) (len len) (out '()))
  502. (if (zero? len)
  503. (reverse! out)
  504. (mapn (cdr l1) (map cdr rest) (1- len)
  505. (cons (apply f (car l1) (map car rest)) out))))))))
  506. (define map-in-order map)
  507. (define for-each
  508. (case-lambda
  509. ((f l)
  510. (let for-each1 ((hare l) (tortoise l) (move? #f))
  511. (if (pair? hare)
  512. (if move?
  513. (if (eq? tortoise hare)
  514. (scm-error 'wrong-type-arg "for-each" "Circular list: ~S"
  515. (list l) #f)
  516. (begin
  517. (f (car hare))
  518. (for-each1 (cdr hare) (cdr tortoise) #f)))
  519. (begin
  520. (f (car hare))
  521. (for-each1 (cdr hare) tortoise #t)))
  522. (if (not (null? hare))
  523. (scm-error 'wrong-type-arg "for-each" "Not a list: ~S"
  524. (list l) #f)))))
  525. ((f l1 . rest)
  526. (let ((len (fold (lambda (ls len)
  527. (let ((ls-len (length+ ls)))
  528. (if len
  529. (if ls-len (min ls-len len) len)
  530. ls-len)))
  531. (length+ l1)
  532. rest)))
  533. (if (not len)
  534. (scm-error 'wrong-type-arg "for-each"
  535. "Args do not contain a proper (finite) list: ~S"
  536. (list (cons l1 rest)) #f))
  537. (let for-eachn ((l1 l1) (rest rest) (len len))
  538. (if (> len 0)
  539. (begin
  540. (apply f (car l1) (map car rest))
  541. (for-eachn (cdr l1) (map cdr rest) (1- len)))))))))
  542. (define (append-map f clist1 . rest)
  543. (concatenate (apply map f clist1 rest)))
  544. (define (append-map! f clist1 . rest)
  545. (concatenate! (apply map f clist1 rest)))
  546. ;; OPTIMIZE-ME: Re-use cons cells of list1
  547. (define map! map)
  548. (define (filter-map proc list1 . rest)
  549. "Apply PROC to to the elements of LIST1... and return a list of the
  550. results as per SRFI-1 `map', except that any #f results are omitted from
  551. the list returned."
  552. (if (null? rest)
  553. (let lp ((l list1)
  554. (rl '()))
  555. (if (null? l)
  556. (reverse! rl)
  557. (let ((res (proc (car l))))
  558. (if res
  559. (lp (cdr l) (cons res rl))
  560. (lp (cdr l) rl)))))
  561. (let lp ((l (cons list1 rest))
  562. (rl '()))
  563. (if (any1 null? l)
  564. (reverse! rl)
  565. (let ((res (apply proc (map car l))))
  566. (if res
  567. (lp (map cdr l) (cons res rl))
  568. (lp (map cdr l) rl)))))))
  569. (define (pair-for-each f clist1 . rest)
  570. (if (null? rest)
  571. (let lp ((l clist1))
  572. (if (null? l)
  573. (if #f #f)
  574. (begin
  575. (f l)
  576. (lp (cdr l)))))
  577. (let lp ((l (cons clist1 rest)))
  578. (if (any1 null? l)
  579. (if #f #f)
  580. (begin
  581. (apply f l)
  582. (lp (map cdr l)))))))
  583. ;;; Searching
  584. (define (take-while pred ls)
  585. "Return a new list which is the longest initial prefix of LS whose
  586. elements all satisfy the predicate PRED."
  587. (cond ((null? ls) '())
  588. ((not (pred (car ls))) '())
  589. (else
  590. (let ((result (list (car ls))))
  591. (let lp ((ls (cdr ls)) (p result))
  592. (cond ((null? ls) result)
  593. ((not (pred (car ls))) result)
  594. (else
  595. (set-cdr! p (list (car ls)))
  596. (lp (cdr ls) (cdr p)))))))))
  597. (define (take-while! pred lst)
  598. "Linear-update variant of `take-while'."
  599. (let loop ((prev #f)
  600. (rest lst))
  601. (cond ((null? rest)
  602. lst)
  603. ((pred (car rest))
  604. (loop rest (cdr rest)))
  605. (else
  606. (if (pair? prev)
  607. (begin
  608. (set-cdr! prev '())
  609. lst)
  610. '())))))
  611. (define (drop-while pred lst)
  612. "Drop the longest initial prefix of LST whose elements all satisfy the
  613. predicate PRED."
  614. (let loop ((lst lst))
  615. (cond ((null? lst)
  616. '())
  617. ((pred (car lst))
  618. (loop (cdr lst)))
  619. (else lst))))
  620. (define (span pred lst)
  621. "Return two values, the longest initial prefix of LST whose elements
  622. all satisfy the predicate PRED, and the remainder of LST."
  623. (let lp ((lst lst) (rl '()))
  624. (if (and (not (null? lst))
  625. (pred (car lst)))
  626. (lp (cdr lst) (cons (car lst) rl))
  627. (values (reverse! rl) lst))))
  628. (define (span! pred list)
  629. "Linear-update variant of `span'."
  630. (let loop ((prev #f)
  631. (rest list))
  632. (cond ((null? rest)
  633. (values list '()))
  634. ((pred (car rest))
  635. (loop rest (cdr rest)))
  636. (else
  637. (if (pair? prev)
  638. (begin
  639. (set-cdr! prev '())
  640. (values list rest))
  641. (values '() list))))))
  642. (define (break pred clist)
  643. "Return two values, the longest initial prefix of LST whose elements
  644. all fail the predicate PRED, and the remainder of LST."
  645. (let lp ((clist clist) (rl '()))
  646. (if (or (null? clist)
  647. (pred (car clist)))
  648. (values (reverse! rl) clist)
  649. (lp (cdr clist) (cons (car clist) rl)))))
  650. (define (break! pred list)
  651. "Linear-update variant of `break'."
  652. (let loop ((l list)
  653. (prev #f))
  654. (cond ((null? l)
  655. (values list '()))
  656. ((pred (car l))
  657. (if (pair? prev)
  658. (begin
  659. (set-cdr! prev '())
  660. (values list l))
  661. (values '() list)))
  662. (else
  663. (loop (cdr l) l)))))
  664. (define (any pred ls . lists)
  665. (if (null? lists)
  666. (any1 pred ls)
  667. (let lp ((lists (cons ls lists)))
  668. (cond ((any1 null? lists)
  669. #f)
  670. ((any1 null? (map cdr lists))
  671. (apply pred (map car lists)))
  672. (else
  673. (or (apply pred (map car lists)) (lp (map cdr lists))))))))
  674. (define (any1 pred ls)
  675. (let lp ((ls ls))
  676. (cond ((null? ls)
  677. #f)
  678. ((null? (cdr ls))
  679. (pred (car ls)))
  680. (else
  681. (or (pred (car ls)) (lp (cdr ls)))))))
  682. (define (every pred ls . lists)
  683. (if (null? lists)
  684. (every1 pred ls)
  685. (let lp ((lists (cons ls lists)))
  686. (cond ((any1 null? lists)
  687. #t)
  688. ((any1 null? (map cdr lists))
  689. (apply pred (map car lists)))
  690. (else
  691. (and (apply pred (map car lists)) (lp (map cdr lists))))))))
  692. (define (every1 pred ls)
  693. (let lp ((ls ls))
  694. (cond ((null? ls)
  695. #t)
  696. ((null? (cdr ls))
  697. (pred (car ls)))
  698. (else
  699. (and (pred (car ls)) (lp (cdr ls)))))))
  700. (define (list-index pred clist1 . rest)
  701. "Return the index of the first set of elements, one from each of
  702. CLIST1 ... CLISTN, that satisfies PRED."
  703. (if (null? rest)
  704. (let lp ((l clist1) (i 0))
  705. (if (null? l)
  706. #f
  707. (if (pred (car l))
  708. i
  709. (lp (cdr l) (+ i 1)))))
  710. (let lp ((lists (cons clist1 rest)) (i 0))
  711. (cond ((any1 null? lists)
  712. #f)
  713. ((apply pred (map car lists)) i)
  714. (else
  715. (lp (map cdr lists) (+ i 1)))))))
  716. ;;; Association lists
  717. (define alist-cons acons)
  718. (define (alist-copy alist)
  719. "Return a copy of ALIST, copying both the pairs comprising the list
  720. and those making the associations."
  721. (let lp ((a alist)
  722. (rl '()))
  723. (if (null? a)
  724. (reverse! rl)
  725. (lp (cdr a) (alist-cons (caar a) (cdar a) rl)))))
  726. (define* (alist-delete key alist #:optional (k= equal?))
  727. (let lp ((a alist) (rl '()))
  728. (if (null? a)
  729. (reverse! rl)
  730. (if (k= key (caar a))
  731. (lp (cdr a) rl)
  732. (lp (cdr a) (cons (car a) rl))))))
  733. (define* (alist-delete! key alist #:optional (k= equal?))
  734. (alist-delete key alist k=)) ; XXX:optimize
  735. ;;; Delete / assoc / member
  736. (define* (member x ls #:optional (= equal?))
  737. (cond
  738. ((eq? = eq?) (memq x ls))
  739. ((eq? = eqv?) (memv x ls))
  740. (else (find-tail (lambda (y) (= x y)) ls))))
  741. ;;; Set operations on lists
  742. (define (lset<= = . rest)
  743. (if (null? rest)
  744. #t
  745. (let lp ((f (car rest)) (r (cdr rest)))
  746. (or (null? r)
  747. (and (every (lambda (el) (member el (car r) =)) f)
  748. (lp (car r) (cdr r)))))))
  749. (define (lset= = . rest)
  750. (if (null? rest)
  751. #t
  752. (let lp ((f (car rest)) (r (cdr rest)))
  753. (or (null? r)
  754. (and (every (lambda (el) (member el (car r) =)) f)
  755. (every (lambda (el) (member el f (lambda (x y) (= y x)))) (car r))
  756. (lp (car r) (cdr r)))))))
  757. ;; It's not quite clear if duplicates among the `rest' elements are meant to
  758. ;; be cast out. The spec says `=' is called as (= lstelem restelem),
  759. ;; suggesting perhaps not, but the reference implementation shows the "list"
  760. ;; at each stage as including those elements already added. The latter
  761. ;; corresponds to what's described for lset-union, so that's what's done.
  762. ;;
  763. (define (lset-adjoin = list . rest)
  764. "Add to LIST any of the elements of REST not already in the list.
  765. These elements are `cons'ed onto the start of LIST (so the return shares
  766. a common tail with LIST), but the order they're added is unspecified.
  767. The given `=' procedure is used for comparing elements, called
  768. as `(@var{=} listelem elem)', i.e., the second argument is one of the
  769. given REST parameters."
  770. ;; If `=' is `eq?' or `eqv?', users won't be able to tell which arg is
  771. ;; first, so we can pass the raw procedure through to `member',
  772. ;; allowing `memq' / `memv' to be selected.
  773. (define pred
  774. (if (or (eq? = eq?) (eq? = eqv?))
  775. =
  776. (lambda (x y) (= y x))))
  777. (let lp ((ans list) (rest rest))
  778. (if (null? rest)
  779. ans
  780. (lp (if (member (car rest) ans pred)
  781. ans
  782. (cons (car rest) ans))
  783. (cdr rest)))))
  784. (define (lset-union = . rest)
  785. ;; Likewise, allow memq / memv to be used if possible.
  786. (define pred
  787. (if (or (eq? = eq?) (eq? = eqv?))
  788. =
  789. (lambda (x y) (= y x))))
  790. (fold (lambda (lis ans) ; Compute ANS + LIS.
  791. (cond ((null? lis) ans) ; Don't copy any lists
  792. ((null? ans) lis) ; if we don't have to.
  793. ((eq? lis ans) ans)
  794. (else
  795. (fold (lambda (elt ans)
  796. (if (member elt ans pred)
  797. ans
  798. (cons elt ans)))
  799. ans lis))))
  800. '()
  801. rest))
  802. (define (lset-intersection = list1 . rest)
  803. (let lp ((l list1) (acc '()))
  804. (if (null? l)
  805. (reverse! acc)
  806. (if (every (lambda (ll) (member (car l) ll =)) rest)
  807. (lp (cdr l) (cons (car l) acc))
  808. (lp (cdr l) acc)))))
  809. (define (lset-difference = list1 . rest)
  810. (if (null? rest)
  811. list1
  812. (let lp ((l list1) (acc '()))
  813. (if (null? l)
  814. (reverse! acc)
  815. (if (any (lambda (ll) (member (car l) ll =)) rest)
  816. (lp (cdr l) acc)
  817. (lp (cdr l) (cons (car l) acc)))))))
  818. ;(define (fold kons knil list1 . rest)
  819. (define (lset-xor = . rest)
  820. (fold (lambda (lst res)
  821. (let lp ((l lst) (acc '()))
  822. (if (null? l)
  823. (let lp0 ((r res) (acc acc))
  824. (if (null? r)
  825. (reverse! acc)
  826. (if (member (car r) lst =)
  827. (lp0 (cdr r) acc)
  828. (lp0 (cdr r) (cons (car r) acc)))))
  829. (if (member (car l) res =)
  830. (lp (cdr l) acc)
  831. (lp (cdr l) (cons (car l) acc))))))
  832. '()
  833. rest))
  834. (define (lset-diff+intersection = list1 . rest)
  835. (let lp ((l list1) (accd '()) (acci '()))
  836. (if (null? l)
  837. (values (reverse! accd) (reverse! acci))
  838. (let ((appears (every (lambda (ll) (member (car l) ll =)) rest)))
  839. (if appears
  840. (lp (cdr l) accd (cons (car l) acci))
  841. (lp (cdr l) (cons (car l) accd) acci))))))
  842. (define (lset-union! = . rest)
  843. (apply lset-union = rest)) ; XXX:optimize
  844. (define (lset-intersection! = list1 . rest)
  845. (apply lset-intersection = list1 rest)) ; XXX:optimize
  846. (define (lset-xor! = . rest)
  847. (apply lset-xor = rest)) ; XXX:optimize
  848. (define (lset-diff+intersection! = list1 . rest)
  849. (apply lset-diff+intersection = list1 rest)) ; XXX:optimize
  850. ;;; srfi-1.scm ends here