ki
ki copied to clipboard
arguments var missing in ki functions
Sometimes it's useful to have the arguments
var available, just like js functions offer. Some cases can't quite be covered with variadic arity / multimethod functions. For example variable args with last arg a callback, or whatever other edge-case scenario. In any case, people could write their functions in ki without missing javascript's arguments
or falling back to javascript for that reason. Otherwise useful just for the sake of matching-up the host language.
This one is tricky. ki uses a lot of intermediate immediate function invocations to achieve proper lexical scoping and at the same time the JavaScript arguments
object only contains the arguments provided to the enclosing function.
What we could do is store the content of the arguments
object in a ki-specific args
(or whatever) object which gets overwritten only when a ki fn
is invoked. Then we'll have to make sure the previous value of args
is put back when the function returns.
I'm wondering whether this is the right thing to do as opposed to trying to cover the edge cases directly. Any thoughts? Also, can you provide an example of edge case with code? Thanks!
Actually, it's easier than I thought.
Let's start from the current state of things: arguments is correct and available right after entering the function body, e.g.
ki require core
ki (do
(defn f [] (prn arguments))
(f 1 2 3))
prints { '0': 1, '1': 2, '2': 3 }
, since there's no intermediate immediate functions in the way at that point.
However, the only way to have arguments
survive the rest of the scope is to assign it to a variable. However, using let
wouldn't work, because the assignment happens within an immediate function (for lexical scoping reasons), which is passed no arguments. In fact,
ki require core
ki (do
(defn f [] (let [args arguments] (prn arguments)))
(f 1 2 3))
prints {}
.
However, we can get to it with the help of a macro
ki require core
ki macro (defargs $args) (js var $args = arguments)
ki (do
(defn f [] (defargs args) (let [foo 1 bar 2] (prn args)))
(f 1 2 3))
prints { '0': 1, '1': 2, '2': 3 }
.
Feel free to let me know your thoughts.
Much better than nothing! This is a working solution. And considering that the args
variable is not used often, making this obvious call is even better, which will also remove the unnecessary overhead where args
is never used.. So maybe putting (defargs ..)
and some argumentless form of it like (use-args)
into the core would be good.
Thanks for the feedback.
Another couple of (not necessarily better) options
(letargs arg_binding ...)
ki require core
ki macro (defargs $args) (js var $args = arguments)
ki (do
(defn f [] (letargs args (let [foo 1 bar 2] (prn args))))
(f 1 2 3))
(defnargs [arg1 arg2 ...] ...)
ki require core
ki macro (defargs $args) (js var $args = arguments)
ki (do
(defnargs f [] args (let [foo 1 bar 2] (prn args)))
(f 1 2 3))