Arc Forumnew | comments | leaders | submitlogin
4 points by conanite 5086 days ago | link | parent

Thanks, and well spotted. Using this with optional args gives the wrong error message: "reference to undefined identifier: _o"

> Anybody have ideas on how to fix that?

yes! A little function to extract arg names from an arg list:

  (def extract-arg-names (args)
    (flat:afnwith (args args o? nil)
      (if args
          (if atom.args
              args
              (let arg car.args
                (if atom.arg
                    (if (or no.o? (isnt arg 'o))
                        (cons arg (self cdr.args nil))
                        cadr.args)
                    (cons (self car.args t)
                          (self cdr.args nil))))))))

Gives:

  arc> (extract-arg-names 'xs)
  (xs)
  arc> (extract-arg-names '(x))
  (x)
  arc> (extract-arg-names '(a b))
  (a b)
  arc> (extract-arg-names '(a b (c d)))
  (a b c d)
  arc> (extract-arg-names '(a b c (d e (f g) (o h "foo")) (o i a) (o j 1)))
  (a b c d e f g h i j)
So using 'extract-arg-names instead of 'flat removes the problem of optional args. Use this function whenever you have a macro that needs to manipulate parameter lists!

The new and improved 'unsafe-def

  (unless (bound 'unsafe-def)
    (assign unsafe-def def)
    (mac def (name args . body)
      `(unsafe-def ,name ,args
         (on-err (fn (ex) (err:string "error in "
                                      ',name 
                                      (tostring:pr:list ,@(extract-arg-names args)) 
                                      "\n"
                                      (details ex)))
                 (fn ()   ,@body)))))
Which now returns the correct error msg:

  arc> (def myothermap (f (o xs '(a b c)))
    (map f xs))
  #<procedure:zz>
  arc> (def otherfoo (bar)
    (myothermap bar))
  #<procedure: otherfoo>
  arc> (otherfoo nil)
  Error: "error in otherfoo(nil)\nerror in myothermap(nil (a b c))\nFunction call on inappropriate object nil (a)"