[comp.lang.scheme] Question with binding

shap@POLYA.STANFORD.EDU (Jonathan S. Shapiro) (04/18/89)

I have been thinking about compiling scheme, and am confused about the
following possibility:

	(define foo (lambda (x) (+ x 2)))
	(define + (lambda (x y) something))
	(foo)

If this is legal, I don't understand how a compiler can validly inline
primitives.  Is there some provision in R3RS or R4RS that resolves
this problem, or is it really a problem?  If the latter, how do
compilers deal with it?

Jon

dorai@titan.rice.edu (Dorai Sitaram) (04/18/89)

In article <8904171910.AA26688@polya.Stanford.EDU> shap@POLYA.STANFORD.EDU (Jonathan S. Shapiro) writes:
>I have been thinking about compiling scheme, and am confused about the
>following possibility:
>
>	(define foo (lambda (x) (+ x 2)))
>	(define + (lambda (x y) something))
>	(foo)
>
>If this is legal, I don't understand how a compiler can validly inline
>primitives.  Is there some provision in R3RS or R4RS that resolves
>this problem, or is it really a problem?  If the latter, how do
>compilers deal with it?
>
>Jon

Indiana University's Schemefolk treated this problem as follows (it's
possible I err here, in which case I profusely apologize to those
concerned): 

A bunch of primitive functions, e.g., +, cons, etc., were treated as
_constants_ in the sense that the names could not have other values
assigned to them. This is not weird, since it recalls the usual
treatment of certain other constant names, e.g., 1, nil (or rather
#f), "hello", etc.  Thus your (define + ...) would bomb.

They went on to add the facility (declare-constant ...) to the
language (Scheme84) so that the user could define hir own set of
constants. This was merely for the user's convenience, _not_ a
directive to the compiler to inline.

Just to make things interesting, they also added the facility
(undeclare-constant ...). It works as expected for user-defined
constants, which aren't inlined anyway. But for the system-constants,
while previous inlining stays, any new uses of the constant name take
on the new definition if any. (Is that clear? >:-])

--dorai
------------------------------------------------------------------------------
We must believe in free will. We have no choice.       --Isaac Bashevis Singer
------------------------------------------------------------------------------

jinx@CHAMARTIN.AI.MIT.EDU (Guillermo J. Rozas) (04/18/89)

    I have been thinking about compiling scheme, and am confused about the
    following possibility:

	    (define foo (lambda (x) (+ x 2)))
	    (define + (lambda (x y) something))
	    (foo)

    If this is legal, I don't understand how a compiler can validly inline
    primitives.  Is there some provision in R3RS or R4RS that resolves
    this problem, or is it really a problem?  If the latter, how do
    compilers deal with it?

Hopefully calling foo with no arguments gives a "wrong number of
arguments error" irrelevant of whether + is open coded. :-)

Now seriously, according to (my interpretation of) r3rs/r4rs,
assigning a new value to the variables which hold the standard
procedures is legal, and should have the "expected" effect.  Thus open
coding standard procedures is "strictly" illegal in a pure r3rs/r4rs
environment.

In MIT Scheme, no open coding happens by default, and there are no
constant bindings.  There are, however, a variety of declarations, of
which the most frequently found is

(declare (usual-integrations))

which tell the compiler that some set of common variables will have
their standard values at run time and that the compiler can freely
integrate/open-code these values.

In the absence of this (or another relevant) declaration, the compiler
will issue code which will act as if it referenced the variable at
call time and then invoked the resulting value.  Thus changing the
value of + at run time will change the behavior of compiled code that
references +.

