srfi-1.scm 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. ;;; srfi-1.scm --- List Library
  2. ;; Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 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 2.1 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. ;;; Author: Martin Grabmueller <mgrabmue@cs.tu-berlin.de>
  18. ;;; Date: 2001-06-06
  19. ;;; Commentary:
  20. ;; This is an implementation of SRFI-1 (List Library).
  21. ;;
  22. ;; All procedures defined in SRFI-1, which are not already defined in
  23. ;; the Guile core library, are exported. The procedures in this
  24. ;; implementation work, but they have not been tuned for speed or
  25. ;; memory usage.
  26. ;;
  27. ;; This module is fully documented in the Guile Reference Manual.
  28. ;;; Code:
  29. (define-module (srfi srfi-1)
  30. :export (
  31. ;;; Constructors
  32. ;; cons <= in the core
  33. ;; list <= in the core
  34. xcons
  35. ;; cons* <= in the core
  36. ;; make-list <= in the core
  37. list-tabulate
  38. list-copy
  39. circular-list
  40. ;; iota ; Extended.
  41. ;;; Predicates
  42. proper-list?
  43. circular-list?
  44. dotted-list?
  45. ;; pair? <= in the core
  46. ;; null? <= in the core
  47. null-list?
  48. not-pair?
  49. list=
  50. ;;; Selectors
  51. ;; car <= in the core
  52. ;; cdr <= in the core
  53. ;; caar <= in the core
  54. ;; cadr <= in the core
  55. ;; cdar <= in the core
  56. ;; cddr <= in the core
  57. ;; caaar <= in the core
  58. ;; caadr <= in the core
  59. ;; cadar <= in the core
  60. ;; caddr <= in the core
  61. ;; cdaar <= in the core
  62. ;; cdadr <= in the core
  63. ;; cddar <= in the core
  64. ;; cdddr <= in the core
  65. ;; caaaar <= in the core
  66. ;; caaadr <= in the core
  67. ;; caadar <= in the core
  68. ;; caaddr <= in the core
  69. ;; cadaar <= in the core
  70. ;; cadadr <= in the core
  71. ;; caddar <= in the core
  72. ;; cadddr <= in the core
  73. ;; cdaaar <= in the core
  74. ;; cdaadr <= in the core
  75. ;; cdadar <= in the core
  76. ;; cdaddr <= in the core
  77. ;; cddaar <= in the core
  78. ;; cddadr <= in the core
  79. ;; cdddar <= in the core
  80. ;; cddddr <= in the core
  81. ;; list-ref <= in the core
  82. first
  83. second
  84. third
  85. fourth
  86. fifth
  87. sixth
  88. seventh
  89. eighth
  90. ninth
  91. tenth
  92. car+cdr
  93. take
  94. drop
  95. take-right
  96. drop-right
  97. take!
  98. drop-right!
  99. split-at
  100. split-at!
  101. last
  102. ;; last-pair <= in the core
  103. ;;; Miscelleneous: length, append, concatenate, reverse, zip & count
  104. ;; length <= in the core
  105. length+
  106. ;; append <= in the core
  107. ;; append! <= in the core
  108. concatenate
  109. concatenate!
  110. ;; reverse <= in the core
  111. ;; reverse! <= in the core
  112. append-reverse
  113. append-reverse!
  114. zip
  115. unzip1
  116. unzip2
  117. unzip3
  118. unzip4
  119. unzip5
  120. count
  121. ;;; Fold, unfold & map
  122. fold
  123. fold-right
  124. pair-fold
  125. pair-fold-right
  126. reduce
  127. reduce-right
  128. unfold
  129. unfold-right
  130. ;; map ; Extended.
  131. ;; for-each ; Extended.
  132. append-map
  133. append-map!
  134. map!
  135. ;; map-in-order ; Extended.
  136. pair-for-each
  137. filter-map
  138. ;;; Filtering & partitioning
  139. ;; filter <= in the core
  140. partition
  141. remove
  142. ;; filter! <= in the core
  143. partition!
  144. remove!
  145. ;;; Searching
  146. find
  147. find-tail
  148. take-while
  149. take-while!
  150. drop-while
  151. span
  152. span!
  153. break
  154. break!
  155. any
  156. every
  157. ;; list-index ; Extended.
  158. ;; member ; Extended.
  159. ;; memq <= in the core
  160. ;; memv <= in the core
  161. ;;; Deletion
  162. ;; delete ; Extended.
  163. ;; delete! ; Extended.
  164. delete-duplicates
  165. delete-duplicates!
  166. ;;; Association lists
  167. ;; assoc ; Extended.
  168. ;; assq <= in the core
  169. ;; assv <= in the core
  170. alist-cons
  171. alist-copy
  172. alist-delete
  173. alist-delete!
  174. ;;; Set operations on lists
  175. lset<=
  176. lset=
  177. lset-adjoin
  178. lset-union
  179. lset-intersection
  180. lset-difference
  181. lset-xor
  182. lset-diff+intersection
  183. lset-union!
  184. lset-intersection!
  185. lset-difference!
  186. lset-xor!
  187. lset-diff+intersection!
  188. ;;; Primitive side-effects
  189. ;; set-car! <= in the core
  190. ;; set-cdr! <= in the core
  191. )
  192. :re-export (cons list cons* make-list pair? null?
  193. car cdr caar cadr cdar cddr
  194. caaar caadr cadar caddr cdaar cdadr cddar cdddr
  195. caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr
  196. cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr
  197. list-ref last-pair length append append! reverse reverse!
  198. filter filter! memq memv assq assv set-car! set-cdr!)
  199. :replace (iota map for-each map-in-order list-copy list-index member
  200. delete delete! assoc)
  201. )
  202. (cond-expand-provide (current-module) '(srfi-1))
  203. ;; Load the compiled primitives from the shared library.
  204. ;;
  205. (load-extension "libguile-srfi-srfi-1-v-3" "scm_init_srfi_1")
  206. ;;; Constructors
  207. ;; internal helper, similar to (scsh utilities) check-arg.
  208. (define (check-arg-type pred arg caller)
  209. (if (pred arg)
  210. arg
  211. (scm-error 'wrong-type-arg caller
  212. "Wrong type argument: ~S" (list arg) '())))
  213. ;; the srfi spec doesn't seem to forbid inexact integers.
  214. (define (non-negative-integer? x) (and (integer? x) (>= x 0)))
  215. (define (circular-list elt1 . elts)
  216. (set! elts (cons elt1 elts))
  217. (set-cdr! (last-pair elts) elts)
  218. elts)
  219. (define (iota count . rest)
  220. (check-arg-type non-negative-integer? count "iota")
  221. (let ((start (if (pair? rest) (car rest) 0))
  222. (step (if (and (pair? rest) (pair? (cdr rest))) (cadr rest) 1)))
  223. (let lp ((n 0) (acc '()))
  224. (if (= n count)
  225. (reverse! acc)
  226. (lp (+ n 1) (cons (+ start (* n step)) acc))))))
  227. ;;; Predicates
  228. (define (proper-list? x)
  229. (list? x))
  230. (define (circular-list? x)
  231. (if (not-pair? x)
  232. #f
  233. (let lp ((hare (cdr x)) (tortoise x))
  234. (if (not-pair? hare)
  235. #f
  236. (let ((hare (cdr hare)))
  237. (if (not-pair? hare)
  238. #f
  239. (if (eq? hare tortoise)
  240. #t
  241. (lp (cdr hare) (cdr tortoise)))))))))
  242. (define (dotted-list? x)
  243. (cond
  244. ((null? x) #f)
  245. ((not-pair? x) #t)
  246. (else
  247. (let lp ((hare (cdr x)) (tortoise x))
  248. (cond
  249. ((null? hare) #f)
  250. ((not-pair? hare) #t)
  251. (else
  252. (let ((hare (cdr hare)))
  253. (cond
  254. ((null? hare) #f)
  255. ((not-pair? hare) #t)
  256. ((eq? hare tortoise) #f)
  257. (else
  258. (lp (cdr hare) (cdr tortoise)))))))))))
  259. (define (null-list? x)
  260. (cond
  261. ((proper-list? x)
  262. (null? x))
  263. ((circular-list? x)
  264. #f)
  265. (else
  266. (error "not a proper list in null-list?"))))
  267. (define (list= elt= . rest)
  268. (define (lists-equal a b)
  269. (let lp ((a a) (b b))
  270. (cond ((null? a)
  271. (null? b))
  272. ((null? b)
  273. #f)
  274. (else
  275. (and (elt= (car a) (car b))
  276. (lp (cdr a) (cdr b)))))))
  277. (or (null? rest)
  278. (let lp ((lists rest))
  279. (or (null? (cdr lists))
  280. (and (lists-equal (car lists) (cadr lists))
  281. (lp (cdr lists)))))))
  282. ;;; Selectors
  283. (define first car)
  284. (define second cadr)
  285. (define third caddr)
  286. (define fourth cadddr)
  287. (define take list-head)
  288. (define drop list-tail)
  289. ;;; Miscelleneous: length, append, concatenate, reverse, zip & count
  290. (define (zip clist1 . rest)
  291. (let lp ((l (cons clist1 rest)) (acc '()))
  292. (if (any null? l)
  293. (reverse! acc)
  294. (lp (map1 cdr l) (cons (map1 car l) acc)))))
  295. (define (unzip1 l)
  296. (map1 first l))
  297. (define (unzip2 l)
  298. (values (map1 first l) (map1 second l)))
  299. (define (unzip3 l)
  300. (values (map1 first l) (map1 second l) (map1 third l)))
  301. (define (unzip4 l)
  302. (values (map1 first l) (map1 second l) (map1 third l) (map1 fourth l)))
  303. (define (unzip5 l)
  304. (values (map1 first l) (map1 second l) (map1 third l) (map1 fourth l)
  305. (map1 fifth l)))
  306. ;;; Fold, unfold & map
  307. (define (fold-right kons knil clist1 . rest)
  308. (if (null? rest)
  309. (let f ((list1 clist1))
  310. (if (null? list1)
  311. knil
  312. (kons (car list1) (f (cdr list1)))))
  313. (let f ((lists (cons clist1 rest)))
  314. (if (any null? lists)
  315. knil
  316. (apply kons (append! (map1 car lists) (list (f (map1 cdr lists)))))))))
  317. (define (pair-fold kons knil clist1 . rest)
  318. (if (null? rest)
  319. (let f ((knil knil) (list1 clist1))
  320. (if (null? list1)
  321. knil
  322. (let ((tail (cdr list1)))
  323. (f (kons list1 knil) tail))))
  324. (let f ((knil knil) (lists (cons clist1 rest)))
  325. (if (any null? lists)
  326. knil
  327. (let ((tails (map1 cdr lists)))
  328. (f (apply kons (append! lists (list knil))) tails))))))
  329. (define (pair-fold-right kons knil clist1 . rest)
  330. (if (null? rest)
  331. (let f ((list1 clist1))
  332. (if (null? list1)
  333. knil
  334. (kons list1 (f (cdr list1)))))
  335. (let f ((lists (cons clist1 rest)))
  336. (if (any null? lists)
  337. knil
  338. (apply kons (append! lists (list (f (map1 cdr lists)))))))))
  339. (define (unfold p f g seed . rest)
  340. (let ((tail-gen (if (pair? rest)
  341. (if (pair? (cdr rest))
  342. (scm-error 'wrong-number-of-args
  343. "unfold" "too many arguments" '() '())
  344. (car rest))
  345. (lambda (x) '()))))
  346. (let uf ((seed seed))
  347. (if (p seed)
  348. (tail-gen seed)
  349. (cons (f seed)
  350. (uf (g seed)))))))
  351. (define (unfold-right p f g seed . rest)
  352. (let ((tail (if (pair? rest)
  353. (if (pair? (cdr rest))
  354. (scm-error 'wrong-number-of-args
  355. "unfold-right" "too many arguments" '()
  356. '())
  357. (car rest))
  358. '())))
  359. (let uf ((seed seed) (lis tail))
  360. (if (p seed)
  361. lis
  362. (uf (g seed) (cons (f seed) lis))))))
  363. ;; Internal helper procedure. Map `f' over the single list `ls'.
  364. ;;
  365. (define map1 map)
  366. (define (append-map f clist1 . rest)
  367. (concatenate (apply map f clist1 rest)))
  368. (define (append-map! f clist1 . rest)
  369. (concatenate! (apply map f clist1 rest)))
  370. ;; OPTIMIZE-ME: Re-use cons cells of list1
  371. (define map! map)
  372. (define (pair-for-each f clist1 . rest)
  373. (if (null? rest)
  374. (let lp ((l clist1))
  375. (if (null? l)
  376. (if #f #f)
  377. (begin
  378. (f l)
  379. (lp (cdr l)))))
  380. (let lp ((l (cons clist1 rest)))
  381. (if (any1 null? l)
  382. (if #f #f)
  383. (begin
  384. (apply f l)
  385. (lp (map1 cdr l)))))))
  386. ;;; Searching
  387. (define (any pred ls . lists)
  388. (if (null? lists)
  389. (any1 pred ls)
  390. (let lp ((lists (cons ls lists)))
  391. (cond ((any1 null? lists)
  392. #f)
  393. ((any1 null? (map1 cdr lists))
  394. (apply pred (map1 car lists)))
  395. (else
  396. (or (apply pred (map1 car lists)) (lp (map1 cdr lists))))))))
  397. (define (any1 pred ls)
  398. (let lp ((ls ls))
  399. (cond ((null? ls)
  400. #f)
  401. ((null? (cdr ls))
  402. (pred (car ls)))
  403. (else
  404. (or (pred (car ls)) (lp (cdr ls)))))))
  405. (define (every pred ls . lists)
  406. (if (null? lists)
  407. (every1 pred ls)
  408. (let lp ((lists (cons ls lists)))
  409. (cond ((any1 null? lists)
  410. #t)
  411. ((any1 null? (map1 cdr lists))
  412. (apply pred (map1 car lists)))
  413. (else
  414. (and (apply pred (map1 car lists)) (lp (map1 cdr lists))))))))
  415. (define (every1 pred ls)
  416. (let lp ((ls ls))
  417. (cond ((null? ls)
  418. #t)
  419. ((null? (cdr ls))
  420. (pred (car ls)))
  421. (else
  422. (and (pred (car ls)) (lp (cdr ls)))))))
  423. ;;; Association lists
  424. (define alist-cons acons)
  425. (define (alist-delete key alist . rest)
  426. (let ((k= (if (pair? rest) (car rest) equal?)))
  427. (let lp ((a alist) (rl '()))
  428. (if (null? a)
  429. (reverse! rl)
  430. (if (k= key (caar a))
  431. (lp (cdr a) rl)
  432. (lp (cdr a) (cons (car a) rl)))))))
  433. (define (alist-delete! key alist . rest)
  434. (let ((k= (if (pair? rest) (car rest) equal?)))
  435. (alist-delete key alist k=))) ; XXX:optimize
  436. ;;; Set operations on lists
  437. (define (lset<= = . rest)
  438. (if (null? rest)
  439. #t
  440. (let lp ((f (car rest)) (r (cdr rest)))
  441. (or (null? r)
  442. (and (every (lambda (el) (member el (car r) =)) f)
  443. (lp (car r) (cdr r)))))))
  444. (define (lset= = . rest)
  445. (if (null? rest)
  446. #t
  447. (let lp ((f (car rest)) (r (cdr rest)))
  448. (or (null? r)
  449. (and (every (lambda (el) (member el (car r) =)) f)
  450. (every (lambda (el) (member el f (lambda (x y) (= y x)))) (car r))
  451. (lp (car r) (cdr r)))))))
  452. (define (lset-union = . rest)
  453. (let ((acc '()))
  454. (for-each (lambda (lst)
  455. (if (null? acc)
  456. (set! acc lst)
  457. (for-each (lambda (elem)
  458. (if (not (member elem acc
  459. (lambda (x y) (= y x))))
  460. (set! acc (cons elem acc))))
  461. lst)))
  462. rest)
  463. acc))
  464. (define (lset-intersection = list1 . rest)
  465. (let lp ((l list1) (acc '()))
  466. (if (null? l)
  467. (reverse! acc)
  468. (if (every (lambda (ll) (member (car l) ll =)) rest)
  469. (lp (cdr l) (cons (car l) acc))
  470. (lp (cdr l) acc)))))
  471. (define (lset-difference = list1 . rest)
  472. (if (null? rest)
  473. list1
  474. (let lp ((l list1) (acc '()))
  475. (if (null? l)
  476. (reverse! acc)
  477. (if (any (lambda (ll) (member (car l) ll =)) rest)
  478. (lp (cdr l) acc)
  479. (lp (cdr l) (cons (car l) acc)))))))
  480. ;(define (fold kons knil list1 . rest)
  481. (define (lset-xor = . rest)
  482. (fold (lambda (lst res)
  483. (let lp ((l lst) (acc '()))
  484. (if (null? l)
  485. (let lp0 ((r res) (acc acc))
  486. (if (null? r)
  487. (reverse! acc)
  488. (if (member (car r) lst =)
  489. (lp0 (cdr r) acc)
  490. (lp0 (cdr r) (cons (car r) acc)))))
  491. (if (member (car l) res =)
  492. (lp (cdr l) acc)
  493. (lp (cdr l) (cons (car l) acc))))))
  494. '()
  495. rest))
  496. (define (lset-diff+intersection = list1 . rest)
  497. (let lp ((l list1) (accd '()) (acci '()))
  498. (if (null? l)
  499. (values (reverse! accd) (reverse! acci))
  500. (let ((appears (every (lambda (ll) (member (car l) ll =)) rest)))
  501. (if appears
  502. (lp (cdr l) accd (cons (car l) acci))
  503. (lp (cdr l) (cons (car l) accd) acci))))))
  504. (define (lset-union! = . rest)
  505. (apply lset-union = rest)) ; XXX:optimize
  506. (define (lset-intersection! = list1 . rest)
  507. (apply lset-intersection = list1 rest)) ; XXX:optimize
  508. (define (lset-xor! = . rest)
  509. (apply lset-xor = rest)) ; XXX:optimize
  510. (define (lset-diff+intersection! = list1 . rest)
  511. (apply lset-diff+intersection = list1 rest)) ; XXX:optimize
  512. ;;; srfi-1.scm ends here