Skip to content

Instantly share code, notes, and snippets.

@alandipert
Created December 8, 2020 19:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alandipert/ccea4c063b8c65fdbfa1e97760cc6e31 to your computer and use it in GitHub Desktop.
Save alandipert/ccea4c063b8c65fdbfa1e97760cc6e31 to your computer and use it in GitHub Desktop.
(defconstant mv-limit 20)
(defparameter *mv-expected* 1)
(defparameter *mv* (make-array mv-limit))
(defun mv (&rest vals)
(do ((i 0 (1+ i))
(vs vals (cdr vs)))
((or (eql i *mv-expected*) (null vs))
(setq *mv-expected* (min i mv-limit))
(car vals))
(setf (aref *mv* i) (car vs))))
(defmacro mv-list (form)
(let ((val1# (gensym)))
`(let* ((*mv-expected* mv-limit)
(,val1# ,form))
(if (eql *mv-expected* mv-limit)
(list ,val1#)
(coerce (subseq *mv* 0 *mv-expected*)
'list)))))
(defun make-mv-bindings (vars val1# &aux (i 0))
(mapcar (lambda (var)
(prog1
(if (zerop i)
`(,var ,val1#)
`(,var (when (< ,i *mv-expected* mv-limit)
(aref *mv* ,i))))
(incf i)))
vars))
(defmacro mv-bind (vars expr &body body)
(if (null vars)
`(progn () (progn ,expr nil) ,@body)
(let ((val1# (gensym)))
`(let* ((*mv-expected* ,(length vars))
(,val1# ,expr))
(let ,(make-mv-bindings vars val1#)
,@body)))))
(mv-bind (x) nil
(format t "x = ~A~%" x))
(mv-bind (x) 123
(format t "x = ~A~%" x))
(mv-bind (x y) (mv 1 2 3)
(format t "x = ~A, y = ~A~%" x y))
(mv-bind (x y) ((lambda () (mv 1 2 3)))
(format t "x = ~A, y = ~A~%" x y))
(mv-list (foo))
;; ;;
;; (defun values* (&rest values)
;; (if (and (boundp '*values*)
;; (> (length values) 1))
;; (progn
;; (setf (fill-pointer *values*) 20)
;; (loop
;; for v in values
;; for i upfrom 0
;; do (setf (elt *values* i) v)
;; finally (progn (setf (fill-pointer *values*) (1+ i))
;; (return *values*))))
;; (first values)))
;; (defmacro multiple-value-bind* (vars mv-form &body body)
;; (let ((values# (gensym)))
;; `(let (,@(mapcar #'list vars)
;; (,values# (let ((*values* (if (boundp '*values*)
;; *values*
;; (make-array '(20) :fill-pointer 0))))
;; ,mv-form)))
;; (if (eq ,values# *values*)
;; (prog () ,@(loop
;; for v in vars
;; for i upfrom 0
;; collect `(when (> (length ,values#) ,i)
;; (setq ,v (elt ,values# ,i)))))
;; ,(when (> (length vars) 0)
;; `(prog () (setq ,(first vars) ,values#))))
;; ,@body)))
;; (format t "~A~%" (multiple-value-bind* () nil))
;; (multiple-value-bind* (x) nil
;; (format t "x = ~A~%" x))
;; (multiple-value-bind* (x) 123
;; (format t "x = ~A~%" x))
;; (multiple-value-bind* (x y) (values* 1 2 3)
;; (format t "x = ~A, y = ~A~%" x y))
;; (multiple-value-bind* (x y) ((lambda () (values* 1 2 3)))
;; (format t "x = ~A, y = ~A~%" x y))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment