From: Tunc Simsek
Subject: [side-effects] Can we avoid them?
Date: 
Message-ID: <Pine.SOL.4.10.10008201653400.26113-100000@stout.EECS.Berkeley.EDU>
Regards,  please excuse me if this question
has an obvious answer.  I'm curious whether
its possible to ensure that a function
in CL (or via non-standard features in CMUCL/Allegro)
does not have side-effects.

Thanks,
Tunc

From: Colin Walters
Subject: Re: [side-effects] Can we avoid them?
Date: 
Message-ID: <87wvhbqvco.church.of.emacs@meta.verbum.org>
Tunc Simsek <······@stout.EECS.Berkeley.EDU> writes:

> Regards, please excuse me if this question has an obvious answer.
> I'm curious whether its possible to ensure that a function in CL (or
> via non-standard features in CMUCL/Allegro) does not have
> side-effects.

I think your question can be interpreted in different ways; however,
one thing you can do in CMUCL is say

(declaim (ext:constant-function foo))
(defun foo (x)
  (+ x 1))

And then if later you say

(foo 2)

in your code, then Python should be able to reduce this at
compile-time to simply '3'.

Does this help?
From: Tunc Simsek
Subject: Re: [side-effects] Can we avoid them?
Date: 
Message-ID: <Pine.SOL.4.10.10008202140360.26276-100000@stout.EECS.Berkeley.EDU>
On 20 Aug 2000, Colin Walters wrote:

> Tunc Simsek <······@stout.EECS.Berkeley.EDU> writes:
> 
> > Regards, please excuse me if this question has an obvious answer.
> > I'm curious whether its possible to ensure that a function in CL (or
> > via non-standard features in CMUCL/Allegro) does not have
> > side-effects.
> 
> I think your question can be interpreted in different ways; however,
> one thing you can do in CMUCL is say

I guess so.  Perhaps if I give an example:

(format t "hello world") is a side effect since
the value of some special variable (represented by t)
is being changed.

(let ((x 1))

   (defun incx () 
	(incf x)))

has side effects, since (incx) will not return
the same value for 2 different calls.

Perhaps a more precise definition would be:
  can we ensure that a given function is
	a.) indeed a function (i.e. always
		returns the same value on 
		the same arguments)
	b.) calling the function will not
		change the environment

> 
> (declaim (ext:constant-function foo))
> (defun foo (x)
>   (+ x 1))
> 
> And then if later you say
> 
> (foo 2)
> 
> in your code, then Python should be able to reduce this at
> compile-time to simply '3'.
> 
> Does this help?

yes it does, but not for this particular question.  I
remember looking for this kind of declaration a while back.

Thanks,
Tunc

> 
> 
> 
From: Barry Margolin
Subject: Re: [side-effects] Can we avoid them?
Date: 
Message-ID: <_gCo5.18$L56.1035@burlma1-snr2>
In article <·········································@stout.EECS.Berkeley.EDU>,
Tunc Simsek  <······@stout.EECS.Berkeley.EDU> wrote:
>Regards,  please excuse me if this question
>has an obvious answer.  I'm curious whether
>its possible to ensure that a function
>in CL (or via non-standard features in CMUCL/Allegro)
>does not have side-effects.

You can go through all the built-in functions and determine which ones are
side-effect-free.  If a function only calls side-effect-free functions,
then it is also guaranteed to be side-effect-free.

There's no portable way to determine what functions are called by a
function.

-- 
Barry Margolin, ······@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Tunc Simsek
Subject: Re: [side-effects] Can we avoid them?
Date: 
Message-ID: <Pine.SOL.4.10.10008222001570.3567-100000@stout.EECS.Berkeley.EDU>
On Tue, 22 Aug 2000, Barry Margolin wrote:

> In article <·········································@stout.EECS.Berkeley.EDU>,
> Tunc Simsek  <······@stout.EECS.Berkeley.EDU> wrote:
> >Regards,  please excuse me if this question
> >has an obvious answer.  I'm curious whether
> >its possible to ensure that a function
> >in CL (or via non-standard features in CMUCL/Allegro)
> >does not have side-effects.
> 
> You can go through all the built-in functions and determine which ones are
> side-effect-free.  If a function only calls side-effect-free functions,
> then it is also guaranteed to be side-effect-free.

