[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: binding and assignment
- To: pyramid!uunet!mc.lcs.mit.edu!scheme-request@tub.UUCP, esosun!jackson%seismo.css.gov@tub.BITNET
- Subject: Re: binding and assignment
- From: alti%tub-tfs.uucp%TUB.BITNET@MITVMA.MIT.EDU (Thorsten Altenkirch)
- Date: Wed, 27 Jul 88 18:43:57 +0200
- Cc: scheme%mc.lcs.mit.edu@tub.BITNET
- In-reply-to: Jerry Jackson's message as of Jul 26, 13:53.
() It occurred to me that there is an inconsistency in the scheme/lisp
() treatment of assignment when it comes to symbols -- in all other
() cases assignment means changing the contents of a cell of some kind,
() while assignment to a symbol is treated as a renaming operation. I
() figured this had resulted from the functional programming perspective
() -- a binding is simply the name for a value in a particular context...
() It seems non-intuitive that assigning to "a" is actually removing
() the name "a" from some value and naming a different value "a".
I don't understand what you mean. You assign values to symbols and
this is realized by modifying the innermost environment, where the
symbol is bound.
You can use this scheme to define any mutable data structure. Consider
following implementation of cons (see also Abelson/Sussman,"The structure
and the interpretation of Computer Programs", pp 207) :
(define (my-cons x y)
(cond ((eq? m 'car) x)
((eq? m 'cdr) y)
((eq? m 'set-car!) (lambda (v) (set! x v)))
((eq? m 'set-cdr!) (lambda (v) (set! y v))))))
(define my-car (x) (x 'my-car))
(define my-cdr (x) (x 'my-cdr))
(define my-set-car! (x v) ((x 'set-car!) v))
(define my-set-cdr! (x v) ((x 'set-cdr!) v))
These implementation of cons is heavily influenced by the
representation of data structures in the lambda calculus. But you have
no assignment in the lambda calculus. I found it quite interesting how
well a very general assignment and lambda calculus can live together
(if you have call-by-name semantics).
() I thought that a slightly different model might be useful.
However your idea with the "var"- form is not so bad. (I only can't
understand the reasons you gave). A thing like this is realized in ML
(which is also a functional, but typed language, developed at
Edinburgh, from Robin Milner et al.)
They have a type 'a ref ('a is a type-variable) with the following
ref : 'a -> 'a ref
! : 'a ref -> 'a
(op :=) : 'a ref * 'a -> unit (* op means infix & unit is novalue).
A simple example (see R.Harpers "Introduction to Standard ML", p. 36):
(- is what the user types in, > are the systems responses).
- val x = ref 0;
> val x = ref(0) : int ref
> 0 : int
- x := 3;
> () : unit
> 3 : int
As might be clear you can use ref as a part of every data structure.
() This produces several benefits:
() 1) the 'setf' form of CL is obtained for free in a much less
() kludgey way -- e.g. after:
() 4) assignment becomes completely consistent and only one assignment
() special form is needed instead of one for each type of mutable data --
() It is no longer necessary to have vector-set!, set-car!,...
OK. But you export more about the implementation of a data type. No
problems with vectors and things like this, but if you implement a
more complex data type, you may decide to change the implementation
w.o. changing the interface. That becomes impossible, if your export
includes referential types.
() 2) built-in functions can be defined at the top level without using the
() 'var' form so that they cannot be redefined...
() 6) inlining (or direct linking -- not through a symbol) of built-ins
() is now allowable without constraints
I think that's more a point of the module structure of your program.
You often use modules and you don't want to change them, not only the
primitive functions. It should be possible to declare these different
usages of modules. (CommonLisp has package to realize modules, but it
lacks the possibility to declare a package as read-only).
() 3) the need for things like "named-lambda" is lessened -- If a recursive
() function is defined without using 'var', the value will never change
() and you get the effect of a named-lambda for free
named-lambda is a derivative from rec, and rec is the fixed-point
combinator. I think this is the onliest semantical clean way tp define
recursion. You should get an error if you use a variable on a point
where it is not defined. (That's the way ML works).
() 5) quoted constants are now actually guaranteed to be constant --
() no more accidental program modification
This should be garanteed by the production system, independenly of the
philosophy of assignments.