lists.scm 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. ;;; Lists
  2. ;;; Copyright (C) 2024 Igalia, S.L.
  3. ;;;
  4. ;;; Licensed under the Apache License, Version 2.0 (the "License");
  5. ;;; you may not use this file except in compliance with the License.
  6. ;;; You may obtain a copy of the License at
  7. ;;;
  8. ;;; http://www.apache.org/licenses/LICENSE-2.0
  9. ;;;
  10. ;;; Unless required by applicable law or agreed to in writing, software
  11. ;;; distributed under the License is distributed on an "AS IS" BASIS,
  12. ;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. ;;; See the License for the specific language governing permissions and
  14. ;;; limitations under the License.
  15. ;;; Commentary:
  16. ;;;
  17. ;;; Lists.
  18. ;;;
  19. ;;; Code:
  20. (library (hoot lists)
  21. (export length
  22. list-ref list-set! list-tail
  23. list?
  24. make-list
  25. reverse append list-copy
  26. map for-each fold
  27. acons
  28. sort)
  29. (import (only (hoot primitives) %append)
  30. (hoot apply)
  31. (hoot cond-expand)
  32. (hoot inline-wasm)
  33. (hoot match)
  34. (hoot numbers)
  35. (hoot pairs)
  36. (hoot syntax)
  37. (hoot values))
  38. (define (not x) (if x #f #t))
  39. (define (length l)
  40. (let lp ((len 0) (l l))
  41. (if (null? l) len (lp (1+ len) (cdr l)))))
  42. (define (list-ref l n)
  43. (let lp ((l l) (n n))
  44. (if (zero? n)
  45. (car l)
  46. (lp (cdr l) (1- n)))))
  47. (define (list-set! l n x)
  48. (let lp ((l l) (n n))
  49. (if (zero? n)
  50. (set-car! l x)
  51. (lp (cdr l) (1- n)))))
  52. (define (list-tail l n)
  53. (let lp ((l l) (n n))
  54. (if (zero? n)
  55. l
  56. (lp (cdr l) (1- n)))))
  57. (define (list? l)
  58. (let lp ((l l))
  59. (match l
  60. (() #t)
  61. ((_ . l) (lp l))
  62. (_ #f))))
  63. (define (make-list n init)
  64. (let lp ((n n) (out '()))
  65. (if (zero? n)
  66. out
  67. (lp (1- n) (cons init out)))))
  68. (define (reverse l)
  69. (let lp ((out '()) (l l))
  70. (match l
  71. (() out)
  72. ((head . tail) (lp (cons head out) tail)))))
  73. (define append
  74. (case-lambda
  75. (() '())
  76. ((x) x)
  77. ((x y) (%append x y))
  78. ((x y . z) (%append x (apply append y z)))))
  79. (define (list-copy l)
  80. (append l '()))
  81. (define (fold f seed l)
  82. (let lp ((seed seed) (l l))
  83. (match l
  84. (() seed)
  85. ((x . l) (lp (f x seed) l)))))
  86. ;; Temp definitions!
  87. (define map
  88. (case-lambda
  89. ((f l)
  90. (let lp ((l l))
  91. (match l
  92. (() '())
  93. ((x . l) (cons (f x) (lp l))))))
  94. ((f l1 l2)
  95. (let lp ((l1 l1) (l2 l2))
  96. (match l1
  97. (() '())
  98. ((x . l1)
  99. (match l2
  100. (() '())
  101. ((y . l2)
  102. (cons (f x y) (lp l1 l2))))))))))
  103. (define for-each
  104. (case-lambda
  105. ((f l)
  106. (let lp ((l l))
  107. (unless (null? l)
  108. (f (car l))
  109. (lp (cdr l)))))
  110. ((f l1 l2)
  111. (let lp ((l1 l1) (l2 l2))
  112. (match l1
  113. (() (values))
  114. ((x . l1)
  115. (match l2
  116. (() (values))
  117. ((y . l2)
  118. (f x y)
  119. (lp l1 l2)))))))))
  120. (define (acons x y z) (cons (cons x y) z))
  121. (define (sort items <)
  122. (define (split k items)
  123. (if (zero? k)
  124. (values '() items)
  125. (match items
  126. ((x . rest)
  127. (call-with-values (lambda () (split (1- k) rest))
  128. (lambda (left right)
  129. (values (cons x left) right)))))))
  130. (define (merge left right)
  131. (match left
  132. (() right)
  133. ((a . rest-left)
  134. (match right
  135. (() left)
  136. ((b . rest-right)
  137. (if (< b a)
  138. (cons b (merge left rest-right))
  139. (cons a (merge rest-left right))))))))
  140. (define (mergesort items k)
  141. (match items
  142. ((_) items)
  143. (_
  144. (let ((k/2 (quotient k 2)))
  145. (call-with-values (lambda () (split k/2 items))
  146. (lambda (left right)
  147. (let ((left (mergesort left k/2))
  148. (right (mergesort right (- k k/2))))
  149. (merge left right))))))))
  150. (match items
  151. (() '())
  152. (_ (mergesort items (length items)))))
  153. (cond-expand
  154. (guile-vm)
  155. (hoot
  156. (%inline-wasm
  157. '(func (param $append (ref $proc))
  158. (global.set $append-primitive (local.get $append)))
  159. (lambda (x z)
  160. (let lp ((x x))
  161. (if (null? x)
  162. z
  163. (cons (car x) (lp (cdr x))))))))))