I don't see how that will help.  SETF by itself may lead to side-effect
free functions or otherwise:

	(defun test1 (x)
	   (setf x 10))

	(let ((x 10))
	  (defun test2 ()
		(setf x 10)))

> 
> There's no portable way to determine what functions are called by a
> function.

By portable may I assume that you mean ANSI?  Infact, I've been looking
at this problem with my Allegro 5.x, which has a package called XREF.
Via calls like (xref:get-relation :uses 'test :wild) etc ... it is
possible to

1. check whether a function directly binds, uses and/or sets a global
   variable (where I guess that by global they mean a variable defined
	at the top-level via DEFVAR or DEFPARAMETER)
2. get the list of functions called by a function.

note: these apply to compiled functions.

Thus, by a careful algorithm, it becomes possible to check side-effects
on global vars.  But I was really aiming to capture side effects on
lexically bound vars, because it's my opinion that globals (which I'll
prefer to call specials) should, in careful circumstances, be allowed
side-effects: e.g. FORMAT on globally defined streams.  

BTW, I currently support CMUCL,Allegro in my applications (hopefully CLISP
sometime soon).

I've looked at M. Kantrowitz' xref tool, and that is similar in
functionality to Allegro's.  

Thanks for any insight to this matter,
Tunc

> 
> -- 
> Barry Margolin, ······@genuity.net
> Genuity, Burlington, MA
> *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
> Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
> 
> 
From: Johan Kullstam
Subject: Re: [side-effects] Can we avoid them?
Date: 
Message-ID: <m37l98hxn5.fsf@sysengr.res.ray.com>
Tunc Simsek <······@stout.EECS.Berkeley.EDU> writes:

> On Tue, 22 Aug 2000, Barry Margolin wrote:
> 
> > In article <·········································@stout.EECS.Berkeley.EDU>,
> > Tunc Simsek  <······@stout.EECS.Berkeley.EDU> wrote:
> > >Regards,  please excuse me if this question
> > >has an obvious answer.  I'm curious whether
> > >its possible to ensure that a function
> > >in CL (or via non-standard features in CMUCL/Allegro)
> > >does not have side-effects.
> > 
> > You can go through all the built-in functions and determine which ones are
> > side-effect-free.  If a function only calls side-effect-free functions,
> > then it is also guaranteed to be side-effect-free.
> 
> I don't see how that will help.  SETF by itself may lead to side-effect
> free functions or otherwise:

barry's criterion is sufficient but not necessary to ensure that the
function presents a side-effect free face.  SETF, in particular, is
not side-effect free (aside from the fact that it's not a function
and neither is SETQ should it resolve to that).  however, not all
functions employing SETF have external effects.

> 	(defun test1 (x)
> 	   (setf x 10))

the above is side effect free despite calling a function with side
effect.  this shows that you can have functions with internal side
effects that do not escape.

> 	(let ((x 10))
> 	  (defun test2 ()
> 		(setf x 10)))

again, SETF isn't side effect free.  however, this function doesn't
seem to have any side effects either.  X just remains 10.  TEST2 keeps
returning the value 10 no matter how often you call it.

i am not sure what you mean to show by these examples.

> > There's no portable way to determine what functions are called by a
> > function.
> 
> By portable may I assume that you mean ANSI?  Infact, I've been looking
> at this problem with my Allegro 5.x, which has a package called XREF.
> Via calls like (xref:get-relation :uses 'test :wild) etc ... it is
> possible to

this sounds interesting and useful.

> 1. check whether a function directly binds, uses and/or sets a global
>    variable (where I guess that by global they mean a variable defined
> 	at the top-level via DEFVAR or DEFPARAMETER)

what about closures?  e.g.,

(let ((count 0))
  (defun increment ()
     (incf count)))

> 2. get the list of functions called by a function.
> 
> note: these apply to compiled functions.

for the compiler system, it should be fairly easy to capture these
aspects during compile and stash them away somewhere for later recall.

> Thus, by a careful algorithm, it becomes possible to check side-effects
> on global vars.  But I was really aiming to capture side effects on
> lexically bound vars, because it's my opinion that globals (which I'll
> prefer to call specials) should, in careful circumstances, be allowed
> side-effects: e.g. FORMAT on globally defined streams.  

no.  format should *not* be allowed.

consider this loop to make 10 newlines.

