list.sls 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. ;;; Copyright © 2016 Federico Beffa <beffa@fbengineering.ch>
  2. ;;;
  3. ;;; This program is free software; you can redistribute it and/or modify it
  4. ;;; under the terms of the GNU General Public License as published by
  5. ;;; the Free Software Foundation; either version 3 of the License, or (at
  6. ;;; your option) any later version.
  7. ;;;
  8. ;;; This program is distributed in the hope that it will be useful, but
  9. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. ;;; GNU General Public License for more details.
  12. ;;;
  13. ;;; You should have received a copy of the GNU General Public License
  14. ;;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. ;;; Code
  16. #!chezscheme
  17. (library (mit list)
  18. (export reduce-left ;fold-left
  19. keyword-list?
  20. get-keyword-value guarantee-alist
  21. alist? list-of-type? guarantee-list-of-type
  22. make-initialized-list delq!
  23. find-matching-item
  24. sublist
  25. guarantee-pair except-last-pair)
  26. (import (except (rnrs) error assert)
  27. (rnrs mutable-pairs)
  28. (only (chezscheme) void list-head)
  29. (only (srfi :1) reduce)
  30. (mit core)
  31. (mit curry)
  32. (mit arithmetic))
  33. (define (reduce-left procedure initial list)
  34. (reduce (lambda (a b) (procedure b a)) initial list))
  35. ;; (define fold-left fold)
  36. (define (keyword-list? object)
  37. (let loop ((l1 object) (l2 object))
  38. (if (pair? l1)
  39. (and (symbol? (car l1))
  40. (pair? (cdr l1))
  41. (not (eq? (cdr l1) l2))
  42. (loop (cdr (cdr l1)) (cdr l1)))
  43. (null? l1))))
  44. (define (get-keyword-value klist key)
  45. (let ((lose (lambda () (error ":not-keyword-list" klist 'GET-KEYWORD-VALUE))))
  46. (let loop ((klist klist))
  47. (if (pair? klist)
  48. (begin
  49. (if (not (pair? (cdr klist)))
  50. (lose))
  51. (if (eq? (car klist) key)
  52. (car (cdr klist))
  53. (loop (cdr (cdr klist)))))
  54. (begin
  55. (if (not (null? klist))
  56. (lose))
  57. (void))))))
  58. (define* (guarantee-alist object #:optional caller)
  59. (if (not (alist? object))
  60. (error "not-alist" object caller)))
  61. (define (alist? object)
  62. (list-of-type? object pair?))
  63. (define (list-of-type? object predicate)
  64. (let loop ((l1 object) (l2 object))
  65. (if (pair? l1)
  66. (and (predicate (car l1))
  67. (let ((l1 (cdr l1)))
  68. (and (not (eq? l1 l2))
  69. (if (pair? l1)
  70. (and (predicate (car l1))
  71. (loop (cdr l1) (cdr l2)))
  72. (null? l1)))))
  73. (null? l1))))
  74. (define* (guarantee-list-of-type object predicate description #:optional caller)
  75. (if (not (list-of-type? object predicate))
  76. (error ":wrong-type-argument" object
  77. description
  78. (if (default-object? caller) #f caller))))
  79. (define (make-initialized-list length initialization)
  80. ;;(guarantee-index-fixnum length 'MAKE-INITIALIZED-LIST)
  81. (let loop ((index (fix:- length 1)) (result '()))
  82. (if (fix:< index 0)
  83. result
  84. (loop (fix:- index 1)
  85. (cons (initialization index) result)))))
  86. (define (%delete! item items = caller)
  87. (letrec
  88. ((trim-initial-segment
  89. (lambda (items)
  90. (if (pair? items)
  91. (if (= item (car items))
  92. (trim-initial-segment (cdr items))
  93. (begin
  94. (locate-initial-segment items (cdr items))
  95. items))
  96. (begin
  97. (if (not (null? items))
  98. (lose))
  99. '()))))
  100. (locate-initial-segment
  101. (lambda (last this)
  102. (if (pair? this)
  103. (if (= item (car this))
  104. (set-cdr! last
  105. (trim-initial-segment (cdr this)))
  106. (locate-initial-segment this (cdr this)))
  107. (if (not (null? this))
  108. (error ":not-list" items caller)))))
  109. (lose
  110. (lambda ()
  111. (error ":not-list" items caller))))
  112. (trim-initial-segment items)))
  113. (define (delq! item items)
  114. (%delete! item items eq? 'DELQ!))
  115. (define (find-matching-item l pred)
  116. (if (null? l)
  117. #f
  118. (if (pred (car l))
  119. (car l)
  120. (find-matching-item (cdr l) pred))))
  121. (define (sublist list start end)
  122. (list-head (list-tail list start) (- end start)))
  123. (define* (guarantee-pair object #:optional caller)
  124. (unless (pair? object)
  125. (error "Not a pair" object caller)))
  126. (define (except-last-pair list)
  127. (guarantee-pair list 'EXCEPT-LAST-PAIR)
  128. (if (not (pair? (cdr list)))
  129. '()
  130. (let ((head (cons (car list) '())))
  131. (let loop ((list (cdr list)) (previous head))
  132. (if (pair? (cdr list))
  133. (let ((new (cons (car list) '())))
  134. (set-cdr! previous new)
  135. (loop (cdr list) new))
  136. head)))))
  137. )