Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!bloom-beacon!tub-tfs.UUCP!alti From: alti@tub-tfs.UUCP (Thorsten Altenkirch) Newsgroups: comp.lang.scheme Subject: Re: binding and assignment Message-ID: <8807271643.AA03879@tub-tfs.uucp> Date: 27 Jul 88 16:43:57 GMT Sender: daemon@bloom-beacon.MIT.EDU Organization: The Internet Lines: 107 () 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) (lambda (m) (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 operations : 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 - !x; > 0 : int - x := 3; > () : unit - !x; > 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. Thorsten