From: jimka
Subject: sharing structure with the last argument to apply.
Date: 
Message-ID: <a8d3a8a9-c51d-41b5-a5eb-8c1d2d54d539@f40g2000pri.googlegroups.com>
according to CLHS 3.4.1.3 ... The value of a rest parameter is
permitted, but not required, to share structure with the last argument
to apply.

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

From: jimka
Subject: Re: sharing structure with the last argument to apply.
Date: 
Message-ID: <0957d262-74b1-4d1a-bc64-315e64c7a35c@d36g2000prf.googlegroups.com>
On Jan 4, 11:11 pm, jimka <·····@rdrop.com> wrote:
> according to CLHS 3.4.1.3 ... The value of a rest parameter is
> permitted, but not required, to share structure with the last argument
> to apply.
>
> 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.
From: Marco Antoniotti
Subject: Re: sharing structure with the last argument to apply.
Date: 
Message-ID: <ce167506-4dfb-4e6b-86eb-163448686e95@u18g2000pro.googlegroups.com>
On Jan 4, 5:11 pm, jimka <·····@rdrop.com> wrote:
> according to CLHS 3.4.1.3 ... The value of a rest parameter is
> permitted, but not required, to share structure with the last argument
> to apply.
>
> 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

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
From: jimka
Subject: Re: sharing structure with the last argument to apply.
Date: 
Message-ID: <8ccdcdfe-9e49-4dff-b6a3-9bf7cc526acc@p2g2000prn.googlegroups.com>
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?



On Jan 4, 11:27 pm, Marco Antoniotti <·······@gmail.com> wrote:
> On Jan 4, 5:11 pm, jimka <·····@rdrop.com> wrote:
>
> > according to CLHS 3.4.1.3 ... The value of a rest parameter is
> > permitted, but not required, to share structure with the last argument
> > to apply.
>
> > 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
>
From: Marco Antoniotti
Subject: Re: sharing structure with the last argument to apply.
Date: 
Message-ID: <f7653dc4-4124-4ae9-91bc-cfd243defeac@t26g2000prh.googlegroups.com>
On Jan 4, 5:49 pm, jimka <·····@rdrop.com> wrote:
> 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?
>
> On Jan 4, 11:27 pm, Marco Antoniotti <·······@gmail.com> wrote:
>
> > On Jan 4, 5:11 pm, jimka <·····@rdrop.com> wrote:
>
> > > according to CLHS 3.4.1.3 ... The value of a rest parameter is
> > > permitted, but not required, to share structure with the last argument
> > > to apply.
>
> > > 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
>
>

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.

Cheers
--
Marco Antoniotti
www.european-lisp-symposium.org
From: Pascal J. Bourguignon
Subject: Re: sharing structure with the last argument to apply.
Date: 
Message-ID: <87y6xqbqur.fsf@informatimago.com>
jimka <·····@rdrop.com> writes:

> 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__
From: jimka
Subject: Re: sharing structure with the last argument to apply.
Date: 
Message-ID: <706cc072-7a9a-4d35-a3dd-eb6a6ce44b4a@z28g2000prd.googlegroups.com>
no actually, i'm using the &rest primarily because the lambda list
might be
arbitrarily complex, and i do not want to have to reproduce the
semantics of lambda
list binding myself.  For example the original function might have
optional
arguments and keyword arguments with used-p and default expressions
with
side effects.  The &rest trick works regardless of the complexity of
the
function lambda list.
-jim

>
> 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__
From: Thomas A. Russ
Subject: Re: sharing structure with the last argument to apply.
Date: 
Message-ID: <ymiaba5bjt1.fsf@blackcat.isi.edu>
jimka <·····@rdrop.com> writes:

> 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
From: jimka
Subject: Re: sharing structure with the last argument to apply.
Date: 
Message-ID: <1822c983-e133-46ed-b385-52e3be8eb125@g1g2000pra.googlegroups.com>
On Jan 5, 9:05 pm, ····@sevak.isi.edu (Thomas A. Russ) wrote:
> jimka <·····@rdrop.com> writes:
> > 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))
From: Stanisław Halik
Subject: Re: sharing structure with the last argument to apply.
Date: 
Message-ID: <gjtbgp$4d8$1@opal.icpnet.pl>
thus spoke jimka <·····@rdrop.com>:

> 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
From: jimka
Subject: Re: sharing structure with the last argument to apply.
Date: 
Message-ID: <ed0dadf7-8b12-4170-a96d-c650a05ffc6b@o4g2000pra.googlegroups.com>
On Jan 5, 5:12 pm, Stanis³aw Halik <·······@test123.ltd.pl> wrote:
> thus spoke jimka <·····@rdrop.com>:
>
> > 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 have to worry about those unforeseen consequences anyway because
the spec says the list MIGHT have shared structure.
From: Pascal J. Bourguignon
Subject: Re: sharing structure with the last argument to apply.
Date: 
Message-ID: <873afyd86x.fsf@informatimago.com>
jimka <·····@rdrop.com> writes:

> according to CLHS 3.4.1.3 ... The value of a rest parameter is
> permitted, but not required, to share structure with the last argument
> to apply.
>
> 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))
>

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__