srfi-1.scm 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  1. ;;; srfi-1.scm --- List Library
  2. ;; Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010, 2011, 2014 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. (define (wrong-type-arg caller arg)
  217. (scm-error 'wrong-type-arg (symbol->string caller)
  218. "Wrong type argument: ~S" (list arg) '()))
  219. (define-syntax-rule (check-arg pred arg caller)
  220. (if (not (pred arg))
  221. (wrong-type-arg 'caller 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 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 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. (check-arg procedure? elt= list=)
  302. (or (null? rest)
  303. (let lp ((lists rest))
  304. (or (null? (cdr lists))
  305. (and (lists-equal (car lists) (cadr lists))
  306. (lp (cdr lists)))))))
  307. ;;; Selectors
  308. (define first car)
  309. (define second cadr)
  310. (define third caddr)
  311. (define fourth cadddr)
  312. (define (fifth x) (car (cddddr x)))
  313. (define (sixth x) (cadr (cddddr x)))
  314. (define (seventh x) (caddr (cddddr x)))
  315. (define (eighth x) (cadddr (cddddr x)))
  316. (define (ninth x) (car (cddddr (cddddr x))))
  317. (define (tenth x) (cadr (cddddr (cddddr x))))
  318. (define (car+cdr x)
  319. "Return two values, the `car' and the `cdr' of PAIR."
  320. (values (car x) (cdr x)))
  321. (define take list-head)
  322. (define drop list-tail)
  323. ;;; TAKE-RIGHT and DROP-RIGHT work by getting two pointers into the list,
  324. ;;; off by K, then chasing down the list until the lead pointer falls off
  325. ;;; the end. Note that they diverge for circular lists.
  326. (define (take-right lis k)
  327. (let lp ((lag lis) (lead (drop lis k)))
  328. (if (pair? lead)
  329. (lp (cdr lag) (cdr lead))
  330. lag)))
  331. (define (drop-right lis k)
  332. (let recur ((lag lis) (lead (drop lis k)))
  333. (if (pair? lead)
  334. (cons (car lag) (recur (cdr lag) (cdr lead)))
  335. '())))
  336. (define (take! lst i)
  337. "Linear-update variant of `take'."
  338. (if (= i 0)
  339. '()
  340. (let ((tail (drop lst (- i 1))))
  341. (set-cdr! tail '())
  342. lst)))
  343. (define (drop-right! lst i)
  344. "Linear-update variant of `drop-right'."
  345. (let ((tail (drop lst i)))
  346. (if (null? tail)
  347. '()
  348. (let loop ((prev lst)
  349. (tail (cdr tail)))
  350. (if (null? tail)
  351. (if (pair? prev)
  352. (begin
  353. (set-cdr! prev '())
  354. lst)
  355. lst)
  356. (loop (cdr prev)
  357. (cdr tail)))))))
  358. (define (split-at lst i)
  359. "Return two values, a list of the elements before index I in LST, and
  360. a list of those after."
  361. (if (< i 0)
  362. (out-of-range 'split-at i)
  363. (let lp ((l lst) (n i) (acc '()))
  364. (if (<= n 0)
  365. (values (reverse! acc) l)
  366. (lp (cdr l) (- n 1) (cons (car l) acc))))))
  367. (define (split-at! lst i)
  368. "Linear-update variant of `split-at'."
  369. (cond ((< i 0)
  370. (out-of-range 'split-at! i))
  371. ((= i 0)
  372. (values '() lst))
  373. (else
  374. (let lp ((l lst) (n (- i 1)))
  375. (if (<= n 0)
  376. (let ((tmp (cdr l)))
  377. (set-cdr! l '())
  378. (values lst tmp))
  379. (lp (cdr l) (- n 1)))))))
  380. (define (last pair)
  381. "Return the last element of the non-empty, finite list PAIR."
  382. (car (last-pair pair)))
  383. ;;; Miscelleneous: length, append, concatenate, reverse, zip & count
  384. (define (zip clist1 . rest)
  385. (let lp ((l (cons clist1 rest)) (acc '()))
  386. (if (any null? l)
  387. (reverse! acc)
  388. (lp (map cdr l) (cons (map car l) acc)))))
  389. (define (unzip1 l)
  390. (map first l))
  391. (define (unzip2 l)
  392. (values (map first l) (map second l)))
  393. (define (unzip3 l)
  394. (values (map first l) (map second l) (map third l)))
  395. (define (unzip4 l)
  396. (values (map first l) (map second l) (map third l) (map fourth l)))
  397. (define (unzip5 l)
  398. (values (map first l) (map second l) (map third l) (map fourth l)
  399. (map fifth l)))
  400. ;;; Fold, unfold & map
  401. (define fold
  402. (case-lambda
  403. "Apply PROC to the elements of LIST1 ... LISTN to build a result, and return
  404. that result. See the manual for details."
  405. ((kons knil list1)
  406. (check-arg procedure? kons fold)
  407. (check-arg list? list1 fold)
  408. (let fold1 ((knil knil) (list1 list1))
  409. (if (pair? list1)
  410. (fold1 (kons (car list1) knil) (cdr list1))
  411. knil)))
  412. ((kons knil list1 list2)
  413. (check-arg procedure? kons fold)
  414. (let* ((len1 (length+ list1))
  415. (len2 (length+ list2))
  416. (len (if (and len1 len2)
  417. (min len1 len2)
  418. (or len1 len2))))
  419. (unless len
  420. (scm-error 'wrong-type-arg "fold"
  421. "Args do not contain a proper (finite) list: ~S"
  422. (list (list list1 list2)) #f))
  423. (let fold2 ((knil knil) (list1 list1) (list2 list2) (len len))
  424. (if (zero? len)
  425. knil
  426. (fold2 (kons (car list1) (car list2) knil)
  427. (cdr list1) (cdr list2) (1- len))))))
  428. ((kons knil list1 . rest)
  429. (check-arg procedure? kons fold)
  430. (let foldn ((knil knil) (lists (cons list1 rest)))
  431. (if (any null? lists)
  432. knil
  433. (let ((cars (map car lists))
  434. (cdrs (map cdr lists)))
  435. (foldn (apply kons (append! cars (list knil))) cdrs)))))))
  436. (define (fold-right kons knil clist1 . rest)
  437. (check-arg procedure? kons fold-right)
  438. (if (null? rest)
  439. (let loop ((lst (reverse clist1))
  440. (result knil))
  441. (if (null? lst)
  442. result
  443. (loop (cdr lst)
  444. (kons (car lst) result))))
  445. (let loop ((lists (map reverse (cons clist1 rest)))
  446. (result knil))
  447. (if (any1 null? lists)
  448. result
  449. (loop (map cdr lists)
  450. (apply kons (append! (map car lists) (list result))))))))
  451. (define (pair-fold kons knil clist1 . rest)
  452. (check-arg procedure? kons pair-fold)
  453. (if (null? rest)
  454. (let f ((knil knil) (list1 clist1))
  455. (if (null? list1)
  456. knil
  457. (let ((tail (cdr list1)))
  458. (f (kons list1 knil) tail))))
  459. (let f ((knil knil) (lists (cons clist1 rest)))
  460. (if (any null? lists)
  461. knil
  462. (let ((tails (map cdr lists)))
  463. (f (apply kons (append! lists (list knil))) tails))))))
  464. (define (pair-fold-right kons knil clist1 . rest)
  465. (check-arg procedure? kons pair-fold-right)
  466. (if (null? rest)
  467. (let f ((list1 clist1))
  468. (if (null? list1)
  469. knil
  470. (kons list1 (f (cdr list1)))))
  471. (let f ((lists (cons clist1 rest)))
  472. (if (any null? lists)
  473. knil
  474. (apply kons (append! lists (list (f (map cdr lists)))))))))
  475. (define* (unfold p f g seed #:optional (tail-gen (lambda (x) '())))
  476. (define (reverse+tail lst seed)
  477. (let loop ((lst lst)
  478. (result (tail-gen seed)))
  479. (if (null? lst)
  480. result
  481. (loop (cdr lst)
  482. (cons (car lst) result)))))
  483. (check-arg procedure? p unfold)
  484. (check-arg procedure? f unfold)
  485. (check-arg procedure? g unfold)
  486. (check-arg procedure? tail-gen unfold)
  487. (let loop ((seed seed)
  488. (result '()))
  489. (if (p seed)
  490. (reverse+tail result seed)
  491. (loop (g seed)
  492. (cons (f seed) result)))))
  493. (define* (unfold-right p f g seed #:optional (tail '()))
  494. (check-arg procedure? p unfold-right)
  495. (check-arg procedure? f unfold-right)
  496. (check-arg procedure? g unfold-right)
  497. (let uf ((seed seed) (lis tail))
  498. (if (p seed)
  499. lis
  500. (uf (g seed) (cons (f seed) lis)))))
  501. (define (reduce f ridentity lst)
  502. "`reduce' is a variant of `fold', where the first call to F is on two
  503. elements from LST, rather than one element and a given initial value.
  504. If LST is empty, RIDENTITY is returned. If LST has just one element
  505. then that's the return value."
  506. (check-arg procedure? f reduce)
  507. (if (null? lst)
  508. ridentity
  509. (fold f (car lst) (cdr lst))))
  510. (define (reduce-right f ridentity lst)
  511. "`reduce-right' is a variant of `fold-right', where the first call to
  512. F is on two elements from LST, rather than one element and a given
  513. initial value. If LST is empty, RIDENTITY is returned. If LST
  514. has just one element then that's the return value."
  515. (check-arg procedure? f reduce)
  516. (if (null? lst)
  517. ridentity
  518. (fold-right f (last lst) (drop-right lst 1))))
  519. (define map
  520. (case-lambda
  521. ((f l)
  522. (check-arg procedure? f map)
  523. (check-arg list? l map)
  524. (let map1 ((l l))
  525. (if (pair? l)
  526. (cons (f (car l)) (map1 (cdr l)))
  527. '())))
  528. ((f l1 l2)
  529. (check-arg procedure? f map)
  530. (let* ((len1 (length+ l1))
  531. (len2 (length+ l2))
  532. (len (if (and len1 len2)
  533. (min len1 len2)
  534. (or len1 len2))))
  535. (unless len
  536. (scm-error 'wrong-type-arg "map"
  537. "Args do not contain a proper (finite) list: ~S"
  538. (list (list l1 l2)) #f))
  539. (let map2 ((l1 l1) (l2 l2) (len len))
  540. (if (zero? len)
  541. '()
  542. (cons (f (car l1) (car l2))
  543. (map2 (cdr l1) (cdr l2) (1- len)))))))
  544. ((f l1 . rest)
  545. (check-arg procedure? f map)
  546. (let ((len (fold (lambda (ls len)
  547. (let ((ls-len (length+ ls)))
  548. (if len
  549. (if ls-len (min ls-len len) len)
  550. ls-len)))
  551. (length+ l1)
  552. rest)))
  553. (if (not len)
  554. (scm-error 'wrong-type-arg "map"
  555. "Args do not contain a proper (finite) list: ~S"
  556. (list (cons l1 rest)) #f))
  557. (let mapn ((l1 l1) (rest rest) (len len))
  558. (if (zero? len)
  559. '()
  560. (cons (apply f (car l1) (map car rest))
  561. (mapn (cdr l1) (map cdr rest) (1- len)))))))))
  562. (define map-in-order map)
  563. (define for-each
  564. (case-lambda
  565. ((f l)
  566. (check-arg procedure? f for-each)
  567. (check-arg list? l for-each)
  568. (let for-each1 ((l l))
  569. (unless (null? l)
  570. (f (car l))
  571. (for-each1 (cdr l)))))
  572. ((f l1 l2)
  573. (check-arg procedure? f for-each)
  574. (let* ((len1 (length+ l1))
  575. (len2 (length+ l2))
  576. (len (if (and len1 len2)
  577. (min len1 len2)
  578. (or len1 len2))))
  579. (unless len
  580. (scm-error 'wrong-type-arg "for-each"
  581. "Args do not contain a proper (finite) list: ~S"
  582. (list (list l1 l2)) #f))
  583. (let for-each2 ((l1 l1) (l2 l2) (len len))
  584. (unless (zero? len)
  585. (f (car l1) (car l2))
  586. (for-each2 (cdr l1) (cdr l2) (1- len))))))
  587. ((f l1 . rest)
  588. (check-arg procedure? f for-each)
  589. (let ((len (fold (lambda (ls len)
  590. (let ((ls-len (length+ ls)))
  591. (if len
  592. (if ls-len (min ls-len len) len)
  593. ls-len)))
  594. (length+ l1)
  595. rest)))
  596. (if (not len)
  597. (scm-error 'wrong-type-arg "for-each"
  598. "Args do not contain a proper (finite) list: ~S"
  599. (list (cons l1 rest)) #f))
  600. (let for-eachn ((l1 l1) (rest rest) (len len))
  601. (if (> len 0)
  602. (begin
  603. (apply f (car l1) (map car rest))
  604. (for-eachn (cdr l1) (map cdr rest) (1- len)))))))))
  605. (define (append-map f clist1 . rest)
  606. (concatenate (apply map f clist1 rest)))
  607. (define (append-map! f clist1 . rest)
  608. (concatenate! (apply map f clist1 rest)))
  609. ;; OPTIMIZE-ME: Re-use cons cells of list1
  610. (define map! map)
  611. (define (filter-map proc list1 . rest)
  612. "Apply PROC to the elements of LIST1... and return a list of the
  613. results as per SRFI-1 `map', except that any #f results are omitted from
  614. the list returned."
  615. (check-arg procedure? proc filter-map)
  616. (if (null? rest)
  617. (let lp ((l list1)
  618. (rl '()))
  619. (if (null? l)
  620. (reverse! rl)
  621. (let ((res (proc (car l))))
  622. (if res
  623. (lp (cdr l) (cons res rl))
  624. (lp (cdr l) rl)))))
  625. (let lp ((l (cons list1 rest))
  626. (rl '()))
  627. (if (any1 null? l)
  628. (reverse! rl)
  629. (let ((res (apply proc (map car l))))
  630. (if res
  631. (lp (map cdr l) (cons res rl))
  632. (lp (map cdr l) rl)))))))
  633. (define (pair-for-each f clist1 . rest)
  634. (check-arg procedure? f pair-for-each)
  635. (if (null? rest)
  636. (let lp ((l clist1))
  637. (if (null? l)
  638. (if #f #f)
  639. (begin
  640. (f l)
  641. (lp (cdr l)))))
  642. (let lp ((l (cons clist1 rest)))
  643. (if (any1 null? l)
  644. (if #f #f)
  645. (begin
  646. (apply f l)
  647. (lp (map cdr l)))))))
  648. ;;; Searching
  649. (define (take-while pred ls)
  650. "Return a new list which is the longest initial prefix of LS whose
  651. elements all satisfy the predicate PRED."
  652. (check-arg procedure? pred take-while)
  653. (cond ((null? ls) '())
  654. ((not (pred (car ls))) '())
  655. (else
  656. (let ((result (list (car ls))))
  657. (let lp ((ls (cdr ls)) (p result))
  658. (cond ((null? ls) result)
  659. ((not (pred (car ls))) result)
  660. (else
  661. (set-cdr! p (list (car ls)))
  662. (lp (cdr ls) (cdr p)))))))))
  663. (define (take-while! pred lst)
  664. "Linear-update variant of `take-while'."
  665. (check-arg procedure? pred take-while!)
  666. (let loop ((prev #f)
  667. (rest lst))
  668. (cond ((null? rest)
  669. lst)
  670. ((pred (car rest))
  671. (loop rest (cdr rest)))
  672. (else
  673. (if (pair? prev)
  674. (begin
  675. (set-cdr! prev '())
  676. lst)
  677. '())))))
  678. (define (drop-while pred lst)
  679. "Drop the longest initial prefix of LST whose elements all satisfy the
  680. predicate PRED."
  681. (check-arg procedure? pred drop-while)
  682. (let loop ((lst lst))
  683. (cond ((null? lst)
  684. '())
  685. ((pred (car lst))
  686. (loop (cdr lst)))
  687. (else lst))))
  688. (define (span pred lst)
  689. "Return two values, the longest initial prefix of LST whose elements
  690. all satisfy the predicate PRED, and the remainder of LST."
  691. (check-arg procedure? pred span)
  692. (let lp ((lst lst) (rl '()))
  693. (if (and (not (null? lst))
  694. (pred (car lst)))
  695. (lp (cdr lst) (cons (car lst) rl))
  696. (values (reverse! rl) lst))))
  697. (define (span! pred list)
  698. "Linear-update variant of `span'."
  699. (check-arg procedure? pred span!)
  700. (let loop ((prev #f)
  701. (rest list))
  702. (cond ((null? rest)
  703. (values list '()))
  704. ((pred (car rest))
  705. (loop rest (cdr rest)))
  706. (else
  707. (if (pair? prev)
  708. (begin
  709. (set-cdr! prev '())
  710. (values list rest))
  711. (values '() list))))))
  712. (define (break pred clist)
  713. "Return two values, the longest initial prefix of LST whose elements
  714. all fail the predicate PRED, and the remainder of LST."
  715. (check-arg procedure? pred break)
  716. (let lp ((clist clist) (rl '()))
  717. (if (or (null? clist)
  718. (pred (car clist)))
  719. (values (reverse! rl) clist)
  720. (lp (cdr clist) (cons (car clist) rl)))))
  721. (define (break! pred list)
  722. "Linear-update variant of `break'."
  723. (check-arg procedure? pred break!)
  724. (let loop ((l list)
  725. (prev #f))
  726. (cond ((null? l)
  727. (values list '()))
  728. ((pred (car l))
  729. (if (pair? prev)
  730. (begin
  731. (set-cdr! prev '())
  732. (values list l))
  733. (values '() list)))
  734. (else
  735. (loop (cdr l) l)))))
  736. (define (any pred ls . lists)
  737. (check-arg procedure? pred any)
  738. (if (null? lists)
  739. (any1 pred ls)
  740. (let lp ((lists (cons ls lists)))
  741. (cond ((any1 null? lists)
  742. #f)
  743. ((any1 null? (map cdr lists))
  744. (apply pred (map car lists)))
  745. (else
  746. (or (apply pred (map car lists)) (lp (map cdr lists))))))))
  747. (define (any1 pred ls)
  748. (let lp ((ls ls))
  749. (cond ((null? ls)
  750. #f)
  751. ((null? (cdr ls))
  752. (pred (car ls)))
  753. (else
  754. (or (pred (car ls)) (lp (cdr ls)))))))
  755. (define (every pred ls . lists)
  756. (check-arg procedure? pred every)
  757. (if (null? lists)
  758. (every1 pred ls)
  759. (let lp ((lists (cons ls lists)))
  760. (cond ((any1 null? lists)
  761. #t)
  762. ((any1 null? (map cdr lists))
  763. (apply pred (map car lists)))
  764. (else
  765. (and (apply pred (map car lists)) (lp (map cdr lists))))))))
  766. (define (every1 pred ls)
  767. (let lp ((ls ls))
  768. (cond ((null? ls)
  769. #t)
  770. ((null? (cdr ls))
  771. (pred (car ls)))
  772. (else
  773. (and (pred (car ls)) (lp (cdr ls)))))))
  774. (define (list-index pred clist1 . rest)
  775. "Return the index of the first set of elements, one from each of
  776. CLIST1 ... CLISTN, that satisfies PRED."
  777. (check-arg procedure? pred list-index)
  778. (if (null? rest)
  779. (let lp ((l clist1) (i 0))
  780. (if (null? l)
  781. #f
  782. (if (pred (car l))
  783. i
  784. (lp (cdr l) (+ i 1)))))
  785. (let lp ((lists (cons clist1 rest)) (i 0))
  786. (cond ((any1 null? lists)
  787. #f)
  788. ((apply pred (map car lists)) i)
  789. (else
  790. (lp (map cdr lists) (+ i 1)))))))
  791. ;;; Association lists
  792. (define alist-cons acons)
  793. (define (alist-copy alist)
  794. "Return a copy of ALIST, copying both the pairs comprising the list
  795. and those making the associations."
  796. (let lp ((a alist)
  797. (rl '()))
  798. (if (null? a)
  799. (reverse! rl)
  800. (lp (cdr a) (alist-cons (caar a) (cdar a) rl)))))
  801. (define* (alist-delete key alist #:optional (k= equal?))
  802. (check-arg procedure? k= alist-delete)
  803. (let lp ((a alist) (rl '()))
  804. (if (null? a)
  805. (reverse! rl)
  806. (if (k= key (caar a))
  807. (lp (cdr a) rl)
  808. (lp (cdr a) (cons (car a) rl))))))
  809. (define* (alist-delete! key alist #:optional (k= equal?))
  810. (alist-delete key alist k=)) ; XXX:optimize
  811. ;;; Delete / assoc / member
  812. (define* (member x ls #:optional (= equal?))
  813. (cond
  814. ;; This might be performance-sensitive, so punt on the check here,
  815. ;; relying on memq/memv to check that = is a procedure.
  816. ((eq? = eq?) (memq x ls))
  817. ((eq? = eqv?) (memv x ls))
  818. (else
  819. (check-arg procedure? = member)
  820. (find-tail (lambda (y) (= x y)) ls))))
  821. ;;; Set operations on lists
  822. (define (lset<= = . rest)
  823. (check-arg procedure? = lset<=)
  824. (if (null? rest)
  825. #t
  826. (let lp ((f (car rest)) (r (cdr rest)))
  827. (or (null? r)
  828. (and (every (lambda (el) (member el (car r) =)) f)
  829. (lp (car r) (cdr r)))))))
  830. (define (lset= = . rest)
  831. (check-arg procedure? = lset<=)
  832. (if (null? rest)
  833. #t
  834. (let lp ((f (car rest)) (r (cdr rest)))
  835. (or (null? r)
  836. (and (every (lambda (el) (member el (car r) =)) f)
  837. (every (lambda (el) (member el f (lambda (x y) (= y x)))) (car r))
  838. (lp (car r) (cdr r)))))))
  839. ;; It's not quite clear if duplicates among the `rest' elements are meant to
  840. ;; be cast out. The spec says `=' is called as (= lstelem restelem),
  841. ;; suggesting perhaps not, but the reference implementation shows the "list"
  842. ;; at each stage as including those elements already added. The latter
  843. ;; corresponds to what's described for lset-union, so that's what's done.
  844. ;;
  845. (define (lset-adjoin = list . rest)
  846. "Add to LIST any of the elements of REST not already in the list.
  847. These elements are `cons'ed onto the start of LIST (so the return shares
  848. a common tail with LIST), but the order they're added is unspecified.
  849. The given `=' procedure is used for comparing elements, called
  850. as `(@var{=} listelem elem)', i.e., the second argument is one of the
  851. given REST parameters."
  852. ;; If `=' is `eq?' or `eqv?', users won't be able to tell which arg is
  853. ;; first, so we can pass the raw procedure through to `member',
  854. ;; allowing `memq' / `memv' to be selected.
  855. (define pred
  856. (if (or (eq? = eq?) (eq? = eqv?))
  857. =
  858. (begin
  859. (check-arg procedure? = lset-adjoin)
  860. (lambda (x y) (= y x)))))
  861. (let lp ((ans list) (rest rest))
  862. (if (null? rest)
  863. ans
  864. (lp (if (member (car rest) ans pred)
  865. ans
  866. (cons (car rest) ans))
  867. (cdr rest)))))
  868. (define (lset-union = . rest)
  869. ;; Likewise, allow memq / memv to be used if possible.
  870. (define pred
  871. (if (or (eq? = eq?) (eq? = eqv?))
  872. =
  873. (begin
  874. (check-arg procedure? = lset-union)
  875. (lambda (x y) (= y x)))))
  876. (fold (lambda (lis ans) ; Compute ANS + LIS.
  877. (cond ((null? lis) ans) ; Don't copy any lists
  878. ((null? ans) lis) ; if we don't have to.
  879. ((eq? lis ans) ans)
  880. (else
  881. (fold (lambda (elt ans)
  882. (if (member elt ans pred)
  883. ans
  884. (cons elt ans)))
  885. ans lis))))
  886. '()
  887. rest))
  888. (define (lset-intersection = list1 . rest)
  889. (check-arg procedure? = lset-intersection)
  890. (let lp ((l list1) (acc '()))
  891. (if (null? l)
  892. (reverse! acc)
  893. (if (every (lambda (ll) (member (car l) ll =)) rest)
  894. (lp (cdr l) (cons (car l) acc))
  895. (lp (cdr l) acc)))))
  896. (define (lset-difference = list1 . rest)
  897. (check-arg procedure? = lset-difference)
  898. (if (null? rest)
  899. list1
  900. (let lp ((l list1) (acc '()))
  901. (if (null? l)
  902. (reverse! acc)
  903. (if (any (lambda (ll) (member (car l) ll =)) rest)
  904. (lp (cdr l) acc)
  905. (lp (cdr l) (cons (car l) acc)))))))
  906. ;(define (fold kons knil list1 . rest)
  907. (define (lset-xor = . rest)
  908. (check-arg procedure? = lset-xor)
  909. (fold (lambda (lst res)
  910. (let lp ((l lst) (acc '()))
  911. (if (null? l)
  912. (let lp0 ((r res) (acc acc))
  913. (if (null? r)
  914. (reverse! acc)
  915. (if (member (car r) lst =)
  916. (lp0 (cdr r) acc)
  917. (lp0 (cdr r) (cons (car r) acc)))))
  918. (if (member (car l) res =)
  919. (lp (cdr l) acc)
  920. (lp (cdr l) (cons (car l) acc))))))
  921. '()
  922. rest))
  923. (define (lset-diff+intersection = list1 . rest)
  924. (check-arg procedure? = lset-diff+intersection)
  925. (let lp ((l list1) (accd '()) (acci '()))
  926. (if (null? l)
  927. (values (reverse! accd) (reverse! acci))
  928. (let ((appears (every (lambda (ll) (member (car l) ll =)) rest)))
  929. (if appears
  930. (lp (cdr l) accd (cons (car l) acci))
  931. (lp (cdr l) (cons (car l) accd) acci))))))
  932. (define (lset-union! = . rest)
  933. (check-arg procedure? = lset-union!)
  934. (apply lset-union = rest)) ; XXX:optimize
  935. (define (lset-intersection! = list1 . rest)
  936. (check-arg procedure? = lset-intersection!)
  937. (apply lset-intersection = list1 rest)) ; XXX:optimize
  938. (define (lset-xor! = . rest)
  939. (check-arg procedure? = lset-xor!)
  940. (apply lset-xor = rest)) ; XXX:optimize
  941. (define (lset-diff+intersection! = list1 . rest)
  942. (check-arg procedure? = lset-diff+intersection!)
  943. (apply lset-diff+intersection = list1 rest)) ; XXX:optimize
  944. ;;; srfi-1.scm ends here