Sophie

Sophie

distrib > Mageia > 7 > i586 > by-pkgid > 9451edd25456e3a771e4c01f92dd0fc3 > files > 90

gcl-2.6.12-7.mga7.i586.rpm


Proclaimed functions of a fixed number of args are much more
efficient.   It is still possible to pass multiple values
efficiently (but not quite with the CL semantics)

Here are two examples, one using ordinary multiple-value-setq
and the other our-multiple-value-setq.
For 1,000,000 calls:

Type   :      CL 2 values   our 2 values              1 value
Time   :         7.9 sec      3.5                     2.35
name   :         foo-mv       foo-our-mv              foo 
Uses   : multiple-value-setq our-multiple-value-setq  Only 1 value passed.

(defun foo-mv (n)
  (let (x y)
  (sloop for i below n
	 do (multiple-value-setq(x y) (goo-mv)))))

(defun goo-mv () (values 1 2))


And then an equivalent one:
(proclaim '(function foo-our-mv (t) t))
(proclaim '(function goo-our-mv () t))
(defun foo-our-mv (n)
  (let (x y)
   (sloop for i below n
       	 do (our-multiple-value-setq (x y) (goo-our-mv)))
  (list x y)))	

(defun goo-our-mv  () (our-values 1 2))

The times:
>(time (foo-our-mv 1000000))
real time : 3.617 secs
run time  : 3.583 secs
(1 2)
>(time (foo-mv 1000000))
real time : 8.033 secs
run time  : 7.800 secs
(1 2)

Here are the our-mv macros:

(use-package "SLOOP")


(defmacro our-values (a &rest l)
  (or (< (length l) (length *vals*)) (error "too many values"))
  `(prog1 ,a ,@ (sloop for v in l
		       for u in *vals*
		       collect `(setq ,u ,v))))

(defmacro our-multiple-value-setq ((x &rest l) form)
  (or (< (length l) (length *vals*)) (error "too many values"))
  `(prog1 (setq ,x ,form)
     ,@ (sloop for w in *vals*
	       for v in l
	       collect `(setq ,v ,w))))

(defvar *vals*
  '(*val1* *val2* *val3* *val4* *val5* *val6* *val7* *val8* *val9* *val10*))


(defvar *val1* nil)
(defvar *val2* nil)
(defvar *val3* nil)
(defvar *val4* nil)
(defvar *val5* nil)
(defvar *val6* nil)
(defvar *val7* nil)
(defvar *val8* nil)
(defvar *val9* nil)
(defvar *val10* nil)

;; Note that this method does not penalize ordinary calls at all.
;; It is not the same as the common lisp multiple values in general:
;;    1)  The information on how many values are being passed is not
;;        recorded [ unless of course that number is one of the values ! ]
;;    2)  If you ask for more values than were specified you will get
;;        a random value.   Common lisp values would say you get nil.
;; Now it is true that it would be possible to make AKCL pass multiple
;; values more efficiently, but this is really a large overhaul of the
;; system.   There are lots of system functions, hand coded using the
;; old scheme.   I have been thinking about ways to do this for the
;; last little while, but have not settled on anything.

Bill