Skip to content

default parameter values #7

@luxint

Description

@luxint

Hi,

have had a lot of fun hacking with your lisp(s)! What I missed where default values/expressions for parameters so I made something myself, maybe usefull, use it if you like it. As a consequence there is no error message anymore for not enough actual parameters , any remaining parameters are bounded to nil/empty list or default value, which is quite usefull to prevent some 'helper' functions. See below the relevant part of the eval function (from closure to macro) which I have changed (have declared cv and cx variables at the top)

   else if (T(*f) == CLOS) {                   /* if f is a closure, then */
      *d = cdr(*f);                             /* construct an extended local environment d from f's static scope */
      if (T(*d) == NIL)                         /* if f's static scope is nil, then use global env as static scope */
        *d = env;
      v = car(car(*f));                         /* get the parameters v of closure f */
      while (T(v) == CONS && T(x) == CONS) {    /* bind parameters v to argument values x to extend the local scope d */
        cv = car(v);                            /* to check if parameter is a list with default value*/  
        if (T(cv) == CONS){                     /* check if parameter has a default */
          cx = eval(car(x),e);                 
          /* if argument is not nil then bind it else bind  default value*/ 
          *d = pair(car(car(v)), !not(cx) ? cx : eval(car(cdr(car(v))), e), *d);
        } 
        else
          *d = pair(car(v), eval(car(x),e), *d); /* add new binding to the front of d */
        v = cdr(v);
        x = cdr(x);
      }
      if (T(v) == CONS) {                       /* continue binding v if x is after a dot (... . x) by evaluating x */
        *y = eval(x, e);                        /* evaluate x and save its value y to protect it from getting GC'ed */
        while (T(v) == CONS && T(*y) == CONS) {
            *d = pair(car(v), car(*y), *d);      /* add new binding to the front of d */
          v = cdr(v);
          *y = cdr(*y);
        }
        while (T(v) == CONS){                    /* no more actual arguments, bind remaining parameters to nil or default*/
          cv=car(v); 
          if (T(cv) == CONS)                     /* check if parameter has default value*/                             
            *d = pair(car(car(v)), eval(car(cdr(car(v))),e), *d);
          else
            *d = pair(car(v), nil, *d);
          v=cdr(v);
        }
        x = *y;
      }
      else if (T(x) == CONS)                    /* if more arguments x are provided then evaluate them all */
        x = evlis(x, e);
      else if (T(x) != NIL)                     /* else if last argument x is after a dot (... . x) then evaluate x */
        x = eval(x, e);
      if (T(v) != NIL)                          /* if last parameter v is after a dot (... . v) then bind it to x */
        *d = pair(v, x, *d);
      x = *y = cdr(car(*f));                    /* tail recursion optimization: evaluate the body x of closure f next */
      e = *z = *d;                              /* the new environment e is d to evaluate x, put in *z to protect */
    }
    else if (T(*f) == MACR) {                   /* else if f is a macro, then */
      *d = env;                                 /* construct an extended local environment d from global env */
      v = car(*f);                              /* get the parameters v of macro f */
      while (T(v) == CONS && T(x) == CONS) {    /* bind parameters v to arguments x to extend the local scope d */
        cv=car(v);                              /* if no more actual arguments bind remaining parameters to nil or default*/
        if (T(cv) == CONS)                      /* check to see if default values */  
          *d = pair(car(cv), !not(car(x)) ? car(x) : car(cdr(cv)), *d);
        else
          *d = pair(car(v), car(x), *d);
        v = cdr(v);
        x = cdr(x);
      }
      while (T(v)== CONS) {                     /*  if no more actual arguments bind remaining parameters to nil or default*/
        cv=car(v);                   
        if (T(cv) == CONS)                       /* check if parameter has default value, if so bind against if car(x) is nil  */
          *d = pair(car(cv), car(cdr(cv)), *d);
        else
         *d = pair(car(v), nil, *d);
        v = cdr(v);
      }
      if (T(v) != NIL)                          /* if last parameter v is after a dot (... . v) then bind it to x */
        *d = pair(v, x, *d);
      x = *y = eval(cdr(*f), *d);               /* evaluated body of the macro to evaluate next, put in *z to protect */
    }

Tests:

4112+7740>(def test (a (b 1) (c 2) . d) (println a b c d ))
test
4080+7734>(test)
()12()
()
4080+7734>(test 1 2)
122()
()
4080+7734>(test 1 2 3)
123()
()
4080+7734>(test 1 2 3 4 5 6)
123(4 5 6)
()
4080+7734>(test 1 () 3 4 5 6)
113(4 5 6)
()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions