vlist.test 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. ;;;; vlist.test --- VLists. -*- mode: scheme; coding: utf-8; -*-
  2. ;;;;
  3. ;;;; Ludovic Courtès <ludo@gnu.org>
  4. ;;;;
  5. ;;;; Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
  6. ;;;;
  7. ;;;; This library is free software; you can redistribute it and/or
  8. ;;;; modify it under the terms of the GNU Lesser General Public
  9. ;;;; License as published by the Free Software Foundation; either
  10. ;;;; version 3 of the License, or (at your option) any later version.
  11. ;;;;
  12. ;;;; This library is distributed in the hope that it will be useful,
  13. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. ;;;; Lesser General Public License for more details.
  16. ;;;;
  17. ;;;; You should have received a copy of the GNU Lesser General Public
  18. ;;;; License along with this library; if not, write to the Free Software
  19. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. (define-module (test-vlist)
  21. #:use-module (test-suite lib)
  22. #:use-module (ice-9 vlist)
  23. #:use-module (srfi srfi-1)
  24. #:use-module (srfi srfi-26))
  25. ;;;
  26. ;;; VLists.
  27. ;;;
  28. (with-test-prefix "vlist"
  29. (pass-if "vlist?"
  30. (and (vlist? vlist-null)
  31. (vlist? (vlist-cons 'a vlist-null))))
  32. (pass-if "vlist-null?"
  33. (vlist-null? vlist-null))
  34. (pass-if "vlist-cons"
  35. (let* ((v1 (vlist-cons 1 vlist-null))
  36. (v2 (vlist-cons 2 v1))
  37. (v3 (vlist-cons 3 v2))
  38. (v4 (vlist-cons 4 v3)))
  39. (every vlist? (list v1 v2 v3 v4))))
  40. (pass-if "vlist-head"
  41. (let* ((v1 (vlist-cons 1 vlist-null))
  42. (v2 (vlist-cons 2 v1))
  43. (v3 (vlist-cons 3 v2))
  44. (v4 (vlist-cons 4 v3)))
  45. (equal? (map vlist-head (list v1 v2 v3 v4))
  46. '(1 2 3 4))))
  47. (pass-if "vlist-tail"
  48. (let* ((v1 (vlist-cons 1 vlist-null))
  49. (v2 (vlist-cons 2 v1))
  50. (v3 (vlist-cons 3 v2))
  51. (v4 (vlist-cons 4 v3)))
  52. (equal? (map vlist-head
  53. (map vlist-tail (list v2 v3 v4)))
  54. '(1 2 3))))
  55. (pass-if "vlist->list"
  56. (let* ((v1 (vlist-cons 1 vlist-null))
  57. (v2 (vlist-cons 2 v1))
  58. (v3 (vlist-cons 3 v2))
  59. (v4 (vlist-cons 4 v3)))
  60. (equal? '(4 3 2 1)
  61. (vlist->list v4))))
  62. (pass-if "list->vlist"
  63. (equal? (vlist->list (list->vlist '(1 2 3 4 5)))
  64. '(1 2 3 4 5)))
  65. (pass-if "vlist-drop"
  66. (equal? (vlist->list (vlist-drop (list->vlist (iota 77)) 7))
  67. (drop (iota 77) 7)))
  68. (pass-if "vlist-cons2"
  69. ;; Example from Bagwell's paper, Figure 2.
  70. (let* ((top (list->vlist '(8 7 6 5 4 3)))
  71. (part (vlist-tail (vlist-tail top)))
  72. (test (vlist-cons 9 part)))
  73. (equal? (vlist->list test)
  74. '(9 6 5 4 3))))
  75. (pass-if "vlist-cons3"
  76. (let ((vlst (vlist-cons 'a
  77. (vlist-cons 'b
  78. (vlist-drop (list->vlist (iota 5))
  79. 3)))))
  80. (equal? (vlist->list vlst)
  81. '(a b 3 4))))
  82. (pass-if "vlist-map"
  83. (equal? (vlist->list (vlist-map 1+ (list->vlist '(1 2 3 4 5))))
  84. '(2 3 4 5 6)))
  85. (pass-if "vlist-length"
  86. (= (vlist-length (list->vlist (iota 77)))
  87. 77))
  88. (pass-if "vlist-length complex"
  89. (= (vlist-length (fold vlist-cons
  90. (vlist-drop (list->vlist (iota 77)) 33)
  91. (iota (- 33 7))))
  92. 70))
  93. (pass-if "vlist-ref"
  94. (let* ((indices (iota 111))
  95. (vlst (list->vlist indices)))
  96. (equal? (map (lambda (i)
  97. (vlist-ref vlst i))
  98. indices)
  99. indices)))
  100. (pass-if "vlist-ref degenerate"
  101. ;; Degenerate case where VLST contains only 1-element blocks.
  102. (let* ((indices (iota 111))
  103. (vlst (fold (lambda (i vl)
  104. (let ((vl (vlist-cons 'x vl)))
  105. (vlist-cons i (vlist-tail vl))))
  106. vlist-null
  107. indices)))
  108. (equal? (map (lambda (i)
  109. (vlist-ref vlst i))
  110. (reverse indices))
  111. indices)))
  112. (pass-if "vlist-filter"
  113. (let* ((lst (iota 33))
  114. (vlst (fold-right vlist-cons vlist-null lst)))
  115. (equal? (vlist->list (vlist-filter even? vlst))
  116. (filter even? lst))))
  117. (pass-if "vlist-delete"
  118. (let* ((lst '(a b c d e))
  119. (vlst (fold-right vlist-cons vlist-null lst)))
  120. (equal? (vlist->list (vlist-delete 'c vlst))
  121. (delete 'c lst))))
  122. (pass-if "vlist-take"
  123. (let* ((lst (iota 77))
  124. (vlst (fold-right vlist-cons vlist-null lst)))
  125. (equal? (vlist->list (vlist-take vlst 44))
  126. (take lst 44))))
  127. (pass-if "vlist-unfold"
  128. (let ((results (map (lambda (unfold)
  129. (unfold (lambda (i) (> i 100))
  130. (lambda (i) i)
  131. (lambda (i) (+ i 1))
  132. 0))
  133. (list unfold vlist-unfold))))
  134. (equal? (car results)
  135. (vlist->list (cadr results)))))
  136. (pass-if "vlist-append"
  137. (let* ((lists '((a) (b c) (d e f) (g)))
  138. (vlst (apply vlist-append (map list->vlist lists)))
  139. (lst (apply append lists)))
  140. (equal? lst (vlist->list vlst)))))
  141. ;;;
  142. ;;; VHash.
  143. ;;;
  144. (with-test-prefix "vhash"
  145. (pass-if "vhash?"
  146. (vhash? (vhash-cons "hello" "world" vlist-null)))
  147. (pass-if "vhash-assoc vlist-null"
  148. (not (vhash-assq 'a vlist-null)))
  149. (pass-if "vhash-assoc simple"
  150. (let ((vh (vhash-cons "hello" "world" vlist-null)))
  151. (equal? (cons "hello" "world")
  152. (vhash-assoc "hello" vh))))
  153. (pass-if "vhash-assoc regular"
  154. (let* ((keys '(a b c d e f g h i))
  155. (values '(1 2 3 4 5 6 7 8 9))
  156. (vh (fold vhash-cons vlist-null keys values)))
  157. (fold (lambda (k v result)
  158. (and result
  159. (equal? (cons k v)
  160. (vhash-assoc k vh eq?))))
  161. #t
  162. keys
  163. values)))
  164. (pass-if "vhash-assoc tail"
  165. (let* ((keys '(a b c d e f g h i))
  166. (values '(1 2 3 4 5 6 7 8 9))
  167. (vh1 (fold vhash-consq vlist-null keys values))
  168. (vh2 (vhash-consq 'x 'x (vlist-tail vh1))))
  169. (and (fold (lambda (k v result)
  170. (and result
  171. (equal? (cons k v)
  172. (vhash-assq k vh2))))
  173. #t
  174. (cons 'x (delq 'i keys))
  175. (cons 'x (delv 9 values)))
  176. (not (vhash-assq 'i vh2)))))
  177. (pass-if "vhash-assoc degenerate"
  178. (let* ((keys '(a b c d e f g h i))
  179. (values '(1 2 3 4 5 6 7 8 9))
  180. (vh (fold (lambda (k v vh)
  181. ;; Degenerate case where VH2 contains only
  182. ;; 1-element blocks.
  183. (let* ((vh1 (vhash-cons 'x 'x vh))
  184. (vh2 (vlist-tail vh1)))
  185. (vhash-cons k v vh2)))
  186. vlist-null keys values)))
  187. (and (fold (lambda (k v result)
  188. (and result
  189. (equal? (cons k v)
  190. (vhash-assoc k vh))))
  191. #t
  192. keys
  193. values)
  194. (not (vhash-assoc 'x vh)))))
  195. (pass-if "vhash as vlist"
  196. (let* ((keys '(a b c d e f g h i))
  197. (values '(1 2 3 4 5 6 7 8 9))
  198. (vh (fold vhash-cons vlist-null keys values))
  199. (alist (fold alist-cons '() keys values)))
  200. (and (equal? (vlist->list vh) alist)
  201. (= (length alist) (vlist-length vh))
  202. (fold (lambda (i result)
  203. (and result
  204. (equal? (list-ref alist i)
  205. (vlist-ref vh i))))
  206. #t
  207. (iota (vlist-length vh))))))
  208. (pass-if "vhash entry shadowed"
  209. (let* ((a (vhash-consq 'a 1 vlist-null))
  210. (b (vhash-consq 'a 2 a)))
  211. (and (= 1 (cdr (vhash-assq 'a a)))
  212. (= 2 (cdr (vhash-assq 'a b)))
  213. (= 1 (cdr (vhash-assq 'a (vlist-tail b)))))))
  214. (pass-if "vlist-filter"
  215. (let* ((keys '(a b c d e f g h i))
  216. (values '(1 2 3 4 5 6 7 8 9))
  217. (vh (fold vhash-cons vlist-null keys values))
  218. (alist (fold alist-cons '() keys values))
  219. (pred (lambda (k+v)
  220. (case (car k+v)
  221. ((c f) #f)
  222. (else #t)))))
  223. (let ((vh (vlist-filter pred vh))
  224. (alist (filter pred alist)))
  225. (and (equal? (vlist->list vh) alist)
  226. (= (length alist) (vlist-length vh))
  227. (fold (lambda (i result)
  228. (and result
  229. (equal? (list-ref alist i)
  230. (vlist-ref vh i))))
  231. #t
  232. (iota (vlist-length vh)))))))
  233. (pass-if "vhash-delete"
  234. (let* ((keys '(a b c d e f g d h i))
  235. (values '(1 2 3 4 5 6 7 0 8 9))
  236. (vh (fold vhash-cons vlist-null keys values))
  237. (alist (fold alist-cons '() keys values)))
  238. (let ((vh (vhash-delete 'd vh))
  239. (alist (alist-delete 'd alist)))
  240. (and (= (length alist) (vlist-length vh))
  241. (fold (lambda (k result)
  242. (and result
  243. (equal? (assq k alist)
  244. (vhash-assoc k vh eq?))))
  245. #t
  246. keys)))))
  247. (pass-if "vhash-delete honors HASH"
  248. ;; In 2.0.0, `vhash-delete' would construct a new vhash without
  249. ;; using the supplied hash procedure, which could lead to
  250. ;; inconsistencies.
  251. (let* ((s "hello")
  252. (vh (fold vhash-consv
  253. (vhash-consv s "world" vlist-null)
  254. (iota 300)
  255. (iota 300))))
  256. (and (vhash-assv s vh)
  257. (pair? (vhash-assv s (vhash-delete 123 vh eqv? hashv))))))
  258. (pass-if "vhash-fold"
  259. (let* ((keys '(a b c d e f g d h i))
  260. (values '(1 2 3 4 5 6 7 0 8 9))
  261. (vh (fold vhash-cons vlist-null keys values))
  262. (alist (fold alist-cons '() keys values)))
  263. (equal? alist (reverse (vhash-fold alist-cons '() vh)))))
  264. (pass-if "vhash-fold-right"
  265. (let* ((keys '(a b c d e f g d h i))
  266. (values '(1 2 3 4 5 6 7 0 8 9))
  267. (vh (fold vhash-cons vlist-null keys values))
  268. (alist (fold alist-cons '() keys values)))
  269. (equal? alist (vhash-fold-right alist-cons '() vh))))
  270. (pass-if "alist->vhash"
  271. (let* ((keys '(a b c d e f g d h i))
  272. (values '(1 2 3 4 5 6 7 0 8 9))
  273. (alist (fold alist-cons '() keys values))
  274. (vh (alist->vhash alist))
  275. (alist2 (vlist-fold cons '() vh)))
  276. (and (equal? alist (reverse alist2))
  277. (fold (lambda (k result)
  278. (and result
  279. (equal? (assq k alist)
  280. (vhash-assoc k vh eq?))))
  281. #t
  282. keys))))
  283. (pass-if "vhash-fold*"
  284. (let* ((keys (make-list 10 'a))
  285. (values (iota 10))
  286. (vh (fold vhash-cons vlist-null keys values)))
  287. (equal? (vhash-fold* cons '() 'a vh)
  288. values)))
  289. (pass-if "vhash-fold* tail"
  290. (let* ((keys (make-list 100 'a))
  291. (values (iota 100))
  292. (vh (fold vhash-cons vlist-null keys values)))
  293. (equal? (vhash-fold* cons '() 'a (vlist-drop vh 42))
  294. (take values (- 100 42)))))
  295. (pass-if "vhash-fold* interleaved"
  296. (let* ((keys '(a b a b a b a b a b c d e a b))
  297. (values '(1 0 2 0 3 0 4 0 5 0 0 0 0 6 0))
  298. (vh (fold vhash-cons vlist-null keys values)))
  299. (equal? (vhash-fold* cons '() 'a vh)
  300. (filter (cut > <> 0) values))))
  301. (pass-if "vhash-foldq* degenerate"
  302. (let* ((keys '(a b a b a a a b a b a a a z))
  303. (values '(1 0 2 0 3 4 5 0 6 0 7 8 9 0))
  304. (vh (fold (lambda (k v vh)
  305. ;; Degenerate case where VH2 contains only
  306. ;; 1-element blocks.
  307. (let* ((vh1 (vhash-consq 'x 'x vh))
  308. (vh2 (vlist-tail vh1)))
  309. (vhash-consq k v vh2)))
  310. vlist-null keys values)))
  311. (equal? (vhash-foldq* cons '() 'a vh)
  312. (filter (cut > <> 0) values)))))