vanMeule@ALLEGHENY.SCRC.SYMBOLICS.COM (Andre van Meulebrouck) (04/18/89)

    Date: 17 Apr 89 20:36:41 GMT
    From: titan!dorai@rice.edu  (Dorai Sitaram)
    Subject: Re: Question with binding
    Message-Id: <3107@kalliope.rice.edu>
    
    In article <8904171910.AA26688@polya.Stanford.EDU> shap@POLYA.STANFORD.EDU (Jonathan S. Shapiro) writes:
    >I have been thinking about compiling scheme, and am confused about the
    >following possibility:
    >
    >	(define foo (lambda (x) (+ x 2)))
    >	(define + (lambda (x y) something))
    >	(foo)
    >
    >If this is legal, I don't understand how a compiler can validly inline
    >primitives.  Is there some provision in R3RS or R4RS that resolves
    >this problem, or is it really a problem?  If the latter, how do
    >compilers deal with it?
    >
    >Jon
    
    [...]
    A bunch of primitive functions, e.g., +, cons, etc., were treated as
    _constants_ in the sense that the names could not have other values
    assigned to them.  [...]
    
^^That's my understanding too:  the idea that certain procedures can't change
during the course of a compilation/computation, otherwise things couldn't be
guaranteed to make sense if they were meanwhile allowed to change underneath
your feet during the computation/compilation.  As to user defined
functions--well if you want to do those sorts of things with your own functions,
okay, but the system won't let you do that with its functions (upon which it
might depend, or otherwise feels some responsibility to protect the integrity
of).  Something like that...(and I too profusely apologize if I misstated or
oversimply stated...).

In MacScheme, if you try (define + ...) you get:

ERROR:  Integrable procedures may not be redefined.  
(set! + ...)

I like the idea of that a great deal...I don't think the convenience of being
able to redefine things (advertently or inadvertently--with or without warning)
is a wonderful feature.  You can always write your own similar functions with
different names, and call out to those in preference if a system function isn't
quite what you wanted, right?

    --dorai

mitchemt@silver.bacs.indiana.edu (04/19/89)

As far as I know, (define + (lambda (x y) (* x y))) will work just fine under
Chez Scheme. I agree that it would be hard to write a compiler for this type
of code. I don't think it will bomb but you might get some weird results. Hope
this is of some help.
  Terrence Mitchem, Indiana University.

pierce@lanai.cs.ucla.edu (Brad Pierce) (04/19/89)

In article <56700003@silver> mitchemt@silver.bacs.indiana.edu writes:
>
>As far as I know, (define + (lambda (x y) (* x y))) will work just fine under
>Chez Scheme. I agree that it would be hard to write a compiler for this type
>of code. I don't think it will bomb but you might get some weird results. Hope
>this is of some help.
>  Terrence Mitchem, Indiana University.

The way Chez Scheme handles this problem is to have 4 different
optimization levels, numbered 0-3.  At levels 0 and 1, the lower
levels, this definition will work just fine.  At levels 2 and 3
redefining a primitive such as + will not be allowed. This has
worked well for me. Why force one approach or the other on a 
user when both needs can be accomodated? 

-- Brad Pierce, UCLA

dorai@titan.rice.edu (Dorai Sitaram) (04/21/89)

In article <8904191633.AA14869@sesame.Stanford.EDU> mkatz@sesame (Morris Katz) writes:
$   Date: Tue, 18 Apr 89 01:07 EDT
$   From: Andre van Meulebrouck <vanMeule@ALLEGHENY.SCRC.Symbolics.COM>
$       Date: 17 Apr 89 20:36:41 GMT
$       From: titan!dorai@rice.edu  (Dorai Sitaram)
$       [...]
$       A bunch of primitive functions, e.g., +, cons, etc., were treated as
$       _constants_ in the sense that the names could not have other values
$       assigned to them.  [...]
$
$   ^^That's my understanding too:  the idea that certain procedures can't change
$   during the course of a compilation/computation, otherwise things couldn't be
$   guaranteed to make sense if they were meanwhile allowed to change underneath
$   your feet during the computation/compilation.  As to user defined
$   functions--well if you want to do those sorts of things with your own functions,
$   okay, but the system won't let you do that with its functions (upon which it
$   might depend, or otherwise feels some responsibility to protect the integrity
$   of). [...]
$
$   In MacScheme, if you try (define + ...) you get:
$
$   ERROR:  Integrable procedures may not be redefined.  
$   (set! + ...)
$
$   I like the idea of that a great deal...I don't think the convenience of being
$   able to redefine things (advertently or inadvertently--with or without warning)
$   is a wonderful feature.  You can always write your own similar functions with
$   different names, and call out to those in preference if a system function isn't
$   quite what you wanted, right?
$
$       --dorai
	^^^^^^^
