I think I discovered a (rather serious!) bug in elephant. Calling MAP-BTREE with both the :FROM-END and :END arguments on a BDB store controller leads to this condition:
There is no applicable method for the generic function #<STANDARD-GENERIC-FUNCTION CURSOR-NEXT-NODUP (2)> when called with arguments (#<DB-BDB::BDB-CURSOR {1006E31451}>). [Condition of type SIMPLE-ERROR] This can be replicated quite simply with the included example test code. FWIW, changing the definition of MAP-BTREE-FROM-END from (defun map-btree-from-end (fn btree start end collect) (with-map-wrapper (fn btree collect cur) (iterate-map-btree :start (if end (with-cursor-values (cursor-set-range cur end) (cond ((and exists? (lisp-compare-equal skey end)) (cursor-next-nodup cur) (cursor-prev cur)) (t (cursor-prev cur)))) (cursor-last cur)) :continue (or (null start) (lisp-compare>= key start)) :step (cursor-prev cur)))) to (defun map-btree-from-end (fn btree start end collect) (with-map-wrapper (fn btree collect cur) (iterate-map-btree :start (if end (with-cursor-values (cursor-set-range cur end) (cond ((and exists? (lisp-compare-equal skey end)) (cursor-next cur) (cursor-prev cur)) (t (cursor-prev cur)))) (cursor-last cur)) :continue (or (null start) (lisp-compare>= key start)) :step (cursor-prev cur)))) "fixes" the problem, in my simple test case, but I don't understand that function deeply enough to be convinced that this is a correct fix in all circumstances. If it's only ever called on btrees, which can contain no duplicates, it's presumably OK, but if it can be called on indexed trees, then it would not be OK, and we would need a definition of CURSOR-NEXT-NODUP on regular cursors. --alain ================================================================ ;;;; -*- Mode: lisp; Package: elephant; Syntax: Common-lisp -*- ;; ;; Copyright (C) 2011 TechNo Wait. ;; All rights reserved. ;; ;; Author: Alain Picard ;; ;;;; Code: (in-package :elephant) (defun *test-tree* () (or (get-from-root :test-tree) (add-to-root :test-tree (make-btree)))) (defun ap/prepare-1 () (dotimes (i 10) (setf (get-value i (*test-tree*)) (format nil "~:R" i)))) (defun ap-print2 (a b) (print (list a b))) (defun ap/test-1 () (map-btree 'ap-print2 (*test-tree*)) (print "ap/test-1 OK")) (defun ap/test-2 () (map-btree 'ap-print2 (*test-tree*) :from-end t) (print "ap/test-2 OK")) (defun ap/test-3 () (map-btree 'ap-print2 (*test-tree*) :from-end t :end 7) (print "ap/test-3 OK")) (defun ap/run-tests () (ap/test-1) (ap/test-2) (ap/test-3)) #+foo (eval-when (:load-toplevel :execute) (ap/prepare-1) (ap/run-tests)) ;;; BUG2.LISP ends here ================================================================ -- Please read about why Top Posting is evil at: http://en.wikipedia.org/wiki/Top-posting and http://www.dickalba.demon.co.uk/usenet/guide/faq_topp.html Please read about why HTML in email is evil at: http://www.birdhouse.org/etc/evilmail.html _______________________________________________ elephant-devel site list elephant-devel@common-lisp.net http://common-lisp.net/mailman/listinfo/elephant-devel