Add varfn.

This commit is contained in:
Calvin Rose 2019-10-03 20:20:42 -05:00
parent 841b58042f
commit e9f3dc7d5c
2 changed files with 25 additions and 0 deletions

View File

@ -2,6 +2,7 @@
All notable changes to this project will be documented in this file.
## Unreleased
- Add `varfn` macro
- Add compile time arity checking when function in function call is known.
- Added `slice` to the core library.
- The `*/slice` family of functions now can take nil as start or end to get

View File

@ -1538,6 +1538,30 @@
(set current (macex1 current on-binding)))
current)
(defmacro varfn
"Create a function that can be rebound. varfn has the same signature
as defn, but defines functions in the environment as vars. If a var 'name'
already exists in the environment, it is rebound to the new function. Returns
a function."
[name & body]
(def expansion (apply defn name body))
(def fbody (last expansion))
(def modifiers (tuple/slice expansion 2 -2))
(def metadata @{})
(each m modifiers
(cond
(keyword? m) (put metadata m true)
(string? m) (put metadata :doc m)
(error (string "invalid metadata " m))))
(with-syms [entry old-entry f]
~(let [,old-entry (,dyn ',name)]
(def ,entry (or ,old-entry @{:ref @[nil]}))
(,setdyn ',name ,entry)
(def ,f ,fbody)
(,put-in ,entry [:ref 0] ,f)
(,merge-into ,entry ',metadata)
,f)))
###
###
### Function shorthand