initial commit: release 0.04 of cl-heresy
[el-heresy.git] / heresy.lisp
blob9cf2afacd486d437728d56c5e39abcf6e0b1bfc9
1 ;;; Copyright (c) 2007, Matthew Lamari (matt.lamari@gmail.com). All rights reserved.
3 ;;; Redistribution and use in source and binary forms, with or without
4 ;;; modification, are permitted provided that the following conditions
5 ;;; are met:
7 ;;; * Redistributions of source code must retain the above copyright
8 ;;; notice, this list of conditions and the following disclaimer.
10 ;;; * Redistributions in binary form must reproduce the above
11 ;;; copyright notice, this list of conditions and the following
12 ;;; disclaimer in the documentation and/or other materials
13 ;;; provided with the distribution.
15 ;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED
16 ;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 ;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 ;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19 ;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 ;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21 ;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 ;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 ;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 ;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 ;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 ; (load "c:/prog/lisp/common/stdutils.lisp")
30 (in-package :heresy)
33 (eval-when (:compile-toplevel :load-toplevel :execute)
34 (cl-user::load-lutils))
38 (eval-when (:compile-toplevel :load-toplevel :execute)
41 (define-compiler-macro funcall2 (&whole form &rest params)
42 `(handler-case
43 (funcall ,@params)
44 (error (err) (error (format nil "~S ~S" err ,params)))))
45 (defun funcall2 (&rest rest) (apply #'funcall rest))
50 (defmacro defunm (function-name params &body body)
51 `(progn
52 (defun ,function-name ,params ,(eval `(let ,(mapcar (lambda (elt) `(,elt ',elt)) params) ,@body)))
53 (define-compiler-macro ,function-name ,params ,@body)))
55 (defclass function-form () ())
57 (defclass function-form-symbol (function-form)
58 ((symbol :type symbol :initarg :symbol :reader get-symbol)))
60 (defclass function-form-lambda (function-form)
61 ((args :initarg :args :type list :reader get-args)
62 (body :initarg :body :type list :reader get-body)))
64 (defclass function-form-expression (function-form)
65 ((expression :initarg :expression :reader get-expression)))
67 (defclass function-form-partial (function-form)
68 ((sub-function-form :initarg :sub-function-form :type function-form :reader get-sub-function-form)
69 (known-args :initarg :known-args :type list :reader get-known-args)
70 (new-arg-side :initarg :new-arg-side :type :symbol :reader get-new-arg-side))) ; new-arg-side should be :right for curried, :left for rcurried
72 (defclass function-form-composed (function-form)
73 ((functions-reversed :initarg :functions-reversed :type list :reader get-functions-reversed)))
75 (defclass function-form-constantly (function-form)
76 ((value :initarg :value :reader get-value)))
80 (defun function-literal-to-form (function)
81 (cond
82 ((when (consp function)
83 (case (car function)
84 ('function
85 (destructuring-bind (function-sym function)
86 function
87 (typecase function
88 (cons
89 (when (eql (car function) 'lambda)
90 (destructuring-bind (lambda args &body body)
91 function
92 (make-instance 'function-form-lambda :args args :body body))))
93 (symbol (make-instance 'function-form-symbol :symbol function)))))
94 ('lambda
95 (make-instance 'function-form-lambda :args (second function) :body (cddr function)))
96 ('curried
97 (destructuring-bind (curried-sym curried &rest known-args)
98 function
99 (make-instance 'function-form-partial :sub-function-form (function-literal-to-form curried) :new-arg-side :right :known-args known-args)))
100 ('rcurried
101 (destructuring-bind (curried-sym curried &rest known-args)
102 function
103 (make-instance 'function-form-partial :sub-function-form (function-literal-to-form curried) :new-arg-side :left :known-args known-args)))
104 ('constantly
105 (destructuring-bind (constantly-sym value)
106 function
107 (make-instance 'function-form-constantly :value value)))
108 ('composed
109 (make-instance 'function-form-composed :functions-reversed (nreverse (mapcar #'function-literal-to-form (cdr function))))))))
110 (t (make-instance 'function-form-expression :expression function))))
112 (defmethod get-call-form-precond-parameters ((function function-form) (parameter-count integer))
113 (list (loop for i from 1 to parameter-count collect (gensym))))
115 (defmethod get-call-form-precond-parameters ((function function-form-lambda) (parameter-count integer))
116 (assert (eql parameter-count (length (get-args function))))
117 (list (get-args function)))
119 (defmethod get-call-form-precond-parameters ((function function-form-partial) (parameter-count integer))
120 (let* ((known-arg-count (length (get-known-args function)))
121 (sub-form-preconds (get-call-form-precond-parameters (get-sub-function-form function) (+ parameter-count known-arg-count))))
122 (ecase (get-new-arg-side function)
123 (:right ; normal curried
124 (cons (last (first sub-form-preconds) parameter-count) sub-form-preconds))
125 (:left ; rcurried
126 (cons (subseq (first sub-form-preconds) 0 parameter-count) sub-form-preconds)))))
128 (defmethod get-call-form-precond-parameters ((function function-form-composed) (parameter-count integer))
129 (get-call-form-precond-parameters (first (get-functions-reversed function)) parameter-count))
133 (defmethod get-call-form ((function function-form-symbol) (call-form-precond-parameters list) &optional (per-precond-parameter-actions nil))
134 `(,(get-symbol function) ,@(if per-precond-parameter-actions (mapcar #'funcall per-precond-parameter-actions (first call-form-precond-parameters)) (first call-form-precond-parameters))))
136 (defmethod get-call-form ((function function-form-expression) (call-form-precond-parameters list) &optional (per-precond-parameter-actions nil))
137 `(funcall ,(get-expression function) ,@(first call-form-precond-parameters)))
139 (defmethod get-call-form ((function function-form-lambda) (call-form-precond-parameters list) &optional (per-precond-parameter-actions nil))
140 (if per-precond-parameter-actions
141 `(progn
142 ,@(mapcar (lambda (precond-parameter action) `(setq ,precond-parameter ,(funcall action precond-parameter))) (first call-form-precond-parameters) per-precond-parameter-actions)
143 (let nil ,@(get-body function)))
144 `(let nil ,@(get-body function))))
146 (defmethod get-call-form ((function function-form-partial) (call-form-precond-parameters list) &optional (per-precond-parameter-actions nil))
147 (let* ((known-arg-count (length (get-known-args function)))
148 ; (sub-form-preconds (get-call-form-precond-parameters (get-sub-function-form function) (+ (length (first call-form-precond-parameters)) known-arg-count)))
149 (sub-form-preconds (cdr call-form-precond-parameters))
151 (ecase (get-new-arg-side function)
152 (:right
153 `(let ,(mapcar (lambda (precond known) `(,precond ,known)) (first sub-form-preconds) (get-known-args function))
154 ,@(when per-precond-parameter-actions
155 (loop for precond in (last (first sub-form-preconds) (length (first call-form-precond-parameters)))
156 for action in per-precond-parameter-actions
157 collect `(setq ,precond ,(funcall action precond))))
158 ,(get-call-form (get-sub-function-form function) sub-form-preconds nil)))
159 (:left
160 `(let ,(mapcar (lambda (precond known) `(,precond ,known)) (last (first sub-form-preconds) known-arg-count) (get-known-args function))
161 ,@(when per-precond-parameter-actions
162 (loop for precond in (subseq (first sub-form-preconds) 0 (length (first call-form-precond-parameters)))
163 for action in per-precond-parameter-actions
164 collect `(setq ,precond ,(funcall action precond))))
165 ,(get-call-form (get-sub-function-form function) sub-form-preconds nil))))))
167 (defmethod get-call-form ((function function-form-composed) (call-form-precond-parameters list) &optional (per-precond-parameter-actions nil))
168 (destructuring-bind (last . not-last-reversed)
169 (get-functions-reversed function)
170 (let ((result-sym (gensym)))
171 `(let ((,result-sym
172 ,(get-call-form last call-form-precond-parameters per-precond-parameter-actions)))
173 ,@(loop for function in not-last-reversed collect
174 `(setq ,result-sym
175 ,(let ((precond-parameters (get-call-form-precond-parameters function 1)))
176 (destructuring-bind (sole-result-sym) ; there must be only one.
177 (first precond-parameters)
178 `(let ((,sole-result-sym ,result-sym))
179 ,(get-call-form function precond-parameters nil))))))
180 ,result-sym))))
182 (defmethod get-call-form ((function function-form-constantly) (call-form-precond-parameters list) &optional (per-precond-parameter-action nil))
183 (get-value function))
185 (defun composed (&rest functions)
186 (if functions
187 (let (reversed last)
188 (loop for remainder on functions do
189 (if (cdr remainder)
190 (push (car remainder) reversed)
191 (setq last (car remainder))))
192 (lambda (&rest args)
193 (let ((result (apply last args)))
194 (loop for elt in reversed do (setq result (funcall elt result)))
195 result)))
196 #'identity))
200 (defun curried (function &rest largs)
201 (assert (functionp function))
202 (lambda (&rest rargs)
203 (apply function (append largs rargs))))
205 (defun rcurried (function &rest rargs)
206 (assert (functionp function))
207 (lambda (&rest largs)
208 (apply function (append largs rargs))))
217 (eval-when (:compile-toplevel :load-toplevel :execute)
218 (defstruct traversal-link
219 get-link
220 get-link-with-tail-override))
224 (eval-when (:compile-toplevel :load-toplevel :execute)
227 (defmacro get-traversal-result (traversal-link)
228 `(funcall (resolved ,traversal-link) :get-link))
231 (defstruct unresolved call)
232 (defmacro unresolved (&body body) `(make-unresolved :call (lambda () ,@body)))
233 (defmacro resolved (&body body)
234 (let ((temp-sym (gensym)))
235 (if (cdr body)
236 `(let ((,temp-sym ,@body)) (loop while (typep ,temp-sym 'unresolved) do (setq ,temp-sym (funcall (unresolved-call ,temp-sym)))) ,temp-sym)
237 (let ((current body))
238 (loop while (and (consp (car current)) (not (cdr current)) (or (eql (caar current) 'unresolved) (eql (caar current) 'resolved))) do (setq current (cdr (car current))))
239 `(let ((,temp-sym ,@current)) (loop while (typep ,temp-sym 'unresolved) do (setq ,temp-sym (funcall (unresolved-call ,temp-sym)))) ,temp-sym)))))
241 (defmacro tut (&body body)
242 "Trampoline unless TCO can be assumed"
243 `(unresolved ,@body))
246 (defclass traversal-result () ((value :initarg :value :accessor get-value) (next :initarg :next :accessor get-next)))
247 (defun traversal-result (value next)
248 (make-instance 'traversal-result :value value :next next))
251 (defmacro def-traversal-link (cases &key (sub-cases-sink nil))
252 (let ((control-sym (gensym))
253 (params-sym (gensym))
254 (sub-cases-sink-sym (gensym)))
255 `(let ((,sub-cases-sink-sym ,sub-cases-sink))
256 (lambda (,control-sym &rest ,params-sym)
257 (case ,control-sym
258 ,@(mapcar
259 (lambda (case)
260 (destructuring-bind (control args &body body)
261 case
262 `(,control
263 (destructuring-bind ,args
264 ,params-sym
265 ,@body))))
266 cases)
267 (:get-sub-cases-sink ,sub-cases-sink-sym)
269 (if ,sub-cases-sink-sym
270 (apply ,sub-cases-sink-sym ,control-sym ,params-sym)
271 (error (format nil "No sub-cases for ~A" ,control-sym)))))))))
273 (defparameter **standard-terminating-end-call**
274 (def-traversal-link
275 ((:get-link () (traversal-result nil nil))
276 (:get-link-with-tail-override (end-call) (unresolved (get-traversal-result end-call)))
277 (:slam (&rest rest) (first rest) (second rest) (unresolved (funcall (second rest) (first rest)))))))
282 (defmacro assured-traversal-result (&body body)
283 (let ((result-sym (gensym)))
284 `(let ((,result-sym (resolved (progn ,@body))))
285 (when (not (typep ,result-sym 'traversal-result)) (error (format nil "Not a Traversal-result: ~S" ',body)))
286 ,result-sym)))
289 (defmacro! with-slam-sinks ((slam-params) &body body)
290 `(let ((,g!slam-params ,slam-params))
291 (destructuring-bind (,g!prior-count ,g!sink-count ,g!single-sym ,g!sequence-sym)
292 ,g!slam-params
293 (labels ((slam-single (single) (funcall ,g!single-sym single))
294 (slam-sequence (sequence) (funcall ,g!sequence-sym sequence)))
295 (macrolet! ((end-call-thing (,g!end-call-sym count)
296 `(let ((,g!count ,count))
297 (unresolved (apply (resolved ,,g!end-call-sym) :slam (+ ,g!count ,',g!prior-count) (cdr ,',g!slam-params)))))
298 (slam-next (,g!next-sym count)
299 `(let ((,g!count ,count))
300 (unresolved (apply ,,g!next-sym :slam (+ ,g!count ,',g!prior-count) (cdr ,',g!slam-params)))))
301 (slam-for-continue (list sink-count)
302 `(apply #'slam-cont ,list ,',g!prior-count ,sink-count (cddr ,',g!slam-params))))
303 ,@body)))))
306 (defmacro! standard-traversal-link-parametric ((build-func-sym (end-call-sym &rest build-params) &body body) (&rest build-actual-params))
307 `(labels ((,build-func-sym (,end-call-sym ,@build-params)
308 (lambda (,g!control-sym &rest ,g!params-sym)
309 (case ,g!control-sym
310 (:slam
311 (do-slam ,g!params-sym ,body ,end-call-sym))
313 (let ((,end-call-sym
314 (ecase ,g!control-sym
315 (:get-link ,end-call-sym)
316 (:get-link-with-tail-override
317 (destructuring-bind (,end-call-sym)
318 ,g!params-sym
319 ,end-call-sym)))))
320 ,@body))))))
321 (,build-func-sym **standard-terminating-end-call** ,@build-actual-params)))
324 (defmacro standard-traversal-link-sequence-slam ((build-func-sym (end-call-sym &rest build-params) &body body)
325 sequence
326 (&rest build-actual-params))
327 `(macrolet ((do-slam (params-sym body end-call-sym)
328 `(with-slam-sinks (,params-sym)
329 (let* ((seq ,',sequence)
330 (length (length seq)))
331 (slam-sequence seq)
332 (end-call-thing ,end-call-sym length)))))
333 (standard-traversal-link-parametric (,build-func-sym (,end-call-sym ,@build-params) ,@body) (,@build-actual-params))))
336 (let ((control-sym (gensym))
337 (params-sym (gensym)))
338 `(labels ((,build-func-sym (,end-call-sym ,@build-params)
339 (lambda (,control-sym &rest ,params-sym)
340 (case ,control-sym
341 (:slam
342 (with-slam-sinks (,params-sym)
343 (slam-sequence ,sequence)
344 (tut (apply (resolved ,end-call-sym) :slam ,params-sym))))
346 (let ((,end-call-sym
347 (ecase ,control-sym
348 (:get-link ,end-call-sym)
349 (:get-link-with-tail-override
350 (destructuring-bind (,end-call-sym)
351 ,params-sym
352 ,end-call-sym)))))
353 ,@body))))))
354 (,build-func-sym **standard-terminating-end-call** ,@build-actual-params))))
361 (defmacro! standard-traversal-link ((build-func-sym (end-call-sym &rest build-params) &body body) (&rest build-actual-params))
362 `(macrolet! ((do-slam (params-sym body end-call-sym)
363 `(with-slam-sinks (,params-sym)
364 (let* ((,g!result-sym (resolved (progn ,@body)))
365 (,g!next-sym (get-next ,g!result-sym)))
366 (cond
367 (,g!next-sym
368 (slam-single (resolved (get-value ,g!result-sym)))
369 (slam-next ,g!next-sym 1))
371 (end-call-thing ,end-call-sym 0)))))))
372 (standard-traversal-link-parametric (,build-func-sym (,end-call-sym ,@build-params) ,@body) (,@build-actual-params))))
377 (defmacro standard-traversal-link ((build-func-sym (end-call-sym &rest build-params) &body body) (&rest build-actual-params))
378 (let ((control-sym (gensym))
379 (params-sym (gensym)))
380 `(labels ((,build-func-sym (,end-call-sym ,@build-params)
381 (lambda (,control-sym &rest ,params-sym)
382 (case ,control-sym
383 (:slam
384 (with-slam-sinks (,params-sym)
385 (let* ((,result-sym (resolved (progn ,@body)))
386 (,next-sym (get-next ,result-sym)))
387 (cond
388 (,next-sym
389 (slam-single (get-value ,result-sym))
390 (tut (apply ,next-sym :slam ,params-sym)))
392 (tut (apply (resolved ,end-call-sym) :slam ,params-sym)))))))
394 (let ((,end-call-sym
395 (ecase ,control-sym
396 (:get-link ,end-call-sym)
397 (:get-link-with-tail-override
398 (destructuring-bind (,end-call-sym)
399 ,params-sym
400 ,end-call-sym)))))
401 ,@body))))))
402 (,build-func-sym **standard-terminating-end-call** ,@build-actual-params))))
405 (defun slam-cont (lazy-list current-count sink-count sink-single sink-sequence)
406 (funcall (get-call-for-first lazy-list) :slam current-count sink-count sink-single sink-sequence))
408 (defun slam (lazy-list sink-single sink-sequence)
409 (let ((result nil))
410 (resolved (slam-cont lazy-list 0 (lambda (count) (setq result count)) sink-single sink-sequence))
411 result))
415 (defmacro standard-traversal-link-with-sub ((build-func-sym (end-call-sym &rest build-params) &body body) sub-cases (&rest build-actual-params))
416 `(labels ((,build-func-sym (,end-call-sym ,@build-params)
417 (def-traversal-link
418 ((:get-link () ,@body)
419 (:get-link-with-tail-override (,end-call-sym) ,@body))
420 :sub-cases-sink (def-traversal-link ,sub-cases))))
421 (,build-func-sym **standard-terminating-end-call** ,@build-actual-params)))
426 Was experimental/to keep sub-cases but the situation for them went away
427 (defmacro sub-case-preserving-traversal-link ((build-func-sym (end-call-sym call-sym &rest build-params) &body body) (&rest build-actual-params))
428 `(labels ((,build-func-sym (,end-call-sym ,call-sym ,@build-params)
429 (def-traversal-link
430 ((:get-link () ,@body)
431 (:get-link-with-tail-override (,end-call-sym) ,@body))
432 :sub-cases-sink `(funcall ,call-sym :sub-cases-sink))))
433 (,build-func-sym **standard-terminating-end-call** ,@build-actual-params)))
439 (defmacro fixed-traversal-link-from-result-form (traversal-result-form)
440 (let ((end-call-sym (gensym))
441 (next-sym (gensym))
442 (result-sym (gensym))
443 (v-sym (gensym))
444 (n-sym (gensym)))
445 `(def-traversal-link
446 ((:get-link () ,traversal-result-form)
447 (:get-link-with-tail-override (,end-call-sym)
448 (let* ((,result-sym (resolved ,traversal-result-form))
449 (,next-sym (resolved (get-next ,result-sym))))
450 (if ,next-sym
451 (traversal-result
452 (get-value ,result-sym)
453 (unresolved
454 (with-traversal-result
455 (,v-sym ,n-sym)
456 (funcall ,next-sym :get-link-with-tail-override ,end-call-sym)
457 (fixed-traversal-link ,v-sym ,n-sym))))
458 (unresolved (get-traversal-result ,end-call-sym)))))))))
461 (defmacro fixed-traversal-link (value next)
462 (let ((end-call-sym (gensym))
463 (next-sym (gensym))
464 (slam-params-sym (gensym)))
465 `(def-traversal-link
466 ((:get-link () (traversal-result ,value ,next))
467 (:get-link-with-tail-override (,end-call-sym)
468 (let ((,next-sym (resolved ,next)))
469 (if ,next-sym
471 ; (traversal-result ,value (unresolved (funcall ,next-sym :get-link-with-tail-override ,end-call-sym)))
472 (tail-override-for-fixed-traversal-link ,value ,next-sym ,end-call-sym)
474 (unresolved (get-traversal-result ,end-call-sym)))))
475 (:slam (&rest ,slam-params-sym)
476 (with-slam-sinks (,slam-params-sym)
477 (let ((,next-sym (resolved ,next)))
478 (when ,next-sym
479 (slam-single (resolved ,value))
480 (unresolved (apply ,next-sym :slam ,slam-params-sym))))))))))
482 (defun tail-override-for-fixed-traversal-link (value next end-call)
483 (traversal-result value (unresolved (fixed-traversal-link-from-result-form (funcall next :get-link-with-tail-override end-call)))))
487 (defmacro get-traversal-result-new-end-call (traversal-link new-end-call)
488 `(funcall (resolved ,traversal-link) :get-link-with-tail-override ,new-end-call))
490 (defmacro! deferred-traversal-link-from-call-maker (call-maker-form)
491 `(def-traversal-link
492 ((:get-link () (get-traversal-result ,call-maker-form))
493 (:get-link-with-tail-override (,g!end-call) (get-traversal-result-new-end-call ,call-maker-form ,g!end-call))
494 (:slam (&rest ,g!slam-params)
495 (with-slam-sinks (,g!slam-params)
496 (unresolved (apply ,call-maker-form :slam ,g!slam-params)))))))
499 (with-traversal-result
500 (,g!value ,g!next)
501 (get-traversal-result ,call-maker-form)
502 (let ((,g!next (resolved ,g!next)))
503 (when ,g!next
504 (slam-single (resolved ,g!value))
505 (unresolved (apply ,g!next :slam ,g!slam-params)))))
509 (defun confirmed-traversal-result (val)
510 (assert (typep val 'traversal-result))
511 val)
513 (defmacro with-traversal-result ((val-sym next-sym) form &body body)
514 (let ((sym (gensym)))
515 `(with-slots ((,val-sym value) (,next-sym next))
516 ; (let ((,sym ,form)) (assert (typep ,sym 'traversal-result)) ,sym)
517 ; (confirmed-traversal-result ,form)
518 (let ((,sym (resolved ,form)))
519 (when (not (typep ,sym 'traversal-result))
520 (print (list "bad type for traversal type " ,sym ',body))
522 ,sym)
523 ,@body)))
526 (defclass lazy-list () ((call-for-first :initarg :call-for-first :accessor get-call-for-first)))
529 (defmethod get-call-for-first ((list lazy-list) (call-for-end function))
530 (resolved (funcall (get-call-for-first-maker list) call-for-end)))
533 (defclass lazy-list-under-cdrs (lazy-list)
534 ((underlying-call-for-first :initarg :underlying-call-for-first :accessor get-underlying-call-for-first)
535 (cdr-count :initarg :cdr-count :accessor get-cdr-count)))
537 (defclass lazy-list-with-some-persistence (lazy-list) ())
539 (defclass lazy-list-with-persistence (lazy-list-with-some-persistence) ())
541 (defclass lazy-list-read-point-based (lazy-list-with-some-persistence) ((read-point :initarg :read-point :accessor get-read-point)))
543 (defclass lazy-list-known-empty (lazy-list-with-persistence) ())
545 (defclass lazy-list-list-based (lazy-list-with-persistence)
546 ((list-head :initarg :list-head :accessor get-list-head)))
548 (defclass lazy-list-pair-based (lazy-list-with-persistence)
549 ((cons :initarg :cons :accessor get-cons)))
552 (defun make-instance-2 (type &rest params)
553 (when (eql type 'lazy-list-read-point-based)
554 (when (not (getf params :read-point))
555 (error "No read-point")))
556 (apply #'make-instance type params))
559 (defmacro lazy-list-from-call (call)
560 (let ((call-sym (gensym)))
561 `(let ((,call-sym ,call))
562 ; (assert (typep ,call-sym 'traversal-link))
563 (make-instance-2 'lazy-list :call-for-first ,call-sym))))
566 (defmacro lazy-list-from-traversal-link (traversal-link)
567 (let ((sym (gensym)))
568 `(let ((,sym ,traversal-link))
569 ; (assert (typep ,sym 'traversal-link))
570 (make-instance-2 'lazy-list :call-for-first ,sym))))
573 (defmacro deferred-lazy-list (list-definition)
574 `(lazy-list-from-call
575 (deferred-traversal-link-from-call-maker
576 (get-call-for-first (to-lazy-list ,list-definition)))))
580 (defparameter **in-lazy-mode** nil)
583 (defun in-lazy-mode ()
584 (declare (special **in-lazy-mode**))
585 **in-lazy-mode**)
586 (define-compiler-macro in-lazy-mode () `**in-lazy-mode**)
589 (defmacro if-lazy-eager (if-lazy if-strict)
590 `(if (in-lazy-mode)
591 ,if-lazy
592 ,if-strict))
594 (defmacro lazy (&body body)
595 "Enters a \"lazy\" context - calls to functions such as tail/ defer traversal.
596 This context uses a special variable, and extends into sub-calls until overridden."
597 `(let ((**in-lazy-mode** t))
598 ,@body))
600 (defmacro eager (&body body)
601 "Enters an \"eager\" context - calls to functions such as tail/ do traversal before returning.
602 This context uses a special variable, and extends into sub-calls until overridden."
603 `(let ((**in-lazy-mode** nil))
604 ,@body))
608 (defparameter **respecting-thread-safety** nil)
610 (defstruct read-point
611 rp-value
612 rp-next
613 rp-lock)
615 (defstruct read-point-value-resolver
616 run)
618 (defstruct read-point-next-resolver
620 get-call)
622 (defmacro respecting-lock-if-present ((lock) &body body)
623 `(if ,lock
624 (bordeaux-threads::with-lock-held (,lock) ,@body)
625 (progn ,@body)))
627 (defmacro respecting-read-point-lock ((read-point) &body body)
628 (let ((lock-sym (gensym)))
629 `(let ((,lock-sym (read-point-rp-lock ,read-point)))
630 (respecting-lock-if-present (,lock-sym) ,@body))))
632 (defmacro assure-readpoint-value-resolved (read-point)
633 (let ((sym (gensym)))
634 `(let ((,sym (read-point-rp-value ,read-point)))
635 (when (typep ,sym 'read-point-value-resolver)
636 (funcall (read-point-value-resolver-run ,sym))))))
638 (defmacro assure-readpoint-next-resolved (read-point)
639 (let ((sym (gensym)))
640 `(let ((,sym (read-point-rp-next ,read-point)))
641 (when (typep ,sym 'read-point-next-resolver)
642 (funcall (read-point-next-resolver-run ,sym))))))
644 (defun read-point-value (read-point)
645 (assert (typep read-point 'read-point))
646 (respecting-read-point-lock
647 (read-point)
648 (assure-readpoint-value-resolved read-point)
649 (read-point-rp-value read-point)))
651 (defun read-point-at-end (read-point)
652 (assert (typep read-point 'read-point))
653 (respecting-read-point-lock
654 (read-point)
655 (assure-readpoint-next-resolved read-point)
656 (not (read-point-rp-next read-point))))
659 (defun read-point-advanced (read-point)
660 (assert (typep read-point 'read-point))
661 (respecting-read-point-lock
662 (read-point)
663 (assure-readpoint-next-resolved read-point)
664 (read-point-rp-next read-point)))
667 (defun read-point-from-call (call &optional (lock (when **respecting-thread-safety** (bordeaux-threads:make-lock))))
668 (let ((read-point nil))
669 (setq read-point
670 (make-read-point
671 :rp-lock lock
672 :rp-value (make-read-point-value-resolver
673 :run
674 (lambda ()
675 (respecting-lock-if-present
676 (lock)
677 (with-traversal-result
678 (value next)
679 (resolved (get-traversal-result call))
680 (setf (read-point-rp-value read-point) (resolved value))
681 (setf (read-point-rp-next read-point)
682 (make-read-point-next-resolver
683 :run
684 (lambda ()
685 (respecting-lock-if-present
686 (lock)
687 (setf (read-point-rp-next read-point)
688 (let ((next (resolved next)))
689 (when next (read-point-from-call next (when lock (bordeaux-threads:make-lock))))))))
690 :get-call
691 (lambda ()
692 (respecting-lock-if-present
693 (lock)
694 (let ((next (resolved next)))
695 (setf (read-point-rp-next read-point)
696 (when next (read-point-from-call next (when lock (bordeaux-threads:make-lock)))))
697 next)))))))))
698 :rp-next (make-read-point-next-resolver
699 :run
700 (lambda ()
702 (respecting-lock-if-present
703 (lock)
704 (with-traversal-result
705 (value next)
706 (resolved (get-traversal-result call))
707 (let ((next (resolved next)))
708 (setf (read-point-rp-next read-point) (when next (read-point-from-call next (when lock (bordeaux-threads:make-lock)))))
709 (setf (read-point-rp-value read-point)
710 (when next
711 (if (typep value 'unresolved)
712 (make-read-point-value-resolver
713 :run
714 (lambda ()
715 (respecting-lock-if-present
716 (lock)
717 (setf (read-point-rp-value read-point) (resolved value)))))
718 value)))))))
719 :get-call
720 (lambda ()
721 (respecting-lock-if-present
722 (lock)
723 (with-traversal-result
724 (value next)
725 (resolved (get-traversal-result call))
726 (let ((next (resolved next)))
727 (setf (read-point-rp-next read-point) (when next (read-point-from-call next (when lock (bordeaux-threads:make-lock)))))
728 (setf (read-point-rp-value read-point)
729 (when next
730 (if (typep value 'unresolved)
731 (make-read-point-value-resolver
732 :run
733 (lambda ()
734 (respecting-lock-if-present
735 (lock)
736 (setf (read-point-rp-value read-point) (resolved value)))))
737 value)))
738 next)))))))
739 read-point))
741 (defun read-point-built (list)
742 (etypecase list
743 (lazy-list-read-point-based (get-read-point list))
744 (lazy-list
745 (read-point-from-call (get-call-for-first list)))))
747 (defun call-for-read-point-taken-to-end (read-point)
748 (assert (typep read-point 'read-point))
749 (standard-traversal-link
750 (build (end-call read-point)
751 (if (read-point-at-end read-point)
752 (unresolved (get-traversal-result end-call))
753 (let ((advanced (read-point-advanced read-point))) ; calc here to (potentially) advance value
754 (let ((value (read-point-rp-value read-point)))
755 (traversal-result
756 (if (typep value 'read-point-value-resolver)
757 (unresolved (read-point-value read-point))
758 value)
759 (build end-call advanced))))))
760 (read-point)))
762 (defun call-to-detach-from-read-point (read-point)
763 (assert (typep read-point 'read-point))
764 (standard-traversal-link
765 (build (end-call read-point)
766 (let ((result
767 (respecting-read-point-lock
768 (read-point)
769 (let ((rp-next (read-point-rp-next read-point)))
770 (cond
771 ((null rp-next) (get-traversal-result end-call))
773 (etypecase rp-next
774 (read-point (traversal-result (unresolved (read-point-value read-point)) (build end-call rp-next)))
775 (read-point-next-resolver
776 (unresolved
777 (let ((nexts-call (funcall (read-point-next-resolver-get-call rp-next))))
778 (if nexts-call
779 (traversal-result
780 (unresolved (read-point-value read-point))
781 (with-traversal-result
782 (val next)
783 (get-traversal-result-new-end-call nexts-call end-call)
784 (let ((next (resolved next)))
785 (if next
786 (fixed-traversal-link val next)
787 end-call))))
788 (get-traversal-result end-call))))))))))))
789 result))
790 (read-point)))
793 (defun lazy-list-from-read-point (read-point)
794 (make-instance-2 'lazy-list-read-point-based :call-for-first (call-for-read-point-taken-to-end read-point) :read-point read-point))
797 ; Runs in block nil (return will break out)
798 (defmacro loop-over/ (symbol lazy-list &body body)
799 (let ((current-sym (gensym)) (value-sym (gensym)) (next-sym (gensym)) (top-sym (gensym)) (list-sym (gensym)))
800 "Most trivial loop construct - loops a symbol across lazy-list running body. Runs in block NIL."
801 `(let ((,list-sym ,lazy-list))
802 (typecase ,list-sym
803 (lazy-list-known-empty nil)
804 (lazy-list-list-based (loop for ,symbol in (get-list-head ,list-sym) do ,@body))
806 (block nil
807 (let ((,current-sym (get-call-for-first ,lazy-list)))
808 (tagbody
809 ,top-sym
810 (with-traversal-result (,value-sym ,next-sym)
811 (resolved (get-traversal-result ,current-sym))
812 (let ((,next-sym (resolved ,next-sym))
813 (,value-sym (resolved ,value-sym)))
814 (when ,next-sym
815 (let ((,symbol (resolved ,value-sym)))
816 ,@body
817 (setf ,current-sym ,next-sym)
818 (go ,top-sym)))))))))))))
820 (defmethod print-object ((lazy-list lazy-list) stream)
821 ; (format stream "(LIST/ #|Known Type: ~S|#" (type-of lazy-list))
822 (format stream "(LIST/")
823 (loop-over/ elt lazy-list (format stream " ~S" elt))
824 (format stream ")"))
826 (defmacro list-to-lazy-list-call (origin &key (terminator-generator (lambda (rest-sym) rest-sym)) (value-generator (lambda (rest-sym) `(car ,rest-sym))))
827 (let* ((build-sym (gensym))
828 (rest-sym (gensym))
829 (end-call-sym (gensym)))
830 `(standard-traversal-link
831 (,build-sym (,end-call-sym ,rest-sym)
832 (if ,(funcall (eval terminator-generator) rest-sym)
833 (traversal-result ,(funcall (eval value-generator) rest-sym) (,build-sym ,end-call-sym (cdr ,rest-sym)))
834 (unresolved (get-traversal-result ,end-call-sym))))
835 (,origin))))
839 (defun to-lazy-list (list)
840 (etypecase list
841 (lazy-list list)
842 (list (if list
843 (make-instance-2 'lazy-list-list-based :call-for-first (list-to-lazy-list-call list) :list-head list)
844 (make-instance-2 'lazy-list-known-empty :call-for-first **standard-terminating-end-call**)))
845 (vector
846 (let ((length (length list)))
847 (make-instance-2 'lazy-list-with-persistence
848 :call-for-first
849 (standard-traversal-link-sequence-slam
850 (build (end-call current-index)
851 (if (eql current-index length)
852 (unresolved (get-traversal-result end-call))
853 (traversal-result
854 (aref list current-index)
855 (build end-call (1+ current-index)))))
856 list
857 (0)))))
858 (array
859 (let* ((dimensions (array-dimensions list))
860 (array-rank (array-rank list)))
861 (make-instance-2 'lazy-list-with-persistence
862 :call-for-first
863 (standard-traversal-link
864 (build (end-call current-dimension-head prior-coords current-coord)
865 (if (eq (car current-dimension-head) current-coord) ; test for end of axis.
866 (unresolved (get-traversal-result end-call))
867 (traversal-result
868 (if (cdr current-dimension-head) ; Another axis.
869 (lazy-list-from-call (build **standard-terminating-end-call** (cdr current-dimension-head) (append prior-coords (list current-coord)) 0))
870 (apply #'aref list (append prior-coords (list current-coord))))
871 (build end-call current-dimension-head prior-coords (1+ current-coord)))))
872 (dimensions nil 0)))))))
875 (defun memoized/ (list)
876 "Caches list on first traversal (unless it's determined to already be implemented in terms of persistence)."
877 (etypecase list
878 (sequence (to-lazy-list list))
879 (lazy-list-with-some-persistence list)
880 (lazy-list (lazy-list-from-read-point (read-point-built list)))))
883 (defun lazy-listp (potential)
884 (typep potential 'lazy-list))
886 (defun listp/ (potential)
887 (or (listp potential) (typep potential 'lazy-list)))
889 (defun list/ (&rest rest)
890 "Lazy equivalent of CL's list function - returning a lazy-list (although one that has the parameter list at its core)."
891 (if rest
892 (make-instance-2 'lazy-list-list-based :call-for-first (list-to-lazy-list-call rest) :list-head rest)
893 (make-instance-2 'lazy-list-known-empty :call-for-first **standard-terminating-end-call**)))
896 (defun iterate/ (from-previous element &optional (end-before-func (constantly nil)))
897 "Haskell's iterate function - returns element, then (funcall from-previous element), etc. against result"
898 (assert (functionp from-previous))
899 (lazy-list-from-call
900 (standard-traversal-link
901 (get-val (end-call elt)
902 (if (funcall end-before-func elt)
903 (unresolved (get-traversal-result end-call))
904 (traversal-result
906 (get-val end-call (funcall from-previous elt)))))
907 (element))))
909 (define-compiler-macro iterate/ (&whole form from-previous element &optional (end-before-func '(constantly nil)))
910 (let ((get-val-sym (gensym))
911 (end-call-sym (gensym))
912 (end-before-precond-parameters (get-call-form-precond-parameters (function-literal-to-form end-before-func) 1))
913 (from-previous-precond-parameters (get-call-form-precond-parameters (function-literal-to-form from-previous) 1))
914 (elt-sym (gensym))
916 `(lazy-list-from-call
917 (standard-traversal-link
918 (,get-val-sym (,end-call-sym ,elt-sym)
919 (if (let ((,(caar end-before-precond-parameters) ,elt-sym)) ,(get-call-form (function-literal-to-form end-before-func) end-before-precond-parameters nil))
920 (unresolved (get-traversal-result ,end-call-sym))
921 (traversal-result
922 ,elt-sym
923 (,get-val-sym ,end-call-sym (let ((,(caar from-previous-precond-parameters) ,elt-sym)) ,(get-call-form (function-literal-to-form from-previous) from-previous-precond-parameters nil))))))
924 (,element)))))
928 ; (pprint (funcall (compiler-macro-function 'iterate/) '(iterate/ #'1+ 1 (lambda (x) (> x 20))) nil))
929 ; (defun test () (iterate/ #'1+ 1 (lambda (x) (> x 20))))
934 (defun iteratex/ (input-to-contribution initial-input)
935 (assert (functionp input-to-contribution))
936 (labels ((build (input)
937 (lambda ()
938 (block nil
939 (let ((current-input input))
940 (tagbody
942 (let ((contribution (funcall input-to-contribution current-input)))
943 (destructuring-bind (primary-result
944 &key
945 (emissions #| (list current-input) |# nil emissions-supplied-p)
946 (emission nil emission-supplied-p)
947 (exit-before nil)
948 (exit-after nil)
949 (next-input primary-result))
950 contribution
951 (assert (not (and emissions-supplied-p emission-supplied-p))) ; can *NOT* supply both
952 (cond
953 (exit-before (return (call-for-end)))
954 ((and emissions-supplied-p (null/ emissions)) (setq current-input next-input) (go top))
956 (if emission-supplied-p
957 (return
958 (values emission
959 (if exit-after
960 #'call-for-end
961 (build next-input))))
962 (labels ((build-for-read-point (read-point)
963 (values (read-point-value read-point)
964 (let ((advanced (read-point-advanced read-point)))
965 (if (read-point-at-end advanced)
966 (if exit-after
967 #'call-for-end
968 (build next-input))
969 (lambda () (build-for-read-point advanced)))))))
970 (return (build-for-read-point (read-point-built (to-lazy-list emissions))))))))))))))))
971 (lazy-list-from-call (build initial-input))))
973 (defun to-list (list)
974 "Returns the proper list corresponding to the passed-in list designator - attempts to minimize work involved if list is a CL sequence
975 or a lazy-list based upon a fixed container"
976 (etypecase list
977 (lazy-list-list-based (get-list-head list))
978 (lazy-list-pair-based (destructuring-bind (first . second) (get-cons list) (list first second)))
979 (lazy-list
980 (let ((result nil))
981 (loop-over/ elt list (push elt result))
982 (nreverse result)))
983 (list list)
984 (sequence (map 'list #'identity list))))
986 (defun to-array (list &rest array-params)
987 "Returns the array corresponding to the passed-in list designator - attempts minimize work involved if list is a CL sequence or lazy-list
988 based upon a fixed container"
989 (etypecase list
990 (sequence (apply #'make-array (length list) :initial-contents list array-params))
992 (let ((result nil)
993 (count 0))
994 (loop-over/ elt (to-lazy-list list) (progn (push elt result) (incf count)))
995 (apply #'make-array count :initial-contents (nreverse result) array-params)))))
998 (defun string-from-chars/ (chars-list)
999 "Returns a string from the supplied chars list"
1000 (typecase chars-list
1001 (string chars-list)
1002 (array (let ((result (make-string (length chars-list))))
1003 (loop for i from 0
1004 for elt across chars-list do
1005 (setf (aref result i) elt))
1006 result))
1007 (list
1008 (with-output-to-string (str)
1009 (loop for elt in chars-list do
1010 (write-char elt str))))
1012 (with-output-to-string (str)
1013 (loop-over/ elt (to-lazy-list chars-list)
1014 (write-char elt str)))
1016 (let ((result nil)
1017 (count 0))
1018 (loop-over/ elt (to-lazy-list chars-list) (progn (push elt result) (incf count)))
1019 (let ((string (make-string count)))
1020 (loop for index from (1- count) downto 0
1021 for elt in result do
1022 (setf (aref string index) elt))
1023 string))
1028 (defun to-string-irresolute (chars-list)
1029 (let ((char-accumulator-r nil)
1030 (char-count-accumulator 0))
1031 (unresolved
1032 (let ((current-call (get-call-for-first (to-lazy-list chars-list)))
1033 (unresolved nil))
1034 (labels ((run ()
1035 (with-traversal-result (value next)
1036 (get-traversal-result (resolved current-call))
1037 (unresolved
1038 (let ((next (resolved next)))
1039 (unresolved
1040 (if next
1041 (unresolved
1042 (let ((value (resolved value)))
1043 (unresolved
1044 (progn
1045 (push value char-accumulator-r)
1046 (incf char-count-accumulator)
1047 (setq current-call next)
1048 unresolved))))
1049 (let ((string (make-string char-count-accumulator)))
1050 (loop for i from (1- char-count-accumulator) downto 0 do
1051 (setf (aref string i) (pop char-accumulator-r)))
1052 string))))))))
1053 (setq unresolved (make-unresolved :call #'run)))))))
1058 (let ((char-accumulator-r nil)
1059 (char-count-accumulator 0)
1060 (current-call (resolved (get-call-for-first (to-lazy-list chars-list))))
1061 (unresolved nil))
1062 (labels ((run ()
1063 (with-traversal-result (value next)
1064 (get-traversal-result current-call)
1065 (let ((next (resolved next)))
1066 (if next
1067 (progn
1068 (push (resolved value) char-accumulator-r)
1069 (incf char-count-accumulator)
1070 (setq current-call next)
1071 unresolved)
1072 (let ((string (make-string char-count-accumulator)))
1073 (loop for i from (1- char-count-accumulator) downto 0 do
1074 (setf (aref string i) (pop char-accumulator-r)))
1075 string))))))
1076 (setq unresolved (make-unresolved :call #'run))))
1081 (defmethod to-string ((chars-list sequence))
1082 "Returns a string from the supplied chars list"
1083 (string-from-chars/ chars-list))
1086 (defmethod to-string ((chars-list lazy-list))
1087 "Returns a string from the supplied chars list"
1088 (string-from-chars/ chars-list))
1092 (defun length/ (list)
1093 "Returns the length of the supplied list, evaluating the list to the end if lazy to measure its length."
1094 (typecase list
1095 (sequence (length list))
1096 (lazy-list-list-based (length (get-list-head list)))
1097 (lazy-list-pair-based 2)
1098 (lazy-list-known-empty 0)
1100 (let ((current (read-point-built (to-lazy-list list)))
1101 (len 0))
1102 (loop while (not (read-point-at-end current)) do
1103 (setq current (read-point-advanced current))
1104 (incf len))
1105 len))))
1107 (eval-when (:compile-toplevel :load-toplevel :execute)
1109 (defun full-cdr-based-form-resolution (form)
1110 ; Attempts to preserve evaluation order of the full expression.
1111 (let ((form-under-cdrs form)
1112 (cdr-items-r nil))
1113 (loop while (and (consp form-under-cdrs) (let ((control (car form-under-cdrs))) (or (eql control 'cdr/) (eql control 'nthcdr/)))) do
1114 (push (butlast form-under-cdrs) cdr-items-r)
1115 (setq form-under-cdrs (car (last form-under-cdrs))))
1116 (let ((sum-of-known-numerics
1117 (loop for elt in cdr-items-r sum
1118 (if (eql (car elt) 'cdr/)
1120 (destructuring-bind (to-drop)
1121 (cdr elt)
1122 (if (integerp to-drop)
1123 to-drop
1124 0)))))
1125 (unevaluated-to-drops
1126 (loop for elt in cdr-items-r append
1127 (when (eql (car elt) 'nthcdr/)
1128 (destructuring-bind (to-drop)
1129 (cdr elt)
1130 (unless (integerp to-drop)
1131 (list to-drop)))))))
1132 (cond
1133 ((and (zerop sum-of-known-numerics) (null unevaluated-to-drops)) form-under-cdrs)
1134 ((and (eql sum-of-known-numerics 1) (null unevaluated-to-drops)) `(cdr/-implementation ,form-under-cdrs))
1135 ((and (null unevaluated-to-drops) `(nthcdr/-implementation ,sum-of-known-numerics ,form-under-cdrs)))
1137 (if (and cdr-items-r (eql (caar cdr-items-r) 'nthcdr/) (not (integerp (cadar cdr-items-r))))
1138 (let ((inner-most-to-drop-sym (gensym))
1139 (sub-list-sym (gensym)))
1140 `(let ((,inner-most-to-drop-sym ,(car unevaluated-to-drops))
1141 (,sub-list-sym ,form-under-cdrs))
1142 (nthcdr/-implementation (+ ,@(when (plusp sum-of-known-numerics) (list sum-of-known-numerics)) ,inner-most-to-drop-sym ,@(cdr unevaluated-to-drops)) ,sub-list-sym)))
1143 (let ((sub-list-sym (gensym)))
1144 `(let ((,sub-list-sym ,form-under-cdrs))
1145 (nthcdr/-implementation (+ ,@(when (plusp sum-of-known-numerics) (list sum-of-known-numerics)) ,@unevaluated-to-drops) ,sub-list-sym)))))))))
1150 (defun cdr/-implementation (list)
1151 "Equivalent of Haskell's tail function or CL's CDR - traverses in eager context, defers in lazy."
1152 (typecase list
1153 (lazy-list-known-empty list)
1154 (list (to-lazy-list (cdr list)))
1155 (lazy-list-list-based (to-lazy-list (cdr (get-list-head list))))
1156 (lazy-list
1157 (if-lazy-eager
1158 (typecase list
1159 (lazy-list-under-cdrs
1160 (let ((new-cdr-count (1+ (get-cdr-count list)))
1161 (underlying-call-for-first (get-underlying-call-for-first list)))
1162 (assert (> new-cdr-count 0))
1163 (make-instance-2 'lazy-list-under-cdrs
1164 :call-for-first
1165 (standard-traversal-link
1166 (build (end-call)
1167 (let ((current (resolved (with-traversal-result (value next) (resolved (get-traversal-result-new-end-call underlying-call-for-first end-call)) next))))
1168 (loop for i from 2 to new-cdr-count
1169 while current
1171 (when current (with-traversal-result (value next) (resolved (get-traversal-result current)) (setq current (resolved next)))))
1172 (if current
1173 (get-traversal-result current)
1174 (traversal-result nil nil))))
1176 :cdr-count new-cdr-count
1177 :underlying-call-for-first underlying-call-for-first)))
1179 (let ((call-for-first (get-call-for-first list)))
1180 (make-instance-2 'lazy-list-under-cdrs
1181 :call-for-first
1182 (standard-traversal-link
1183 (build (end-call)
1184 (with-traversal-result
1185 (value next)
1186 (get-traversal-result-new-end-call call-for-first end-call)
1187 (unresolved
1188 (get-traversal-result next))))
1190 :cdr-count 1
1191 :underlying-call-for-first call-for-first))))
1192 (typecase list
1193 (lazy-list-read-point-based
1194 (let ((read-point (get-read-point list)))
1195 (if (read-point-at-end read-point)
1196 (make-instance-2 'lazy-list-known-empty :call-for-first **standard-terminating-end-call**)
1197 (let ((advanced (read-point-advanced read-point)))
1198 (make-instance-2 'lazy-list-read-point-based :call-for-first (call-for-read-point-taken-to-end advanced end-call) :read-point advanced)))))
1200 (make-instance-2
1201 (case (type-of list) ; tail keeps persistence
1202 ((lazy-list-with-persistence lazy-list-with-some-persistence) (type-of list))
1203 (t 'lazy-list))
1204 :call-for-first
1205 (with-traversal-result
1206 (value next)
1207 (get-traversal-result (get-call-for-first list))
1208 (let ((next (resolved next)))
1209 (cond (next) ; Man not having this check was HARD to track down. . . .
1210 (t **standard-terminating-end-call**)))))))))
1211 (t (cdr/ (to-lazy-list list)))))
1212 (defun cdr/ (list) (cdr/-implementation list))
1213 (define-compiler-macro cdr/ (&whole form list)
1214 (full-cdr-based-form-resolution form))
1218 (defun tail/ (list)
1219 "Equivalent of Haskell's tail function (or cdr/ ) - traverses in eager context, defers in lazy."
1220 (cdr/ list))
1221 (define-compiler-macro tail/ (list)
1222 `(cdr/ ,list))
1225 (defun car/ (list)
1226 "Equivalent of CL's car/first or Haskell's head - returns first value in list, or nil if list is empty"
1227 (typecase list
1228 (list (car list))
1229 (lazy-list-list-based (car (get-list-head list)))
1230 (lazy-list
1231 (with-traversal-result (value next) (get-traversal-result (get-call-for-first list)) (resolved value)))
1232 (t (with-traversal-result (value next) (get-traversal-result (get-call-for-first (to-lazy-list list))) (resolved value)))))
1234 (defun head/ (list)
1235 "Equivalent of CL's car/first or Haskell's head - returns first value in list, or nil if list is empty"
1236 (car/ list))
1237 (define-compiler-macro head/ (list) `(car/ ,lst))
1239 (defun first/ (list)
1240 "Equivalent of CL's car/first or Haskell's head - returns first value in list, or nil if list is empty"
1241 (car/ list))
1242 (define-compiler-macro head/ (list) `(cdr/ ,lst))
1244 (defmacro build-car-things ()
1245 `(progn
1246 ,@(loop for len from 2 to 5 collect
1247 `(progn
1248 ,@(labels ((build-it (bits-left val)
1249 (if (zerop bits-left)
1250 (list nil #'identity)
1251 (destructuring-bind (char-list func)
1252 (build-it (1- bits-left) (floor (/ val 2)))
1253 (if (evenp val)
1254 (list (cons #\a char-list) (lambda (elt) `(car/ ,(funcall func elt))))
1255 (list (cons #\d char-list) (lambda (elt) `(cdr/ ,(funcall func elt)))))))))
1256 (loop for combo from 0 to (1- (expt 2 len)) collect
1257 (destructuring-bind (char-list func)
1258 (build-it len combo)
1259 ; (format t ":~A" (concatenate 'string "c" (map 'string #'identity char-list) "r/"))
1260 ;(terpri)
1261 ;(force-output)
1262 (labels ((make-core-string (char-list)
1263 (concatenate 'string "c" (map 'string #'identity char-list) "r"))
1264 (th (n) (case n (1 "1st") (2 "2nd") (3 "3rd") (t (format nil "~Ath" n)))))
1265 `(progn
1266 (defun ,(read-from-string (concatenate 'string (make-core-string char-list) "/"))
1267 (list-designator)
1268 ,(let ((a-count (length (remove-if-not (lambda (elt) (eql elt #\a)) char-list)))
1269 (d-count (length (remove-if-not (lambda (elt) (eql elt #\d)) char-list))))
1270 (cond
1271 ((zerop a-count)
1272 (format nil "Returns list-designator's list with ~A item skipped, as a lazy-list" d-count))
1273 ((= 1 a-count)
1274 (format nil "Returns ~A element in list-designator" (th (1+ d-count))))
1276 (let ((trailing-d-count (length (loop for char in (reverse char-list) while (eql #\d char) collect char))))
1277 (case trailing-d-count
1278 (0 (format nil "~A/ of first element in list-designator" (make-core-string (butlast char-list))))
1280 (format nil "~A/ of ~A element in list-designator" (make-core-string (butlast char-list (1+ trailing-d-count))) (th trailing-d-count))))))))
1281 ,(funcall func 'list-designator))
1282 ,(let ((list-sym (gensym)))
1283 `(define-compiler-macro ,(read-from-string (concatenate 'string (make-core-string char-list) "/"))
1284 (,list-sym)
1285 ,(funcall func list-sym))))))))))))
1286 (build-car-things)
1290 ; returns head and tail as successive values
1291 (defun head-tail/ (list)
1292 "Returns head and tail of list as successive values, and whether or not head is a valid value as the third result."
1293 (etypecase list
1294 (list (values (car list) (to-lazy-list (cdr list)) (consp list)))
1295 (lazy-list-list-based (destructuring-bind (head . tail) (get-list-head list) (values head (to-lazy-list tail) (consp (get-list-head list)))))
1296 (t (with-traversal-result (head tail-call) (resolved (get-traversal-result (get-call-for-first (to-lazy-list list))))
1297 (let ((tail-call (resolved tail-call)))
1298 (if tail-call
1299 (values (resolved head) (lazy-list-from-call tail-call) t)
1300 (values)))))))
1304 (defun nthcdr/-implementation (to-drop list)
1305 "Equivalent to CL's nthcdr or Haskell's drop - returns list with to-drop elements skipped - traversing at point of call in eager context,
1306 deferring traversal in lazy context."
1307 (labels ((nthcdr-known-lazy-list/ (list)
1308 (if-lazy-eager
1309 (lazy-list-from-call
1310 (deferred-traversal-link-from-call-maker
1311 (standard-traversal-link
1312 (build (end-call)
1313 (let ((current (get-call-for-first list)))
1314 (loop for i from 1 to to-drop while current do
1315 (setq current (resolved (with-traversal-result (value next) (get-traversal-result current) (resolved next)))))
1316 (if current
1317 (get-traversal-result-new-end-call current end-call)
1318 (get-traversal-result end-call))))
1319 ())))
1320 (lazy-list-from-call
1321 (let ((current (get-call-for-first list)))
1322 (loop for i from 1 to to-drop while current do
1323 (setq current (resolved (with-traversal-result (value next) (get-traversal-result current) (resolved next)))))
1324 (if current
1325 current
1326 **standard-terminating-end-call**)))
1329 (standard-traversal-link
1330 (build (end-call)
1331 (let ((current (get-call-for-first list)))
1332 (loop for i from 1 to to-drop while current do
1333 (setq current (resolved (with-traversal-result (value next) (get-traversal-result current) (resolved next)))))
1334 (if current
1335 (get-traversal-result-new-end-call current end-call)
1336 (get-traversal-result end-call))))
1337 ()))
1341 (typecase list
1342 (list (to-lazy-list (nthcdr to-drop list)))
1343 (lazy-list-list-based (to-lazy-list (nthcdr to-drop (get-list-head list))))
1344 (lazy-list
1345 (nthcdr-known-lazy-list/ list))
1346 (t (nthcdr-known-lazy-list/ (to-lazy-list list))))))
1347 (defun nthcdr/ (to-drop list) (nthcdr/-implementation to-drop list))
1348 (define-compiler-macro nthcdr/ (&whole form to-drop list)
1349 (full-cdr-based-form-resolution form))
1354 (defun drop/ (to-drop list)
1355 "Equivalent to CL's nthcdr or Haskell's drop - returns list with to-drop elements skipped - traversing at point of call in eager context,
1356 deferring traversal in lazy context."
1357 (nthcdr/ to-drop list))
1358 (define-compiler-macro drop/ (to-drop list)
1359 `(nthcdr/ ,to-drop ,list))
1363 (defun null/ (list)
1364 "Returns nil if list has contents, a value otherwise. Will only traverse a single element for lazy-lists"
1365 (etypecase list
1366 (null t)
1367 (list (null list))
1368 (sequence (zerop (length list)))
1369 (lazy-list-list-based (null (get-list-head list)))
1370 (lazy-list-known-empty t)
1371 (lazy-list (with-traversal-result (value next) (resolved (get-traversal-result (get-call-for-first list))) (not (resolved next))))
1372 (t nil)))
1374 (defun non-null/ (list)
1375 "Not null/"
1376 (not (null/ list)))
1377 (define-compiler-macro non-null/ (list)
1378 `(not (null/ ,list)))
1383 (defun take/ (to-take list)
1384 "Returns a lazy-list of the first to-take elements from list. Performance note: The resulting lazy-list will tend to maintain a reference to the original list, convert to a static container
1385 (via to-list of to-array) to break this link."
1386 (assert (integerp to-take))
1387 (if (zerop to-take)
1388 (make-instance-2 'lazy-list-known-empty :call-for-first **standard-terminating-end-call**)
1389 (lazy-list-from-call
1390 (standard-traversal-link
1391 (build (end-call current-call num-left)
1392 (if current-call
1393 (with-traversal-result
1394 (value next)
1395 (get-traversal-result current-call)
1396 (let ((next (resolved next)))
1397 (if next
1398 (let ((new-num-left (1- num-left)))
1399 (traversal-result value (build end-call (if (zerop new-num-left) nil next) new-num-left)))
1400 (unresolved (get-traversal-result end-call)))))
1401 (unresolved (get-traversal-result end-call))))
1402 ((get-call-for-first (to-lazy-list list)) to-take)))))
1407 (defun split-when---experimental/ (predicate list)
1408 "Returns lazy-lists for before-split-point, and split-point-and-after, as first and second value results"
1409 (labels ((get-split-result ()
1410 (labels ((split-for-proper-list (list)
1411 (let ((current list)
1412 (before-predicate-r nil))
1413 (tagbody
1415 (when current
1416 (let ((val (car current)))
1417 (when (not (funcall predicate val))
1418 (setq current (cdr current))
1419 (push val before-predicate-r)))))
1420 (values (to-lazy-list (nreverse before-predicate-r)) (to-lazy-list current)))))
1421 (let* ((list (to-lazy-list list))
1422 (current (read-point-built list))
1423 (before-predicate-r nil))
1424 (tagbody
1426 (when (not (read-point-at-end current))
1427 (let ((val (read-point-value current)))
1428 (when (not (funcall predicate val))
1429 (setq current (read-point-advanced current))
1430 (push val before-predicate-r)
1431 (go top)))))
1432 (values
1433 (to-lazy-list (nreverse before-predicate-r))
1434 (typecase list
1435 (lazy-list-read-point-based (lazy-list-from-read-point current))
1436 (lazy-list-with-persistence (make-instance-2 'lazy-list-with-persistence :call-for-first (call-to-detach-from-read-point current)))
1437 (t (make-instance-2 'lazy-list :call-for-first (call-to-detach-from-read-point current)))))))))
1438 (if-lazy-eager
1439 (let ((lock (make-thread-lock))
1440 (result-known nil)
1441 (result-first nil)
1442 (result-second nil))
1443 (labels ((ensure-result ()
1444 (when (not result-known) (respecting-lock-if-present (lock) (when (not result-known) (multiple-value-setq (result-first result-second) (get-split-result)) (setq result-known t))))))
1445 (values
1446 (lazy-list-from-call (lambda () (ensure-result) (funcall (get-call-for-first result-first))))
1447 (lazy-list-from-call (lambda () (ensure-result) (funcall (get-call-for-first result-second)))))))
1448 (get-split-result))))
1452 (defun intersperse/ (val list)
1453 "Equivalent of Haskell's intersperse function - returns a lazy-list of val interspersed between elements of list. If list is of length 0 or 1, val does not appear."
1454 (let ((traversal-result (resolved (get-traversal-result (get-call-for-first (to-lazy-list list))))))
1455 (let ((next (resolved (get-next traversal-result))))
1456 (if next
1457 (lazy-list-from-call
1458 (standard-traversal-link
1459 (build (end-call current-value current-resolved-next)
1460 (traversal-result
1461 current-value
1462 (fixed-traversal-link-from-result-form
1463 (if current-resolved-next
1464 (with-traversal-result
1465 (value next)
1466 (get-traversal-result current-resolved-next)
1467 (let ((next (resolved next)))
1468 (if next
1469 (traversal-result
1471 (build end-call value next))
1472 (get-traversal-result end-call))))
1473 (get-traversal-result end-call)))))
1474 ((get-value traversal-result) next)))
1475 (make-instance-2 'lazy-list-known-empty :call-for-first **standard-terminating-end-call**)))))
1478 ; returns 3 values - lazy-list to predicate true, lazy-list of remainder, and (lambda () (values value true-if-found)) at predicate true
1479 (defun split-on-test/ (test list)
1480 (let* ((split-value-known nil)
1481 (known-split-value nil)
1482 (known-post-value-remainder nil)
1483 (rest-of-pre-predicate-read-point
1484 (read-point-from-call
1485 (standard-traversal-link
1486 (build (end-call current-read-point)
1487 (if (read-point-at-end current-read-point)
1488 (progn
1489 (setq rest-of-pre-predicate-read-point (read-point-from-call **standard-terminating-end-call**))
1490 (setq known-post-value-remainder (read-point-from-call **standard-terminating-end-call**))
1491 (get-traversal-result end-call))
1492 (let ((value (read-point-value current-read-point))
1493 (advanced (read-point-advanced current-read-point)))
1494 (if (funcall test value)
1495 (progn
1496 (setq known-split-value value)
1497 (setq split-value-known t)
1498 (setq rest-of-pre-predicate-read-point (read-point-from-call **standard-terminating-end-call**))
1499 (setq known-post-value-remainder advanced)
1500 (get-traversal-result end-call))
1501 (progn
1502 (setq rest-of-pre-predicate-read-point advanced)
1503 (traversal-result value (build end-call advanced)))))))
1504 ((read-point-built (to-lazy-list list)))))))
1505 (values
1506 (lazy-list-from-read-point rest-of-pre-predicate-read-point)
1507 (lazy-list-from-call
1508 (standard-traversal-link
1509 (build (end-call)
1510 (loop while (progn (read-point-at-end rest-of-pre-predicate-read-point) (not known-post-value-remainder)) do (setq rest-of-pre-predicate-read-point (read-point-advanced rest-of-pre-predicate-read-point)))
1511 (get-traversal-result-new-end-call (call-to-detach-from-read-point known-post-value-remainder) end-call))
1512 ()))
1513 (lambda ()
1514 (loop while (progn (read-point-at-end rest-of-pre-predicate-read-point) (not known-post-value-remainder)) do (setq rest-of-pre-predicate-read-point (read-point-advanced rest-of-pre-predicate-read-point)))
1515 (values known-split-value split-value-known)))))
1519 (defun split-on-test-to-first-non-empty-before/ (test list)
1520 (multiple-value-bind (before after call)
1521 (split-on-test/ test list)
1522 (let ((before before)
1523 (call call)
1524 (after after))
1525 (let ((before-null (null/ before))
1526 (after-null (null/ after)))
1527 (loop while (and before-null (not after-null)) do
1528 (multiple-value-setq (before after call)
1529 (split-on-test/ test after))
1530 (setq before-null (null/ before))
1531 (setq after-null (null/ after)))
1532 (multiple-value-bind (split-val split-val-present)
1533 (funcall call)
1534 (if (and before-null after-null (not split-val-present))
1535 (call-for-end)
1536 (values split-val split-val-present before before-null after after-null)))))))
1539 ; returns list of list, value, list, value, list, value, list where value = something that triggers test
1540 (defun split-down-on-test/ (test list &key (keep-split-causing-elements nil) (keep-empty-non-split t) (process-split-causing-element #'identity) (process-non-split-causing-elements-list #'identity))
1541 (lazy-list-from-call
1542 (if keep-split-causing-elements
1543 (standard-traversal-link
1544 (build-keep (end-call list)
1545 (multiple-value-bind (before after val-maker)
1546 (split-on-test/ test list)
1547 (multiple-value-bind (v exists)
1548 (funcall val-maker)
1549 (cond
1550 ((and exists (null/ before) (not keep-empty-non-split)) (traversal-result (funcall process-split-causing-element v) (build-keep end-call after)))
1551 (exists (traversal-result
1552 (funcall process-non-split-causing-elements-list before)
1553 (fixed-traversal-link (funcall process-split-causing-element v) (build-keep end-call after))))
1554 ((not (null/ before)) (traversal-result
1555 (funcall process-non-split-causing-elements-list before)
1556 end-call))
1557 (t (unresolved (get-traversal-result end-call)))))))
1558 (list))
1559 (standard-traversal-link
1560 (build-no-keep (end-call list)
1561 ; Find first non-null "before"
1562 ; (progn (to-list list) (print "list good 1"))
1563 (multiple-value-bind (before after call)
1564 (split-on-test/ test list)
1565 (let ((before before)
1566 (call call)
1567 (after after))
1568 (let ((before-null (null/ before))
1569 (after-null (null/ after)))
1570 (unless keep-empty-non-split
1571 (loop while (and before-null (not after-null)) do
1572 (multiple-value-setq (before after call)
1573 (split-on-test/ test after))
1574 (setq before-null (null/ before))
1575 (setq after-null (null/ after))))
1576 (if (and before-null after-null)
1577 (unresolved (get-traversal-result end-call))
1578 (progn
1579 (traversal-result
1580 before
1581 (build-no-keep end-call after))))))))
1582 (list)))))
1588 (defun map/ (function first &rest other-lazy-lists)
1589 (assert (functionp function))
1590 (lazy-list-from-call
1591 (standard-traversal-link (build (end-call callers-list)
1592 (let ((result-stash
1593 (loop for caller in callers-list collect
1594 (with-traversal-result (value next)
1595 (get-traversal-result caller)
1596 (let ((next (resolved next)))
1597 (if next
1598 (cons next value)
1599 (return nil)))))))
1600 (if result-stash
1601 (traversal-result
1602 (apply function (mapcar (lambda (elt) (resolved (cdr elt))) result-stash))
1603 (build end-call (mapcar #'car result-stash)))
1604 (unresolved (get-traversal-result end-call)))))
1605 ((mapcar
1606 (lambda (elt) (get-call-for-first (to-lazy-list elt)))
1607 (cons first other-lazy-lists))))))
1612 (eval-when (:compile-toplevel :load-toplevel :execute)
1613 (defparameter **sequence-sources**
1615 (:standard-lazy-list
1616 ,(lambda (input)
1617 `(:get-first-link (get-call-for-first (to-lazy-list ,input))
1618 :get-value-next-extractor ,(lambda (link-sym exit-form)
1619 `(with-traversal-result (value next)
1620 (get-traversal-result ,link-sym)
1621 (let ((next (resolved next)))
1622 (unless next ,exit-form)
1623 (values value next))))
1624 :get-value-resolution ,(lambda (value-sym) `(resolved ,value-sym)))))
1629 ;? Temporarily shelved.
1631 (define-compiler-macro map/ (&whole form func first &rest rest)
1632 (let* ((call-form-precond-parameters (get-call-form-precond-parameters (function-literal-to-form func) (1+ (length rest))))
1633 (result-sym-lists (mapcar #'list* (first call-form-precond-parameters) (loop for i from 0 to (length rest) collect (list (gensym) (gensym) (gensym)))))
1634 (per-source-generators (loop for input in (cons first rest) collect (funcall (second (assoc :standard-lazy-list **sequence-sources**)) input)))
1635 (end-call-sym (gensym))
1636 (exit-sym (gensym))
1637 (next-sym (gensym))
1638 (value-sym (gensym))
1639 (build-func-sym (gensym)))
1640 `(lazy-list-from-call
1641 (standard-traversal-link
1642 (,build-func-sym (,end-call-sym ,@(mapcar #'fourth result-sym-lists))
1643 (block ,exit-sym
1644 (let ,(loop for result-sym-list in result-sym-lists append
1645 (list (second result-sym-list) (third result-sym-list)))
1646 ,@(loop for result-sym-list in result-sym-lists
1647 for per-source-generator in per-source-generators
1648 collect
1649 `(multiple-value-bind (,value-sym ,next-sym)
1650 ,(funcall (getf per-source-generator :get-value-next-extractor)
1651 (fourth result-sym-list)
1652 `(return-from ,exit-sym (unresolved (get-traversal-result ,end-call-sym))))
1653 (setq ,(second result-sym-list) ,next-sym)
1654 (setq ,(third result-sym-list) ,value-sym)))
1655 (traversal-result
1656 (let ,(loop for result-sym-list in result-sym-lists collect `(,(first result-sym-list) ,(third result-sym-list)))
1657 ,(get-call-form (function-literal-to-form func) call-form-precond-parameters (mapcar (rcurried #'getf :get-value-resolution) per-source-generators)))
1658 (,build-func-sym ,end-call-sym ,@(mapcar #'second result-sym-lists))))))
1659 ; ,(mapcar (lambda (input) `(get-call-for-first (to-lazy-list ,input))) (cons first rest))
1660 ,(mapcar (rcurried #'getf :get-first-link) per-source-generators)
1661 ))))
1665 ; (funcall (compiler-macro-function 'map/) '(map/ #'1+ '(1 2 3 4)) nil)
1666 ; (pprint (funcall (compiler-macro-function 'map/) '(map/ (lambda (x) (* x 2)) '(1 2 3 4)) nil))
1667 ; (pprint (funcall (compiler-macro-function 'map/) '(map/ (lambda (x y) (* x y 2)) '(1 2 3 4) '(5 6 7 8)) nil))
1668 ; (defun test () (map/ (lambda (x y) (* x y 2)) '(1 2 3 4) '(5 6 7 8)))
1669 ; (defun test () (map/ #'+ '(1 2 3 4) '(5 6 7 8)))
1670 ; (pprint (funcall (compiler-macro-function 'map/) '(map/ (curried (curried #'+ 100) 200) '(1 2 3 4)) nil))
1671 ; (pprint (funcall (compiler-macro-function 'map/) '(map/ (curried (curried (lambda (a b c) (+ a b c)) 100) 200) '(1 2 3 4)) nil))
1672 ; (defun test () (map/ (curried (curried (lambda (a b c) (+ a b c)) 100) 200) '(1 2 3 4)))
1673 ; (pprint (funcall (compiler-macro-function 'map/) '(map/ (composed #'1+ #'1+) '(1 2 3 4)) nil))
1674 ; (defun test () (map/ (composed #'1+ #'1+) '(1 2 3 4)))
1675 ; (pprint (funcall (compiler-macro-function 'map/) '(map/ (constantly 69) '(1 2 3 4)) nil))
1681 (defun split-positional/ (positional list)
1682 "Splits on positional - positional can be an integer zero-index, a function
1683 (that validates that an index is a split-point), or a list of indices that is assumed to already be sorted."
1684 (typecase positional
1685 (integer (multiple-value-bind (before after call)
1686 (split-on-test/ (lambda (elt) (= (cdr elt) positional)) (map/ (lambda (elt pos) (cons elt pos)) list (iterate/ #'1+ 0)))
1687 (multiple-value-bind (split-val split-val-valid)
1688 (funcall call)
1689 (values (map/ #'car before) (map/ #'car (append/ (when split-val-valid split-val) after))))))
1691 (let ((split-masks
1692 (typecase positional
1693 (function (map/ positional (iterate/ #'1+ 0)))
1695 (map/
1696 (lambda (elt) (eql (car elt) (first/ (cdr elt))))
1697 (iterate/
1698 (lambda (elt)
1699 (eager
1700 (destructuring-bind (index . remainder) elt (cons (1+ index) (if (eql index (car/ remainder)) (cdr/ remainder) remainder)))))
1701 (cons 0 positional)))))))
1702 (labels ((build (split-remainder)
1703 (lambda ()
1704 (multiple-value-bind (head tail valid)
1705 (head-tail/ split-remainder)
1706 (if valid
1707 (if (consp head)
1708 (if (null/ tail)
1709 (values (list/ head) (lambda () nil nil))
1710 (multiple-value-bind (th tt tv)
1711 (head-tail/ tail)
1712 (if (consp th)
1713 (values (list/ head) (build tail))
1714 (values (list*/ head th) (build tt)))))
1715 (values head (build tail)))
1716 (call-for-end))))))
1717 (map/ (curried #'map/ #'car) (lazy-list-from-call (build (split-down-on-test/ #'cdr (map/ #'cons list split-masks) :keep-split-causing-elements t :keep-empty-non-split nil)))))))))
1721 (defun take-while/ (test list)
1722 "Returns a lazy-list representing elements of list while test (run against values) returns true. Performance note: Will tend to maintain reference to the original list,
1723 create a new static list (via to-list or to-array) if this is a concern."
1724 (assert (functionp test))
1725 (lazy-list-from-call
1726 (standard-traversal-link
1727 (build (end-call current-call)
1728 (if current-call
1729 (with-traversal-result
1730 (value next)
1731 (get-traversal-result current-call)
1732 (let ((next (resolved next)))
1733 (if next
1734 (let ((value (resolved value)))
1735 (if (funcall test value)
1736 (traversal-result value (build end-call next))
1737 (unresolved (get-traversal-result end-call))))
1738 (unresolved (get-traversal-result end-call)))))
1739 (unresolved (get-traversal-result end-call))))
1740 ((resolved (get-call-for-first (to-lazy-list list)))))))
1744 (defun drop-while/ (test list)
1745 "Returns the subset of list after test returns false - in eager context, traverses immediately - in lazy, upon first traversal of resultant lazy-list. Performance note: If list uses
1746 some form of memoization/caching, and another instance has \"cached ahead\", the result lazy-list will be bound to the cache until it can overtake it."
1747 (assert (functionp test))
1748 (labels ((get-read-point-after-test ()
1749 (let ((current (read-point-built (to-lazy-list list))))
1750 (tagbody
1752 (when (and (not (read-point-at-end current)) (funcall test (read-point-value current)))
1753 (setq current (read-point-advanced current))
1754 (go top)))
1755 current)))
1756 (if-lazy-eager
1757 (lazy-list-from-call (fixed-traversal-link-from-result-form (get-traversal-result (call-to-detach-from-read-point (get-read-point-after-test)))))
1758 (lazy-list-from-call (call-to-detach-from-read-point (get-read-point-after-test))))))
1761 (defun position/ (item list &key (test #'eql))
1762 "Returns the first 0-index of item in list that satisfies test, nil if not found"
1763 (let ((current (read-point-built (to-lazy-list list)))
1764 (pos 0))
1765 (tagbody
1767 (when (and (not (read-point-at-end current)) (not (funcall test (read-point-value current) item)))
1768 (setq current (read-point-advanced current))
1769 (incf pos)
1770 (go top)))
1771 (if (read-point-at-end current)
1773 pos)))
1777 (defun nth/ (index list)
1778 "Equivalent of CL's NTH; but traverses CL sequences or lazy-lists"
1779 (assert (integerp index))
1780 (typecase list
1781 (array (aref list index))
1782 (list (nth index list))
1784 (let ((read-point (read-point-built (to-lazy-list list)))
1785 (known-at-end nil))
1786 (setq list nil) ; to help make "list" eligible for gc.
1787 (loop for i from 1 to index
1788 while (not (setq known-at-end (read-point-at-end read-point)))
1790 (setq read-point (read-point-advanced read-point)))
1791 (unless known-at-end
1792 (read-point-value read-point))))))
1795 (defun second/ (list)
1796 "Like CL's second; but can acommodate lazy-lists or CL sequences"
1797 (car/ (cdr/ list)))
1799 (define-compiler-macro second/ (list) `(cadr/ ,list))
1801 (defun third/ (list)
1802 "Like CL's third; but can acommodate lazy-lists or CL sequences"
1803 (car/ (cdr/ (cdr/ list))))
1804 (define-compiler-macro third/ (list) `(caddr/ ,list))
1808 (defun tails/ (list)
1809 "Returns list of lists, with each list being the (cdr/) of the previous one. Final list in sequence is empty list."
1810 (labels ((tails-list-for-proper-list (list)
1811 (make-instance-2 'lazy-list-with-persistence
1812 :call-for-first
1813 (standard-traversal-link
1814 (build (end-call remainder)
1815 (if remainder
1816 (traversal-result (to-lazy-list remainder) (build end-call (cdr remainder)))
1817 (traversal-result (list/) end-call)))
1818 (list)))))
1819 (typecase list
1820 (list (tails-list-for-proper-list list))
1821 (lazy-list-list-based (tails-list-for-proper-list (get-list-head list)))
1823 (let ((new-class-type
1824 (cond
1825 ((typep list 'lazy-list-with-persistence) 'lazy-list-with-persistence) ; list based or with full persist, this persist (minor calc)
1827 ((typep list 'lazy-list-with-some-persistence) 'lazy-list-with-some-persistence) ; will not grant the memoize - may want memoized to
1828 ; surrender the readpoint
1829 (t 'lazy-list))))
1830 (make-instance-2 new-class-type
1831 :call-for-first
1832 (standard-traversal-link
1833 (build (end-call call)
1834 (with-traversal-result (value next)
1835 (get-traversal-result call)
1836 (let ((next (resolved next)))
1837 (if next
1838 (let ((value (resolved value)))
1839 (traversal-result
1840 (make-instance-2 new-class-type :call-for-first (fixed-traversal-link value next))
1841 (build end-call next)))
1842 (traversal-result (list/) (fixed-traversal-link-from-result-form (get-traversal-result end-call)))))))
1843 ((get-call-for-first (to-lazy-list list))))))))))
1852 (defun concat/ (list)
1853 (lazy-list-from-call
1854 (macrolet! ((do-slam (params-sym body end-call-sym)
1855 `(unresolved
1856 (with-slam-sinks (,params-sym)
1857 (labels ((,g!slam-func (,g!tlc ,g!accum)
1858 (with-traversal-result (,g!sub-list ,g!call-for-next)
1859 (resolved (get-traversal-result ,g!tlc))
1860 (let ((,g!call-for-next (resolved ,g!call-for-next)))
1861 (if ,g!call-for-next
1862 (slam-for-continue (to-lazy-list (resolved ,g!sub-list))
1863 (lambda (,g!count)
1864 (,g!slam-func ,g!call-for-next (+ ,g!count ,g!accum))))
1865 (end-call-thing ,end-call-sym ,g!accum))))))
1866 (,g!slam-func top-level-call 0))))))
1867 (standard-traversal-link-parametric
1868 (build (end-call top-level-call)
1869 (with-traversal-result (sub-list call-for-next-sublist)
1870 (resolved (get-traversal-result top-level-call))
1871 (let ((call-for-next-sublist (resolved call-for-next-sublist)))
1872 (if call-for-next-sublist
1873 (unresolved
1874 (get-traversal-result-new-end-call
1875 (get-call-for-first (to-lazy-list (resolved sub-list)))
1876 (unresolved (build end-call call-for-next-sublist))))
1877 (unresolved (get-traversal-result end-call))))))
1878 ((get-call-for-first (to-lazy-list list)))))))
1881 (defun append/ (&rest list-of-lists)
1882 (if (cdr list-of-lists) ; i.e. more than one
1883 (concat/ list-of-lists)
1884 (to-lazy-list (first list-of-lists))))
1886 ; (A B C) == (cons A (cons B C))
1887 (defun list*/ (&rest list-list-terminated)
1888 "Basically CL's list* - \"conses\" all elements but last onto list in last parameter, returning a lazy-list."
1889 (lazy-list-from-call
1890 (standard-traversal-link
1891 (build (end-call remainder)
1892 (destructuring-bind (car-remainder &rest cdr-remainder) ; so as to only capture required pieces.
1893 remainder
1894 (if cdr-remainder
1895 (traversal-result car-remainder (build end-call cdr-remainder))
1896 (unresolved (get-traversal-result-new-end-call (get-call-for-first (to-lazy-list car-remainder)) end-call)))))
1897 (list-list-terminated))))
1902 (defun assoc/ (item alist &rest rest)
1903 "CL's assoc; but works with lazy-lists of cons pairs"
1904 (typecase alist
1905 (list (apply #'assoc item alist rest))
1907 (destructuring-bind (&key (test #'eql) (key #'identity))
1908 rest
1909 (let ((current (read-point-built alist)))
1910 (tagbody
1912 (when (not (read-point-at-end current))
1913 (when (not (funcall test item (funcall key (first (read-point-value current)))))
1914 (setq current (read-point-advanced current))
1915 (go top))))
1916 (when (not (read-point-at-end current))
1917 (read-point-value current)))))))
1920 (defun prepend/ (&rest list-list-terminated)
1921 "CL's list*, returning a lazy-list"
1922 (apply #'list*/ list-list-terminated))
1926 (defun filter/ (predicate list)
1927 (lazy-list-from-call
1928 (standard-traversal-link
1929 (filter-call (end-call current-call)
1930 (with-traversal-result
1931 (value next)
1932 (get-traversal-result current-call)
1933 (let ((next (resolved next))
1934 (value value))
1935 (block nil
1936 (tagbody
1938 (if next
1939 (let ((val (resolved value)))
1940 (if (funcall predicate val)
1941 (return (traversal-result val (filter-call end-call next)))
1942 (with-traversal-result
1943 (v2 n2)
1944 (get-traversal-result next)
1945 (setq next n2)
1946 (setq value v2)
1947 (go top))))
1948 (return (get-traversal-result end-call))))))))
1949 ((get-call-for-first (to-lazy-list list))))))
1957 ; Needs optimization, to put
1958 (defun nub-by/ (equality list)
1959 (let ((hash (make-hash-table :test equality))
1960 (readpoint-seeking-end nil))
1961 (values
1962 (let ((return-list
1963 (memoized/
1964 (lazy-list-from-call
1965 (standard-traversal-link
1966 (read-point-to-call (end-call start)
1967 (let ((current start)
1968 (value nil))
1969 (tagbody
1971 (when (not (read-point-at-end current))
1972 (setq value (read-point-value current))
1973 (multiple-value-bind (current-val current-val-valid)
1974 (gethash value hash)
1975 (if current-val-valid
1976 (progn
1977 (setq current (read-point-advanced current))
1978 (go top))
1979 (setf (gethash value hash) t)))))
1980 (if (read-point-at-end current)
1981 (unresolved (get-traversal-result end-call))
1982 (traversal-result
1983 value
1984 (read-point-to-call end-call (read-point-advanced current))))))
1985 ((read-point-built (to-lazy-list list))))))))
1986 (setq readpoint-seeking-end (read-point-built return-list))
1987 return-list)
1988 (lambda (key)
1989 (when readpoint-seeking-end
1990 (loop while (not (read-point-at-end readpoint-seeking-end)) do (setq readpoint-seeking-end (read-point-advanced readpoint-seeking-end))))
1991 (multiple-value-bind (dummy exists) (gethash key hash) exists)))))
1993 (defun nub/ (list) (nub-by/ #'eql list))
1995 (defun and/ (list)
1996 "Returns last element or nil"
1997 (let ((last nil))
1998 (block :exit
1999 (loop-over/ elt (to-lazy-list list)
2000 (if elt
2001 (setq last elt)
2002 (return-from :exit nil)))
2003 last)))
2005 (defun or/ (list)
2006 ; "Returns first non-nil element or nil"
2007 (block :exit
2008 (loop-over/ elt (to-lazy-list list)
2009 (if elt
2010 (return-from :exit elt)))
2011 nil))
2013 (defun latch-on/ (func list &key (initial-value nil))
2014 (labels ((build (read-point latched latched-val)
2015 (lambda ()
2016 (if (read-point-at-end read-point)
2017 (call-for-end)
2018 (if latched
2019 (values latched-val (build (read-point-advanced read-point) t latched-val))
2020 (let ((val (read-point-value read-point)))
2021 (if (funcall func val)
2022 (values val (build (read-point-advanced read-point) t val))
2023 (values
2024 initial-value
2025 (build (read-point-advanced read-point) nil nil)))))))))
2026 (lazy-list-from-call (build (read-point-built (to-lazy-list list)) nil nil))))
2028 (defun foldl/ (function first list)
2029 (assert (functionp function))
2030 (etypecase list
2031 (sequence (reduce function list :from-end nil :initial-value first))
2032 (lazy-list-list-based
2033 (reduce function (get-list-head list) :from-end nil :initial-value first))
2034 (lazy-list
2035 (let ((accum first)
2036 (current (get-call-for-first list)))
2037 (tagbody
2039 (with-traversal-result (val next)
2040 (get-traversal-result current)
2041 (let ((next (resolved next)))
2042 (when next
2043 (setf accum (funcall function accum (resolved val)))
2044 (setf current next)
2045 (go top)))))
2046 accum))))
2051 (defun foldl1/ (function list)
2052 (typecase list
2053 (sequence (reduce function list :from-end nil))
2054 (lazy-list-list-based (reduce function (get-list-head list) :from-end nil))
2056 (with-traversal-result (value next)
2057 (get-traversal-result (get-call-for-first (to-lazy-list list)))
2058 (let ((current (resolved next))
2059 (accum (resolved value)))
2060 (loop while current do
2061 (with-traversal-result (value next)
2062 (get-traversal-result current)
2063 (let ((next (resolved next)))
2064 (setq current next)
2065 (when next
2066 (setq accum (funcall function accum (resolved value)))))))
2067 accum)))))
2071 (defun foldr/ (function first list)
2072 (assert (functionp function))
2073 (etypecase list
2074 (sequence (reduce function list :from-end t :initial-value first))
2075 (lazy-list-list-based
2076 (reduce function (get-list-head list) :from-end t :initial-value first))
2077 (lazy-list
2078 (reduce function (to-list list) :from-end t :initial-value first))))
2080 (defun foldr1/ (function list)
2081 (assert (functionp function))
2082 (etypecase list
2083 (sequence (reduce function list :from-end t ))
2084 (lazy-list-list-based
2085 (reduce function (get-list-head list) :from-end t))
2086 (lazy-list
2087 (reduce function (to-list list) :from-end t ))))
2090 (defun scanl/ (function first list)
2091 (lazy-list-from-call
2092 (standard-traversal-link
2093 (build (end-call first call)
2094 (with-traversal-result
2095 (val next)
2096 (get-traversal-result call)
2097 (let ((next (resolved next)))
2098 (if next
2099 (traversal-result first (build end-call (funcall function first (resolved val)) next))
2100 (traversal-result first end-call)))))
2101 (first (get-call-for-first (to-lazy-list list))))))
2104 (defun scanl1/ (function list)
2105 (lazy-list-from-call
2106 (standard-traversal-link
2107 (build (end-call first first-valid call)
2108 (with-traversal-result
2109 (val next)
2110 (get-traversal-result call)
2111 (let ((next (resolved next)))
2112 (if next
2113 (if first-valid
2114 (traversal-result first (build end-call (funcall function first (resolved val)) t next))
2115 (unresolved (get-traversal-result (build end-call (resolved val) t next))))
2116 (traversal-result first end-call)))))
2117 (nil nil (get-call-for-first (to-lazy-list list))))))
2120 (defun scanr/ (function first list)
2121 (labels ((build-result-list-call ()
2122 (let ((result (list first)))
2123 (loop for elt in (reverse (to-list list)) do
2124 (push (funcall function elt (car result)) result))
2125 (list-to-lazy-list-call result))))
2126 (if-lazy-eager
2127 (lazy-list-from-call
2128 (deferred-traversal-link-from-call-maker (build-result-list-call)))
2129 (lazy-list-from-call (build-result-list-call)))))
2133 (defun scanr1/ (function list)
2134 (labels ((build-result-list-call ()
2135 (let* ((reversed (reverse (to-list list)))
2136 (result (list (first reversed))))
2137 (if reversed
2138 (progn
2139 (loop for elt in (cdr reversed) do
2140 (push (funcall function elt (car result)) result))
2141 (list-to-lazy-list-call result))
2142 (list-to-lazy-list-call nil)))))
2143 (if-lazy-eager
2144 (lazy-list-from-call
2145 (deferred-traversal-link-from-call-maker (build-result-list-call)))
2146 (lazy-list-from-call (build-result-list-call)))))
2150 (defun grouped-by-firsts/ (test list-of-pair-conses)
2151 (labels ((build-list ()
2152 (let ((hash (make-hash-table :test test)))
2153 (loop-over/
2155 (to-lazy-list list-of-pair-conses)
2156 (destructuring-bind (key . value) (to-list elt)
2157 (setf (gethash key hash) (cons value (gethash key hash)))))
2158 (values
2159 (get-call-for-first
2160 (map/ (lambda (key) (cons key (gethash key hash)))
2161 (loop for key being the hash-keys of hash collect (progn (setf (gethash key hash) (nreverse (gethash key hash))) key))))
2162 (lambda (key)
2163 (gethash key hash))))))
2164 (if-lazy-eager
2165 (let ((build-call-values-list nil))
2166 (labels ((verify-data-ready ()
2167 (cond (build-call-values-list)
2168 (t (setq build-call-values-list (multiple-value-list (build-list)))))))
2169 (values
2170 (lazy-list-from-call
2171 (fixed-traversal-link-from-result-form (get-traversal-result (first (verify-data-ready)))))
2172 (second (verify-data-ready)))))
2173 (multiple-value-bind (list query)
2174 (build-list)
2175 (values
2176 (lazy-list-from-call list)
2177 query)))))
2181 (defun grouped-cdrs-by-car/ (list-of-cons-pairs &key (test 'eql))
2182 "Takes a list of cons pairs, of the form (first . second) - returns a list of conses of the form (first . (second 0 second1 second2 second3....)) as the first value, where the seconds are matches on first.
2183 Second return value is a function, that returns a list of seconds based on a search key/first as first value, found (T or NIL) as second.
2184 When run in an eager context, grouped-by-first-in-cons-pairs/ calculates the internal hash immediately.
2185 When run in a lazy context, the creation of the internal hash is deferred - and is on the first request of either the resultant list, or execution of the second return value."
2186 (grouped-by-firsts/ test list-of-cons-pairs))
2188 (defun grouped-seconds-by-first/ (list-of-list-pairs &key (test 'eql))
2189 "Equivalent to grouped-cdrs-by-car/ , except that the input pairs come as a list of lists, instead of a list of conses."
2190 (grouped-by-firsts/ test (map/ (curried #'apply #'cons) list-of-list-pairs)))
2195 (defun sort-by/ (ordering list)
2196 (labels ((get-as-distinct-sortable ()
2197 (typecase list
2198 (list (copy-seq list))
2199 (sequence (map 'list #'identity list))
2200 (lazy-list-list-based (copy-seq (to-list list)))
2201 (t (to-list list))))) ; based on assumption that only sequences and lazy-list-list-based will to-list to a sequence
2203 (assert (functionp ordering))
2204 (if-lazy-eager
2205 (lazy-list-from-call
2206 (fixed-traversal-link-from-result-form
2207 (let ((sorted (get-as-distinct-sortable)))
2208 (setq sorted (sort sorted ordering))
2209 (get-traversal-result
2210 (get-call-for-first (to-lazy-list sorted))))))
2211 (let ((sorted (get-as-distinct-sortable)))
2212 (setq sorted (sort sorted ordering))
2213 (to-lazy-list sorted)))))
2215 (defun sort/ (list)
2216 (sort-by/ #'< list))
2223 (defmacro self-ref-list/ (ref-name &body definition)
2224 (let ((self-sym (gensym))
2225 (end-call-sym (gensym)))
2226 `(lazy-list-from-call
2227 (fixed-traversal-link-from-result-form
2228 (get-traversal-result
2229 (get-call-for-first
2230 (let ((,self-sym :error))
2231 (symbol-macrolet ((,ref-name (lazy-list-from-call (fixed-traversal-link-from-result-form (get-traversal-result ,self-sym)))))
2232 (let* ((ref (memoized/ (lazy ,@definition)))
2233 (call (get-call-for-first ref)))
2234 (setq ,self-sym call)
2235 ref)))))))))
2239 (defmacro let/ (definitions &body body)
2240 `(let
2241 ,(mapcar
2242 (lambda (entry)
2243 (if (consp entry)
2244 (destructuring-bind (var-name value-clause)
2245 (if (consp entry) entry (list entry nil))
2246 `(,var-name
2247 (self-ref-list/ ,var-name ,value-clause)))
2248 entry))
2249 definitions)
2250 ,@body))
2254 (defstruct hash-table-description
2255 (hash-function :error :type function :read-only t)
2256 (test :error :type function :read-only t))
2258 (defstruct (const-hash-table
2259 (:constructor new-const-hash-table (hash-table-description root-node)))
2260 (hash-table-description :error :read-only t)
2261 (root-node :error :read-only t))
2262 ; (defconstant old-make-const-hash-table #'make-const-hash-table)
2266 (defmethod print-object ((const-hash-table const-hash-table) stream)
2267 (format stream "Const Hashtable"))
2270 (defstruct equal-hash-key-value-pairs
2271 (count :error :type fixnum :read-only t)
2272 (key-value-pairs :error :type cons :read-only t)) ; this is a list, BIGGER than one; but ending not on nil but on the hash value.
2273 ; hash value is only needed when strikign the end. Hash value is a fixnum.
2275 (defstruct hash-leaf-node
2276 (hash :error :type fixnum :read-only t)
2277 (key-value :error :type cons :read-only t))
2279 (defstruct (hash-bucket-node
2280 (:constructor new-hash-bucket-node (count contents-mask lookup)))
2281 (count :error :type fixnum :read-only t)
2282 (contents-mask :error :type fixnum :read-only t)
2283 (lookup :error :type simple-array :read-only t))
2286 (eval-when (:compile-toplevel :load-toplevel :execute)
2287 (defparameter **bucket-node-bucket-size** 16)
2288 (defparameter **per-level-shift** 4)
2291 (defmacro shift-at-end (shift)
2292 `(< ,shift -31))
2295 (defun make-const-hash-table (&key (hash-function #'sxhash) (test #'eql) (key-value-pairs nil))
2296 (let ((result (new-const-hash-table (make-hash-table-description :test test :hash-function hash-function) nil)))
2297 (if key-value-pairs
2298 (const-hash-table-with-changes result nil key-value-pairs)
2299 result)))
2302 (defun const-hash-table-count (const-hash-table)
2303 (let ((root-node (const-hash-table-root-node const-hash-table)))
2304 (etypecase root-node
2305 (hash-bucket-node (hash-bucket-node-count root-node))
2306 (hash-leaf-node 1)
2307 (cons 1)
2308 (equal-hash-key-value-pairs (equal-hash-key-value-pairs-count root-node))
2309 (null 0))))
2312 ; second value is nil if not found
2313 (defun const-hash-table-lookup (const-hash-table key)
2314 (with-accessors ((hash-table-description const-hash-table-hash-table-description))
2315 const-hash-table
2316 (with-accessors ((hash-function hash-table-description-hash-function)
2317 (test hash-table-description-test))
2318 hash-table-description
2319 (let* ((hash (funcall hash-function key))
2320 (rolling-hash hash)
2321 (node (const-hash-table-root-node const-hash-table)))
2322 (declare (type fixnum hash rolling-hash))
2323 (block :exit
2324 (loop
2325 (etypecase node
2326 (hash-bucket-node
2327 (let ((bucket-to-find (logand rolling-hash #.(1- **bucket-node-bucket-size**)))
2328 (contents-mask (hash-bucket-node-contents-mask node)))
2329 (declare (type fixnum bucket-to-find contents-mask))
2330 (if (plusp (logand contents-mask (ash 1 bucket-to-find))) ; see if there's an entry at the bucket we want.
2331 (let ((current-bucket-index 0)) ; loop through others to get the index in lookup
2332 (declare (type fixnum current-bucket-index))
2333 (loop for bucket from 0 to (1- bucket-to-find) do
2334 (when (plusp (logand contents-mask (ash 1 bucket)))
2335 (incf current-bucket-index)))
2336 (setq node (aref (hash-bucket-node-lookup node) current-bucket-index))
2337 (setq rolling-hash (ash rolling-hash #.(- **per-level-shift**))))
2338 (return-from :exit (values nil nil)))))
2339 (hash-leaf-node
2340 (return-from :exit
2341 (if (funcall test key (car (hash-leaf-node-key-value node)))
2342 (values (cdr (hash-leaf-node-key-value node)) t)
2343 (values nil nil))))
2344 (cons
2345 (return-from :exit
2346 (if (funcall test key (car node))
2347 (values (cdr node) t)
2348 (values nil nil))))
2349 (equal-hash-key-value-pairs
2350 (loop for key-value-remainder on (equal-hash-key-value-pairs-key-value-pairs node) do
2351 (declare (type cons key-value-remainder))
2352 (let ((key-value (car key-value-remainder)))
2353 (declare (type cons key-value))
2354 (when (funcall test key (car key-value))
2355 (return-from :exit (values (cdr key-value) t)))))
2356 (return-from :exit (values nil nil)))
2357 (null (return-from :exit (values nil nil))))))))))
2360 (defun const-hash-table-with-changes (const-hash-table keys-to-remove key-value-pairs-to-add)
2361 (with-accessors ((hash-table-description const-hash-table-hash-table-description)
2362 (root-node const-hash-table-root-node))
2363 const-hash-table
2364 (let ((test (hash-table-description-test hash-table-description))
2365 (hash-function (hash-table-description-hash-function hash-table-description)))
2366 (labels ((get-node-element-count (node)
2367 (etypecase node
2368 (hash-bucket-node (hash-bucket-node-count node))
2369 (hash-leaf-node 1)
2370 (cons 1)
2371 (equal-hash-key-value-pairs (equal-hash-key-value-pairs-count node))))
2372 (from-hash-leaf-nodes (hash-leaf-nodes-to-add shift)
2373 (declare (type fixnum shift))
2374 (cond
2375 ((null hash-leaf-nodes-to-add) nil)
2376 ((cdr hash-leaf-nodes-to-add) ; more than one to add - if at shift-end, they're all equal-hash else make lookup.
2377 (if (shift-at-end shift)
2378 (let ((count 0)
2379 (key-value-pairs-r (hash-leaf-node-hash (cdar hash-leaf-nodes-to-add))) ; list will dot-end with hash value instead of nil
2380 ; (known-hash (hash-leaf-node-hash (cdar hash-leaf-nodes-to-add)))
2382 (declare (type fixnum count known-hash))
2383 (loop while hash-leaf-nodes-to-add do
2384 (let* ((current hash-leaf-nodes-to-add) ; we'll be recycling the cons "current"
2385 (new-key-value (hash-leaf-node-key-value (cdar current)))
2386 (new-key (car new-key-value)))
2387 (setf hash-leaf-nodes-to-add (cdr current))
2388 (unless ; loop returns true if replacement made
2389 (loop for key-value-pairs-r-remainder on key-value-pairs-r do
2390 (when (funcall test (caar key-value-pairs-r-remainder) new-key)
2391 (setf (car key-value-pairs-r-remainder) new-key-value)
2392 (return t)))
2393 (incf count) ; only count additions, not the replacement inside the loop.
2394 (setf (car current) new-key-value) ; recycle cons "current"
2395 (setf (cdr current) key-value-pairs-r)
2396 (setf key-value-pairs-r current))))
2397 (case count
2398 (1 (car key-value-pairs-r)) ; safe assumption - if we only have one, all ins must have been identical and we kept the last.
2399 (t (make-equal-hash-key-value-pairs :count count :key-value-pairs key-value-pairs-r)))) ; reversal doesn't matter here - list is new and unique
2400 (let ((contents-mask 0))
2401 (declare (type fixnum num-additions))
2402 ; Modify all the cars in the hash-leaf-nodes-to-add list to contain the bucket-hash
2403 (loop for hash-leaf-node-to-add in hash-leaf-nodes-to-add do
2404 (let ((bucket (logand (ash (hash-leaf-node-hash (cdr hash-leaf-node-to-add)) shift) #.(1- **bucket-node-bucket-size**))))
2405 (declare (type fixnum bucket))
2406 (setf contents-mask (logior contents-mask (ash 1 bucket)))
2407 (setf (car hash-leaf-node-to-add)
2408 bucket)))
2409 (let* ((current-ordered (stable-sort hash-leaf-nodes-to-add (lambda (a b) (< (the fixnum (car a)) (the fixnum (car b))))))
2410 (lookup (make-array (the fixnum (logcount contents-mask)))) ; safe to assume as no additions to nil will return 0 count/nil
2411 (count 0)
2412 (sub-shift (- shift #.**per-level-shift**))
2413 (basis-if-single nil)
2414 (current-insertion-index 0))
2415 (declare (type fixnum num-buckets-represented count current-insertion-index sub-shift))
2416 (loop while current-ordered do
2417 (let* ((bucket-number (caar current-ordered))
2418 (additions-for-bucket-r current-ordered))
2419 (setf current-ordered (cdr current-ordered))
2420 (setf (cdr additions-for-bucket-r) nil)
2421 (loop while (and current-ordered (eql (caar current-ordered) bucket-number)) do
2422 (let ((temp current-ordered))
2423 (setf current-ordered (cdr current-ordered))
2424 (setf (cdr temp) additions-for-bucket-r)
2425 (setf additions-for-bucket-r temp)))
2426 (setq basis-if-single (cdar additions-for-bucket-r))
2427 (let ((result (from-hash-leaf-nodes (nreverse additions-for-bucket-r) sub-shift)))
2428 (incf count (get-node-element-count result))
2429 (setf (aref lookup current-insertion-index) result)
2430 (incf current-insertion-index))))
2431 (if (and (= count 1) basis-if-single)
2432 (progn
2433 basis-if-single)
2434 (new-hash-bucket-node count contents-mask lookup))))))
2435 ((shift-at-end shift) (hash-leaf-node-key-value (cdar hash-leaf-nodes-to-add)))
2436 (t (cdar hash-leaf-nodes-to-add))))
2437 (with-removals-and-additions (node hash-key-pairs-to-remove hash-leaf-nodes-to-add shift)
2438 (declare (type fixnum shift)
2439 (type list hash-key-pairs-to-remove hash-leaf-nodes-to-add))
2440 (etypecase node
2441 (null (from-hash-leaf-nodes hash-leaf-nodes-to-add shift))
2442 (hash-leaf-node
2443 (if (block :full-removal-test
2444 (loop for hash-key-pair-to-remove in hash-key-pairs-to-remove do
2445 (let ((actual-pair-to-remove (cdr hash-key-pair-to-remove)))
2446 (when (and
2447 (eql (car actual-pair-to-remove) (hash-leaf-node-hash node)) ; hashes equal
2448 (funcall test (cdr actual-pair-to-remove) (car (hash-leaf-node-key-value node))))
2449 (return-from :full-removal-test t))))
2450 (loop for hash-leaf-node-to-add in hash-leaf-nodes-to-add do
2451 (let ((actual-hash-leaf-node (cdr hash-leaf-node-to-add)))
2452 (when (and
2453 (eql (hash-leaf-node-hash actual-hash-leaf-node) (hash-leaf-node-hash node))
2454 (funcall test (car (hash-leaf-node-key-value node)) (car (hash-leaf-node-key-value actual-hash-leaf-node))))
2455 (return-from :full-removal-test t))))) ; test to see if "node" should be removed.
2456 (from-hash-leaf-nodes hash-leaf-nodes-to-add shift) ; forget about this, and build off a new nil with the adds only.
2457 (from-hash-leaf-nodes (cons (cons nil node) hash-leaf-nodes-to-add) shift))) ; order not important - no match
2458 (equal-hash-key-value-pairs
2459 ; note - by the time we get here, all hashes should match already. Only thing to do is deletions and additions based on equality tests.
2460 ; first thing to do is find the unaffected sublist, i.e. the one that will not be modded by removal or addition (overwrite).
2461 (let ((intact-retained-sublist (equal-hash-key-value-pairs-key-value-pairs node))
2462 (intact-retained-sublist-start-index 0)
2463 (indices-to-remove-r nil)
2464 (num-indices-to-remove 0)
2465 (spare-cons-bank nil))
2466 (declare (type fixnum num-indices-to-remove intact-retained-sublist-start-index))
2467 (macrolet ((cons-from-spares (car cdr)
2468 (let ((sym (gensym)))
2469 `(let ((,sym spare-cons-bank))
2470 (setq spare-cons-bank (cdr spare-cons-bank))
2471 (setf (car ,sym) ,car)
2472 (setf (cdr ,sym) ,cdr)
2473 ,sym)))
2474 (cons-from-spares-if-available (car cdr)
2475 `(if spare-cons-bank
2476 (cons-from-spares ,car ,cdr)
2477 (cons ,car ,cdr)))
2478 (recycle-cons (cons)
2479 (let ((sym (gensym)))
2480 `(let ((,sym ,cons))
2481 (setf (cdr ,sym) spare-cons-bank)
2482 (setq spare-cons-bank ,sym))))
2483 (advance-cons-recycling-prior (var)
2484 (assert (symbolp var))
2485 (let ((next (gensym)))
2486 (assert (symbolp var))
2487 `(let ((,next (cdr ,var)))
2488 (recycle-cons ,var)
2489 (setq ,var ,next))))
2490 (strip-data-slots-for-cons-spares (list)
2491 (let ((current-sym (gensym))
2492 (temp-sym (gensym)))
2493 `(let ((,current-sym ,list))
2494 (loop while ,current-sym do
2495 (let ((,temp-sym (car ,current-sym)))
2496 (setf (car ,current-sym) (cdar ,current-sym))
2497 (setf (cdr ,temp-sym) spare-cons-bank)
2498 (setf spare-cons-bank ,temp-sym)
2499 (setf ,current-sym (cdr ,current-sym))))))))
2500 ; note - data slots are being stripped out of the input vars
2501 (strip-data-slots-for-cons-spares hash-key-pairs-to-remove)
2502 (strip-data-slots-for-cons-spares hash-leaf-nodes-to-add)
2503 ; destroy the hash-leaf-nodes-to-add by pulling out the key-value-pairs to list instead
2504 (let ((key-value-pairs-to-add hash-leaf-nodes-to-add))
2505 (loop for elt on hash-leaf-nodes-to-add do (setf (car elt) (hash-leaf-node-key-value (car elt))))
2506 ; Following code works on the following assumption: Everything CURRENTLY in the list
2507 ; is unique. So there should be enough conses in "spare-cons-bank", as
2508 ; there can't be more values destroyed or overwritten than there were overwriters.
2509 (loop for key-value-remainder on (equal-hash-key-value-pairs-key-value-pairs node)
2510 for current-index from 0 do
2511 (let* ((key-value (the cons (car key-value-remainder)))
2512 (key (car key-value)))
2513 (when (cond
2514 ((loop for hash-key-pair-to-remove in hash-key-pairs-to-remove do
2515 (when (funcall test (cdr hash-key-pair-to-remove) key)
2516 (return t))))
2518 (loop for key-value-pair-to-add in key-value-pairs-to-add do
2519 (when (funcall test (car key-value-pair-to-add) key)
2520 (return t)))))
2521 (setq intact-retained-sublist (cdr key-value-remainder))
2522 (setq intact-retained-sublist-start-index (1+ current-index))
2523 (incf num-indices-to-remove)
2524 (setf indices-to-remove-r (cons-from-spares current-index indices-to-remove-r)))))
2525 ; hash-key-pairs-to-remove no longer required. Recycle the conses.
2526 (let ((current hash-key-pairs-to-remove))
2527 (loop while current do
2528 (let ((next (cdr current)))
2529 (setf (cdar current) spare-cons-bank)
2530 (setf spare-cons-bank (car current))
2531 (setf (cdr current) spare-cons-bank)
2532 (setf spare-cons-bank current)
2533 (setq current next))))
2534 ; note - cannot damage any of node's key-valuepairs or their conses.
2535 (let ((copied-out-sublist-r intact-retained-sublist)
2536 (vulnerable-range-of-cos 0)
2537 (count-delta 0)
2538 (current-index-to-remove (nreverse indices-to-remove-r)))
2539 (declare (type fixnum vulnerable-range-of-cos))
2540 (loop for key-value-pair-remainder on (equal-hash-key-value-pairs-key-value-pairs node)
2541 for current-index from 0 to (1- intact-retained-sublist-start-index) do
2542 (let ((key-value-pair (the cons (car (the cons key-value-pair-remainder)))))
2543 (if (eql current-index (car current-index-to-remove))
2544 (progn
2545 (incf count-delta -1)
2546 (advance-cons-recycling-prior current-index-to-remove))
2547 (progn
2548 (incf vulnerable-range-of-cos)
2549 (setq copied-out-sublist-r (cons-from-spares-if-available key-value-pair copied-out-sublist-r))))))
2550 (let ((remaining-key-value-pairs-to-add key-value-pairs-to-add))
2551 (loop while remaining-key-value-pairs-to-add do
2552 (let ((key-value-pair-to-add (car remaining-key-value-pairs-to-add)))
2553 (cond ((loop for copied-out-sub-head on copied-out-sublist-r
2554 for dummy from 1 to vulnerable-range-of-cos
2556 (when (funcall test (caar copied-out-sub-head) (car key-value-pair-to-add))
2557 (setf (car copied-out-sub-head) key-value-pair-to-add)
2558 (advance-cons-recycling-prior remaining-key-value-pairs-to-add)
2559 (incf count-delta) ; added a new. Will be a wash if a replacement caused by a prior removal building copied-out-sublist-r originally.
2560 (return t))))
2562 (let ((next (cdr remaining-key-value-pairs-to-add)))
2563 (setf (cdr remaining-key-value-pairs-to-add) copied-out-sublist-r)
2564 (setf copied-out-sublist-r remaining-key-value-pairs-to-add)
2565 (setf remaining-key-value-pairs-to-add next)
2566 (incf vulnerable-range-of-cos)))))))
2567 (let ((count (+ count-delta (equal-hash-key-value-pairs-count node))))
2568 (declare (type fixnum count))
2569 (case count
2570 (0 nil)
2571 (1 (make-hash-leaf-node :hash (cdr copied-out-sublist-r) :key-value (first copied-out-sublist-r)))
2572 (t (make-equal-hash-key-value-pairs
2573 :count (+ count-delta (equal-hash-key-value-pairs-count node))
2574 :key-value-pairs copied-out-sublist-r)))))))))
2575 (hash-bucket-node
2576 (macrolet ((hash-to-mask (hash)
2577 `(ash 1 (logand (ash ,hash shift) #.(1- **bucket-node-bucket-size**)))))
2578 (let ((original-contents-mask (hash-bucket-node-contents-mask node))
2579 (all-removals-mask 0)
2580 (additions-to-existing-buckets-mask 0)
2581 (additions-to-new-buckets-mask 0))
2582 (declare (type fixnum original-contents-mask additions-to-existing-buckets-mask additions-to-new-buckets-mask))
2583 ; first, go through hash-key-pairs-to-remove and update the car to masks.
2584 ; any whose masks don't "and" with original-contents-mask can be outright discarded.
2585 (let ((hash-key-pairs-to-remove-r nil))
2586 (let ((current hash-key-pairs-to-remove))
2587 (loop while current do
2588 (let ((next (cdr current))
2589 (mask (hash-to-mask (cadar current))))
2590 (declare (type fixnum mask))
2591 (unless (zerop (logand mask original-contents-mask)) ; make sure it's removing something that may be there.
2592 (setf all-removals-mask (logior mask all-removals-mask))
2593 (setf (caar current) mask)
2594 (setf (cdr current) hash-key-pairs-to-remove-r)
2595 (setf hash-key-pairs-to-remove-r current))
2596 (setq current next))))
2597 (setq hash-key-pairs-to-remove-r (sort hash-key-pairs-to-remove-r (lambda (a b) (< (the fixnum (car a)) (the fixnum (car b))))))
2598 ; hash-key-pairs-to-remove-r is what should be used, hash-key-pairs-to-remove is now destroyed.
2599 ; Now, go through additions and give them masks too. Sort into 2 lists - new-bucket and clashing.
2600 (let ((additions-existing-bucket-r nil)
2601 (additions-new-bucket-r nil))
2602 (let ((current hash-leaf-nodes-to-add))
2603 (loop while current do
2604 (let ((next (cdr current))
2605 (mask (hash-to-mask (hash-leaf-node-hash (cdar current)))))
2606 (declare (type fixnum mask))
2607 (setf (caar current) mask)
2608 (if (zerop (logand mask original-contents-mask))
2609 (progn
2610 (setf additions-to-new-buckets-mask (logior mask additions-to-new-buckets-mask))
2611 (setf (cdr current) additions-new-bucket-r)
2612 (setf additions-new-bucket-r current))
2613 (progn
2614 (setf additions-to-existing-buckets-mask (logior mask additions-to-existing-buckets-mask))
2615 (setf (cdr current) additions-existing-bucket-r)
2616 (setf additions-existing-bucket-r current)))
2617 (setq current next))))
2618 (let ((additions-existing-bucket (stable-sort (nreverse additions-existing-bucket-r) (lambda (a b) (< (the fixnum (car a)) (the fixnum (car b))))))
2619 (additions-new-bucket (stable-sort (nreverse additions-new-bucket-r) (lambda (a b) (< (the fixnum (car a)) (the fixnum (car b)))))))
2620 ; additions-existing-bucket and additions-new-bucket set up, hash-leaf-nodes-to-add should be considered destroyed.
2621 ; I'll go to hell for this unhygienic macro action :(
2622 (macrolet ((get-changed-bucket (&body body)
2623 `(let ((old-lookup (hash-bucket-node-lookup node))
2624 (current-read-index 0)
2625 (current-read-mask 1)
2626 (sub-shift (- shift #.**per-level-shift**))
2627 (positive-contents-mask (logior additions-to-existing-buckets-mask additions-to-new-buckets-mask original-contents-mask))
2628 (changes-to-existing-mask (logior additions-to-existing-buckets-mask all-removals-mask)))
2629 (declare (type fixnum current-read-index current-read-mask positive-contents-mask changes-to-existing-mask sub-shift))
2630 (loop while (<= current-read-mask positive-contents-mask) do
2631 (cond ((plusp (logand changes-to-existing-mask current-read-mask))
2632 (let ((additions-r nil)
2633 (removals-r nil))
2634 (loop while (and additions-existing-bucket (eql (caar additions-existing-bucket) current-read-mask)) do
2635 (let ((next (cdr additions-existing-bucket)))
2636 (setf (cdr additions-existing-bucket) additions-r)
2637 (setq additions-r additions-existing-bucket)
2638 (setq additions-existing-bucket next)))
2639 (loop while (and hash-key-pairs-to-remove-r (eql (caar hash-key-pairs-to-remove-r) current-read-mask)) do
2640 (let ((next (cdr hash-key-pairs-to-remove-r)))
2641 (setf (cdr hash-key-pairs-to-remove-r) removals-r)
2642 (setq removals-r hash-key-pairs-to-remove-r)
2643 (setq hash-key-pairs-to-remove-r next)))
2644 (let ((node-if-single (when (not removals-r) (if additions-r (cdar additions-r) (aref old-lookup current-read-index))))
2645 (result (with-removals-and-additions (aref old-lookup current-read-index) removals-r (nreverse additions-r) sub-shift)))
2646 (incf current-read-index)
2647 (sink-result current-read-mask result node-if-single))))
2648 ((plusp (logand current-read-mask additions-to-new-buckets-mask))
2649 (let ((additions-r nil))
2650 (loop while (and additions-new-bucket (eql (caar additions-new-bucket) current-read-mask)) do
2651 (let ((next (cdr additions-new-bucket)))
2652 (setf (cdr additions-new-bucket) additions-r)
2653 (setq additions-r additions-new-bucket)
2654 (setq additions-new-bucket next)))
2655 (let ((node-if-single (when additions-r (cdar additions-r)))
2656 (result (from-hash-leaf-nodes (nreverse additions-r) sub-shift)))
2657 (sink-result current-read-mask result node-if-single))))
2658 ((plusp (logand current-read-mask original-contents-mask))
2659 (sink-result current-read-mask (aref old-lookup current-read-index))
2660 (incf current-read-index))) ; no change to count.
2661 (setf current-read-mask (ash current-read-mask 1)))
2662 (let nil ,@body))))
2663 (if (zerop (logand all-removals-mask (lognot additions-to-existing-buckets-mask))) ; no removals without subsequent additions - deterministic array size.
2664 (let ((lookup-array-length (logcount (logior original-contents-mask additions-to-new-buckets-mask))))
2665 (declare (type fixnum lookup-array-length))
2666 (let ((lookup (make-array lookup-array-length))
2667 (current-insertion-index 0)
2668 ; (outer-node-if-single nil)
2669 (count 0))
2670 (declare (type fixnum current-insertion-index count))
2671 (macrolet ((sink-result (insertion-mask result &optional (node-if-single nil))
2672 `(progn
2673 ; (when ,node-if-single (setq outer-node-if-single ,node-if-single))
2674 (incf count (get-node-element-count (setf (aref lookup current-insertion-index) ,result)))
2675 (incf current-insertion-index))))
2676 (get-changed-bucket
2677 (if (and (= count 1) (typep (aref lookup 0) 'hash-leaf-node))
2678 (aref lookup 0) ; only one under this bucket, and it's a hash-leaf-node - just return it.
2679 (new-hash-bucket-node count positive-contents-mask lookup))))))
2680 (let ((lookup-elements-r nil)
2681 (lookup-element-count 0)
2682 (final-contents-mask 0)
2683 ; (outer-node-if-single nil)
2684 (count 0))
2685 (declare (type fixnum count lookup-element-count final-contents-mask))
2686 (macrolet ((sink-result (insertion-mask result &optional (node-if-single nil))
2687 `(progn
2688 (let ((result ,result))
2689 (when result ; nil = don't add to the array
2690 ; (when ,node-if-single (setq outer-node-if-single ,node-if-single))
2691 (incf count (get-node-element-count result))
2692 (incf lookup-element-count)
2693 (incf final-contents-mask ,insertion-mask)
2694 (push result lookup-elements-r))))))
2695 (get-changed-bucket
2696 (if lookup-elements-r ; return nil when empty - element above will accept it
2697 (if (and (= count 1) (typep (first lookup-elements-r) 'hash-leaf-node))
2698 (first lookup-elements-r)
2699 (new-hash-bucket-node count final-contents-mask (make-array lookup-element-count :initial-contents (nreverse lookup-elements-r))))
2700 (progn
2701 (assert (zerop count))
2702 nil))))))))))))))))
2703 (new-const-hash-table
2704 hash-table-description
2705 (with-removals-and-additions
2706 root-node
2707 (let ((keys-to-remove-r nil))
2708 (loop-over/ key-to-remove (to-lazy-list keys-to-remove)
2709 (push (list* nil (funcall hash-function key-to-remove) key-to-remove) keys-to-remove-r))
2710 (nreverse keys-to-remove-r))
2711 (let ((key-value-pairs-to-add-r nil))
2712 (loop-over/ key-value-pair-to-add (to-lazy-list key-value-pairs-to-add)
2713 (push (list* nil (make-hash-leaf-node :hash (funcall hash-function (car key-value-pair-to-add)) :key-value key-value-pair-to-add)) key-value-pairs-to-add-r))
2714 (nreverse key-value-pairs-to-add-r))
2715 0))))))
2718 (defun const-hash-table-with-additions (const-hash-table key-value-pairs-to-add)
2719 (const-hash-table-with-changes const-hash-table nil key-value-pairs-to-add))
2720 (define-compiler-macro const-hash-table-with-additions (const-hash-table key-value-pairs-to-add)
2721 `(const-hash-table-with-changes ,const-hash-table nil ,key-value-pairs-to-add))
2722 (defun const-hash-table-with-addition (const-hash-table key value)
2723 (const-hash-table-with-changes const-hash-table nil (list (cons key value))))
2724 (define-compiler-macro const-hash-table-with-addition (const-hash-table key value)
2725 `(const-hash-table-with-changes ,const-hash-table nil (list (cons ,key ,value))))
2728 (defun const-hash-table-with-removals (const-hash-table keys-to-remove)
2729 (const-hash-table-with-changes const-hash-table keys-to-remove nil))
2730 (define-compiler-macro const-hash-table-with-removals (const-hash-table keys-to-remove)
2731 `(const-hash-table-with-changes ,const-hash-table ,keys-to-remove nil))
2732 (defun const-hash-table-with-removal (const-hash-table key)
2733 (const-hash-table-with-changes const-hash-table (list key) nil))
2734 (define-compiler-macro const-hash-table-with-removal (const-hash-table key)
2735 `(const-hash-table-with-changes ,const-hash-table (list ,key) nil))
2738 (defun const-hash-table-key-value-pairs (const-hash-table)
2739 (labels ((get-key-value-pairs (node)
2740 (etypecase node
2741 (hash-bucket-node (concat/ (map/ #'get-key-value-pairs (hash-bucket-node-lookup node))))
2742 (hash-leaf-node (list/ (hash-leaf-node-key-value node)))
2743 (nil nil)
2744 (equal-hash-key-value-pairs
2745 (lazy-list-from-call
2746 (standard-traversal-link
2747 (build (end-call remaining-key-value-pairs)
2748 (if (consp remaining-key-value-pairs)
2749 (traversal-result
2750 (car remaining-key-value-pairs)
2751 (build end-call (cdr remaining-key-value-pairs)))
2752 (get-traversal-result end-call)))
2753 ((equal-hash-key-value-pairs-key-value-pairs node))))))))
2754 (let ((root-node (const-hash-table-root-node const-hash-table)))
2755 (if root-node
2756 (get-key-value-pairs root-node)
2757 (list/)))))
2759 (defun const-hash-table-keys (const-hash-table)
2760 (map/ #'car (const-hash-table-key-value-pairs const-hash-table)))
2761 (define-compiler-macro const-hash-table-keys (const-hash-table)
2762 `(map/ #'car (const-hash-table-key-value-pairs ,const-hash-table)))
2764 (defun const-hash-table-values (const-hash-table)
2765 (map/ #'cdr (const-hash-table-key-value-pairs const-hash-table)))
2766 (define-compiler-macro const-hash-table-values (const-hash-table)
2767 `(map/ #'cdr (const-hash-table-key-value-pairs ,const-hash-table)))
2773 (defparameter **unit-tests**
2775 ("To-from-list"
2777 ("Proper List" (let ((lista (loop for elt from 1 to 10 collect elt))
2778 (listb (loop for elt from 1 to 10 collect elt)))
2779 (values (and (equal (to-list (to-lazy-list lista)) listb) (equal lista listb)))))
2781 ("Array" (let ((arraya (make-array 10 :initial-contents (loop for elt from 1 to 10 collect elt)))
2782 (arrayb (make-array 10 :initial-contents (loop for elt from 1 to 10 collect elt))))
2783 (values (and (equal (to-list (to-lazy-list arraya)) (map 'list #'identity arrayb)) (equalp arraya arrayb)))))))
2785 ("Standard operations"
2786 ,(apply #'nconc
2787 (loop for in-type in `(("list" ,#'identity)
2788 ("list-based lazy list" ,#'to-lazy-list)
2789 ("lazy-list eager-value" ,(curried #'map/ #'identity))
2790 ("lazy-list lazy-value" ,(curried #'map/ (lambda (elt) (unresolved elt))))) collect
2791 (mapcar
2792 (lambda (test)
2793 `(,(concatenate 'string (first test) " " (first in-type))
2794 ,(second test)))
2795 (labels ((transformed (list) `(funcall ,(second in-type) ',list)))
2796 (let ((equality-check-sets
2797 `(("foldl/" (= (foldl/ #'/ 64 ,(transformed '(4 2 4))) 2))
2798 ("foldl1/" (= (foldl1/ #'/ ,(transformed '(64 4 2 8))) 1))
2799 ("foldr/" (= (foldr/ #'/ 2 ,(transformed '(8 12 24 4))) 8))
2800 ("foldr1/" (= (foldr1/ #'/ ,(transformed '(8 12 24 4))) 4))
2802 ("head-tail/ multiple"
2803 (equal
2804 (multiple-value-bind (head tail) (head-tail/ ,(transformed '(1 2 3 4))) (list head (to-list tail)))
2805 '(1 (2 3 4))))
2806 ("head-tail/ short"
2807 (equal
2808 (multiple-value-bind (head tail) (head-tail/ ,(transformed '(1))) (list head (to-list tail)))
2809 '(1 nil)))
2810 ("nth/ empty"
2811 (equal (nth/ 3 ,(transformed nil)) nil))
2812 ("nth/ stocked"
2813 (equal (nth/ 3 ,(transformed '(10 20 30 40))) 40))
2815 ("assoc/"
2816 (equal (assoc/ 3 ,(transformed '((2 . "A") (3 . "B") (4 . "C")))) '(3 . "B")))
2818 ("and/ true" (and/ ,(transformed '(1 2 3 4))))
2819 ("and/ false" (equal (and/ ,(transformed '(1 2 nil 3 4))) nil))
2821 ; ("scanl/" (equal (to-list (scanl/ #'/ 64 ,(transformed '(4 2 4)))) '(64 16 8 2)))
2822 ; ("scanl1/" (equal (to-list (scanl1/ #'/ ,(transformed '(64 4 2 8)))) '(64 16 8 1)))
2823 ; ("scanr/" (equal (to-list (scanr/ #'/ 2 ,(transformed '(8 12 24 4)))) '(8 1 12 2 2)))
2824 ; ("scanr1/" (equal (to-list (scanr1/ #'/ ,(transformed '(8 12 24 2)))) '(8 1 12 2)))
2825 ; ("nub/" (equal (to-list (nub/ ,(transformed '(9 8 4 4 1 4 9)))) '(9 8 4 1)))
2826 ; ("append/" (equal (to-list (append/ ,(transformed '(1 2 3 4)) ,(transformed '(5 6 7 8)))) '(1 2 3 4 5 6 7 8)))
2827 ; ("concat/" (equal (to-list (concat/ ,(transformed '((1 2 3) (4 5 6))))) '(1 2 3 4 5 6)))
2828 ("car/" (equal (car/ ,(transformed '(5 6 7 8))) 5))
2829 ; ("cdr/" (equal (to-list (cdr/ ,(transformed '(5 6 7 8)))) '(6 7 8)))
2830 ; ,@(loop for i from 0 to 10 collect `(,(format nil "nthcdr/ ~S" i) (equal (to-list (nthcdr/ ,i ,(transformed (loop for i from 1 to 8 collect i)))) (nthcdr i (loop for i from 1 to 8 collect i)))))
2832 (list-checks
2833 `(("map/" (map/ #'+ ,(transformed '(1 2 3)) ,(transformed '(4 5 6 7))) '(5 7 9))
2834 ("scanl/" (scanl/ #'/ 64 ,(transformed '(4 2 4))) '(64 16 8 2))
2835 ("scanl1/" (scanl1/ #'/ ,(transformed '(64 4 2 8))) '(64 16 8 1))
2836 ("scanr/" (scanr/ #'/ 2 ,(transformed '(8 12 24 4))) '(8 1 12 2 2))
2837 ("scanr1/" (scanr1/ #'/ ,(transformed '(8 12 24 2))) '(8 1 12 2))
2838 ("nub/" (nub/ ,(transformed '(9 8 4 4 1 4 9))) '(9 8 4 1))
2839 ("append/" (append/ ,(transformed '(1 2 3 4)) ,(transformed '(5 6 7 8))) '(1 2 3 4 5 6 7 8))
2840 ("concat/" (concat/ ,(transformed '((1 2 3) (4 5 6)))) '(1 2 3 4 5 6))
2841 ("intersperse/ empty-case" (intersperse/ "Intersp" ,(transformed nil)) nil)
2842 ("intersperse/ single-case" (intersperse/ "Intersp" ,(transformed '(1))) '(1))
2843 ("intersperse/ multiple-case" (intersperse/ "Intersp" ,(transformed '(1 2 3 4))) '(1 "Intersp" 2 "Intersp" 3 "Intersp" 4))
2844 ("take-while/ empty-case" (take-while/ #'identity ,(transformed nil)) nil)
2845 ("take-while/ single-case inc" (take-while/ #'identity ,(transformed '(1))) '(1))
2846 ("take-while/ single-case exc" (take-while/ #'null ,(transformed '(1))) nil)
2847 ("take-while/ multiple partial" (take-while/ #'identity ,(transformed '(1 2 nil 3 4))) '(1 2))
2848 ("take-while/ multiple end" (take-while/ #'identity ,(transformed '(1 2 3 4 nil))) '(1 2 3 4))
2849 ("take-while/ multiple start" (take-while/ #'identity ,(transformed '(nil 1 2 3 4))) nil)
2850 ("take-while/ multiple full" (take-while/ #'identity ,(transformed '(1 2 3 4))) '(1 2 3 4))
2852 ("drop-while/ empty-case" (drop-while/ #'identity ,(transformed nil)) nil)
2853 ("drop-while/ single-case inc" (drop-while/ #'identity ,(transformed '(1))) nil)
2854 ("drop-while/ single-case exc" (drop-while/ #'null ,(transformed '(1))) '(1))
2855 ("drop-while/ multiple partial" (drop-while/ #'identity ,(transformed '(1 2 nil 3 4))) '(nil 3 4))
2856 ("drop-while/ multiple end" (drop-while/ #'identity ,(transformed '(1 2 3 4 nil))) '(nil))
2857 ("drop-while/ multiple start" (drop-while/ #'identity ,(transformed '(nil 1 2 3 4))) '(nil 1 2 3 4))
2858 ("drop-while/ multiple full" (drop-while/ #'identity ,(transformed '(1 2 3 4))) nil)
2860 ("list*/ empty" (list*/ ,(transformed nil)) nil)
2861 ("list*/ frontloaded only" (list*/ 1 2 3 4 ,(transformed nil)) '(1 2 3 4))
2862 ("list*/ backloaded only" (list*/ ,(transformed '(1 2 3 4))) '(1 2 3 4))
2863 ("list*/ mixed" (list*/ 1 2 ,(transformed '(3 4))) '(1 2 3 4))
2865 ("tails/" (map/ #'to-list (tails/ ,(transformed '(1 2 3 4)))) '((1 2 3 4) (2 3 4) (3 4) (4) nil))
2866 ("tails/ lazy-list path" (to-list (concat/ (filter/ #'non-null/ (tails/ (map/ #'identity ,(transformed '(1 2 3 4))))))) '(1 2 3 4 2 3 4 3 4 4))
2868 ("filter/" (filter/ #'identity ,(transformed '(1 2 nil 3 4))) '(1 2 3 4))
2870 ("grouped-by-firsts/" (grouped-by-firsts/ #'eql '((1 . 2) (1 . 3) (2 . 4) (1 . 2))) '((1 2 3 2) (2 4)))
2871 ("sort/" (sort/ ,(transformed '(5 3 2 1 9))) '(1 2 3 5 9))
2872 ("iterate/" (take/ 100 (iterate/ #'1+ 1)) (loop for i from 1 to 100 collect i))
2873 ("nthcdr/" (nthcdr/ 3 ,(transformed '(1 2 3 4 5 6))) '(4 5 6))
2875 ("cdr/" (cdr/ ,(transformed '(5 6 7 8))) '(6 7 8))
2877 ,@(loop for i from 0 to 10 collect
2878 `(,(format nil "nthcdr/ ~S" i) (nthcdr/ ,i ,(transformed (loop for i from 1 to 8 collect i))) (nthcdr ,i (loop for i from 1 to 8 collect i))))
2879 ,@(loop for i from 0 to 10 collect
2880 `(,(format nil "take/ ~S" i) (take/ ,i ,(transformed (loop for i from 1 to 8 collect i))) (subseq (loop for i from 1 to 8 collect i) 0 (min ,i 8))))
2883 (append
2884 equality-check-sets
2885 (mapcan (lambda (elt)
2886 (destructuring-bind (name lazy-form result-form)
2888 `((,name (equal (to-list ,lazy-form) ,result-form))
2889 (,(concatenate 'string name " concat test")
2890 (equal
2891 (to-list (append/ (append/ ,lazy-form ,lazy-form ,lazy-form) (append/ ,lazy-form ,lazy-form ,lazy-form)))
2892 (append (append ,result-form ,result-form ,result-form) (append ,result-form ,result-form ,result-form)))))))
2893 list-checks))))))))
2895 ("Multifunctionality Sanity tests"
2898 ("Cliched Fibonacci to 100"
2899 (funcall (compile nil (lambda () (= (nth/ 100 (self-ref-list/ fib (list*/ 1 1 (map/ #'+ fib (tail/ fib))))) 573147844013817084101)))))
2902 ("Fibonacci capped but taken to 1,000,000 - leak test"
2903 (nth/ 1000000
2904 (self-ref-list/ fib (list*/ 1 1 (map/ (curried #'max 10) fib (tail/ fib))))))
2906 ("CSV Parsing Test (split-down-on-test and others)"
2907 (let ((csv-file
2909 "1,2, 3 , I contain \" Quoted, commas, \" you see, 99
2910 g, \"hijk\"lmn
2911 third_line,stuff here"))
2912 (equalp
2913 '(("1" "2" " 3 " " I contain \" Quoted, commas, \" you see" " 99") ("g" " \"hijk\"lmn") ("third_line" "stuff here"))
2914 (to-list
2915 (map/ (composed #'to-list (curried #'map/ (composed #'to-string (curried #'map/ #'car))))
2916 (map/ (composed
2917 (lambda (line) (split-down-on-test/ (curried #'equal '(#\, . nil)) line))
2918 (curried #'scanl1/ (lambda (a b) (cons (car b) (if (cdr a) (not (cdr b)) (cdr b)))))
2919 (curried #'map/ (lambda (elt) (cons elt (eql elt #\")))))
2920 (split-down-on-test/ (curried #'eql #\newline) csv-file)))))))
2927 ("grouped-by-firsts*"
2928 ,(let ((pairs-as-lists '(("Brown" "Bill") ("Smith" "Ian") ("Stein" "Fred") ("Brown" "Sarah") ("Brown" "Lance"))))
2929 (eager
2930 (multiple-value-bind (result-pairs query)
2931 (grouped-seconds-by-first/ pairs-as-lists :test 'equal)
2939 (defstruct diff-hash-table
2940 contents
2941 lock
2944 (defstruct hash-table-delta
2945 base ; diff-hash-table we're based on
2946 removals ; keys removed from base
2947 additions ; keys added or replaced - search this first - alist
2948 test
2952 (defun diff-hash-table (key-value-pairs &key (test #'eql))
2953 (make-diff-hash-table :lock nil
2954 :contents
2955 (let ((hash (make-hash-table :test test)))
2956 (loop-over/ pair (to-lazy-list key-value-pairs)
2957 (setf (gethash (car pair) hash) (cdr pair)))
2958 hash)))
2960 (defun diff-hash-table-changed (diff-hash-table key-value-pairs-to-add keys-to-remove)
2961 (let ((contents (diff-hash-table-contents diff-hash-table)))
2962 (etypecase contents
2963 (hash-table
2964 (let* ((result (make-diff-hash-table :lock nil :contents contents))
2965 (test (hash-table-test contents))
2966 (additions nil)
2967 (removals nil))
2968 (loop-over/ key (to-lazy-list keys-to-remove)
2969 (multiple-value-bind (value is-valid)
2970 (gethash key contents)
2971 (when is-valid
2972 (push (cons key value) additions))
2973 (remhash key contents)))
2974 (loop-over/ key-value-pair (to-lazy-list key-value-pairs-to-add)
2975 (destructuring-bind (key . value)
2976 key-value-pair
2977 (multiple-value-bind (value is-valid)
2978 (gethash key contents)
2979 (if is-valid
2980 (push (cons key value) additions)
2981 (push key removals)))
2982 (setf (gethash key contents) value)))
2983 (setf (diff-hash-table-contents diff-hash-table) (make-hash-table-delta :base result :removals removals :additions additions :test test))
2984 result))
2985 (hash-table-delta
2986 (make-diff-hash-table :lock nil :contents (make-hash-table-delta :base diff-hash-table :removals (to-list keys-to-remove) :additions (to-list key-value-pairs-to-add) :test (hash-table-delta-test contents)))))))
2988 (defun diff-hash-table-with-additions (diff-hash-table key-value-pair-additions)
2989 (diff-hash-table-changed diff-hash-table key-value-pair-additions nil))
2991 (defun diff-hash-table-with-addition (diff-hash-table key value)
2992 (diff-hash-table-changed diff-hash-table (list (cons key value)) nil))
2995 (defun diff-hash-table-with-removals (diff-hash-table keys-to-remove)
2996 (diff-hash-table-changed diff-hash-table nil keys-to-remove))
2998 (defun diff-hash-table-with-removal (diff-hash-table key-to-remove)
2999 (diff-hash-table-changed diff-hash-table nil (list key-to-remove)))
3002 (defun get-diff-hash (key diff-hash-table)
3003 (let ((contents (diff-hash-table-contents diff-hash-table)))
3004 (typecase contents
3005 (hash-table
3006 (gethash key contents))
3007 (hash-table-delta
3008 (let* ((test (hash-table-delta-test contents))
3009 (from-additions (assoc key (hash-table-delta-additions contents) :test test)))
3010 (if from-additions
3011 (values (cdr from-additions) t)
3012 (unless (position key (hash-table-delta-removals contents))
3013 (let ((base (hash-table-delta-base contents)))
3014 (unresolved (get-diff-hash key base))))))))))
3016 (defun unit-test ()
3017 (loop for named-test in **unit-tests** do
3018 (destructuring-bind (identity sub-test-list)
3019 named-test
3020 (format t "Testing ~A" (string identity))
3021 (terpri)
3022 (force-output)
3023 (loop for laziness in '(eager lazy) do
3024 (loop for sub-test in sub-test-list for sub-test-number from 1 do
3025 (loop for compiled in '(nil t) do
3026 (destructuring-bind (sub-test-identity test)
3027 (if (> (length sub-test) 1)
3028 sub-test
3029 (list (format nil "~A: " sub-test-number) (car sub-test)))
3030 ; (format t " ~A: " sub-test-identity)
3031 ; (force-output)
3032 (let ((identity-string (format nil " ~A in ~A mode, ~A: " sub-test-identity laziness (if compiled "compiled" "not compiled"))))
3033 (handler-case
3034 (multiple-value-bind (passed info)
3035 (if compiled
3036 (eval `(funcall (compile nil (lambda () (,laziness ,test)))))
3037 (eval `(,laziness ,test)))
3038 (if passed
3039 nil ;(format t (concatenate 'string identity-string " passed"))
3040 (progn (format t (concatenate 'string identity-string (format nil "!!!failed!!!") (when info (format nil " ~A" info)))) (terpri)))
3041 (force-output))
3042 (error (err)
3043 (format t (concatenate 'string identity-string "failed hard ~A ~S") err err)
3044 (terpri)
3045 (force-output)))))
3046 (force-output))))
3047 (terpri)
3048 (force-output))))
3050 (unit-test)