Skip to content

Instantly share code, notes, and snippets.

@woodrush
Created July 25, 2017 23:13
Show Gist options
  • Save woodrush/5a4537511ff420bee65276421ad9ea14 to your computer and use it in GitHub Desktop.
Save woodrush/5a4537511ff420bee65276421ad9ea14 to your computer and use it in GitHub Desktop.
Hy macros for creating varargs versions of a fixed-args macro
(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