Created
December 8, 2020 19:10
-
-
Save alandipert/ccea4c063b8c65fdbfa1e97760cc6e31 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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