Macros multiple return values

Discussion of Common Lisp
Post Reply
porky11
Posts: 25
Joined: Fri May 02, 2014 6:46 am

Macros multiple return values

Post by porky11 » Sun Feb 08, 2015 6:16 pm

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:

Code: Select all

(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

Code: Select all

(list (special-procedure))

Kohath
Posts: 61
Joined: Mon Jul 07, 2008 8:06 pm
Location: Toowoomba, Queensland, Australia
Contact:

Re: Macros multiple return values

Post by Kohath » Sun Feb 08, 2015 9:29 pm

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.

porky11
Posts: 25
Joined: Fri May 02, 2014 6:46 am

Re: Macros multiple return values

Post by porky11 » Mon Feb 09, 2015 7:09 am

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 ;)

David Mullen
Posts: 78
Joined: Mon Dec 01, 2014 12:29 pm
Contact:

Re: Macros multiple return values

Post by David Mullen » Mon Feb 09, 2015 12:16 pm

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:

Code: Select all

(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.

Post Reply