~skin/nrdl

ac93afa88a2164988e252044e15af73750ccd9a8 — Daniel Jay Haskin a month ago a920f30
Start to extract node into its own thing
4 files changed, 98 insertions(+), 20 deletions(-)

R com.djhaskin.nrdl.asd => com.djhaskin.pcoll.asd
R com.djhaskin.nrdl.ros => com.djhaskin.pcoll.ros
M src/main.lisp
A src/utils.lisp
R com.djhaskin.nrdl.asd => com.djhaskin.pcoll.asd +14 -9
@@ 1,4 1,4 @@
(defsystem "com.djhaskin.nrdl"
(defsystem "com.djhaskin.pcoll"
  :version "0.5.0"
  :author "Daniel Jay Haskin"
  :license "MIT"


@@ 6,26 6,31 @@
               "alexandria"
               "trivial-features"
               )
  :components ((:module "cl"
          :components
          ((:file "main"))))
  :components
    (
     (:module "src"
      :serial t
      :components
      ((:file "utils")
       (:file "node")
       (:file "main"))))
  :description "Nestable Readable Document Language"
  :in-order-to (
                (test-op (test-op "com.djhaskin.nrdl/tests"))))
                (test-op (test-op "com.djhaskin.pcoll/tests"))))

(defsystem "com.djhaskin.nrdl/tests"
(defsystem "com.djhaskin.pcoll/tests"
  :version "0.5.0"
  :author "Daniel Jay Haskin"
  :license "MIT"
  :depends-on (
               "com.djhaskin.nrdl"
               "com.djhaskin.pcoll"
               "parachute")
  :components ((:module "cl-tests"
                :components
                ((:file "main"))))
  :description "Test system for NRDL"
  :description "Test system for pcoll"
  :perform (asdf:test-op (op c)

                         (uiop:symbol-call
                           :parachute
                           :test :com.djhaskin.nrdl/tests)))
                           :test :com.djhaskin.pcoll/tests)))

R com.djhaskin.nrdl.ros => com.djhaskin.pcoll.ros +0 -0
M src/main.lisp => src/main.lisp +62 -11
@@ 14,7 14,7 @@
(in-package #:cl-user)

(defpackage
  #:com.djhaskin.pcoll (:use #:cl)
  #:com.djhaskin.pcoll (:use #:cl #:com.djhaskin.pcoll/utils)
  (:documentation
    "
    Fast Persistent Collections in Common Lisp


@@ 63,6 63,23 @@
             (:include node))
  (middle nil))


(defun reduce-node
    (function tree key from-end start end initial-value)
  (declare (type node tree))
  ;; 1. Bound the tree
  (when (>= start (node-size tree))
    (return (single-reduce function 'unspecified initial-value)))
  (when (>= 

  (if (= 1 (node-height tree))
      ;; Then start is less than the node's number of children
      (cond ((= (node-size tree) 
      (if (large-node-p tree)



  (when (>= 
;;; Here are the polymorphic structs used for finger trees:

;;; Why use an empty struct instead of simply nil? So that finger trees are


@@ 90,15 107,11 @@
;;;
;;; The sequences dictionary has something like that, so let's define it now:

(declaim (inline single-reduce))
(defun single-reduce (function thing initial-value)
  (if (eq initial-value 'unspecified)
      (if (eq thing 'unspecified)
          (funcall function)
          thing)
      (if (eq thing 'unspecified)
          initial-value
          (funcall function initial-value thing))))
        ((> start (node-size (

  (typecase tree
    (large-node
      (if (

(defun
    reduce


@@ 109,8 122,46 @@
              (start 0)
              (end nil)
              (initial-value 'unspecified))
  "
  reduce uses a binary operation, `function`, to combine the elements of sequence
  bounded by `start` and `end`.

  The function must accept as arguments two elements of sequence or the results
  from combining those elements. The function must also be able to accept no
  arguments.

  If `key` is supplied, it is used is used to extract the values to reduce. The
  key function is applied exactly once to each element of sequence in the order
  implied by the reduction order but not to the value of initial-value, if
  supplied. The key function typically returns part of the element of sequence.
  If key is not supplied or is nil, the sequence element itself is used.

  The reduction is left-associative, unless from-end is true in which case it is
  right-associative.

  If initial-value is supplied, it is logically placed before the subsequence
  (or after it if from-end is true) and included in the reduction operation.

  In the normal case, the result of reduce is the combined result of function's
  being applied to successive pairs of elements of sequence. If the subsequence
  contains exactly one element and no initial-value is given, then that element
  is returned and function is not called. If the subsequence is empty and an
  initial-value is given, then the initial-value is returned and function is not
  called. If the subsequence is empty and no initial-value is given, then the
  function is called with zero arguments, and reduce returns whatever function
  does. This is the only case where the function is called with other than two
  arguments.
  "
  ;; Make sure the arguments make sense
  (when (and end
             (>= start end))
    (return (single-reduce 'unspecified initial-value)))



  (typecase sequence
    (large-node
    (node
      (reduce-node
      (if (zerop (node-height sequence))
        (cond ((> start 2)
               (single-reduce 'unspecified initial-value))

A src/utils.lisp => src/utils.lisp +22 -0
@@ 0,0 1,22 @@
(in-package #:cl-user)

(defpackage
  #:com.djhaskin.pcoll/utils (:use #:cl)
  (:documentation
    "
    Fast Persistent Collections in Common Lisp
    ")
    (:import-from #:alexandria)
    )

(in-package #:com.djhaskin.pcoll/utils)

(declaim (inline single-reduce))
(defun single-reduce (function thing initial-value)
  (if (eq initial-value 'unspecified)
      (if (eq thing 'unspecified)
          (funcall function)
          thing)
      (if (eq thing 'unspecified)
          initial-value
          (funcall function initial-value thing))))