Subject: Re: LISP apply question
From: Erik Naggum <erik@naggum.no>
Date: 19 Jan 2004 01:42:33 +0000
Newsgroups: comp.lang.lisp
Message-ID: <3283465353380932KL2065E@naggum.no>

* jennyjennydz@yahoo.com (jennyjenny)
| Here is the line of code I'm trying to translate into unLISPed
| english.
| 
| **start of code chunk
| (defun binomialreg-model (x y n &rest args)
| "Args: (x y n &rest args)
| Returns a binomial regression model. Accepts :LINK, :OFFSET and
| :VERBOSE
| keywords in addition to the keywords accepted by regression-model."
|   (apply #'send binomialreg-proto :new :x x :y y :trials n args))
| **end of code chunk
:
| Is it doing (send binomialreg-proto :new  <args>) with all the things
| after :new as <args>?

  Yes, except that the rest argument list called ARGS above is spread
  into its constituent elements first.

  (apply #'+ 1 2 '(4 5 6)) is just like (+ 1 2 3 4 5 6), but if you have
  a list of arguments, this is the most obvious way to spread them out.
  There is in fact no way to call a function /directly/ with a list of
  arguments.  This is in sharp contrast to, e.g., C, where using varargs
  places significant restrictions on how you can use the argument list.

| Any help on explaining this in nonLISP terms would be greatly
| appreciated.

  Lisps have traditionally regarded the arguments as a list, and even
  though modern Lisp systems use registers and the stack like everybody
  else, conceptually, functions are passed an argument list and hack it
  up into its individual pieces.  For instance, keyword arguments, like
  :X X :Y Y :TRIALS N above, are passed in a list which is parsed by the
  recipient.  Unlike Ada and Perl and other languages that allow callers
  to name arguments, but still pass them in a predefined order, Common
  Lisp conceptually if not actually defers the parsing of the argument
  list to the function that receives it.

  The closest thing to this model is the Unix argument vector which it
  is common to refer to using $* for the entire vector, and $1, $2,
  ... for the individual arguments.  Unix programs have no support at
  all for handling the argument vector, so every program needs to hack
  it up into relevant pieces, picking up any options and any required
  arguments before usually treating the final arguments as a list of
  files to work on.

  In other words, a call to BINOMIALREG-MODEL takes three or more
  arguments, does a slight massage on the argument list and passes it
  onwards to SEND BINOMIALREG-PROTO :NEW, which accepts the three
  keyword arguments X, Y, and TRIALS.  Any excess arguments to the first
  function therefore have to be keyword arguments to the latter.  To see
  what a call to BINOMIALREG-MODEL does, the excess arguments only have
  meaning when you look at what SEND BINOMIALREG-PROTO :NEW accepts.  My
  guess is that you will find a call to BINOMIALREG-MODEL with more than
  three arguments extremely rarely, because they would have the form
  (binomialreg-model x y n :foo foo :bar bar).  If you never find any
  calls like that, you should ignore the flexibility and complexity of
  APPLY and consider (binomialreg-model x y n) /exactly/ the same as a
  call to (send binomialreg-proto :new :x x :y y :trials n).

-- 
Erik Naggum | Oslo, Norway

Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.