Arc Forumnew | comments | leaders | submitlogin
1 point by Pauan 3172 days ago | link | parent

Brilliant! In fact, you could write a macro that would do that for you:

  (mac defreq (name args . body)
    `(w/uniq gen
       (def ,name ,(map (fn (x) `(o ,x gen)) args)
         ,@(map (fn (x) `(if (is ,x gen) (err:string "parameter " ',x " is required"))) args)

  (defreq foo (x y) (+ x y))
  (foo)     -> x is required
  (foo 1)   -> y is required
  (foo 1 2) -> 3
It probably breaks with rest arguments, but I think you could get those working too.

1 point by Pauan 3172 days ago | link

Or this version, which is even better:

  (mac defreq (name vars . body)
    (if (isa vars 'cons)
          (let exp (len vars)
            `(def ,name args
               (let giv (len args)
                 (if (< giv ,exp)
                       (err:string "expected " ,exp " arguments (" giv " given)")
                     (apply (fn ,vars ,@body) args)))))
        `(def ,name ,vars ,@body)))

  (defreq foo (x y) (+ x y))
  (foo)     -> error: expected 2 arguments (0 given)
  (foo 1)   -> error: expected 2 arguments (1 given)
  (foo 1 2) -> 3
  (defreq foo args args)
  (foo)     -> ()
  (foo 1)   -> (1)
  (foo 1 2) -> (1 2)
It fails on functions that take required and rest args, though:

  (defreq foo (x y . args) (list x y args)) -> error
Err... right, you were talking about detecting if an argument was nil or not given... but I realized that the same technique could be used to write a version of def that implements required arguments even in a language where every argument is optional.