This is a read-only archive of lispforum.com. The forum was locked to new users and posts and is preserved here as static HTML from a database snapshot taken on 2019-09-07.

Macros multiple return values

4 posts · 4844 views

It would be nice if macros could have multiple return values.
Then one wouldn't have to write multiple macros to create special-functions, once for defun and once for lambda
Why is it possible with 0 return-values, and with 1 but not with other numbers ;(

Examples:
(defmacro test1 (a b c) (values c b a))
(list (test1 1 2 3)) ; should be the same as: (list 3 2 1)

;;;for special functions i may have to write both macros:
(defmacro special-defun (name arglist &body body)
  `(defun ,name ,arglist (do-something-special)... ,@body (do-rest)...)
(defmacro special-lambda (arglist &body body)
  `(lambda ,arglist (do-something-special)... ,@body (do-rest)...)
;;maybe also a third macro, with progn, if this should also be executed normally

;;;instead i could write this:
(defmacro special-procedure (&body body)
  (apply #'values '(do-something-special) (append body (list '(do-rest)...))))

;;;now I can use this special procedure for lambdas, founctions and in other places like this:
(defun fun (args...) (special-procedure (do-something args...)))
(lambda (args...) (special-procedure (do-something args...)))
;;without defining multiple macros
Are there already libs for this purpose?

Edit:
I know that in most cases I could return `(progn ,values...) by the macro, but this only seems suboptimal. For example, if i want to be able, to save all returnvalues as list i could do
(list (special-procedure))

Re: Macros multiple return values

I don't quite get what you're asking, but some comments:
  • Code produced by macros can return as many values as you want. You can do what you want in the second line of your examples with multiple-value-list.
  • As for a macro returning multiple forms, I think 0 return values will get converted to one return value - nil. I've played around with generating code with multiple 'lines', and it is incredibly confusing (i.e. nested instances of "Is this return value in a progn or do I need to wrap it?"). It is however possible - I just used a top level macro to farm the rest out to functions which I can then handle as I wish - and in the last step you can make it runnable code by e.g. wrapping in a progn or multiple-value-list or ...
  • Multiple values are used in a macro provided by the standard: define-setf-expander. I recommend a read.
blog.metalight.net

Re: Macros multiple return values

Kohath wrote:As for a macro returning multiple forms, I think 0 return values will get converted to one return value - nil. I've played around with generating code with multiple 'lines', and it is incredibly confusing (i.e. nested instances of "Is this return value in a progn or do I need to wrap it?"). It is however possible - I just used a top level macro to farm the rest out to functions which I can then handle as I wish - and in the last step you can make it runnable code by e.g. wrapping in a progn or multiple-value-list or ...
you are right, 0 return-values are convertet to nil. only read-macros can also become nothing (comments or "#+"/"#-")
(I mean the return-values of the macroexpansion)
Maybe I'll rewrite the evaluator ;)

Re: Macros multiple return values

If you want to return values at runtime then you can't do it by using VALUES at macroexpansion time. You'd need to do this—if what you want to do is return the values from all three parts consecutively:
(defmacro special-procedure (&body body)
  `(values-list (append (multiple-value-list (do-something-special))
                        (multiple-value-list (progn ,@body))
                        (multiple-value-list (do-rest)))))
Since a macro form is invariably a single form that's required to give a single form as the expansion, you can't use LIST to get the return values.