Not right (for me). BTW, I did _not_ say the above. They are Andre's
words. I needed to say this, because I tend to the diametrically
opposite opinion >:-].

$Yes, but this may not be the correct way to think about things.  Lets say that
$I want to count the number of cons cells that are formed in a suite of
$programs.  A good way to do this might be to create an environment in which the
$constructors like CONS and LIST were aliased to versions that counted the
$number of cells they allocated.  The program suite could then be run in this
$new environment to gather the desired statistics.  I would find the alternative
$of modifying all of the programs in the test suite much less elegant and quite
$inconvenient.  In on approach the cost of implementation is constant and in the
$other it is proportional to the size of the test suite.
$					Morry Katz

An earlier version of Chez did in fact allow redefinition of system
"constants" to be visible in existing system code, not just in
existing (and of course future) user code. One can use this to good
effect to define modified versions of the interpreter-eval, Morry's
cell-counting cons, etc. However, the current Chez has a most curious
stance on this matter. System "constants" can be redefined, but while
existing user code reflects these changes, system code is immune.
Obviously, there is no inlining going on. It's almost as if the
implementors took care to seal off system code with a huge "let",
i.e., (let ([cons cons] ... [<sys-const> <sys-const>] ...)
<sys-code>), so that any redefinition of the <sys-const>'s doesn't
affect <sys-code>.

I agree with Andre that redefinition of system-defined functions could
infringe upon the integrity of the system. In the old Chez, one needed
to just type (set! cons 0) to have the whole session come tumbling
down like a house of cards. But then, I don't think the guy who said
"Eternal vigilance is the price of liberty" meant it as an argument
_against_ liberty.

--dorai
------------------------------------------------------------------------------
We must believe in free will. We have no choice.       --Isaac Bashevis Singer
------------------------------------------------------------------------------

vanMeule@ALLEGHENY.SCRC.SYMBOLICS.COM (Andre van Meulebrouck) (04/21/89)

    Date: 20 Apr 89 18:49:34 GMT
    From: titan!dorai@rice.edu  (Dorai Sitaram)
    Subject: Re: Question with binding
    Message-Id: <3131@kalliope.rice.edu>

[. . .]

    I agree with Andre that redefinition of system-defined functions could
    infringe upon the integrity of the system. In the old Chez, one needed
    to just type (set! cons 0) to have the whole session come tumbling
    down like a house of cards. But then, I don't think the guy who said
    "Eternal vigilance is the price of liberty" meant it as an argument
    _against_ liberty.

