Does anyone know whether there is a way to do this with SBCL? For
example
I'd expect the following to evaluate to t but it evaluates to nil.
(let ((list1 (list 1 10 100)))
(declare (optimize (safety 0) (space 3)))
(apply (lambda (&rest list2)
(eq list1 list2)) list1))
-jim
seems like in clisp it also returns nil.
In clisp:
C/USER[122]> (funcall (compile nil (lambda (list1)
(apply (lambda (&rest list2) (eq list1 list2))
list1)))
(list 1 10 100))
T
C/USER[123]> (funcall (lambda (list1)
(apply (lambda (&rest list2) (eq list1 list2))
list1))
(list 1 10 100))
NIL
(I would have thought first that some Dynamic-extent declaration would
have been needed, but the determinant thing in clisp is the
compilation).
--
__Pascal Bourguignon__
If the CLHS says that it *may* share structure, then you *should not*
rely on this behavior.
Cheers
--
Marco Antoniotti
www.european-lisp-symposium.org
(defun my-foo (&rest args)
(do-something)
(prog1 (apply #'foo args)
(do-something-else)))
am I wrong? Is there some hidden danger I'm not understanding?
You are not wrong, but that is something you do not have control over,
unless you assume that your implementation is doing something about
it.
My take on these issues is not to worry too much about. If after
profiling this turns out to be a bottleneck then you can go in and do
something about it. But then again this is the standard party line.
> The reason i'm wondering is that if i write a function wrapper like
> the following,
> the the args list gets copied unnecessarily, which in some cases
> causes memory allocation
> and garbage collection issues, or at lest i have to considerer whether
> such considerations
> are real issues. But in the cases where I know i'm not modifying the
> list, but simply
> passing it through, it would be great if the copy could be omitted.
> best case would
> be if the compiler could notice that i'm not destructively modifying
> args, and in that
> case skip the copying.
>
> (defun my-foo (&rest args)
> (do-something)
> (prog1 (apply #'foo args)
> (do-something-else)))
>
>
> am I wrong? Is there some hidden danger I'm not understanding?
This looks like you're using &rest just because you don't know the
argument count, not because the function is of variable arity.
Instead, you could generate:
(defun my-foo (a b c)
(do-something)
(MULTIPLE-VALUE-PROG1 (foo a b c)
(do-something-else)))
assuming foo is ternary. You need to find the number of arguments for
each function you want to wrap efficiently.
--
__Pascal Bourguignon__
> The reason i'm wondering is that if i write a function wrapper like
> the following, the the args list gets copied unnecessarily, which in
> some cases causes memory allocation and garbage collection issues
I'd rather worry the other way around, for unforeseen consequences of
mutating the &rest-list.
--
You only have power over people so long as you don’t take everything
away from them. But when you’ve robbed a man of everything he’s no longer
in your power — he’s free again. -- Aleksandr Isayevich Solzhenitsyn
you have to worry about those unforeseen consequences anyway because
the spec says the list MIGHT have shared structure.
> best case would
> be if the compiler could notice that i'm not destructively modifying
> args, and in that
> case skip the copying.
And while it's at it, the compiler should also warn you about the
infinite loops in the program.
--
Thomas A. Russ, USC/Information Sciences Institute
yes, you're right in general such as the following example, the
results
are undefined according to CLHS 3.4.1.3 and the compiler could not
know.
(defun f1 (&rest args)
(f2)
(apply #'f3 args))
(defun f3 (a b c)
(+ a b c))
(let ((var (list 1 2 3)))
(defun f2 ()
(incf (car var)))
(apply #'f1 var))