Arc Forum | The syntax to add rest args, if it followed the CL example, would be: (dsb (r1 ...

3 points by kennytilton 6466 days ago | link | parent

The syntax to add rest args, if it followed the CL example, would be:

 (dsb (r1 &o o1 &r rest &k k1) data ....)
If data was (1 2 'k1 3) then most params would be bound as expected and then rest would be bound to (k1 3).

But now the data (1 2 'k1 3 4) causes an error "Key list is not even", ie, once you say &k you undertake certain obligations as the caller. Even if you even up the list:

 (1 2 'k1 2 3 5)
...you get an error "3 is an invalid keyword", because 3 appears in a keyword position. This can be avoided by announcing your intention to have undeclared keywords:

 (a b &rest rest &key k1 &allow-other-keys)
That of course is CL, and it kinda makes my day that if I were crazy enough to extend dsb in Arc I would end up with:

 (a b &r rest &k k1 &aok)


1 point by kennytilton 6465 days ago | link

"...if I were crazy enough to extend dsb..."

Was there ever any doubt? :)

Still requiring extensions from earlier posts:

 (def dsb-params-parse (params)
 (withs (reqs nil key? nil opt? nil keys nil opts nil
 rest (mem '&r params)
 rest-var (cadr rest)
 aok? (find '&aok cddr.rest)
 resting? nil
 no-mas nil)
 (each p params
 (if no-mas (assert nil "No params &aok, OK?" ',params)
 (is p '&o) (do (assert ~opt? "Duplicate &o:" ',params)
 (assert ~key? "&k cannot precede &o:" ',params)
 (= opt? t))
 (is p '&k) (do (assert ~key? "Duplicate &k:" ',params)
 (= key? t))
 (is p '&r) (= resting? t)
 (is p '&aok) (= no-mas t)
 key? (push-end p keys)
 (and opt? (no resting?)) (push-end p opts)
 (no resting?) (do (assert (~acons p) "Reqd parameters need not be defaulted:" p)
 (push-end p reqs))))
 (prt 're-obj!!!!! reqs opts rest-var keys aok?)
 (obj reqs reqs opts opts rst rest-var keys keys aok? aok?)))
And man was I happy to have the above as a breakout from the macro itself:

 (mac dsb (params data . body)
 (w/uniq (tree kvs valid-keys aok?)
 `(withs (,tree ,data
 ,@(let plist (dsb-params-parse params)
 (prn `(reqs ,plist!reqs))
 (prn `(rst ,plist!rst))
 (prn `(keys ,plist!keys))
 (prn `(&aok ,plist!aok?))
 (with (n -1)
 (+ (mappend [list _ `(nth ,(++ n) ,tree)] plist!reqs)
 (mappend [list (carif _) `(if (< ,(++ n) (len ,tree))
 (nth ,n ,tree)
 ,(cadrif _))] plist!opts)
 `(,plist!rst (nthcdr ,(++ n) ,tree))
 `(,valid-keys ',plist!keys)
 `(,aok? ',plist!aok?)
 `(,kvs (do (prt 'foing ,valid-keys)
 (when (and ,plist!rst ,valid-keys)
 (assert (even (len ,plist!rst)) "Keyword list not even" ,plist!rst)
 (let ,kvs (pair ,plist!rst)
 (prt 'vetting ,valid-keys 'againt ,kvs)
 (unless ,aok?
 (assert (all [find (car _) ,valid-keys] ,kvs)
 "Invalid key in" (map car ,kvs)))
 (prt 'kvs!!!!! ,kvs)
 ,kvs))))
 (mappend [list (carif _)
 `(do (prt 'kvs!!! ',(carif _) ,kvs)
 (aif (assoc ',(carif _) ,kvs)
 cadr.it
 ,(cadrif _)))] plist!keys)))))
 ,@body)))
What is missing (largely) is graceful handling of invalid use.

-----

1 point by almkglor 6465 days ago | link

> What is missing (largely) is graceful handling of invalid use.

(err:tostring:write ...) works fine for me for reporting errors and aborting

-----




AltStyle によって変換されたページ (->オリジナル) /