[comp.lang.scheme] ``Update functions'' in Scheme.

lyn@BASEL.AI.MIT.EDU (Franklyn Turbak) (05/04/88)

> Did anybody already think about adding ``generalized functions''
> (a la Common-Lisp's setf/defsetf feature) to Scheme?  This would
> eliminate the need for several primitive procedures, among them
> set-car!, set-cdr!, vector-set!, and string-set!.  Instead of writing
> 
>    (set-car! p 5)    or    (vector-set! v 10 'a)
>
> this would make it possible to write
> 
>    (set! (car p) 5)  or    (set! (vector-ref v 10) 'a)


What's so great about SETF?  It doesn't eliminate the *need* for
the setting primitives (after all, they conceptually must still 
be there); it just makes it easier to remember their "names"
by providing a convention for deriving the setter from the
accessor.

But it's easy to develop alternate naming conventions without
altering Scheme.  One simple convention can be carried out
by simple renaming:

  (define set!car set-car!)
  (define set!cdr set-cdr!)
  (define set!vector-ref vector-set!)
  (define set!string-ref string-set!)

Here the name of each setter is the name of the accessor prefixed
by set!  Now we can write

  (set!car p 5)    or   (set!vector-ref v 10 'a)

which, except for the missing pair of parens, looks a lot like
the SETF approach.  And we didn't have to extend Scheme all!

- Lyn -

Ram-Ashwin@cs.yale.edu (Ashwin Ram) (05/09/88)

In article <8805031911.AA04352@basel>, lyn@BASEL (Franklyn Turbak) writes:
> > Did anybody already think about adding ``generalized functions''
> > (a la Common-Lisp's setf/defsetf feature) to Scheme?  This would
> > eliminate the need for several primitive procedures, among them
> > set-car!, set-cdr!, vector-set!, and string-set!.  Instead of writing
> > 
> >    (set-car! p 5)    or    (vector-set! v 10 'a)
> >
> > this would make it possible to write
> > 
> >    (set! (car p) 5)  or    (set! (vector-ref v 10) 'a)
> 
> What's so great about SETF? [...]
>    it's easy to develop alternate naming conventions without
> altering Scheme.  One simple convention can be carried out
> by simple renaming:
> 
>   (define set!car set-car!) [...]
>
>   (set!car p 5)    or   (set!vector-ref v 10 'a)
> 
> which, except for the missing pair of parens, looks a lot like
> the SETF approach.  And we didn't have to extend Scheme all!

I don't know about Common Lisp's SETF, but in the T dialect of Scheme there is a
difference between the two.  When you write (SET (FOO ...) ...), the operation
FOO can specify how it is to be set, i.e., it can handle the operation (SETTER
FOO) and return a setter procedure, which then does the setting appropriately.
This is not a matter of simple renaming; rather, it is a very useful programming
construct which lets you define new operations and their setters within the
existing syntax.

For example, you could implement a two-dimensional array by defining an accessor
operation (array-element A x y), where the definition of the operation would
include a definition of its setter.

Of course, you can do this without this feature too; it just turns out to be a
nice way to program, that's all.

-- Ashwin.

ARPA:    Ram-Ashwin@cs.yale.edu
UUCP:    {decvax,ucbvax,harvard,cmcl2,...}!yale!Ram-Ashwin
BITNET:  Ram@yalecs

gerald@umb.umb.edu (Gerald Ostheimer) (05/10/88)

Following the discussion on assignments in Scheme, and how to have them
performed in subroutines, the following question strikes my mind:

*** Why didn't the designers of Scheme include locations (~anonymous variables)
as first-class values in the language? ***

Wouldn't that fit the Scheme philosophy of orthogonality and 'first-class
everything'? After all, locations are part of the denotational semantics of
Scheme, so this wouldn't be much of an extension to Scheme from an abstract
point of view.
A variable would then be an identifier bound to a location, and we would have
true constants as well, by binding identifiers to values that are not
locations. All identifier bindings would then be irreversible, only locations
could be updated (thus indirectly updating identifiers bound to them).

If that sounds too abstract, consider the following hypothetical program
fragment:

(let ((x (var 1))               ; VAR creates a new location and
      (y 1))                    ;   initializes it to its argument
    (set! x 2)
    (set! x (+ val x) 2))       ; VAL looks up the current value of x
    (set! x (+ y 2)))           ; y can't be set! and needn't be val'ed

The cons function would have to create a pair of locations and initialize them
to its arguments. (So that we could make sense of setcar!)

We could now also write a 'swap' function as in

(define (swap x y)                 ; actual arguments must be variables
    (let ((h (val x)))
        (set! x (val y))
        (set! y h)))

This would not violate the 'call by value' principle, since locations would
_be_ values. First-class variables shouldn't give us any more headaches than
side-effects per se. Separating constants from variables should even simplify
some compiler optimizations (for the constants).
For the very least, we would get rid of having to write macros or extend the
syntax in order to abstract over assignments.

Any takers?

-- 
------------------------------------------------------------------------------
Gerald				"When I use a word, it means
<gerald@grn.umb.edu>		 exactly what I want it to mean"
				 (Humpty Dumpty, Through the Looking Glass)