apply
FUNCTION ARG_TYPE_LIST[FUNCTION]] -> RETURN_TYPE[FUNCTION]
関数にリストを引数を適用するのに便利な関数。最初の数個は指定するが残りは動的につくって渡すという使い方もできる。
code: eval.c
DEFUN ("apply", Fapply, Sapply, 1, MANY, 0,
doc: /* Call FUNCTION with our remaining args, using our last arg as list of args.
Then return the value FUNCTION returns.
With a single argument, call the argument's first element using the
other elements as args.
Thus, (apply \\='+ 1 2 \\='(3 4)) returns 10.
usage: (apply FUNCTION &rest ARGUMENTS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
ptrdiff_t i, funcall_nargs;
Lisp_Object *funcall_args = NULL;
USE_SAFE_ALLOCA;
ptrdiff_t numargs = list_length (spread_arg);
if (numargs == 0)
return Ffuncall (max (1, nargs - 1), args);
else if (numargs == 1)
{
return Ffuncall (nargs, args);
}
numargs += nargs - 2;
/* Optimize for no indirection. */
if (SYMBOLP (fun) && !NILP (fun)
&& (fun = XSYMBOL (fun)->u.s.function, SYMBOLP (fun)))
{
fun = indirect_function (fun);
if (NILP (fun))
/* Let funcall get the error. */
}
if (SUBRP (fun) && XSUBR (fun)->max_args > numargs
/* Don't hide an error by adding missing arguments. */
&& numargs >= XSUBR (fun)->min_args)
{
/* Avoid making funcall cons up a yet another new vector of arguments
by explicitly supplying nil's for optional values. */
SAFE_ALLOCA_LISP (funcall_args, 1 + XSUBR (fun)->max_args);
memclear (funcall_args + numargs + 1,
(XSUBR (fun)->max_args - numargs) * word_size);
funcall_nargs = 1 + XSUBR (fun)->max_args;
}
else
{ /* We add 1 to numargs because funcall_args includes the
function itself as well as its arguments. */
SAFE_ALLOCA_LISP (funcall_args, 1 + numargs);
funcall_nargs = 1 + numargs;
}
memcpy (funcall_args, args, nargs * word_size);
/* Spread the last arg we got. Its first element goes in
the slot that it used to occupy, hence this value of I. */
i = nargs - 1;
while (!NILP (spread_arg))
{
funcall_args i++ = XCAR (spread_arg); spread_arg = XCDR (spread_arg);
}
Lisp_Object retval = Ffuncall (funcall_nargs, funcall_args);
SAFE_FREE ();
return retval;
}
example
code: example1.el
(defun target (a) a)
;; => 1
code: example2.el
(defun target (a b c) (list a b c))
;; => (1 2 3)
;; => (1 2 3)
;; => (1 2 3)
普通に呼び出すのと比較して、引数の扱われ方が違うのが特徴。listをつくって引数に使う場合に便利なことがわかる。
code: example3.el
(defun target (a &rest b) (list a b))
(target 1 2 3)
;; => (1 (2 3))
(target 1 '(2 3))
;; => (1 ((2 3)))
(target 1 2 '(3))
;; => (1 (2 (3)))
;; => (1 (2 3))
;; => (1 (2 3))
;; => (1 (2 3))