You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

191 line
6.9 KiB

  1. (define-module ds
  2. :exports
  3. (alist::make alist::print alist::get alist::find alist::key-exists? alist::remove! alist::set! alist::set-overwrite!
  4. plist::make plist::print plist::get plist::find plist::prop-exists? plist::remove! plist::set! plist::set-overwrite!)
  5. (define-module alist
  6. :imports ("cxr.slime")
  7. :exports (make print get find key-exists? remove! set! set-overwrite!)
  8. (define key-not-found-index -1)
  9. (define (make)
  10. (set-type!
  11. '(())
  12. :alist))
  13. (define (print alist)
  14. (let ((associations (car alist)))
  15. (define (pprint-intern associations)
  16. (when associations
  17. (print " "
  18. (caar associations) "->"
  19. (cdar associations))
  20. (pprint-intern (cdr associations))))
  21. (print "(")
  22. (when associations
  23. (print "\n")
  24. (pprint-intern associations))
  25. (print ")\n")))
  26. (define (get alist key)
  27. (let ((associations (car alist)))
  28. (define (alist-get-intern associations key)
  29. (cond ((null? associations)
  30. (error :key-not-found "key was not found in alist"))
  31. ((= (caar associations) key)
  32. (cdar associations))
  33. (else (alist-get-intern (cdr associations) key))))
  34. (alist-get-intern associations key)))
  35. (define (find alist key)
  36. (let ((associations (car alist)))
  37. (define (alist-find-intern associations key current-index)
  38. (cond ((null? associations) key-not-found-index)
  39. ((= (caar associations) key) current-index)
  40. (else (alist-find-intern (cdr associations)
  41. key
  42. (+ 1 current-index)))))
  43. (alist-find-intern associations key 0)))
  44. (define (key-exists? alist key)
  45. (not (= (find alist key)
  46. key-not-found-index)))
  47. (define (remove! alist key)
  48. (let ((index (find alist key)))
  49. (define (alist-remove!-internal asociations index)
  50. ;; reminder: we only get called if we are not replacing the
  51. ;; first element in the alist
  52. ;; reminder2: we know that the key exists
  53. (if (= index 1)
  54. ;; we want to remove the next one, so we set our
  55. ;; cdr to the next next one
  56. (mutate! associations (cons (car associations)
  57. (cdr (cdr associations))))
  58. ;; else cdr-recurse
  59. (alist-remove!-internal (cdr asociations) (- index 1))))
  60. (cond ((= index key-not-found-index) (error :key-not-found "key to remove was not found"))
  61. ((= index 0) (mutate! alist (cons (cdar alist) ())))
  62. (else (alist-remove!-internal alist index))))
  63. alist)
  64. (define (set! alist key value)
  65. (mutate! alist (set-type! (cons (cons (cons key value)
  66. (car alist))
  67. ())
  68. :alist)))
  69. (define (set-overwrite! alist key value)
  70. (let ((associations (car alist)))
  71. (define (alist-set-overwrite-intern associations key value)
  72. (cond ((= (caar associations) key)
  73. (mutate! (car associations) (cons key value)))
  74. ((null? associations) (set! alist key value))
  75. (else (alist-set-overwrite-intern
  76. (cdr associations) key value))))
  77. (alist-set-overwrite-intern associations key value))
  78. alist)
  79. )
  80. (define-module plist
  81. :imports ("cxr.slime")
  82. :exports (make print get find prop-exists? remove! set! set-overwrite!)
  83. ;; plist:
  84. ;; [ |/]
  85. ;; |
  86. ;; V
  87. ;; [ | ]------------->[ | ]-------------> ...
  88. ;; | |
  89. ;; V V
  90. ;; :key1 value1
  91. ;;
  92. ;; '((:key1 value1 :key2 value2))
  93. (define key-not-found-index -1)
  94. (define (make)
  95. (set-type!
  96. '(())
  97. :plist))
  98. (define (print plist)
  99. (let ((props (car plist)))
  100. (define (pprint-intern props)
  101. (when props
  102. (print " "
  103. (car props) "->"
  104. (cadr props))
  105. (pprint-intern (cddr props))))
  106. (print "(")
  107. (when props
  108. (print "\n")
  109. (pprint-intern props))
  110. (print ")\n")))
  111. (define (get plist prop)
  112. (let ((props (car plist)))
  113. (define (plist-get-intern props prop)
  114. (cond ((null? props)
  115. (error :key-not-found "property was not found in plist"))
  116. ((= (car props) prop)
  117. (cadr props))
  118. (else (plist-get-intern (cddr props) prop))))
  119. (plist-get-intern props prop)))
  120. (define (set! plist prop value)
  121. (mutate! plist (set-type! (cons (cons prop (cons value (car plist))) ())
  122. :plist)))
  123. (define (set-overwrite! plist prop value)
  124. (let ((props (car plist)))
  125. (define (plist-set-overwrite-intern props prop value)
  126. (cond ((= (car props) prop)
  127. (mutate! (cdr props) (cons value (cddr props))))
  128. ((null? props) (plist-set! plist prop value))
  129. (else (plist-set-overwrite-intern
  130. (cddr props) prop value))))
  131. (plist-set-overwrite-intern props prop value))
  132. plist)
  133. (define (find plist prop)
  134. (let ((props (car plist)))
  135. (define (plist-find-intern props prop current-index)
  136. (cond ((null? props) key-not-found-index)
  137. ((= (car props) prop) current-index)
  138. (else (plist-find-intern (cddr props) prop
  139. (+ 1 current-index)))))
  140. (plist-find-intern props prop 0)))
  141. (define (prop-exists? plist prop)
  142. (not (= (find plist prop)
  143. key-not-found-index)))
  144. (define (remove! plist prop)
  145. (let ((index (find plist prop)))
  146. (define (plist-remove!-internal props index)
  147. ;; reminder: we only get called if we are not replacing the
  148. ;; first element in the alist
  149. ;; reminder2: we know that the key exists
  150. (if (= index 1)
  151. ;; we want to remove the next one, so we set our
  152. ;; cdr to the next next one
  153. (mutate! (cdar props) (cons (cadar props) ;; xD nice meme dude!!!
  154. (cdr (cdr (cdr (cdar props))))))
  155. ;; else cdr-recurse
  156. (plist-remove!-internal (cddr props) (- index 1))))
  157. (cond ((= index key-not-found-index) (error :key-not-found "prop to remove was not found"))
  158. ((= index 0) (mutate! plist (cons (cddar plist) ())))
  159. (else (plist-remove!-internal plist index))))
  160. plist)
  161. )
  162. )