Function: let

let is a special form defined in eval.c.

Signature

(let VARLIST BODY...)

Documentation

Bind variables according to VARLIST then eval BODY.

The value of the last form in BODY is returned. Each element of VARLIST is a symbol (which is bound to nil) or a list (SYMBOL VALUEFORM) (which binds SYMBOL to the value of VALUEFORM). All the VALUEFORMs are evalled before any symbols are bound.

View in manual

Probably introduced at or before Emacs version 1.12.

Source Code

// Defined in /usr/src/emacs/src/eval.c
{
  Lisp_Object *temps, tem, lexenv;
  Lisp_Object elt;
  specpdl_ref count = SPECPDL_INDEX ();
  ptrdiff_t argnum;
  USE_SAFE_ALLOCA;

  Lisp_Object varlist = XCAR (args);

  /* Make space to hold the values to give the bound variables.  */
  EMACS_INT varlist_len = list_length (varlist);
  SAFE_ALLOCA_LISP (temps, varlist_len);
  ptrdiff_t nvars = varlist_len;

  /* Compute the values and store them in `temps'.  */

  for (argnum = 0; argnum < nvars && CONSP (varlist); argnum++)
    {
      maybe_quit ();
      elt = XCAR (varlist);
      varlist = XCDR (varlist);
      if (SYMBOLP (elt))
	temps[argnum] = Qnil;
      else if (! NILP (Fcdr (Fcdr (elt))))
	signal_error ("`let' bindings can have only one value-form", elt);
      else
	temps[argnum] = eval_sub (Fcar (Fcdr (elt)));
    }
  nvars = argnum;

  lexenv = Vinternal_interpreter_environment;

  varlist = XCAR (args);
  for (argnum = 0; argnum < nvars && CONSP (varlist); argnum++)
    {
      elt = XCAR (varlist);
      varlist = XCDR (varlist);
      Lisp_Object var = maybe_remove_pos_from_symbol (SYMBOLP (elt) ? elt
						      : Fcar (elt));
      CHECK_TYPE (BARE_SYMBOL_P (var), Qsymbolp, var);
      tem = temps[argnum];

      if (!NILP (lexenv) && !XBARE_SYMBOL (var)->u.s.declared_special
	  && NILP (Fmemq (var, Vinternal_interpreter_environment)))
	/* Lexically bind VAR by adding it to the lexenv alist.  */
	lexenv = Fcons (Fcons (var, tem), lexenv);
      else
	/* Dynamically bind VAR.  */
	specbind (var, tem);
    }

  if (!BASE_EQ (lexenv, Vinternal_interpreter_environment))
    /* Instantiate a new lexical environment.  */
    specbind (Qinternal_interpreter_environment, lexenv);

  elt = Fprogn (XCDR (args));
  return SAFE_FREE_UNBIND_TO (count, elt);
}