(dotimes (i 10)
  (format t "~%"))

should i be allowed to hoist FORMAT out of the loop?  it keeps getting
called with the same arguments.  side effect free, imho, means i can
extract it from the loop.

-- 
J o h a n  K u l l s t a m
[········@ne.mediaone.net]
sysengr
From: Tunc Simsek
Subject: Re: [side-effects] Can we avoid them?
Date: 
Message-ID: <39A3FC8C.C68C4E1C@robotics.eecs.berkeley.edu>
Johan Kullstam wrote:
> 
> Tunc Simsek <······@stout.EECS.Berkeley.EDU> writes:
> 
> > On Tue, 22 Aug 2000, Barry Margolin wrote:
> >
> > > In article <·········································@stout.EECS.Berkeley.EDU>,
> > > Tunc Simsek  <······@stout.EECS.Berkeley.EDU> wrote:
> > > >Regards,  please excuse me if this question
> > > >has an obvious answer.  I'm curious whether
> > > >its possible to ensure that a function
> > > >in CL (or via non-standard features in CMUCL/Allegro)
> > > >does not have side-effects.
> > >
> > > You can go through all the built-in functions and determine which ones are
> > > side-effect-free.  If a function only calls side-effect-free functions,
> > > then it is also guaranteed to be side-effect-free.
> >
> > I don't see how that will help.  SETF by itself may lead to side-effect
> > free functions or otherwise:
> 
> barry's criterion is sufficient but not necessary to ensure that the
> function presents a side-effect free face.  SETF, in particular, is
> not side-effect free (aside from the fact that it's not a function
> and neither is SETQ should it resolve to that).  however, not all
> functions employing SETF have external effects.
> 
> >       (defun test1 (x)
> >          (setf x 10))
> 
> the above is side effect free despite calling a function with side
> effect.  this shows that you can have functions with internal side
> effects that do not escape.
> 
> >       (let ((x 10))
> >         (defun test2 ()
> >               (setf x 10)))
> 
> again, SETF isn't side effect free.  however, this function doesn't
> seem to have any side effects either.  X just remains 10.  TEST2 keeps
> returning the value 10 no matter how often you call it.

Infact, if X was bound dynamically, say by DEFVAR, before this form
was compiled, then this would have been a side effect.  However, this
was not my intention, I apologize for the misleading example.  The
kind of form I was looking for was:

(let ((x 0))
  (defun get-inc-x () (incf x)))

> 
> i am not sure what you mean to show by these examples.
> 
> > > There's no portable way to determine what functions are called by a
> > > function.
> >
> > By portable may I assume that you mean ANSI?  Infact, I've been looking
> > at this problem with my Allegro 5.x, which has a package called XREF.
> > Via calls like (xref:get-relation :uses 'test :wild) etc ... it is
> > possible to
> 
> this sounds interesting and useful.
> 
> > 1. check whether a function directly binds, uses and/or sets a global
> >    variable (where I guess that by global they mean a variable defined
> >       at the top-level via DEFVAR or DEFPARAMETER)
> 
> what about closures?  e.g.,
> 
> (let ((count 0))
>   (defun increment ()
>      (incf count)))

From my brief experience with Allegro's XREF and also Mkant's XREF
package, I did not find treatment of lexical closures.

> 
> > 2. get the list of functions called by a function.
> >
> > note: these apply to compiled functions.
> 
> for the compiler system, it should be fairly easy to capture these
> aspects during compile and stash them away somewhere for later recall.

Well, the compiler has all the information available.

> 
> > Thus, by a careful algorithm, it becomes possible to check side-effects
> > on global vars.  But I was really aiming to capture side effects on
> > lexically bound vars, because it's my opinion that globals (which I'll
> > prefer to call specials) should, in careful circumstances, be allowed
> > side-effects: e.g. FORMAT on globally defined streams.
> 
> no.  format should *not* be allowed.
> 
> consider this loop to make 10 newlines.
> 
> (dotimes (i 10)
>   (format t "~%"))
> 
> should i be allowed to hoist FORMAT out of the loop?  it keeps getting
> called with the same arguments.  side effect free, imho, means i can
> extract it from the loop.

I see your point and agree.  


Thanks for the input,
Tunc

> 
> --
> J o h a n  K u l l s t a m
> [········@ne.mediaone.net]
> sysengr