CQNAPS3DTQM3GT2BWSGKG4RG5W3IVCMRVY5XDIKT3B5LPHG7VOWAC 3O4SL4YHDSGOCYWQ7FNSEEPT67ELEQTPP4VPEQDC3OIDG43EP3OQC NEUQJ7FRWFVZ7HPXGLLBU55FH6OSB374SQSRGIAAA233KFGEKTDAC BC5TV4WYYVNWJMYNPHP6GC2GYNHNKR3RIOI34V3G4IGAQEXHX7GAC GSH2PRGCOOMP2GMHQUC2V5NQT5MJCFGVEI7TAMPQFCMT7E4DFHPQC GOXQFKWDQUYUH3XLJSAUL5LPNQ46NDO3ZGFJNVTECB4ARGZ4DW3QC I3MID22EURRK26C4JZ2U5FBEZ57GZVMBT44KFKTU4BBYXKLILWRAC UW27LKXM2BJ77FQLTY4WPKDSSWI2RFNFRJ7CB4U3TS7KYVIV72LQC 2UOWJD64KBUHIWGZTPGUWWJXH5ZIAMOEJRDNZQOW5QWBJDEACURQC DG4L5ELJFZS5JATC47CHOCESJM5H3XSL4WDBXNV4ADTUTMMKWZDAC A2JAXDJWT2FAKADYOY6QOQ7LQRMTTCDIOYT7STSESVHLZQEQJBMAC NBEO3TPNOUG7MRFYRSDDFB5TQKTEDL6GHHFQVOB5MXVPIBKFNZKAC GW4AAYNF7I66D72G5PMFTQRK7B4KZVYKAHKRPC2IY7IX37JKEHJQC JDZASPALXSFZOL3MXCKBPX74CUD3W743ZJ6W2422FIJ7NJOD67ZAC BEOFPS76OOYENP76QFENC7BFGH6GDLEZODWIHFFQOIK3ZHD7IPBAC ICGJDX2EHUCWPATWZRMDCSSTRXGSPW5M4NGU5MAFG6R7QDUC5KPQC keyword-symbol** Keyword arguments#+begin_src glotawk(defun takes-kwargs (a :kw b c) (list b c))(takes-kwargs 42 (:b 5)) ;; => (5 nil)#+end_srcIn the parameter list of a lambda expression, you may write the symbol~:kw~. If you do, then every symbol after that is to be looked up byname in the keyword arguments. When the lambda is called, everytwo-item list after the positional arguments is swept up into analist, and the parameters are assoc'd in it. If there is no keywordargument corresponding to a keyword parameter, that parameter will beset to nil.Naturally, defun follows suit with this syntax.If you already have an alist, you can use ~apply~ to pass it in as thekeyword arguments.
function _bind(vars, args, env, outer_env, d, hdlrs, st, errp, arg_value, lexpr_list) {
# ((:kw1 (+ 1 2)) (:kw2 (* 3 5))) -> ((:kw1 3) (:kw2 15))function _bind_kw_args_alist(args, env, outer_env, d, hdlrs, st, errp, k, v) {if(_is_null(args)) {return _nil()} else if(_atom_awk(args)) {return _error(_cons(_string("_bind_kw_args_alist: improper list"),_nil()),env, d, hdlrs, st, errp)} else {k = _eval3(_caar(args), env, env, d+1, hdlrs, st, errp)v = _eval3(_cadar(args), env, env, d+1, hdlrs, st, errp)return _cons(_cons(k, _cons(v, _nil())),_bind_kw_args_alist(_cdr(args), env, outer_env, d, hdlrs, st, errp))}}function _bind_kw(vars, args_alist, env, outer_env, d, hdlrs, st, errp, sym, dflt, v) {if(_is_null(vars)) {return outer_env} else if(_atom_awk(vars)) {# keyword LEXPR. bind vars to an alist of all the keyword argsreturn _cons(_cons(vars, _cons(args_alist, _nil())),outer_env)} else {# we aren't going to run out of args, because we're going to# default each kw parameter to something, or to nilsym = _car(vars)if(_atom_awk(sym)) {# just a parameter name. _assoc defaults to nil.v = _assoc(_symbol2keyword(sym), args_alist)# assoc returns the pair; take just the valueif(!_is_null(v)) v = _cadr(v)logg_dbg("_bind_kw", "binding " _repr(sym) " = " _repr(v))return _cons(_cons(sym, _cons(v, _nil())),_bind_kw(_cdr(vars), args_alist, env, outer_env, d, hdlrs, st, errp))} else {return _error(_cons(_string("_bind_kw: keyword parameter " _repr(sym) " is not an atom"), _nil()))}}}function _bind(vars, args, env, outer_env, d, hdlrs, st, errp, arg_value, lexpr_list, bkwal) {
if(_is_null(args)) {logg_err("_bind", "no args for vars " _repr(vars))}
if(_is_null(args))return _error(_cons(_string("_bind: no args for vars " _repr(vars)),_nil()),env, d, hdlrs, st, errp)else if(_eq_awk(_car(vars), _keyword("kw"))) {logg_dbg("_bind", ":kw in vars. args is " _repr(args))bkwal = _bind_kw_args_alist(args, env, d, hdlrs, st, errp)logg_dbg("_bind", "bkwal is " _repr(bkwal))return _bind_kw(_cdr(vars),bkwal,env, outer_env, d, hdlrs, st, errp)} else {
arg_value = _cons(_car(vars),_cons(_eval3(_car(args), env, env, d+1, hdlrs, st, errp),_nil()))
arg_value = _cons(_car(vars),_cons(_eval3(_car(args), env, env, d+1, hdlrs, st, errp),_nil()))
return _cons(arg_value,_bind(_cdr(vars), _cdr(args), env, outer_env, d, hdlrs, st, errp))
return _cons(arg_value,_bind(_cdr(vars), _cdr(args), env, outer_env, d, hdlrs, st, errp))}
return _string(substr(_eval3(_cadr(form), env, env, d+1, hdlrs, st, errp), 3))
return _string(_unkeyword(_eval3(_cadr(form), env, env, d+1, hdlrs, st, errp)))else if(car == _symbol("keyword-symbol"))# this too depends on the keyword's atom being "k somestuff"return _symbol(_unkeyword(_eval3(_cadr(form), env, env, d+1, hdlrs, st, errp)))
lisp_eval_should_be '(defun takes-kw-args (a :kw b c) 42)' '(*lambda (a :kw b c) 42)' 'keyword argument definition syntax'lisp_eval_should_be '((lambda (a :kw b c) (list a b c)) 3 (:b 5))' '(3 5 ())' 'keyword argument use; nil if missing'lisp_eval_should_be '((lambda (a :kw b c) (list a b c)) 3 (:c 7) (:b 5))' '(3 5 7)' 'keyword argument use, out of order'lisp_eval_should_be '(label ((args '\''((:b 5) (:c 7))) (fun (lambda (a :kw b c) (list a b c)))) (apply fun 3 args))' '(3 5 7)' 'keyword args from an existing alist'