pvector.lisp 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. ;;;; pvector.lisp
  2. (in-package #:gamao-impl)
  3. ;;; PERSISTENT VECTORS
  4. #|
  5. A simple diff-based persistent vector implementation. API:
  6. Type pvector
  7. make-pvector &rest arguments => value: accepts arguments as make-array, but must be one-dimensional
  8. pvector-ref pvector index => value
  9. pvector-update pvector index value => new-pvector
  10. pvector-reroot pvector => pvector
  11. |#
  12. (defstruct (pvector (:constructor %make-pvector)
  13. (:conc-name %pvector-))
  14. index value next)
  15. (defun make-pvector (&rest arguments)
  16. (%make-pvector :index nil :value nil :next (apply #'make-array arguments)))
  17. (defun pvector-ref (pvector index)
  18. (loop for v = pvector then (%pvector-next v)
  19. for vidx = (%pvector-index v)
  20. when (null vidx) do (return (aref (%pvector-next v) index))
  21. when (= vidx index) do (return (%pvector-value v))))
  22. (defun pvector-update (pvector index value)
  23. (%make-pvector :index index :value value :next pvector))
  24. (defun pvector-reroot (pvector)
  25. (let ((lineage '() ))
  26. (do ((v pvector (%pvector-next v)))
  27. ((null (%pvector-index v)))
  28. (push v lineage))
  29. (dolist (pvector lineage)
  30. (let ((next (%pvector-next pvector))
  31. (index (%pvector-index pvector)))
  32. (pvector-reroot next)
  33. (let ((vector (%pvector-next next)))
  34. (setf (%pvector-next pvector) vector
  35. (%pvector-next next) pvector
  36. (%pvector-index next) (%pvector-index pvector)
  37. (%pvector-value next) (aref vector index)
  38. (aref vector index) (%pvector-value pvector)
  39. (%pvector-index pvector) nil
  40. (%pvector-value pvector) nil)))))
  41. pvector)