From: David Bakhash
Subject: help with `progv'
Date: 
Message-ID: <cxjwwb6nqxx.fsf@hawk.bu.edu>
I'm trying to understand `progv', but I'm having no luck.

can someone explain how it's used?  maybe an example will help.

I can't make heads or tails of the docs, neither in Emacs (CL
extension) or Steele's docs.

dave

From: P. Srinivas
Subject: Re: help with `progv'
Date: 
Message-ID: <6kkikk$glc$1@tribune.usask.ca>
David Bakhash (·····@bu.edu) wrote:
: I'm trying to understand `progv', but I'm having no luck.

: can someone explain how it's used?  maybe an example will help.

: I can't make heads or tails of the docs, neither in Emacs (CL
: extension) or Steele's docs.

: dave

Well, let me try.

PROGV is for binding dynamic variables. This is analogous to LET
which binds static variables. Another aspect is that LET requires
that we know the names of the symbols we want to bind before hand,
Where as PROGV allows binding of symbols which are determinied
(or generated) at run time. The superb Hyperspec has an example.


Assuming *x* is not globally special,

 (let ((*x* 3)) 
    (progv '(*x*) '(4) 
      (list *x* (symbol-value '*x*)))) =>  (3 4)

This does not illustrate the last point I mentioned, though.
That will be useful only when writing macros or generating the code
on the fly to be executed.

Anybody give a better example?

Srini
--------------------
Srinivas Palthepu                       Email: ·····@cs.usask.ca
ARIES laboratory,                      Phones: (306) 966-8654 (lab)
Department of Computer Science,                (306) 966-4759 (office)
University of Saskatchewan,                    (306) 373-6724 (home)    
57 Campus Dr, Saskatoon, SK, S7N 5A9      Fax: (306) 966-4884
From: David Bakhash
Subject: Re: help with `progv'
Date: 
Message-ID: <cxjpvgynlow.fsf@hawk.bu.edu>
(let ((*x* 3)) 
   (progv '(*x*) '(4) 
     (list *x* (symbol-value '*x*)))) ==> (3 4)

I can't see how those two expressions above didn't evaluate to the
same thing.  I can't see why the above is the case, and I can't see
how this can be useful.

I wish Graham had discussed this in his book.  It seems pretty
advanced to me.

dave
From: Lyman S. Taylor
Subject: Re: help with `progv'
Date: 
Message-ID: <6kkp4d$93b@pravda.cc.gatech.edu>
In article <···············@hawk.bu.edu>, David Bakhash  <·····@bu.edu> wrote:
>(let ((*x* 3)) 
>   (progv '(*x*) '(4) 
>     (list *x* (symbol-value '*x*)))) ==> (3 4)
>
>I can't see how those two expressions above didn't evaluate to the
>same thing.  I can't see why the above is the case, and I can't see
>how this can be useful.

  Useful?  Maybe. Confusing, certainly. This example is purposely choose
  names to cause a problem. Personally I avoid dynamically scoped variables 
  like the plague. This is one of spots where mantaining legacy compatibility 
  for dynamically scoped variables with the "new" features for lexically
  scoped variables is problematical. 

  Because as outlined before, all PROGV does is bind a dynamic variable
  to a new value.  It doesn't create any "scope" since dynamic variables
  are "scoped" by their dynamic context.   In this example this expression
  appears WIHTIN the lexical scope of a variable with the same name. 

  This is a contrieved context in that there are TWO variables named *x* 
  active in the same namespace.  One is the lexical variable *x*. That 
  varible is impervious to actions performed by PROGV.  PROGV only acts 
  upon dynamic variables. 

  If this var created by LET had been dynamic.. then you'd get the 
  result you'd expect. 

(let ((*x* 3 ))
  (declare (special *x*))
  (progv '(*x*)  '(4)
     (list *x* (symbol-value '*x*)))) ==>  (4 4 ) 


  Note also that:

(let ((*x* 3 ))
    (symbol-value '*x* ))

Will die a horrible death. From the HyperSpec:

"symbol-value can be used to get the value of a constant variable. 
 symbol-value cannot access the value of a lexical variable."


So in the initial example the  (symbol-value '*x* )    can't possibly
refer to the lexical variable, so it isn't used.  Fortunately, there is 
a dynamic variable lying around with the same name. So it is used. 
Similar to if...


 ? (setf *x* 44 )         
  44 

 ? (let ((*x* 3 ))
    (symbol-value '*x*)) 
  44 

Although with the nesting switched a bit....


If you have dynamic variables it nice if there are globals and named in the
star-name-star format... so folks know they are "different".  Code that uses 
dynamic variables that are "localized" to some process have to be documented
and made "well known" to everyone who might encounter those variables.
(In essence... they're treated like globals. In an important sense,
   landmines waiting to be stepped on,  they are... )



-- 
					
Lyman S. Taylor           "I'm a Doctor! Not a doorstop... "
(·····@cc.gatech.edu)     	The EMH Doctor in "Star Trek: First Contact".
 
			        
From: Scott L. Burson
Subject: Re: help with `progv'
Date: 
Message-ID: <356E004A.167EB0E7@zeta-sqoft.com>
David Bakhash wrote:
> 
> (let ((*x* 3))
>    (progv '(*x*) '(4)
>      (list *x* (symbol-value '*x*)))) ==> (3 4)
> 
> I can't see how those two expressions above didn't evaluate to the
> same thing.  I can't see why the above is the case, and I can't see
> how this can be useful.

This is a very confusing example.

The LET is making a *lexical* binding of *X*, which becomes the first
argument to the LIST call.  Lexical binding have nothing to do with
symbols' value cells.  The PROGV, on the other hand, *dynamically* binds
*X*, which *is* implemented using the symbol's value cell (which is what
SYMBOL-VALUE accesses).

As I think Kent pointed out, the purpose of PROGV is to do things like
establishing a specific set of (dynamic) variable bindings when one
enters a debugger context.  For instance, people (these days) generally
prefer *PRINT-BASE* to be 10. so that integers come out in decimal.  If
somebody wrote

  (let ((*print-base* 8)) (format ...))

and the FORMAT got an error, then when the debugger was entered,
*PRINT-BASE* would still be 8.

A debugger can have a list of such variables, and a corresponding list
of values to bind them to, and use PROGV to accomplish the binding. 
That way, if a user defines a new special variable which affects how the
user interacts with Lisp, they can add the variable and the "standard"
value it should have to the lists.  Furthermore, users can examine and
change the lists to suit their preferences.

I suppose this would be the place to insert my standard rant about how
special variables are a Bad Thing, but I don't have time today.  Maybe
tomorrow.

Anyway, the bottom line is, as Jeffrey Siskind suggested, that
legitimate uses of PROGV are extremely rare.  I can't offhand think of
another example than the one above.

-- Scott

				* * * * *

To use the email address, remove all occurrences of the letter "q".
From: Daitaro Hagihara
Subject: Re: help with `progv'
Date: 
Message-ID: <daiyanh-2905980534080001@ip22.garden-city6.ny.pub-ip.psi.net>
In article <·················@zeta-sqoft.com>, "Scott L. Burson" 
<·····@zeta-sqoft.com> wrote:

> I suppose this would be the place to insert my standard rant about how
> special variables are a Bad Thing, but I don't have time today.  Maybe
> tomorrow.

Could there be a progv for function binding?  If I can do something like

(progv '(#'print) '(#'identity) (print "45") ...)

then the use of progv really makes sense to me.  The above code would
suppress all occurences of printing within the sexp.  Thus there is no
need to resort to implementation dependent advise stuff (which I still
don't understand).  (This example is taken from Alan Hayes' recent
Mathematica tip in which Block is used to reassign Print command, as in
Block[{Print=Identity},Print[45];] --> Null.)  Not a bad thing to be had
in Lisp?

Daitaro Hagihara
From: David Bakhash
Subject: Re: help with `progv'
Date: 
Message-ID: <cxjpvguq5qq.fsf@raven.bu.edu>
·······@mindspring.com (Daitaro Hagihara) writes:

> In article <·················@zeta-sqoft.com>, "Scott L. Burson" 
> <·····@zeta-sqoft.com> wrote:
> 
> > I suppose this would be the place to insert my standard rant about how
> > special variables are a Bad Thing, but I don't have time today.  Maybe
> > tomorrow.
> 
> Could there be a progv for function binding?  If I can do something like
> 
> (progv '(#'print) '(#'identity) (print "45") ...)
> 
> then the use of progv really makes sense to me.  The above code would
> suppress all occurences of printing within the sexp.  Thus there is no
> need to resort to implementation dependent advise stuff (which I still
> don't understand).  (This example is taken from Alan Hayes' recent
> Mathematica tip in which Block is used to reassign Print command, as in
> Block[{Print=Identity},Print[45];] --> Null.)  Not a bad thing to be had
> in Lisp?

Yeah.  I agree.  That's what Emacs Lisp let's you do with an flet, or
a labels, since everything is dynamically scoped.  No matter where the 
program goes, you can alter the way certain functions get called.  I
think that even if this *doesn't* work, you can still advise the
functions, and that should work.  But I figure if `defadvice' works in 
Common Lisp, then there must be a way to do what you want, either with 
progv or something else.

dave
From: Kent M Pitman
Subject: Re: help with `progv'
Date: 
Message-ID: <sfwaf7yc8am.fsf@world.std.com>
·······@mindspring.com (Daitaro Hagihara) writes:

> Could there be a progv for function binding?  If I can do something like
> 
> (progv '(#'print) '(#'identity) (print "45") ...)
> 
> then the use of progv really makes sense to me.  The above code would
> suppress all occurences of printing within the sexp.

Although I agree it's missing in a "symmetry of language" analysis,
I'm not sure this would lead to good programming.  The above program
could and would be thwarted in any of a variety of ways, not just

 (let ((p #'print))
   (progv '(#'print) '(#'identity)
     (funcall p x)))

but also

   (progv '(#'print) '(#'identity)   
     (progn (terpri) (prin1 x) (princ #\Space)))   ;simulate print

and the one I most worry about [using PRIN1 here instead of PRINC deliberately]:

   (progv '(#'prin1) '(#'identity)
     (format t "~A" x))

In this latter case, FORMAT is defined to have ~A be like PRIN1, but it
doesn't say ~A necessarily calls PRIN1.  It might happeen the other way
around.  Or the two might call an internally-known name.

The fact is that variables are about "communication" (lexical and dynamic)
while functions are really not.  At least in "normal practice" in CL.
That's exactly why CL permits function objects, but passes them as values
of variables not as function names--that is, it separates function names
into a space that is more constant.

And with all programs, there is a potential test of wills between caller
and callee as to how much "customization" is permitted.  You might think
the caller has a "right" to do what you did above, but there is equal reason
to believe the callee has a reason to prevent you.  Someone must be right.
I personally think it's the programmer writer, not the caller, who should
get that benefit.

And if the caller WANTS output redirected, he'll provide a hook.  For
example, most CL functions take a stream argument and/or document what
stream output goes to.  This allows you to redirect output without knowing
the underlying implementational mechanism for that output (wheether it
be PRIN1 or FORMAT or whatever).

> Thus there is no
> need to resort to implementation dependent advise stuff (which I still
> don't understand).  (This example is taken from Alan Hayes' recent
> Mathematica tip in which Block is used to reassign Print command, as in
> Block[{Print=Identity},Print[45];] --> Null.)  Not a bad thing to be had
> in Lisp?

Advise is a different beast anyway.  It's generally not done either lexically
or dynamically but globally.  Once in a while there's a :within option 
allowed, I guess, but even so, we're usually talking debugging.  And that's
usually a programmer with his own code.  Once the code is running, the
language intends you to communicate with variables (lexical or dynamic),
not with function NAMES.  [Since functions are first class objects, note
this is NOT saying the language doesn't intend you to do functional
programming--that's a wholly orthogonal issue.]

NOTE WELL:

All of the above are my private opinions based on analysis and use of the
language.  I don't recall any discussions among standards groups about the
idea of a dynamic define, and I have no reason to believe that the reasons
I've cited are why the present state exists.  I'm just saying I think
there ARE good reasons which retroactively justify what we ended up with.
And maybe they explain why so few people ever ask.
From: Scott L. Burson
Subject: Re: help with `progv'
Date: 
Message-ID: <357268D2.237C228A@zeta-sqoft.com>
Kent M Pitman wrote:
> 
> ·······@mindspring.com (Daitaro Hagihara) writes:
> 
> > Could there be a progv for function binding?  If I can do something like
> >
> > (progv '(#'print) '(#'identity) (print "45") ...)
> >
> > then the use of progv really makes sense to me.  The above code would
> > suppress all occurences of printing within the sexp.
> 
> Although I agree it's missing in a "symmetry of language" analysis,
> I'm not sure this would lead to good programming.

This suggestion reminds me of the time I unthinkingly did (TRACE FORMAT)
to find out what arguments my program was passing to FORMAT.  Of course,
since FORMAT is used absolutely everywhere including printing trace
messages, this crashes a Lisp Machine very hard very quickly.  It was
really quite amusing.

-- Scott

				  * * * * *

To use the email address, remove all occurrences of the letter "q".
From: Kent M Pitman
Subject: Re: help with `progv'
Date: 
Message-ID: <sfwaf7xqink.fsf@world.std.com>
"Scott L. Burson" <·····@zeta-sqoft.com> writes:

> I unthinkingly did (TRACE FORMAT)
> to find out what arguments my program was passing to FORMAT.  Of course,
> since FORMAT is used absolutely everywhere including printing trace
> messages, this crashes a Lisp Machine very hard very quickly.  It was
> really quite amusing.

Yeah, it's dependent on the implementation what kind of fireworks you
get.  The VAXLISP group at DEC, as I recall, worked hard to enumerate
the exact set of callees that TRACE needed to work right and sanitized
things so that TRACE had its own private little copies of each so that
you could supposedly not screw yourself through use of TRACE.  That's
not required by the spec and is assumed to be something the market
will sort out.

Then again, as far as I know, there no longer a VAXLISP group
producing a DEC-native Lisp.  (Correct me if you know otherwise!--I'm
not trying to sneak in a dig against a competitor.)  Anyway, that says
something sad about the market's ability to sort out details like
this.  It will select for the "big important things", but will not
always reward the little details.  Sad.
From: Barry Margolin
Subject: Clobbering internals (was Re: help with `progv')
Date: 
Message-ID: <7nzc1.11$334.246969@cam-news-reader1.bbnplanet.com>
In article <·················@zeta-sqoft.com>,
Scott L. Burson <·····@zeta-sqoft.com> wrote:
>This suggestion reminds me of the time I unthinkingly did (TRACE FORMAT)
>to find out what arguments my program was passing to FORMAT.  Of course,
>since FORMAT is used absolutely everywhere including printing trace
>messages, this crashes a Lisp Machine very hard very quickly.  It was
>really quite amusing.

Which reminds me of the time someone at our place accidentally set T to NIL
on a Lispm.  The SETQ function wouldn't let you do it, but the SET function
would!  The system didn't crash immediately, although it acted pretty weird
until it did; I managed to undo it using the FEP Debugger.

In the next release, Symbolics moved T's symbol cell to a read-only memory
page.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
From: Thomas A. Russ
Subject: Re: Clobbering internals (was Re: help with `progv')
Date: 
Message-ID: <ymig1hoj0ik.fsf@sevak.isi.edu>
Barry Margolin <······@bbnplanet.com> writes:
> 
> Which reminds me of the time someone at our place accidentally set T to NIL
> on a Lispm.  The SETQ function wouldn't let you do it, but the SET function
> would!  The system didn't crash immediately, although it acted pretty weird
> until it did; I managed to undo it using the FEP Debugger.

This of course reminds of the the rather clever error messages that
MacLisp would print if you tried (at least with SETQ) to do the same
thing:

(setq t nil)

==>   VERITAS AETERNAE -- DON'T SETQ T


(setq nil t)

==>   NIHIL EX NIHIL  -- DON'T SETQ NIL

-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu    
From: Kent M Pitman
Subject: Re: Clobbering internals (was Re: help with `progv')
Date: 
Message-ID: <sfwra18fgbw.fsf@world.std.com>
···@sevak.isi.edu (Thomas A. Russ) writes:

> This of course reminds of the the rather clever error messages that
> MacLisp would print if you tried (at least with SETQ) to do the same
> thing:
> 
> (setq t nil)
> 
> ==>   VERITAS AETERNAE -- DON'T SETQ T
> 
> 
> (setq nil t)
> 
> ==>   NIHIL EX NIHIL  -- DON'T SETQ NIL

Actually, there was a third if you could ever figure out how to make
another symbol, e.g., MYVAR, that, like T or NIL, had its value cell
on a pure page.  (I think there were no such by default, but Maclisp
was pretty maleable if you were clever with EXqAMINE, DEPOSIT, LH/|,
etc.)

 (setq myvar 'anything)
 ;PURITAS NECESSE EST -- DON'T DO RANDOM BINDINGS

I might have the spelling wrong.  Latin's not my strong suit.
From: Scott L. Burson
Subject: Re: Clobbering internals (was Re: help with `progv')
Date: 
Message-ID: <3573CF74.6201DD56@zeta-sqoft.com>
Kent M Pitman wrote:
> 
> ···@sevak.isi.edu (Thomas A. Russ) writes:
> 
> > ==>   VERITAS AETERNAE -- DON'T SETQ T
> >
> > ==>   NIHIL EX NIHIL  -- DON'T SETQ NIL
> 
>  ;PURITAS NECESSE EST -- DON'T DO RANDOM BINDINGS
> 
> I might have the spelling wrong.  Latin's not my strong suit.

Yours looks right, but I believe the first should be "VERITAS AETERNA"
and the second "NIHIL EX NIHILO".

-- Scott

				  * * * * *

To use the email address, remove all occurrences of the letter "q".
From: Kent M Pitman
Subject: Re: Clobbering internals (was Re: help with `progv')
Date: 
Message-ID: <sfwg1hn6c51.fsf@world.std.com>
"Scott L. Burson" <·····@zeta-sqoft.com> writes:

> Yours looks right, but I believe the first should be "VERITAS AETERNA"
> and the second "NIHIL EX NIHILO".

Maybe in Latin, but not in Maclisp, at least for the second.
I realized I have actual records of this and checked.
The exact error messages were:

VERITAS AETERNA -- DON'T SETQ T.
NIHIL EX NIHIL -- DON'T SETQ NIL.
PURITAS NECESSE EST -- DON'T DO RANDOM BINDINGS.
From: Scott L. Burson
Subject: Re: Clobbering internals (was Re: help with `progv')
Date: 
Message-ID: <357465A8.62319AC4@zeta-sqoft.com>
Kent M Pitman wrote:
> 
> "Scott L. Burson" <·····@zeta-sqoft.com> writes:
> 
> > Yours looks right, but I believe the first should be "VERITAS AETERNA"
> > and the second "NIHIL EX NIHILO".
> 
> Maybe in Latin, but not in Maclisp, at least for the second.
> I realized I have actual records of this and checked.
> The exact error messages were:
> 
> NIHIL EX NIHIL -- DON'T SETQ NIL.

Now checking my Latin references, I discover that "nihil" existed in two
forms: one an indeclinable noun "nihil", for which "ex nihil" would be
correct, and the other a second-declension neuter noun "nihilum", for
which "ex nihilo" would be correct.  So I guess one could use either.  I
do seem to recall seeing "nihil ex nihilo" somewhere -- maybe BSG used
it in Multics Maclisp.

-- Scott

				  * * * * *

To use the email address, remove all occurrences of the letter "q".
From: Jeffrey Mark Siskind
Subject: Re: help with `progv'
Date: 
Message-ID: <yq7vhqqywd7.fsf@qobi.nj.nec.com>
> I'm trying to understand `progv', but I'm having no luck.
> 
> can someone explain how it's used?  maybe an example will help.
> 
> I can't make heads or tails of the docs, neither in Emacs (CL
> extension) or Steele's docs.

OK. Here goes. (I'm going to freely mix Common Lisp terminology, Scheme
terminology, and generic Lisp terminology here because I can't remember the CL
terminology. It's been a long time :-)

One can do four fundamental operations on variables:

1. bind
2. unbind
3. assign
4. access

Bind and unbind are typically done in complementary pairs, by procedure call
and exit. And by things like LET that macroexpand into procedure call and exit.
Assign is done by SET! and access is done by a variable access expression.

Now, Common Lisp provides two different sets of bind/unbind/assign/access
semantics: lexical (default) and dynamic (SPECIAL). And you can choose on a
per-variable basis which semantics you wish. Thus there are eight operations
in all: bind-lexical, unbind-lexical, assign-lexical, access-lexical,
bind-dynamic, unbind-dynamic, assign-dynamic, and access-dynamic. But the
semantics is only well-defined if you consistently use either only the lexical
or only the dynamic operations on a given variable. Since lexical is the
default, if you use the default you are consistent by definition. But if you
use dynamic you must guarantee that the compile knows that all bind, unbind,
assign, and access operations to that variable are dynamic. The normal way to
satisfy this is to make sure that the variable is defined by DEFVAR,
DEFCONSTANT, or DEFPARAMETER before any use of the variable. In the rare
circumstances that this is not appropriate, you need to use DECLARE SPECIAL,
PROCLAIM SPECIAL, or DECLAIM SPECIAL.

Now, PROGV only deals with dynamic semantics. Which is why you need to make
sure that the variables bound by PROGV are declared to have dynamic semantics.
Under dynamic semantics, a variable is a symbol. And the symbol has a value
slot. Access consists of reading that value slot and assignment consists of
writing that value slot. Binding consists of pushing the current value from
the value slot onto a stack and then assigning a new value to the value slot.
Unbinding consists of popping a value off of the stack and assigning it to the
value slot.

Since dynamic variables are symbols, which are in turn just structures, there
are simple procedure-equivalents to the syntactic forms of variable access and
SET!.

   X == (SYMEVAL 'X)
   (SET! X <E>) == (SET 'X <E>)

(Note that the above is *not* true for lexical variables because lexical
variables are not symbols and do not have their values stored in values slots
of symbols).

Now for the answer to your question. SYMEVAL and SET (unlike variable access
expressions and SET!) can take an arbitrary expression that evaluates to a
symbol at runtime. PROGV is to LET what SYMEVAL and SET are to variable access
expressions and SET!. PROGV and LET both bind variables, evaluate some
expression, and then unbind those variables.
(LET ((X1 <E1>) ... (Xn <E1n>)) <E>) binds X1 ... Xn to the values yielded by
E1 ... En, evaluates E, and then unbinds X1 ... Xn.

   (LET ((X1 <E1>) ... (Xn <E1n>)) <E>) ==
     (PROGV '(X1 ... Xn) (LIST <E1> ... <En>) <E>)

(I'm not sure that I got the argument order to PROGV correct. But you get the
idea.) What PROGV allows is that the list of variables (i.e. symbols) to be
bound is computed at run time. Just like SYMEVAL allows the variable
(i.e. symbol) to be accessed to be computed at run time and SET allows the
variable (i.e. symbol) to be assigned to be computed at run time.

Just like it is very rare to need SYMEVAL and SET, it is correspondingly very
rare to need PROGV. In my 18 years of programming in Lisp I have never seen or
used it even once.

    Jeff (http://www.neci.nj.nec.com/homepages/qobi)

P.S. For those who care, yes I know that I described shallow binding and not
deep binding and yes I know that the standard doesn't specify whether shallow
or deep binding is used.