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.