Okay.  All the zeal and arguments shown for allowing the redefinition of car to
garbage sound pretty good.  And, I'm NOT religious or dogmatic about not
allowing redefinition.  (In fact, I'm religious about NOT being religious.)   I
just enjoyed the feature in MacScheme because of all those sleepless nights that
it saved me from lots of potential inadvertent mistakes that could have made
already sleepless nights more sleepless.

Recall also, that MacScheme is a "micro" computer implementation.  Perhaps what
might be nice for "PC"s might not be universally acceptable for "large scale"
systems.

I just have one question for anyone that's in favor of redefinition.

Are you saying you want redefinition-with-wild-abandon?  I.e. do you NOT want
the system to warn you and ask you: "Are you sure?"?  (Admittedly there could be
a hackerish thrill in living dangerously....safety is wimps. :-)

Or, do you want the system to ask you?  (Which could be annoying, especially for
loading files.)

Or, do you want the system to warn you by default, unless you set a
global-dont-warn-me-about-redefinitions flag appropriately?  (And if the latter,
are you prepared to have zillions of such global variables for similar things in
a BIG MOBY system?)

Just curious (And by NO means intending raging controvery and/or heated
religious debates.  If I'm espousing unpopular ideas, well, I derived them from
reading Salmon Rushdie--so he's to blame!)

<Happy trails>  =:0)

    --dorai
    ------------------------------------------------------------------------------
    We must believe in free will. We have no choice.       --Isaac Bashevis Singer
    ------------------------------------------------------------------------------
[. . .]

nick@wacsvax.OZ.AU (Nick Lewins) (04/21/89)

Just to further the argument about redefining primative functions, TI's PC 
Scheme behaves like this:

(define + 
  (lambda (x y n)
    (modulo (+ x y) n)))

(+ 1 2 3)               ==>  0

(define blah
  (lambda ()
    (+ 1 2 3)))

(blah)                  ==>  6

I realise that + is treated specially, but this seems to be an undesirable 
(and inconsistant) way to handle primative function redefinition.  What's
more, the values of pcs-integrate-integrables and pcs-integrate-primatives 
don't seem to affect this behavior.  Comments anyone?

Nick.
-- 
-------------------                      
nick@wacsvax.uwa.oz                "Through Nambocour, and up the coast,
Dept. of Computer Science           the grass is greener, the girls are sweeter,
University of Western Australia     I did it all in the last ten summers."
CRAWLEY 6009                           - Cold Chisel, "Hound dog"

dorai@titan.rice.edu (Dorai Sitaram) (04/22/89)

$From: Andre van Meulebrouck <vanMeule@allegheny.scrc.symbolics.com>
$    From: titan!dorai@rice.edu  (Dorai Sitaram)
$    I agree with Andre that redefinition of system-defined functions could
$    infringe upon the integrity of the system. In the old Chez, one needed
$    to just type (set! cons 0) to have the whole session come tumbling
$    down like a house of cards. But then, I don't think the guy who said
$    "Eternal vigilance is the price of liberty" meant it as an argument
$    _against_ liberty.
$
$Okay.  All the zeal and arguments shown for allowing the redefinition of car to
$garbage sound pretty good.  And, I'm NOT religious or dogmatic about not
$allowing redefinition.  (In fact, I'm religious about NOT being religious.)   I
$just enjoyed the feature in MacScheme because of all those sleepless nights that
$it saved me from lots of potential inadvertent mistakes that could have made
$already sleepless nights more sleepless.
$
$Recall also, that MacScheme is a "micro" computer implementation.  Perhaps what
$might be nice for "PC"s might not be universally acceptable for "large scale"
$systems.
$
$I just have one question for anyone that's in favor of redefinition.
$
$Are you saying you want redefinition-with-wild-abandon?  I.e. do you NOT want
$the system to warn you and ask you: "Are you sure?"?  (Admittedly there could be
$a hackerish thrill in living dangerously....safety is wimps. :-)
$
$Or, do you want the system to ask you?  (Which could be annoying, especially for
$loading files.)
$
$Or, do you want the system to warn you by default, unless you set a
$global-dont-warn-me-about-redefinitions flag appropriately?  (And if the latter,
$are you prepared to have zillions of such global variables for similar things in
$a BIG MOBY system?)
$
$Just curious (And by NO means intending raging controvery and/or heated
$religious debates.  If I'm espousing unpopular ideas, well, I derived them from
$reading Salmon Rushdie--so he's to blame!)
$
$<Happy trails>  =:0)

Your concerns are perfectly legitimate: inadvertent or misguided
redefinition can cause no end of trouble. However, an irreversible
abolition of redefinition is not only aesthetically unpleasing to
those with "hackerish thrills", it is _unnecessary_. "Redefinition
with wild abandon" is not an untam(e)able animal at all. The system
warnings you ask about are also unnecessary. Even for small pc
implementations. Why?

The reason is that you can devise your own security blanket (and sleep
tight ;-}) with the macro system that comes with any Scheme. The
declare-constant and undeclare-constant that I referred to in my
earlier posting are now simple macros. One method would be:

(defmacro (declare-constant x)
  `(put 'x 'constant t))

(defmacro (undeclare-constant x)
  `(put 'x 'constant nil))

(defmacro (setq x v)
  `(if (get 'x 'constant)
       (error "hey watch out, salman rushdie is out to set constants!")
       (set! x ,v)))

The above is a very simple model (it hardly deserves the term
"hack"!). You can of course make it more watertight by avoiding use of
a global property table (make it local to the un/declare-constant and
setq macros). The use of setq as the new set! can also be avoided, by
lexically capturing the old set! (macro-)transform-function and
replacing it with the modified version.  All these are peripheral to
understanding how to get a very satisfactory method of getting safe
"constant" names in a system that provides redefinition.

Anyway, the upshot of all this is that redefinition allows one to get
the best of both worlds, while condemning the system to have immutable
"constants" is an irreversible situation. Which would you choose? :-]

--dorai
------------------------------------------------------------------------------
We must believe in free will. We have no choice.       --Isaac Bashevis Singer
------------------------------------------------------------------------------

jinx@CHAMARTIN.AI.MIT.EDU (Guillermo J. Rozas) (04/22/89)

    I just have one question for anyone that's in favor of redefinition.

    Are you saying you want redefinition-with-wild-abandon?  I.e. do
    you NOT want the system to warn you and ask you: "Are you sure?"?
    (Admittedly there could be a hackerish thrill in living
    dangerously....safety is wimps. :-)

    Or, do you want the system to ask you?  (Which could be annoying,
    especially for loading files.)

    Or, do you want the system to warn you by default, unless you set
    a global-dont-warn-me-about-redefinitions flag appropriately?
    (And if the latter, are you prepared to have zillions of such
    global variables for similar things in a BIG MOBY system?)

There are other possibilities besides global switches and annoying
warnings.

In MIT Scheme and T there are first class environments, called locales
in T, where incremental (top level) definition is legal.  Definition
in these environments affects only them and their "children", but
affects no other first class environments.  Systems can be structured
in such a way that defining in the "user initial" environment does not
affect system code at all, but affects all the user code "loaded"
there.  Thus the user can get whatever definition of CAR s/he wants
while the system continues using whatever else it wants.

If you want to "redefine" something for the system as well, you have
to do a little more work, since you first have to find what binding
(or bindings) affect the system, and then assign it (them) to the
desired value.  Since doing this unadvertently is very unlikely, there
is no need for warnings or switches.

I find that this scenario provides a reasonable degree of system
security against unintentional damage, while providing significant
power to knowledgeable users.

Unfortunately R3RS does not provide any notion of multiple first class
environments or top levels, so it is inconvenient to write an R3RS
portable system that has the above behavior.

dorai@titan.rice.edu (Dorai Sitaram) (04/24/89)

In article <3140@kalliope.rice.edu> I wrote:
$The reason is that you can devise your own security blanket (and sleep
$tight ;-}) with the macro system that comes with any Scheme. The
$declare-constant and undeclare-constant that I referred to in my
$earlier posting are now simple macros. One method would be:
$
$(defmacro (declare-constant x)
$  `(put 'x 'constant t))
$
$(defmacro (undeclare-constant x)
$  `(put 'x 'constant nil))
$
$(defmacro (setq x v)
$  `(if (get 'x 'constant)
$       (error "hey watch out, salman rushdie is out to set constants!")
$       (set! x ,v)))

All the x's above should have commas before them. I guess the constant
shuttling between the new extend-syntax (which doesn't use the
backquote system) and the old def*macro (which does) has taken its
toll.

--dorai
------------------------------------------------------------------------------
We must believe in free will. We have no choice.       --Isaac Bashevis Singer
------------------------------------------------------------------------------