Created
July 25, 2017 23:13
-
-
Save woodrush/5a4537511ff420bee65276421ad9ea14 to your computer and use it in GitHub Desktop.
Hy macros for creating varargs versions of a fixed-args macro
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
(defmacro defmacro-varargsify [m margs &rest mbody] | |
" | |
Defines an N-argument macro to a n*N-argument macro, | |
where the original macro is applied using each of the N arguments. | |
Example: | |
(defmacro-varargsify a [x y] | |
`(print (+ ~x ~y))) | |
(a 1 2 3 4 5 6) | |
==> prints 3, 7, 11 | |
(macroexpand '(a 1 2 3 4 5 6)) | |
==> ('do' ('print' ('+' 1 2)) ('print' ('+' 3 4)) ('print' ('+' 5 6))) | |
" | |
`(defmacro-template | |
(fn [args] | |
(setv n ~(len margs)) | |
(defn split-list-n [l] | |
(cons | |
(list (take n l)) | |
(when (> (len l) n) | |
(split-list-n (list (drop n l)))))) | |
(split-list-n args)) | |
~m ~margs ~mbody)) | |
(defmacro defmacro-varargsify-list [m margs &rest mbody] | |
" | |
Defines an N-argument macro to a n-argument macro | |
where each argument is an N-element list, | |
where the original macro is applied to each of the lists. | |
Example: | |
(defmacro-varargsify-list a [x y] | |
`(print (+ ~x ~y))) | |
(a [1 2] [3 4] [5 6]) | |
==> prints 3, 7, 11 | |
(macroexpand '(a [1 2] [3 4] [5 6])) | |
==> ('do' ('print' ('+' 1 2)) ('print' ('+' 3 4)) ('print' ('+' 5 6))) | |
" | |
`(defmacro-template | |
(fn [args] args) ~m ~margs ~mbody)) | |
(defmacro defmacro-template [passargs-func m margs mbody] | |
" | |
Helper macro for `defmacro-varargsify-list` and `defmacro-varargsify`. | |
" | |
`(defmacro ~(hy.models.HySymbol m) [&rest args] | |
(defn macro-unit [~@margs] | |
~@mbody) | |
`(do | |
~@(map (fn [l] (apply macro-unit l)) (~passargs-func args))))) | |
;======================================================================================= | |
(defmacro macro-varargsify [m numargs mprime] | |
" | |
Defines an varargs version of an already defined N-argument macro, | |
where the original macro is applied using each of the N arguments. | |
Example: | |
(defmacro a [x y] | |
`(print (+ ~x ~y))) | |
(varargsify a 2 a-prime) | |
(a-prime 1 2 3 4 5 6) | |
==> prints 3, 7, 11 | |
(macroexpand '(a-prime 1 2 3 4 5 6)) | |
==> ('do' ('a' 1 2) ('a' 3 4) ('a' 5 6)) | |
" | |
`(defmacro ~(hy.models.HySymbol mprime) [&rest body] | |
(defn varargsify_ [f n body] | |
(cons | |
`(~f ~@(take n body)) | |
(when (> (len body) n) | |
`(~@(varargsify_ '~m '~numargs (list (drop n body))))))) | |
; `m` and `n` Must be quoted, since "Macros live in the world of names, not what they represent." | |
; From http://old.ycombinator.com/arc/tut.txt , | |
; As quoted in https://news.ycombinator.com/item?id=1069997 | |
`(do | |
~@(varargsify_ '~m '~numargs body)))) | |
(defmacro macro-varargsify-list [m mprime] | |
" | |
Defines an N-argument macro to a n-argument macro | |
where each argument is an N-element list, | |
where the original macro is applied to each of the lists. | |
Example: | |
(defmacro a [x y] | |
`(print (+ ~x ~y))) | |
(macro-varargsify-list a a-prime) | |
(a-prime [1 2] [3 4] [5 6]) | |
==> prints 3, 7, 11 | |
(macroexpand '(a-prime [1 2] [3 4] [5 6])) | |
==> ('do' ('a' 1 2) ('a' 3 4) ('a' 5 6)) | |
" | |
`(defmacro ~(hy.models.HySymbol mprime) [&rest body] | |
`(do | |
~@(list (map (fn [l] `(~'~m ~@l)) body))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment